diff --git a/src/OpenStreetBrowserLoader.js b/src/OpenStreetBrowserLoader.js index e8659ed9..4b163a1b 100644 --- a/src/OpenStreetBrowserLoader.js +++ b/src/OpenStreetBrowserLoader.js @@ -2,268 +2,270 @@ var OverpassLayer = require('overpass-layer') const Repository = require('./Repository') -function OpenStreetBrowserLoader () { - this.types = {} - this.categories = {} - this.repoCache = {} - this.repositories = {} - this.templates = {} - this._loadClash = {} // if a category is being loaded multiple times, collect callbacks -} - -OpenStreetBrowserLoader.prototype.setMap = function (map) { - this.map = map -} - -/** - * @param string id ID of the category - * @param [object] options Options. - * @waram {boolean} [options.force=false] Whether repository should be reload or not. - * @param function callback Callback which will be called with (err, category) - */ -OpenStreetBrowserLoader.prototype.getCategory = function (id, options, callback) { - if (typeof options === 'function') { - callback = options - options = {} +class OpenStreetBrowserLoader { + constructor () { + this.types = {} + this.categories = {} + this.repoCache = {} + this.repositories = {} + this.templates = {} + this._loadClash = {} // if a category is being loaded multiple times, collect callbacks } - var ids = this.getFullId(id, options) - if (ids === null) { - return callback(new Error('invalid id'), null) + setMap (map) { + this.map = map } - if (options.force) { - delete this.categories[ids.fullId] - } + /** + * @param string id ID of the category + * @param [object] options Options. + * @waram {boolean} [options.force=false] Whether repository should be reload or not. + * @param function callback Callback which will be called with (err, category) + */ + getCategory (id, options, callback) { + if (typeof options === 'function') { + callback = options + options = {} + } - if (ids.fullId in this.categories) { - return callback(null, this.categories[ids.fullId]) - } + var ids = this.getFullId(id, options) + if (ids === null) { + return callback(new Error('invalid id'), null) + } - var opt = JSON.parse(JSON.stringify(options)) - opt.categoryId = ids.entityId - opt.repositoryId = ids.repositoryId + if (options.force) { + delete this.categories[ids.fullId] + } - this.getRepo(ids.repositoryId, opt, function (err, repoData) { - // maybe loaded in the meantime? if (ids.fullId in this.categories) { return callback(null, this.categories[ids.fullId]) } - if (err) { - return callback(err, null) - } + var opt = JSON.parse(JSON.stringify(options)) + opt.categoryId = ids.entityId + opt.repositoryId = ids.repositoryId - if (!(ids.entityId in repoData.categories)) { - return callback(new Error('category "' + ids.entityId + '" not defined'), null) - } + this.getRepo(ids.repositoryId, opt, function (err, repoData) { + // maybe loaded in the meantime? + if (ids.fullId in this.categories) { + return callback(null, this.categories[ids.fullId]) + } - this.getCategoryFromData(ids.id, opt, repoData.categories[ids.entityId], function (err, category) { - if (category) { - category.setMap(this.map) + if (err) { + return callback(err, null) } - callback(err, category) - }.bind(this)) - }.bind(this)) -} + if (!(ids.entityId in repoData.categories)) { + return callback(new Error('category "' + ids.entityId + '" not defined'), null) + } -/** - * @param string repo ID of the repository - * @parapm [object] options Options. - * @waram {boolean} [options.force=false] Whether repository should be reload or not. - * @param function callback Callback which will be called with (err, repoData) - */ -OpenStreetBrowserLoader.prototype.getRepo = function (repo, options, callback) { - if (options.force) { - delete this.repoCache[repo] - } + this.getCategoryFromData(ids.id, opt, repoData.categories[ids.entityId], function (err, category) { + if (category) { + category.setMap(this.map) + } - if (repo in this.repoCache) { - return callback.apply(this, this.repoCache[repo]) + callback(err, category) + }.bind(this)) + }.bind(this)) } - if (repo in this._loadClash) { - this._loadClash[repo].push(callback) - return - } + /** + * @param string repo ID of the repository + * @parapm [object] options Options. + * @waram {boolean} [options.force=false] Whether repository should be reload or not. + * @param function callback Callback which will be called with (err, repoData) + */ + getRepo (repo, options, callback) { + if (options.force) { + delete this.repoCache[repo] + } - this._loadClash[repo] = [ callback ] + if (repo in this.repoCache) { + return callback.apply(this, this.repoCache[repo]) + } - function reqListener (req) { - if (req.status !== 200) { - console.log('http error when loading repository', req) - this.repoCache[repo] = [ req.statusText, null ] - } else { - try { - let repoData = JSON.parse(req.responseText) - this.repositories[repo] = new Repository(repo, repoData) - this.repoCache[repo] = [ null, repoData ] - } catch (err) { - console.log('couldn\'t parse repository', req.responseText) - this.repoCache[repo] = [ 'couldn\t parse repository', null ] - } + if (repo in this._loadClash) { + this._loadClash[repo].push(callback) + return } - var todo = this._loadClash[repo] - delete this._loadClash[repo] + this._loadClash[repo] = [ callback ] + + function reqListener (req) { + if (req.status !== 200) { + console.log('http error when loading repository', req) + this.repoCache[repo] = [ req.statusText, null ] + } else { + try { + let repoData = JSON.parse(req.responseText) + this.repositories[repo] = new Repository(repo, repoData) + this.repoCache[repo] = [ null, repoData ] + } catch (err) { + console.log('couldn\'t parse repository', req.responseText) + this.repoCache[repo] = [ 'couldn\t parse repository', null ] + } + } - todo.forEach(function (callback) { - callback.apply(this, this.repoCache[repo]) - }.bind(this)) - } + var todo = this._loadClash[repo] + delete this._loadClash[repo] - var param = [] - if (repo) { - param.push('repo=' + encodeURIComponent(repo)) - } - param.push('lang=' + encodeURIComponent(ui_lang)) - param.push(config.categoriesRev) - param = param.length ? '?' + param.join('&') : '' - - var req = new XMLHttpRequest() - req.addEventListener('load', reqListener.bind(this, req)) - req.open('GET', 'repo.php' + param) - req.send() -} + todo.forEach(function (callback) { + callback.apply(this, this.repoCache[repo]) + }.bind(this)) + } -OpenStreetBrowserLoader.prototype.getRepository = function (id, options, callback) { - if (id in this.repositories) { - return callback(null, this.repositories[id]) + var param = [] + if (repo) { + param.push('repo=' + encodeURIComponent(repo)) + } + param.push('lang=' + encodeURIComponent(ui_lang)) + param.push(config.categoriesRev) + param = param.length ? '?' + param.join('&') : '' + + var req = new XMLHttpRequest() + req.addEventListener('load', reqListener.bind(this, req)) + req.open('GET', 'repo.php' + param) + req.send() } - this.getRepo(id, options, (err, repoData) => { - if (err) { - return callback(err) + getRepository (id, options, callback) { + if (id in this.repositories) { + return callback(null, this.repositories[id]) } - callback(null, this.repositories[id]) - }) -} + this.getRepo(id, options, (err, repoData) => { + if (err) { + return callback(err) + } -/** - * @param string id ID of the template - * @parapm [object] options Options. - * @waram {boolean} [options.force=false] Whether repository should be reload or not. - * @param function callback Callback which will be called with (err, template) - */ -OpenStreetBrowserLoader.prototype.getTemplate = function (id, options, callback) { - if (typeof options === 'function') { - callback = options - options = {} + callback(null, this.repositories[id]) + }) } - var ids = this.getFullId(id, options) + /** + * @param string id ID of the template + * @parapm [object] options Options. + * @waram {boolean} [options.force=false] Whether repository should be reload or not. + * @param function callback Callback which will be called with (err, template) + */ + getTemplate (id, options, callback) { + if (typeof options === 'function') { + callback = options + options = {} + } - if (options.force) { - delete this.templates[ids.fullId] - } + var ids = this.getFullId(id, options) - if (ids.fullId in this.templates) { - return callback(null, this.templates[ids.fullId]) - } - - var opt = JSON.parse(JSON.stringify(options)) - opt.templateId = ids.entityId - opt.repositoryId = ids.repositoryId + if (options.force) { + delete this.templates[ids.fullId] + } - this.getRepo(ids.repositoryId, opt, function (err, repoData) { - // maybe loaded in the meantime? if (ids.fullId in this.templates) { return callback(null, this.templates[ids.fullId]) } - if (err) { - return callback(err, null) - } + var opt = JSON.parse(JSON.stringify(options)) + opt.templateId = ids.entityId + opt.repositoryId = ids.repositoryId - if (!repoData.templates || !(ids.entityId in repoData.templates)) { - return callback(new Error('template not defined'), null) - } + this.getRepo(ids.repositoryId, opt, function (err, repoData) { + // maybe loaded in the meantime? + if (ids.fullId in this.templates) { + return callback(null, this.templates[ids.fullId]) + } - this.templates[ids.fullId] = OverpassLayer.twig.twig({ data: repoData.templates[ids.entityId], autoescape: true }) + if (err) { + return callback(err, null) + } - callback(null, this.templates[ids.fullId]) - }.bind(this)) -} + if (!repoData.templates || !(ids.entityId in repoData.templates)) { + return callback(new Error('template not defined'), null) + } -OpenStreetBrowserLoader.prototype.getCategoryFromData = function (id, options, data, callback) { - var ids = this.getFullId(id, options) + this.templates[ids.fullId] = OverpassLayer.twig.twig({ data: repoData.templates[ids.entityId], autoescape: true }) - if (ids.fullId in this.categories) { - return callback(null, this.categories[ids.fullId]) + callback(null, this.templates[ids.fullId]) + }.bind(this)) } - if (!data.type) { - return callback(new Error('no type defined'), null) - } + getCategoryFromData (id, options, data, callback) { + var ids = this.getFullId(id, options) - if (!(data.type in this.types)) { - return callback(new Error('unknown type'), null) - } + if (ids.fullId in this.categories) { + return callback(null, this.categories[ids.fullId]) + } - let repository = this.repositories[ids.repositoryId] + if (!data.type) { + return callback(new Error('no type defined'), null) + } - var opt = JSON.parse(JSON.stringify(options)) - opt.id = ids.id - var layer = new this.types[data.type](opt, data, repository) + if (!(data.type in this.types)) { + return callback(new Error('unknown type'), null) + } - layer.setMap(this.map) + let repository = this.repositories[ids.repositoryId] - this.categories[ids.fullId] = layer + var opt = JSON.parse(JSON.stringify(options)) + opt.id = ids.id + var layer = new this.types[data.type](opt, data, repository) - if ('load' in layer) { - layer.load(function (err) { - callback(err, layer) - }) - } else { - callback(null, layer) - } -} + layer.setMap(this.map) -OpenStreetBrowserLoader.prototype.getFullId = function (id, options) { - var result = {} + this.categories[ids.fullId] = layer - if (!id) { - return null + if ('load' in layer) { + layer.load(function (err) { + callback(err, layer) + }) + } else { + callback(null, layer) + } } - let m = id.match(/^(.*)\/([^/]*)/) - if (m) { - result.id = id - result.repositoryId = m[1] - result.entityId = m[2] - } else if (options.repositoryId && options.repositoryId !== 'default') { - result.repositoryId = options.repositoryId - result.entityId = id - result.id = result.repositoryId + '/' + id - } else { - result.id = id - result.repositoryId = 'default' - result.entityId = id - } + getFullId (id, options) { + var result = {} - result.sublayerId = null - m = result.entityId.split(/:/) - if (m.length > 1) { - result.sublayerId = m[0] - result.entityId = m[1] - } + if (!id) { + return null + } - result.fullId = result.repositoryId + '/' + (result.sublayerId ? result.sublayerId + ':' : '') + result.entityId + let m = id.match(/^(.*)\/([^/]*)/) + if (m) { + result.id = id + result.repositoryId = m[1] + result.entityId = m[2] + } else if (options.repositoryId && options.repositoryId !== 'default') { + result.repositoryId = options.repositoryId + result.entityId = id + result.id = result.repositoryId + '/' + id + } else { + result.id = id + result.repositoryId = 'default' + result.entityId = id + } - return result -} + result.sublayerId = null + m = result.entityId.split(/:/) + if (m.length > 1) { + result.sublayerId = m[0] + result.entityId = m[1] + } -OpenStreetBrowserLoader.prototype.forget = function (id) { - var ids = this.getFullId(id, options) + result.fullId = result.repositoryId + '/' + (result.sublayerId ? result.sublayerId + ':' : '') + result.entityId - this.categories[ids.fullId].remove() - delete this.categories[ids.fullId] -} + return result + } + + forget (id) { + var ids = this.getFullId(id, options) -OpenStreetBrowserLoader.prototype.registerType = function (type, classObject) { - this.types[type] = classObject + this.categories[ids.fullId].remove() + delete this.categories[ids.fullId] + } + + registerType (type, classObject) { + this.types[type] = classObject + } } module.exports = new OpenStreetBrowserLoader()