Browse Source

Merge pull request #4 from plepe/master

Sync
master
Igor Eliezer 6 years ago
committed by GitHub
parent
commit
fa46455b3c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      .gitmodules
  2. 24
      bin/categories-to-lang
  3. 32
      bin/lang-to-categories
  4. 3
      doc/TwigJS.md
  5. 4
      lang/pt.json
  6. 2
      lib/modulekit/form
  7. 2
      lib/modulekit/lang
  8. 2
      modulekit
  9. 2
      modulekit.php
  10. 21
      package.json
  11. 14
      src/CategoryBase.js
  12. 246
      src/CategoryOverpass.js
  13. 22
      src/OpenStreetBrowserLoader.js
  14. 58
      src/addCategories.js
  15. 12
      src/category.css
  16. 6
      src/image.js
  17. 27
      src/index.js
  18. 1
      src/language.js
  19. 5
      src/maki.js
  20. 3
      src/markers.js
  21. 8
      src/options.js
  22. 8
      src/tagTranslations.js
  23. 27
      src/twigFunctions.js

2
.gitmodules

@ -1,12 +1,14 @@
[submodule "modulekit"]
path = modulekit
url = https://github.com/plepe/modulekit.git
branch = nodejs
[submodule "lib/modulekit/base"]
path = lib/modulekit/base
url = https://github.com/plepe/modulekit-base.git
[submodule "lib/modulekit/lang"]
path = lib/modulekit/lang
url = https://github.com/plepe/modulekit-lang.git
branch = master
[submodule "lib/modulekit/form"]
path = lib/modulekit/form
url = https://github.com/plepe/modulekit-form.git

24
bin/categories-to-lang

