Browse Source

Merge branch '3-wikipedia'

master
parent
commit
b083615152
  1. 3
      README.md
  2. 2
      ajax.php
  3. 1
      doc/TwigJS.md
  4. 1
      lang/ast.json
  5. 1
      lang/ca.json
  6. 1
      lang/cs.json
  7. 1
      lang/da.json
  8. 8
      lang/de.json
  9. 1
      lang/el.json
  10. 8
      lang/en.json
  11. 1
      lang/es.json
  12. 1
      lang/et.json
  13. 1
      lang/fr.json
  14. 1
      lang/hu.json
  15. 1
      lang/it.json
  16. 1
      lang/ja.json
  17. 1
      lang/nl.json
  18. 1
      lang/pl.json
  19. 1
      lang/pt-br.json
  20. 1
      lang/ro.json
  21. 1
      lang/ru.json
  22. 1
      lang/sr.json
  23. 1
      lang/template.json
  24. 1
      lang/uk.json
  25. 1
      modulekit.php
  26. 12
      src/CategoryOverpass.js
  27. 23
      src/index.js
  28. 19
      src/language.js
  29. 17
      src/options.js
  30. 3
      src/twigFunctions.js
  31. 175
      src/wikipedia.js
  32. 41
      src/wikipedia.php
  33. 37
      style.css

3
README.md

@ -118,3 +118,6 @@ With the function `register_hook` you can hook into several functions. The follo
* `state-get`: modules can add values into the current state. Parameters: `state`: an object, which can be modified by modules.
* `state-apply`: when a state is applied to the app. Parameters: `state`: state which should be applied.
* `show-details`: called when details are being displayed. Parameters: data (see properties in doc/TwigJS.md), category, dom, callback.
* `show-popup`: called when a popup is being displayed. Parameters: data (see properties in doc/TwigJS.md), category, dom, callback.
* `options_save`: called when options are saved. Parameters: options (the new object), old_options (before save)

2
ajax.php

@ -22,6 +22,6 @@ if ($postdata) {
}
$fun = "ajax_{$_REQUEST['__func']}";
$return = $fun($_REQUEST["param"], $postdata);
$return = $fun($_REQUEST, $postdata);
print json_encode($return);

1
doc/TwigJS.md

@ -24,6 +24,7 @@ There are several extra functions defined for the TwigJS language:
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.
Notes:
* Variables will automatically be HTML escaped, if not the filter raw is used, e.g.: {{ tags.name|raw }}

1
lang/ast.json

@ -1,5 +1,6 @@
{
"main:options": "Opciones",
"more": "más",
"options:data_lang": "Llingua de los datos",
"options:data_lang:local": "Llingua llocal",
"options:ui_lang": "Llingua de la interfaz",

1
lang/ca.json

@ -1,4 +1,5 @@
{
"main:options": "Opcions",
"more": "més",
"save": "Guardar"
}

1
lang/cs.json

@ -1,5 +1,6 @@
{
"main:options": "Nastavení",
"more": "více",
"options:data_lang": "Jazyk dat",
"options:data_lang:local": "Místní jazyk",
"options:ui_lang": "Jazyk rozhraní",

1
lang/da.json

@ -1,5 +1,6 @@
{
"main:options": "Indstillinger",
"more": "mere",
"options:data_lang": "Data sprog",
"options:data_lang:local": "Lokalt sprog",
"options:ui_lang": "Brugerfladesprog",

8
lang/de.json

@ -1,8 +1,13 @@
{
"closed": "geschlossen",
"default": "Standard",
"error": {
"message": "Fehler",
"!=1": "Fehler"
},
"facilities": "Einrichtungen",
"main:options": "Optionen",
"more": "mehr",
"open": "geöffnet",
"options:data_lang": "Datensprache",
"options:data_lang:local": "Lokale Sprache",
@ -13,5 +18,6 @@
"show details": "zeige Details",
"toggle_fullscreen": "(De-)aktiviere Vollbildmodus",
"unknown": "unbekannt",
"unnamed": "Namenlos"
"unnamed": "Namenlos",
"wikipedia:no-url-parse": "Konnte Wikipedia Adresse nicht erkennen"
}

1
lang/el.json

@ -1,5 +1,6 @@
{
"main:options": "Επιλογές",
"more": "περισσότερα",
"options:data_lang": "Γλωσσα δεδομένων",
"options:data_lang:local": "Τοπική γλώσσα",
"options:ui_lang": "Γλώσσα διεπαφής",

8
lang/en.json

@ -1,8 +1,13 @@
{
"closed": "closed",
"default": "default",
"error": {
"message": "Error",
"!=1": "Errors"
},
"facilities": "Facilities",
"main:options": "Options",
"more": "more",
"open": "open",
"options:data_lang": "Data language",
"options:data_lang:desc": "Many map features have their name (and other tags) translated to different languages (e.g. with 'name:en', 'name:de'). Specify which language should be used for displaying, or 'Local language' so that always the untranslated value (e.g. 'name') will be used",
@ -14,5 +19,6 @@
"show details": "show details",
"toggle_fullscreen": "Toggle full screen mode",
"unknown": "unknown",
"unnamed": "unnamed"
"unnamed": "unnamed",
"wikipedia:no-url-parse": "Could not parse Wikipedia URL"
}

1
lang/es.json

@ -1,5 +1,6 @@
{
"main:options": "Opciones",
"more": "más",
"options:data_lang": "Idioma de datos",
"options:data_lang:local": "Idioma local",
"options:ui_lang": "Idioma de interfaz",

1
lang/et.json

@ -1,5 +1,6 @@
{
"main:options": "Valikud",
"more": "lisaks",
"options:data_lang": "Andmete keel",
"options:data_lang:local": "Kohalik keel",
"options:ui_lang": "Kasutajaliidese keel",

1
lang/fr.json

@ -1,5 +1,6 @@
{
"main:options": "Options",
"more": "plus",
"options:data_lang": "Langue des données",
"options:data_lang:local": "Langue locale",
"options:ui_lang": "Langue de l'interface",

1
lang/hu.json

@ -1,5 +1,6 @@
{
"main:options": "Beállítások",
"more": "több",
"options:data_lang": "Adatnyelv",
"options:data_lang:local": "Helyi nyelv",
"options:ui_lang": "Menünyelv",

1
lang/it.json

@ -1,5 +1,6 @@
{
"main:options": "Opzioni",
"more": "altri",
"options:data_lang": "Lingua dei dati",
"options:data_lang:local": "Lingua del tuo browser",
"options:ui_lang": "Lingua dell'interfaccia",

1
lang/ja.json

@ -1,5 +1,6 @@
{
"main:options": "オプション設定",
"more": "もっと",
"options:data_lang": "データ表示",
"options:data_lang:local": "ブラウザの設定言語",
"options:ui_lang": "インタフェース表示",

1
lang/nl.json

@ -1,5 +1,6 @@
{
"main:options": "Opties",
"more": "meer",
"options:data_lang": "Taal voor data",
"options:data_lang:local": "Lokale taal",
"options:ui_lang": "Interfacetaal",

1
lang/pl.json

@ -1,5 +1,6 @@
{
"main:options": "Opcje",
"more": "więcej",
"options:data_lang": "Język danych",
"options:data_lang:local": "Język lokalny",
"options:ui_lang": "Język interfejsu",

1
lang/pt-br.json

@ -1,4 +1,5 @@
{
"more": "mais",
"save": "Salvar",
"unnamed": "sem nome"
}

1
lang/ro.json

@ -1,5 +1,6 @@
{
"main:options": "Optiuni",
"more": "Mai mult",
"options:data_lang": "Limba date",
"options:data_lang:local": "Limba locala",
"options:ui_lang": "Limba interfata",

1
lang/ru.json

@ -1,5 +1,6 @@
{
"main:options": "Настройки",
"more": "Ещё",
"options:data_lang": "Язык информации на карте",
"options:data_lang:local": "Определить язык автоматически",
"options:ui_lang": "Язык интерфейса",

1
lang/sr.json

@ -1,5 +1,6 @@
{
"main:options": "Опције",
"more": "још",
"options:data_lang": "Језик подетака",
"options:data_lang:local": "Локални језик",
"options:ui_lang": "Језик интерфејса",

1
lang/template.json

@ -1,6 +1,7 @@
{
"default": "",
"main:options": "",
"more": "",
"options:data_lang": "",
"options:data_lang:desc": "",
"options:data_lang:local": "",

1
lang/uk.json

@ -1,5 +1,6 @@
{
"main:options": "Налаштування",
"more": "Ще",
"options:data_lang": "Мова мапи",
"options:data_lang:local": "Місцева мова",
"options:ui_lang": "Мова інтерфейсу",

1
modulekit.php

@ -14,6 +14,7 @@ $include = array(
'src/options.php',
'src/language.php',
'src/ip-location.php',
'src/wikipedia.php',
),
'css' => array(
'style.css',

12
src/CategoryOverpass.js

@ -94,6 +94,10 @@ function CategoryOverpass (id, data) {
}
this.updatePopupContent(ob, ob.popup)
if (document.getElementById('content').className === 'details') {
showDetails(ob, this)
}
}.bind(this)
p = document.createElement('div')
@ -219,6 +223,14 @@ CategoryOverpass.prototype.notifyPopupOpen = function (object, popup) {
}
CategoryOverpass.prototype.updatePopupContent = function (object, popup) {
call_hooks_callback('show-popup', object, this, popup._contentNode,
function (err) {
if (err.length) {
console.log('show-popup produced errors:', err)
}
}
)
if (object.data.popupDescription || object.data.description) {
var div = document.createElement('div')
div.className = 'description'

23
src/index.js

@ -26,12 +26,18 @@ require('./fullscreen')
require('./mapLayers')
require('./twigFunctions')
require('./categories')
require('./wikipedia')
window.onload = function () {
initState = config.defaultView
map = L.map('map')
// due to php export, options may be an array -> fix
if (Array.isArray(options)) {
options = {}
}
call_hooks('init')
call_hooks_callback('init_callback', initState, onload2.bind(this, initState))
}
@ -139,17 +145,17 @@ window.setPath = function (path) {
return
}
options = {
var param = {
showDetails: !!path.match(/\/details$/)
}
show(path, options, function (err) {
show(path, param, function (err) {
if (err) {
alert(err)
return
}
call_hooks('show', path, options)
call_hooks('show', path, param)
})
}
@ -199,7 +205,7 @@ function show (id, options, callback) {
})
}
function showDetails (data, category) {
window.showDetails = function (data, category) {
var div, h, dt, dd
var k
var dom = document.getElementById('contentDetails')
@ -228,6 +234,15 @@ function showDetails (data, category) {
div.innerHTML = result
}.bind(this, div))
call_hooks_callback('show-details', data, category, dom,
function (err) {
if (err.length) {
console.log('show-details produced errors:', err)
}
}
)
h = document.createElement('h3')
h.innerHTML = 'Attributes'
dom.appendChild(h)

19
src/language.js

@ -79,12 +79,15 @@ function langName (code) {
}
register_hook('init_callback', function (initState, callback) {
if ('data_lang' in options) {
tagTranslations.setTagLanguage(options.data_lang)
} else {
tagTranslations.setTagLanguage(getPreferredDataLanguage())
if (!('ui_lang' in options)) {
options.ui_lang = ui_lang
}
if (!('data_lang' in options)) {
options.data_lang = getPreferredDataLanguage()
}
tagTranslations.setTagLanguage(options.data_lang)
callback(null)
})
@ -108,10 +111,10 @@ register_hook('options_form', function (def) {
}
})
register_hook('options_save', function (data) {
if ('data_lang' in data) {
if ('data_lang' in options && options.data_lang !== data.data_lang) {
tagTranslations.setTagLanguage(data.data_lang)
register_hook('options_save', function (options, old_options) {
if ('data_lang' in options) {
if (old_options.data_lang !== options.data_lang) {
tagTranslations.setTagLanguage(options.data_lang)
baseCategory.recalc()
}
}

17
src/options.js

@ -1,5 +1,6 @@
/* globals form, ajax, options:true, showRootContent */
var moduleOptions = {}
var prevPage
register_hook('init', function () {
var menu = document.getElementById('menu')
@ -28,6 +29,7 @@ moduleOptions.open = function () {
call_hooks('options_form', def)
var optionsForm = new form('options', def)
prevPage = document.getElementById('content').className
document.getElementById('content').className = 'options'
var dom = document.getElementById('contentOptions')
dom.innerHTML = ''
@ -57,16 +59,17 @@ moduleOptions.submit = function (optionsForm) {
}
}
if (reload) {
location.reload()
}
ajax('options_save', null, data, function (ret) {
call_hooks('options_save', data)
old_options = options
options = data
showRootContent()
document.getElementById('content').className = prevPage
call_hooks('options_save', data, old_options)
if (reload) {
location.reload()
}
})
return false

3
src/twigFunctions.js

@ -36,3 +36,6 @@ OverpassLayer.twig.extendFilter('websiteUrl', function (value) {
return 'http://' + value
})
OverpassLayer.twig.extendFilter('matches', function (value, match) {
return value.match(match)
})

175
src/wikipedia.js

@ -0,0 +1,175 @@
var cache = {}
function stripLinks (dom) {
var as = dom.getElementsByTagName('a')
var as = Array.prototype.slice.call(as)
as.forEach(function (current) {
var c
while (c = current.firstChild) {
current.parentNode.insertBefore(c, current)
}
current.parentNode.removeChild(current)
})
}
function prepare (text) {
var ret = ''
var i
var div = document.createElement('div')
div.innerHTML = text
var contents = div.getElementsByTagName('div')
for (i = 0; i < contents.length; i++) {
if (contents[i].id === 'mw-content-text') {
var content = contents[i]
break
}
}
if (!content) {
return null
}
var p = content.firstChild.firstChild
while (p && p.tagName !== 'P') {
p = p.nextSibling
}
if (!p) {
return null
}
stripLinks(p)
// first image
var imgs = div.getElementsByTagName('img')
for (i = 0; i < imgs.length; i++) {
var img = imgs[i]
// ignore icons
if (img.width <= 64 && img.height <= 64) {
continue
}
img.removeAttribute('width')
img.removeAttribute('height')
p.insertBefore(img, p.firstChild)
break;
}
return p.innerHTML
}
function get (value, callback) {
var cacheId = options.data_lang + ':' + value
if (cacheId in cache) {
return callback(null, cache[cacheId])
}
ajax('wikipedia',
{
page: value,
lang: options.data_lang
},
function (result) {
if (!result.content) {
return callback('error', null)
}
var text = prepare(result.content)
text += ' <a target="_blank" href="' + result.languages[result.language] + '">' + lang('more') + '</a>'
cache[cacheId] = text
callback(null, text)
}
)
}
register_hook('show-details', function (data, category, dom, callback) {
var ob = data.object
var found = 0
var finished = 0
var errs = []
var h
var div = document.createElement('div')
div.className = 'wikipedia'
if ('wikipedia' in ob.tags) {
found++
showWikipedia(ob.tags.wikipedia, div, done)
}
for (var k in ob.tags) {
var m
if (m = k.match(/^(.*):wikipedia$/)) {
h = document.createElement('h4')
h.appendChild(document.createTextNode(lang('tag:' + m[1])))
div.appendChild(h)
found++
showWikipedia(ob.tags[k], div, done)
}
if (m = k.match(/^((.*):)?wikipedia:(.*)$/)) {
if (m[1]) {
h = document.createElement('h4')
h.appendChild(document.createTextNode(lang('tag:' + m[1])))
div.appendChild(h)
}
found++
showWikipedia(m[3] + ':' + ob.tags[k], div, done)
}
}
if (found) {
h = document.createElement('h3')
h.appendChild(document.createTextNode(lang('tag:wikipedia')))
dom.appendChild(h)
dom.appendChild(div)
}
function done (err) {
finished++
if (err) {
errs.push(err)
}
if (found === finished) {
callback(errs.length ? errs : null)
}
}
})
function showWikipedia (tagValue, dom, callback) {
var block = document.createElement('div')
block.className = 'loading'
dom.appendChild(block)
var l = document.createElement('div')
l.innerHTML = '<i class="fa fa-spinner fa-pulse fa-fw"></i><span class="sr-only">Loading...</span>'
l.className = 'loadingIndicator'
block.appendChild(l)
get(tagValue, function (err, text) {
if (!text) {
block.appendChild(document.createTextNode(lang('wikipedia:no-url-parse')))
}
var div = document.createElement('div')
div.innerHTML = text
block.appendChild(div)
block.className = ''
callback(err)
})
}

41
src/wikipedia.php

@ -0,0 +1,41 @@
<?php
function ajax_wikipedia ($param) {
if (preg_match("/^([^:]+):(.*)$/", $param['page'], $m)) {
$wp_lang = $m[1];
$wp_page = $m[2];
}
if (!isset($wp_lang) || !isset($wp_page)) {
return false;
}
$wp_url = "https://{$wp_lang}.wikipedia.org/wiki/" . urlencode(strtr($wp_page, array(" " => "_")));
$content = file_get_contents($wp_url);
$langList = array($wp_lang => $wp_url);
$dom = new DOMDocument();
$dom->loadHTML($content);
$langDiv = $dom->getElementsByTagName('li');//interlanguage-link interwiki-bar');
for ($i = 0; $i < $langDiv->length; $i++) {
$li = $langDiv->item($i);
if (preg_match('/^interlanguage-link interwiki-(.*)$/', $li->getAttribute('class'), $m)) {
$a = $li->firstChild;
$langList[$m[1]] = $a->getAttribute('href');
}
}
if ($wp_lang !== $param['lang'] && array_key_exists($param['lang'], $langList)) {
$content = file_get_contents($langList[$param['lang']]);
$wp_lang = $param['lang'];
}
return array(
'content' => $content,
'languages' => $langList,
'language' => $wp_lang,
);
}

37
style.css

@ -13,9 +13,7 @@ body {
top: 0px;
bottom: 0px;
left: 0px;
width: 250px;
padding-left:10px;
padding-right:10px;
width: 270px;
position: absolute;
}
#map {
@ -43,6 +41,7 @@ body {
}
#sidebar > #header {
padding-top: 27px;
padding-left: 10px;
height:110px;
font-size:18px;
color:#333;
@ -74,6 +73,8 @@ body {
flex: 1;
flex-shrink: 0;
overflow: auto;
padding-left: 10px;
padding-right: 10px;
}
#sidebar > #footer {
@ -488,3 +489,33 @@ a.showDetails {
.leaflet-popup-content ul > li > .key {
font-weight: bold;
}
#contentDetails div > .loadingIndicator {
display: none;
}
#contentDetails div.loading > .loadingIndicator {
float: right;
display: block;
}
/* Wikipedia */
.wikipedia img {
max-width: 100px;
max-height: 100px;
float: right;
margin-left: 0.5em;
margin-bottom: 0.5em;
}
.wikipedia div {
text-align: justify;
}
#contentDetails h3 {
border-bottom: 1px solid black;
clear: both;
}
#contentDetails h4 {
clear: both;
}
.wikipedia .reference {
display: none;
}
Loading…
Cancel
Save