@ -16,18 +16,9 @@ fs.readdir('lang', function (err, files) {
let done = this.async()
let lang = m[1]
fs.readFile('lang/' + f, function (err, contents) {
let data = JSON.parse(contents)
fs.readFile('lang/' + f, function (err) {
if (!(lang in all)) {
all[lang] = {}
}
for (var id in data) {
if (!(id in all[lang])) {
all[lang][id] = data[id]
}
}
done()
@ -69,6 +60,19 @@ fs.readdir(
if (data.type && data.type === 'index') {
parseSubCategories(data.subCategories, all)
}
if (data.type && data.type === 'overpass') {
if (data.lists) {
for (let listId in data.lists) {
let list = data.lists[listId]
let langStrId = 'category:' + id + ':' + listId
allIds.push(langStrId)
for (let lang in list.name) {
all[lang][langStrId] = list.name[lang]
}
}
}
}
}
done()

32
bin/lang-to-categories

@ -5,6 +5,16 @@ const forEach = require('async-foreach').forEach
var all = {}
var allIds = []
function sortKeys (ob) {
let result = {}
let keys = Object.keys(ob)
keys.sort()
for (let i = 0; i < keys.length; i++) {
result[keys[i]] = ob[keys[i]]
}
return result
}
/* read existing translation files in lang/ */
fs.readdir('lang', function (err, files) {
forEach(files, function (f) {
@ -100,14 +110,24 @@ function writeCategories () {
if (data.type && data.type === 'index') {
writeSubCategories(data.subCategories, all)
}
if (data.type && data.type === 'overpass') {
if (data.lists) {
for (let listId in data.lists) {
let list = data.lists[listId]
let langStrId = id + ':' + listId
for (var lang in all[langStrId]) {
if (all[langStrId][lang]) {
list.name[lang] = all[langStrId][lang]
}
}
list.name = sortKeys(list.name)
}
}
}
let result = {}
let keys = Object.keys(data.name)
keys.sort()
for (let i = 0; i < keys.length; i++) {
result[keys[i]] = data.name[keys[i]]
}
data.name = result
data.name = sortKeys(data.name)
fs.writeFile(
f,

3
doc/TwigJS.md

@ -65,6 +65,9 @@ Extra filters:
* filter websiteUrl: return a valid http link. Example: `{{ "www.google.com"|websiteUrl }}` -> "http://www.google.com"; `{{ "https://google.com"|websiteUrl }}` -> "https://google.com"
* filter `matches`: regular expression match. e.g. `{{ "test"|matches("e(st)$") }}` returns `[ "est", "st" ]`. Returns null if it does not match.
* filter `osmDateParse`: returns an array with the lower and upper boundary of the year of a `start_date` tag. See [https://github.com/plepe/openstreetmap-date-parser](openstreetmap-date-parser) for details.
* filter `natsort`: Sort an array naturally, see [https://www.npmjs.com/package/natsort](natsort) for details.
* filter `unique`: Remove duplicate elements from an array.
* filter `md5`: calculate md5 hash of a string.
Notes:
* Variables will automatically be HTML escaped, if not the filter raw is used, e.g.: {{ tags.name|raw }}

4
lang/pt.json

@ -3,7 +3,7 @@
"category-info-tooltip": "Info & Legenda",
"closed": "fechado",
"default": "padrão",
"download:geojson": "",
"download:geojson": "Descarregar como GeoJSON",
"edit": "editar",
"error": {
"message": "Erro",
@ -11,7 +11,7 @@
},
"facilities": "Instalações",
"header:attributes": "Atributos",
"header:export": "",
"header:export": "Exportar",
"header:osm_meta": "OSM Meta",
"images": "Imagens",
"loading": "A carregar...",

2
lib/modulekit/form

@ -1 +1 @@
Subproject commit 464a0cbfab6acad402bc23e7f050bb01ca136b84
Subproject commit 8a2d3015ec181b14441037a79e7db3869453b135

2
lib/modulekit/lang

@ -1 +1 @@
Subproject commit eb4addba3c06cd2ffbb973fb9c8193a1af655aec
Subproject commit 89c651dbbbbd8464f78029d7479e9b719d302aae

2
modulekit

@ -1 +1 @@
Subproject commit 3726732cfa009857e14e63b471d4370a18f6b385
Subproject commit 8c875354b75c413e4ab3c45a97bc270dd86397fc

2
modulekit.php

@ -25,4 +25,4 @@ $include = array(
'style.css',
),
);
$version = "3.x-dev";
$version = "4.0";

21
package.json

@ -1,6 +1,6 @@
{
"name": "openstreetbrowser",
"version": "0.0.0",
"version": "4.0.0",
"description": "A re-make of the famous OpenStreetBrowser (pure JS, using Overpass API)",
"main": "src/export.js",
"repository": "https://github.com/plepe/openstreetbrowser",
@ -10,6 +10,10 @@
"@mapbox/maki": "^4.0.0",
"async": "^2.5.0",
"async-foreach": "^0.1.3",
"babelify": "^8.0.0",
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-preset-env": "^1.6.1",
"color-interpolate": "^1.0.2",
"font-awesome": "^4.7.0",
"i18next-client": "^1.11.4",
@ -21,13 +25,15 @@
"leaflet-textpath": "https://github.com/makinacorpus/Leaflet.TextPath#leaflet0.8-dev",
"leaflet.locatecontrol": "^0.61.0",
"leaflet.polylinemeasure": "https://github.com/ppete2/Leaflet.PolylineMeasure.git",
"md5": "^2.2.1",
"modulekit-tabs": "^0.1.0",
"moment": "^2.18.1",
"natsort": "^1.0.6",
"opening_hours": "^3.5.0",
"openstreetbrowser-categories-main": "https://github.com/plepe/openstreetbrowser-categories-main",
"openstreetmap-date-parser": "^0.1.0",
"openstreetmap-tag-translations": "https://github.com/plepe/openstreetmap-tag-translations",
"overpass-layer": "^1.0.1",
"overpass-layer": "^2.0.0",
"query-string": "^5.0.0",
"sheet-router": "^4.2.3",
"weight-sort": "^1.3.0"
@ -44,7 +50,7 @@
"targets": {
"browsers": [
"last 2 versions",
"> 0.5%",
"> 0.5%",
"safari >= 7",
"ie >= 11"
]
@ -64,10 +70,6 @@
"lint": "standard src/*.js"
},
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-preset-env": "^1.6.1",
"babelify": "^8.0.0",
"browserify": "^14.4.0",
"browserify-css": "^0.14.0",
"standard": "^10.0.2",
@ -92,6 +94,9 @@
"currentPath",
"overpassUrl",
"ajax"
]
],
"rules": {
"camelcase": 0
}
}
}

14
src/CategoryBase.js

@ -1,4 +1,5 @@
/* global lang, ui_lang, options, alert */
/* eslint camelcase: 0 */
var OpenStreetBrowserLoader = require('./OpenStreetBrowserLoader')
var tabs = require('modulekit-tabs')
@ -6,8 +7,7 @@ function CategoryBase (options, data) {
if (typeof options === 'string') {
this.id = options
this.options = {}
}
else {
} else {
this.id = options.id
this.options = options
}
@ -21,8 +21,8 @@ function CategoryBase (options, data) {
var a
if (this.id !== 'index') {
var domHeader = document.createElement('header')
this.dom.appendChild(domHeader)
this.domHeader = document.createElement('header')
this.dom.appendChild(this.domHeader)
if ('name' in this.data) {
if (typeof this.data.name === 'object') {
@ -40,13 +40,13 @@ function CategoryBase (options, data) {
a.appendChild(document.createTextNode(name))
a.href = '#'
a.onclick = this.toggle.bind(this)
domHeader.appendChild(a)
this.domHeader.appendChild(a)
if (this.options.repositoryId && this.options.repositoryId !== 'default') {
a = document.createElement('span')
a.className = 'repoId'
a.appendChild(document.createTextNode(this.options.repositoryId))
domHeader.appendChild(a)
this.domHeader.appendChild(a)
}
if (this.shallShowReload()) {
@ -68,7 +68,7 @@ function CategoryBase (options, data) {
}
})
}.bind(this)
domHeader.appendChild(a)
this.domHeader.appendChild(a)
}
}

246
src/CategoryOverpass.js

@ -1,3 +1,5 @@
/* global showDetails, openstreetbrowserPrefix */
/* eslint camelcase: 0 */
var OpenStreetBrowserLoader = require('./OpenStreetBrowserLoader')
var OverpassLayer = require('overpass-layer')
var OverpassLayerList = require('overpass-layer').List
@ -12,13 +14,6 @@ var defaultValues = {
feature: {
title: "{{ localizedTag(tags, 'name') |default(localizedTag(tags, 'operator')) | default(localizedTag(tags, 'ref')) | default(trans('unnamed')) }}",
markerSign: '',
'style:hover': {
color: 'black',
width: 3,
opacity: 1,
radius: 12,
pane: 'hover'
},
'style:selected': {
color: '#3f3f3f',
width: 3,
@ -26,12 +21,11 @@ var defaultValues = {
radius: 12,
pane: 'selected'
},
markerSymbol: "{{ markerPointer({})|raw }}",
listMarkerSymbol: "{{ markerCircle({})|raw }}",
markerSymbol: '{{ markerPointer({})|raw }}',
listMarkerSymbol: '{{ markerCircle({})|raw }}',
preferredZoom: 16
},
queryOptions: {
split: 64
}
}
@ -47,15 +41,15 @@ function CategoryOverpass (options, data) {
// set undefined data properties from defaultValues
for (var k1 in defaultValues) {
if (!(k1 in data)) {
data[k1] = defaultValues[k1]
data[k1] = JSON.parse(JSON.stringify(defaultValues[k1]))
} else if (typeof defaultValues[k1] === 'object') {
for (var k2 in defaultValues[k1]) {
if (!(k2 in data[k1])) {
data[k1][k2] = defaultValues[k1][k2]
data[k1][k2] = JSON.parse(JSON.stringify(defaultValues[k1][k2]))
} else if (typeof defaultValues[k1][k2] === 'object') {
for (var k3 in defaultValues[k1][k2]) {
if (!(k3 in data[k1][k2])) {
data[k1][k2][k3] = defaultValues[k1][k2][k3]
data[k1][k2][k3] = JSON.parse(JSON.stringify(defaultValues[k1][k2][k3]))
}
}
}
@ -73,8 +67,8 @@ function CategoryOverpass (options, data) {
}
data.feature.appUrl = '#' + this.id + '/{{ id }}'
data.styleNoBindPopup = [ 'hover', 'selected' ]
data.stylesNoAutoShow = [ 'hover', 'selected' ]
data.styleNoBindPopup = [ 'selected' ]
data.stylesNoAutoShow = [ 'selected' ]
data.updateAssets = this.updateAssets.bind(this)
this.layer = new OverpassLayer(data)
@ -91,54 +85,40 @@ function CategoryOverpass (options, data) {
this.parentCategory.notifyChildLoadEnd(this)
}
if (ev.error && ev.error !== 'abort') {
if (ev.error) {
alert('Error loading data from Overpass API: ' + ev.error)
}
}.bind(this)
this.layer.onAppear = function (ob) {
// HOVER
if (ob.listItem) {
ob.listItem.onmouseover = function (id) {
if (this.currentHover) {
this.currentHover.hide()
}
this.currentHover = this.layer.show(id, { styles: [ 'hover' ] }, function () {})
}.bind(this, ob.id)
ob.listItem.onmouseout = function (id) {
if (this.currentHover) {
this.currentHover.hide()
}
this.currentHover = null
}.bind(this, ob.id)
}
}.bind(this)
this.layer.onUpdate = function (ob) {
this.layer.on('update', function (object, ob) {
if (!ob.popup || !ob.popup._contentNode || map._popup !== ob.popup) {
return
}
this.updatePopupContent(ob, ob.popup)
if (document.getElementById('content').className === 'details') {
if (document.getElementById('content').className === 'details open') {
showDetails(ob, this)
}
}.bind(this)
}.bind(this))
p = document.createElement('div')
p.className = 'loadingIndicator'
p.innerHTML = '<i class="fa fa-spinner fa-pulse fa-fw"></i><span class="sr-only">' + lang('loading') + '</span>'
this.dom.appendChild(p)
p = document.createElement('div')
p.className = 'loadingIndicator2'
p.innerHTML = '<div class="bounce1"></div><div class="bounce2"></div><div class="bounce3"></div>'
this.dom.appendChild(p)
this.domStatus = document.createElement('div')
this.domStatus.className = 'status'
this.dom.appendChild(this.domStatus)
if (this.data.lists) {
this.dom.insertBefore(this.domStatus, this.domHeader.nextSibling)
} else {
p = document.createElement('div')
p.className = 'loadingIndicator2'
p.innerHTML = '<div class="bounce1"></div><div class="bounce2"></div><div class="bounce3"></div>'
this.dom.appendChild(p)
this.dom.appendChild(this.domStatus)
}
register_hook('state-get', function (state) {
if (this.isOpen) {
@ -174,7 +154,7 @@ CategoryOverpass.prototype.updateAssets = function (div) {
var src = img.getAttribute('src')
if (src === null) {
} else if (src.match(/^maki:.*/)) {
let m = src.match(/^maki:([a-z0-9\-]*)(?:\?(.*))?$/)
let m = src.match(/^maki:([a-z0-9-]*)(?:\?(.*))?$/)
if (m) {
let span = document.createElement('span')
img.parentNode.insertBefore(span, img)
@ -232,22 +212,22 @@ CategoryOverpass.prototype.updateStatus = function () {
}
}
CategoryOverpass.prototype._getMarker = function (ob) {
if (ob.data.listMarkerSymbol.trim() == 'line') {
var div = document.createElement('div')
CategoryOverpass.prototype._getMarker = function (origGetMarker, origList, ob) {
if (ob.data[origList.options.prefix + 'MarkerSymbol'].trim() === 'line') {
let div = document.createElement('div')
div.className = 'marker'
div.innerHTML = markers.line(ob.data)
return div
} else if (ob.data.listMarkerSymbol.trim() == 'polygon') {
var div = document.createElement('div')
} else if (ob.data[origList.options.prefix + 'MarkerSymbol'].trim() === 'polygon') {
let div = document.createElement('div')
div.className = 'marker'
div.innerHTML = markers.polygon(ob.data)
return div
}
return this.origGetMarker(ob)
return origGetMarker.call(origList, ob)
}
CategoryOverpass.prototype.open = function () {
@ -259,11 +239,74 @@ CategoryOverpass.prototype.open = function () {
this.layer.addTo(this.map)
if (!this.list) {
this.list = new OverpassLayerList(this.layer)
this.list.addTo(this.domContent)
this.origGetMarker = this.list._getMarker
this.list._getMarker = this._getMarker.bind(this)
if (!this.lists) {
this.lists = []
if (this.data.lists) {
this.listsDom = []
let wrapper = document.createElement('div')
wrapper.className = 'categoryWrapper'
this.domContent.appendChild(wrapper)
for (let k in this.data.lists) {
let listData = this.data.lists[k]
let list = new OverpassLayerList(this.layer, listData)
this.lists.push(list)
let dom = document.createElement('div')
dom.className = 'category category-list'
this.listsDom.push(dom)
wrapper.appendChild(dom)
let domHeader = document.createElement('header')
dom.appendChild(domHeader)
let p = document.createElement('div')
p.className = 'loadingIndicator'
p.innerHTML = '<i class="fa fa-spinner fa-pulse fa-fw"></i><span class="sr-only">' + lang('loading') + '</span>'
dom.appendChild(p)
let name
if (typeof listData.name === 'undefined') {
name = k
} else if (typeof listData.name === 'object') {
name = lang(listData.name)
} else {
name = listData.name
}
let a = document.createElement('a')
a.appendChild(document.createTextNode(name))
a.href = '#'
domHeader.appendChild(a)
a.onclick = () => {
dom.classList.toggle('open')
return false
}
let domContent = document.createElement('div')
domContent.className = 'content'
dom.appendChild(domContent)
list.addTo(domContent)
p = document.createElement('div')
p.className = 'loadingIndicator2'
p.innerHTML = '<div class="bounce1"></div><div class="bounce2"></div><div class="bounce3"></div>'
dom.appendChild(p)
}
} else {
let list = new OverpassLayerList(this.layer, {})
this.lists.push(list)
list.addTo(this.domContent)
}
this.lists.forEach(list => {
let origGetMarker = list._getMarker
list._getMarker = this._getMarker.bind(this, origGetMarker, list)
})
}
this.isOpen = true
@ -297,7 +340,7 @@ CategoryOverpass.prototype.updateInfo = function () {
global.currentCategory = this
var data = {
layer_id: this.id,
'const': this.data.const,
'const': this.data.const
}
if (this.map) {
data.map = { zoom: map.getZoom() }
@ -319,7 +362,7 @@ CategoryOverpass.prototype.close = function () {
CategoryBase.prototype.close.call(this)
this.layer.remove()
this.list.remove()
this.lists.forEach(list => list.remove())
state.update()
}
@ -333,11 +376,24 @@ CategoryOverpass.prototype.show = function (id, options, callback) {
this.currentDetails.hide()
}
this.currentDetails = this.layer.show(id,
{
styles: [ 'selected' ]
},
function (err, data) {
let layerOptions = {
styles: [ 'selected' ]
}
let idParts = id.split(/:/)
switch (idParts.length) {
case 2:
id = idParts[1]
layerOptions.sublayer_id = idParts[0]
break
case 1:
break
default:
return callback(new Error('too many id parts! ' + id))
}
this.currentDetails = this.layer.show(id, layerOptions,
function (err, ob, data) {
if (!err) {
if (options.showDetails && !options.hasLocation) {
var preferredZoom = data.data.preferredZoom || 16
@ -359,8 +415,13 @@ CategoryOverpass.prototype.notifyPopupOpen = function (object, popup) {
this.currentSelected.hide()
}
let layerOptions = {
styles: [ 'selected' ],
sublayer_id: object.sublayer_id
}
this.updatePopupContent(object, popup)
this.currentSelected = this.layer.show(object.id, { styles: [ 'selected' ] }, function () {})
this.currentSelected = this.layer.show(object.id, layerOptions, function () {})
}
CategoryOverpass.prototype.notifyPopupClose = function (object, popup) {
@ -376,36 +437,42 @@ CategoryOverpass.prototype.notifyPopupClose = function (object, popup) {
}
CategoryOverpass.prototype.updatePopupContent = function (object, popup) {
if (object.data.popupDescription || object.data.description) {
var div = document.createElement('div')
div.className = 'description'
div.innerHTML = object.data.popupDescription || object.data.description
popup._contentNode.insertBefore(div, popup._contentNode.firstChild.nextSibling)
if (this.popupBodyTemplate) {
var popupBody = popup._contentNode.getElementsByClassName('popupBody')
if (!popupBody.length) {
popupBody = document.createElement('div')
popupBody.className = 'popupBody'
popup._contentNode.appendChild(popupBody)
}
let html = this.popupBodyTemplate.render(object.twigData)
if (popupBody.currentHTML !== html) {
popupBody.innerHTML = html
}
popupBody.currentHTML = html
}
if (this.popupBodyTemplate) {
var popupBody = document.createElement('div')
popupBody.className = 'popupBody'
popup._contentNode.appendChild(popupBody)
let id_with_sublayer = (object.sublayer_id === 'main' ? '' : object.sublayer_id + ':') + object.id
var footer = popup._contentNode.getElementsByClassName('popup-footer')
if (!footer.length) {
footer = document.createElement('ul')
popup._contentNode.appendChild(footer)
footer.className = 'popup-footer'
var data = this.layer.twigData(object.object)
popupBody.innerHTML = this.popupBodyTemplate.render(data)
call_hooks_callback('show-popup', object, this, popup._contentNode,
function (err) {
if (err.length) {
console.log('show-popup produced errors:', err)
}
}
)
}
var footer = document.createElement('ul')
footer.className = 'popup-footer'
var footerContent = '<li><a class="showDetails" href="#' + this.id + '/' + object.id + '/details">' + lang('show details') + '</a></li>'
var footerContent = '<li><a class="showDetails" href="#' + this.id + '/' + id_with_sublayer + '/details">' + lang('show details') + '</a></li>'
footerContent += '<li><a target="_blank" class="editLink" href="https://www.openstreetmap.org/edit?editor=id&' + object.object.type + '=' + object.object.osm_id + '">' + lang('edit') + '</a></li>'
footer.innerHTML = footerContent
popup._contentNode.appendChild(footer)
call_hooks_callback('show-popup', object, this, popup._contentNode,
function (err) {
if (err.length) {
console.log('show-popup produced errors:', err)
}
}
)
}
CategoryOverpass.prototype.renderTemplate = function (object, templateId, callback) {
@ -415,11 +482,10 @@ CategoryOverpass.prototype.renderTemplate = function (object, templateId, callba
return callback(err, null)
}
var data = this.layer.twigData(object.object)
var result = template.render(data)
var result = template.render(object.twigData)
callback(null, result)
}.bind(this))
})
}
OpenStreetBrowserLoader.registerType('overpass', CategoryOverpass)

22
src/OpenStreetBrowserLoader.js

@ -1,5 +1,4 @@
var OverpassLayer = require('overpass-layer')
var jsonMultilineStrings = require('json-multiline-strings')
function OpenStreetBrowserLoader () {
this.types = {}
@ -27,7 +26,7 @@ OpenStreetBrowserLoader.prototype.getCategory = function (id, options, callback)
var ids = this.getFullId(id, options)
if (ids === null) {
return callback('invalid id', null)
return callback(new Error('invalid id'), null)
}
if (options.force) {
@ -94,10 +93,10 @@ OpenStreetBrowserLoader.prototype.getRepo = function (repo, options, callback) {
this.repoCache[repo] = [ req.statusText, null ]
} else {
try {
this.repoCache[repo] = [ null, JSON.parse(req.responseText) ]
this.repoCache[repo] = [ null, JSON.parse(req.responseText) ]
} catch (err) {
console.log('couldn\'t parse repository', req.responseText)
this.repoCache[repo] = [ 'couldn\t parse repository', null ]
console.log('couldn\'t parse repository', req.responseText)
this.repoCache[repo] = [ 'couldn\t parse repository', null ]
}
}
@ -207,8 +206,8 @@ OpenStreetBrowserLoader.prototype.getFullId = function (id, options) {
return null
}
var m
if (m = id.match(/^(.*)\/([^\/]*)/)) {
let m = id.match(/^(.*)\/([^/]*)/)
if (m) {
result.id = id
result.repositoryId = m[1]
result.entityId = m[2]
@ -222,7 +221,14 @@ OpenStreetBrowserLoader.prototype.getFullId = function (id, options) {
result.entityId = id
}
result.fullId = result.repositoryId + '/' + result.entityId
result.sublayerId = null
m = result.entityId.split(/:/)
if (m.length > 1) {
result.sublayerId = m[0]
result.entityId = m[1]
}
result.fullId = result.repositoryId + '/' + (result.sublayerId ? result.sublayerId + ':' : '') + result.entityId
return result
}

58
src/addCategories.js

@ -1,6 +1,9 @@
var OpenStreetBrowserLoader = require('./OpenStreetBrowserLoader')
/* global OverpassLayer, repositoriesGitea */
require('./addCategories.css')
var weightSort = require('weight-sort')
const weightSort = require('weight-sort')
const OpenStreetBrowserLoader = require('./OpenStreetBrowserLoader')
var content
@ -15,8 +18,11 @@ function addCategoriesShow (repo) {
document.getElementById('content').className = 'addCategories'
OpenStreetBrowserLoader.getRepo(repo, {}, function (err, repoData) {
while(content.firstChild)
content.removeChild(content.firstChild)
if (err) {
alert(err)
}
while (content.firstChild) { content.removeChild(content.firstChild) }
var backLink = document.createElement('a')
backLink.className = 'back'
@ -38,7 +44,7 @@ function addCategoriesShow (repo) {
}
content.appendChild(backLink)
var h = document.createElement('h2')
let h = document.createElement('h2')
h.appendChild(document.createTextNode(repo))
content.appendChild(h)
@ -50,12 +56,12 @@ function addCategoriesShow (repo) {
}
content.appendChild(backLink)
var h = document.createElement('h2')
let h = document.createElement('h2')
h.innerHTML = lang('more_categories')
content.appendChild(h)
if (typeof repositoriesGitea === 'object' && repositoriesGitea.url) {
var a = document.createElement('a')
let a = document.createElement('a')
a.href = repositoriesGitea.url
a.target = '_blank'
a.innerHTML = lang('more_categories_gitea')
@ -75,12 +81,12 @@ function addCategoriesShow (repo) {
var repositoryUrl = null
if (data.repositoryUrl) {
repositoryUrl = OverpassLayer.twig.twig({ data: data.repositoryUrl, autoescape: true })
repositoryUrl = OverpassLayer.twig.twig({ data: data.repositoryUrl, autoescape: true })
}
var li = document.createElement('li')
var a = document.createElement('a')
let a = document.createElement('a')
if (repo) {
a.href = '#categories=' + repo + '/' + id
a.onclick = function () {
@ -97,23 +103,23 @@ function addCategoriesShow (repo) {
li.appendChild(a)
a.appendChild(document.createTextNode('name' in data ? lang(data.name) : id))
var editLink = null
if (repo && categoryUrl) {
editLink = document.createElement('a')
editLink.href = categoryUrl.render({ repositoryId: repo, categoryId: id })
}
if (!repo && repositoryUrl) {
editLink = document.createElement('a')
editLink.href = repositoryUrl.render({ repositoryId: id })
}
if (editLink) {
editLink.className = 'source-code'
editLink.title = 'Show source code'
editLink.target = '_blank'
editLink.innerHTML = '<i class="fa fa-file-code-o" aria-hidden="true"></i>'
li.appendChild(document.createTextNode(' '))
li.appendChild(editLink)
}
var editLink = null
if (repo && categoryUrl) {
editLink = document.createElement('a')
editLink.href = categoryUrl.render({ repositoryId: repo, categoryId: id })
}
if (!repo && repositoryUrl) {
editLink = document.createElement('a')
editLink.href = repositoryUrl.render({ repositoryId: id })
}
if (editLink) {
editLink.className = 'source-code'
editLink.title = 'Show source code'
editLink.target = '_blank'
editLink.innerHTML = '<i class="fa fa-file-code-o" aria-hidden="true"></i>'
li.appendChild(document.createTextNode(' '))
li.appendChild(editLink)
}
ul.appendChild(li)
}

12
src/category.css

@ -18,14 +18,16 @@
}
/* Source: http://tobiasahlin.com/spinkit/ */
.category.open.loading > .loadingIndicator2 {
.category.open.loading > .loadingIndicator2,
.category.open.loading > .content > .categoryWrapper > .category-list.open > .loadingIndicator2 {
text-align: left;
display: block;
background: #efefef;
padding-left: 40px;
}
.category.loading > .loadingIndicator2 > div {
.category.loading > .loadingIndicator2 > div,
.category.loading > .content > .categoryWrapper > .category-list.open > .loadingIndicator2 > div {
width: 9px;
height: 9px;
margin-right: 9px;
@ -103,6 +105,12 @@
padding-top: 3px;
background: #efefef;
}
.body h4 {
margin-bottom: 0;
}
.body ul.overpass-layer-list {
padding-left: 40px;
}
.category > div > div> .category {
margin-left: 1em;

6
src/image.js

@ -16,7 +16,7 @@ function showWikimediaImage (image, dom) {
forceServerLoad: true
},
function (err, result) {
if (!result) {
if (err || !result) {
return
}
@ -70,7 +70,7 @@ register_hook('show-details', function (data, category, dom, callback) {
currentLoader.next({
counter: data.detailsImageCounter,
wrap: true
},function (err, img) {
}, function (err, img) {
div.classList.remove('loading')
if (!img) {
@ -138,7 +138,7 @@ register_hook('show-popup', function (data, category, dom, callback) {
currentLoader.first({
counter: data.popupImageCounter
},function (err, img) {
}, function (err, img) {
div.classList.remove('loading')
if (!img) {

27
src/index.js

@ -1,4 +1,4 @@
/* globals map:true, overpassFrontend:true, currentPath:true, options:true, baseCategory:true, overpassUrl:true */
/* globals map:true, overpassFrontend:true, currentPath:true, options:true, baseCategory:true, overpassUrl:true showDetails */
var LeafletGeoSearch = require('leaflet-geosearch')
@ -47,15 +47,13 @@ window.onload = function () {
map.createPane('selected')
map.getPane('selected').style.zIndex = 498
map.createPane('hover')
map.getPane('hover').style.zIndex = 499
}
function onload2 (initState) {
// Measurement plugin
if (L.control.polylineMeasure) {
L.control.polylineMeasure({
}).addTo(map);
}).addTo(map)
}
// Add Geo Search
@ -87,7 +85,7 @@ function onload2 (initState) {
overpassFrontend = new OverpassFrontend(overpassUrl, {
timeGap: 10,
effortPerRequest: 100
effortPerRequest: 512
})
OpenStreetBrowserLoader.setMap(map)
@ -119,7 +117,7 @@ function onload2 (initState) {
map.on('popupopen', function (e) {
if (e.popup.object) {
var url = e.popup.object.layer_id + '/' + e.popup.object.id
var url = e.popup.object.layer_id + '/' + (e.popup.object.sublayer_id === 'main' ? '' : e.popup.object.sublayer_id + ':') + e.popup.object.id
if (location.hash.substr(1) !== url && location.hash.substr(1, url.length + 1) !== url + '/') {
currentPath = url
// only push state, when last popup close happened >1sec earlier
@ -195,7 +193,7 @@ function show (id, options, callback) {
document.getElementById('contentDetails').innerHTML = lang('loading')
}
var m = id.match(/^(.*)\/([nwr]\d+)(\/details)?$/)
var m = id.match(/^(.*)\/((?:[\w\d-]+:)?[nwr]\d+)(\/details)?$/)
if (!m) {
return callback(new Error('unknown request'))
}
@ -247,25 +245,34 @@ window.showDetails = function (data, category) {
div.className = 'title'
div.innerHTML = data.data.title
dom.appendChild(div)
data.sublayer.updateAssets(div, data)
div = document.createElement('div')
div.className = 'description'
div.innerHTML = data.data.description
dom.appendChild(div)
data.sublayer.updateAssets(div, data)
div = document.createElement('div')
div.className = 'body'
div.innerHTML = data.data.body
dom.appendChild(div)
function updateBody (div) {
div.innerHTML = data.data.detailBody || data.data.body
data.sublayer.updateAssets(div, data)
}
data.object.on('update', updateBody.bind(this, div))
updateBody(div)
div = document.createElement('div')
div.className = 'body'
dom.appendChild(div)
category.renderTemplate(data, 'detailsBody', function (div, err, result) {
div.innerHTML = result
data.sublayer.updateAssets(div, data)
}.bind(this, div))
call_hooks_callback('show-details', data, category, dom,
function (err) {
if (err.length) {
@ -317,7 +324,7 @@ window.showDetails = function (data, category) {
dt.appendChild(document.createTextNode('id'))
div.appendChild(dt)
dd = document.createElement('dd')
var a = document.createElement('a')
a = document.createElement('a')
a.appendChild(document.createTextNode(data.object.type + '/' + data.object.osm_id))
a.href = 'https://openstreetmap.org/' + data.object.type + '/' + data.object.osm_id
a.target = '_blank'

1
src/language.js

@ -1,4 +1,5 @@
/* global languages:false, lang_str:false */
/* eslint camelcase:0 */
var tagTranslations = require('./tagTranslations')
function getPreferredDataLanguage () {

5
src/maki.js

@ -1,3 +1,4 @@
/* global openstreetbrowserPrefix */
var loadClash = {}
var cache = {}
@ -14,10 +15,9 @@ function applyOptions (code, options) {
}
function maki (file, options, callback) {
var id
var size = options.size || 15
var m = file.match(/^(.*)\-(11|15)/)
var m = file.match(/^(.*)-(11|15)/)
if (!m) {
file += '-' + size
}
@ -48,7 +48,6 @@ function maki (file, options, callback) {
loadClash[file].forEach(p => p[1](null, applyOptions(cache[file], p[0])))
delete loadClash[file]
return
})
req.open('GET', url)
req.send()

3
src/markers.js

@ -79,8 +79,9 @@ function markerCircle (style) {
var fillColor = 'fillColor' in style ? style.fillColor : '#f2756a'
var color = 'color' in style ? style.color : '#000000'
var width = 'width' in style ? style.width : 1
var radius = 'radius' in style ? style.radius : 12
return '<svg anchorX="13" anchorY="13" width="25" height="25"><circle cx="12.5" cy="12.5" r="12" style="stroke: ' + color + '; stroke-width: ' + width + '; fill: ' + fillColor + ';"/></svg>'
return '<svg anchorX="13" anchorY="13" width="25" height="25"><circle cx="12.5" cy="12.5" r=' + radius + ' style="stroke: ' + color + '; stroke-width: ' + width + '; fill: ' + fillColor + ';"/></svg>'
}
function markerPointer (style) {

8
src/options.js

@ -1,4 +1,4 @@
/* globals form, ajax, options:true, showRootContent */
/* globals form, ajax, options:true */
var moduleOptions = {}
var prevPage
@ -46,7 +46,7 @@ moduleOptions.open = function () {
input.innerHTML = lang('save')
f.appendChild(input)
var input = document.createElement('button')
input = document.createElement('button')
input.innerHTML = lang('cancel')
f.appendChild(input)
input.onclick = function () {
@ -68,12 +68,12 @@ moduleOptions.submit = function (optionsForm) {
}
ajax('options_save', null, data, function (ret) {
let old_options = options
let oldOptions = options
options = data
document.getElementById('content').className = prevPage
call_hooks('options_save', data, old_options)
call_hooks('options_save', data, oldOptions)
if (reload) {
location.reload()

8
src/tagTranslations.js

@ -1,3 +1,5 @@
/* global lang_str lang_non_translated */
/* eslint camelcase:0 */
var OverpassLayer = require('overpass-layer')
var tagLang = null
@ -57,11 +59,7 @@ function tagTranslationsTransList (key, values) {
return tagTranslationsTrans(key, value.trim())
}.bind(this, key))
if (values.length > 1) {
return values.slice(0, -1).join(', ') + ' and ' + values.slice(-1)[0]
}
return values[0]
return lang_enumerate(values)
}
module.exports = {

27
src/twigFunctions.js

@ -2,6 +2,10 @@ var OverpassLayer = require('overpass-layer')
var OpeningHours = require('opening_hours')
var colorInterpolate = require('color-interpolate')
var osmParseDate = require('openstreetmap-date-parser')
const natsort = require('natsort')
const md5 = require('md5')
var md5cache = {}
OverpassLayer.twig.extendFunction('tagsPrefix', function (tags, prefix) {
var ret = {}
@ -39,8 +43,22 @@ OverpassLayer.twig.extendFilter('websiteUrl', function (value) {
return 'http://' + value
})
OverpassLayer.twig.extendFilter('matches', function (value, match) {
if (value === null) {
return false
}
return value.toString().match(match)
})
OverpassLayer.twig.extendFilter('natsort', function (values, options) {
return values.sort(natsort(options))
})
OverpassLayer.twig.extendFilter('unique', function (values, options) {
// source: https://stackoverflow.com/a/14438954
function onlyUnique (value, index, self) {
return self.indexOf(value) === index
}
return values.filter(onlyUnique)
})
OverpassLayer.twig.extendFunction('colorInterpolate', function (map, value) {
var colormap = colorInterpolate(map)
return colormap(value)
@ -48,6 +66,13 @@ OverpassLayer.twig.extendFunction('colorInterpolate', function (map, value) {
OverpassLayer.twig.extendFilter('osmParseDate', function (value) {
return osmParseDate(value)
})
OverpassLayer.twig.extendFilter('md5', function (value) {
if (!(value in md5cache)) {
md5cache[value] = md5(value)
}
return md5cache[value]
})
OverpassLayer.twig.extendFunction('evaluate', function (tags) {
var ob = {
id: 'x0',
@ -61,6 +86,6 @@ OverpassLayer.twig.extendFunction('evaluate', function (tags) {
}
}
var d = global.currentCategory.layer.evaluate(ob)
var d = global.currentCategory.layer.mainlayer.evaluate(ob)
return d
})
Loading…
Cancel
Save