Merge pull request #1085 from umap-project/prettierjs

Apply PrettierJS to the whole codebase
This commit is contained in:
David Larlet 2023-05-12 14:10:07 -04:00 committed by GitHub
commit db2da8f407
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 8789 additions and 7615 deletions

6
.prettierrc.yaml Normal file
View file

@ -0,0 +1,6 @@
trailingComma: "es5"
tabWidth: 2
semi: false
singleQuote: true
printWidth: 88
quoteProps: "consistent"

View file

@ -52,3 +52,9 @@ tx_push:
tx push -s
tx_pull:
tx pull
jsdir = umap/static/umap/js/
filepath = "${jsdir}*.js"
pretty: ## Apply PrettierJS to all JS files (or specified `filepath`)
./node_modules/prettier/bin-prettier.js --write ${filepath}

22
package-lock.json generated
View file

@ -40,6 +40,7 @@
"mocha-phantomjs": "^4.0.1",
"optimist": "~0.4.0",
"phantomjs": "^1.9.18",
"prettier": "^2.8.8",
"sinon": "^1.10.3",
"uglify-js": "~3.17.4"
}
@ -1920,6 +1921,21 @@
"node": ">=0.10.0"
}
},
"node_modules/prettier": {
"version": "2.8.8",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
"dev": true,
"bin": {
"prettier": "bin-prettier.js"
},
"engines": {
"node": ">=10.13.0"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/process-nextick-args": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
@ -4071,6 +4087,12 @@
"pinkie": "^2.0.0"
}
},
"prettier": {
"version": "2.8.8",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
"dev": true
},
"process-nextick-args": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",

View file

@ -12,6 +12,7 @@
"mocha-phantomjs": "^4.0.1",
"optimist": "~0.4.0",
"phantomjs": "^1.9.18",
"prettier": "^2.8.8",
"sinon": "^1.10.3",
"uglify-js": "~3.17.4"
},

View file

@ -1,108 +1,112 @@
L.U.AutoComplete = L.Class.extend({
options: {
placeholder: 'Start typing...',
emptyMessage: 'No result',
allowFree: true,
minChar: 2,
maxResults: 5
maxResults: 5,
},
CACHE: '',
RESULTS: [],
initialize: function (el, options) {
this.el = el;
var ui = new L.U.UI(document.querySelector('header'));
this.xhr = new L.U.Xhr(ui);
L.setOptions(this, options);
var CURRENT = null;
this.el = el
var ui = new L.U.UI(document.querySelector('header'))
this.xhr = new L.U.Xhr(ui)
L.setOptions(this, options)
var CURRENT = null
try {
Object.defineProperty(this, 'CURRENT', {
get: function () {
return CURRENT;
return CURRENT
},
set: function (index) {
if (typeof index === 'object') {
index = this.resultToIndex(index);
index = this.resultToIndex(index)
}
CURRENT = index;
}
});
CURRENT = index
},
})
} catch (e) {
// Hello IE8
}
return this;
return this
},
createInput: function () {
this.input = L.DomUtil.element('input', {
this.input = L.DomUtil.element(
'input',
{
type: 'text',
placeholder: this.options.placeholder,
autocomplete: 'off',
className: this.options.className
}, this.el);
L.DomEvent.on(this.input, 'keydown', this.onKeyDown, this);
L.DomEvent.on(this.input, 'keyup', this.onKeyUp, this);
L.DomEvent.on(this.input, 'blur', this.onBlur, this);
className: this.options.className,
},
this.el
)
L.DomEvent.on(this.input, 'keydown', this.onKeyDown, this)
L.DomEvent.on(this.input, 'keyup', this.onKeyUp, this)
L.DomEvent.on(this.input, 'blur', this.onBlur, this)
},
createContainer: function () {
this.container = L.DomUtil.element('ul', {className: 'umap-autocomplete'}, document.body);
this.container = L.DomUtil.element(
'ul',
{ className: 'umap-autocomplete' },
document.body
)
},
resizeContainer: function()
{
var l = this.getLeft(this.input);
var t = this.getTop(this.input) + this.input.offsetHeight;
this.container.style.left = l + 'px';
this.container.style.top = t + 'px';
var width = this.options.width ? this.options.width : this.input.offsetWidth - 2;
this.container.style.width = width + 'px';
resizeContainer: function () {
var l = this.getLeft(this.input)
var t = this.getTop(this.input) + this.input.offsetHeight
this.container.style.left = l + 'px'
this.container.style.top = t + 'px'
var width = this.options.width ? this.options.width : this.input.offsetWidth - 2
this.container.style.width = width + 'px'
},
onKeyDown: function (e) {
switch (e.keyCode) {
case L.U.Keys.TAB:
if(this.CURRENT !== null) this.setChoice();
L.DomEvent.stop(e);
break;
if (this.CURRENT !== null) this.setChoice()
L.DomEvent.stop(e)
break
case L.U.Keys.ENTER:
L.DomEvent.stop(e);
this.setChoice();
break;
L.DomEvent.stop(e)
this.setChoice()
break
case L.U.Keys.ESC:
L.DomEvent.stop(e);
this.hide();
break;
L.DomEvent.stop(e)
this.hide()
break
case L.U.Keys.DOWN:
if(this.RESULTS.length > 0) {
if(this.CURRENT !== null && this.CURRENT < this.RESULTS.length - 1) { // what if one result?
this.CURRENT++;
this.highlight();
}
else if(this.CURRENT === null) {
this.CURRENT = 0;
this.highlight();
if (this.RESULTS.length > 0) {
if (this.CURRENT !== null && this.CURRENT < this.RESULTS.length - 1) {
// what if one result?
this.CURRENT++
this.highlight()
} else if (this.CURRENT === null) {
this.CURRENT = 0
this.highlight()
}
}
break;
break
case L.U.Keys.UP:
if(this.CURRENT !== null) {
L.DomEvent.stop(e);
if (this.CURRENT !== null) {
L.DomEvent.stop(e)
}
if(this.RESULTS.length > 0) {
if(this.CURRENT > 0) {
this.CURRENT--;
this.highlight();
}
else if(this.CURRENT === 0) {
this.CURRENT = null;
this.highlight();
if (this.RESULTS.length > 0) {
if (this.CURRENT > 0) {
this.CURRENT--
this.highlight()
} else if (this.CURRENT === 0) {
this.CURRENT = null
this.highlight()
}
}
break;
break
}
},
@ -117,198 +121,221 @@ L.U.AutoComplete = L.Class.extend({
L.U.Keys.APPLE,
L.U.Keys.SHIFT,
L.U.Keys.ALT,
L.U.Keys.CTRL
];
if (special.indexOf(e.keyCode) === -1)
{
this.search();
L.U.Keys.CTRL,
]
if (special.indexOf(e.keyCode) === -1) {
this.search()
}
},
onBlur: function () {
var self = this;
var self = this
setTimeout(function () {
self.hide();
}, 100);
self.hide()
}, 100)
},
clear: function () {
this.RESULTS = [];
this.CURRENT = null;
this.CACHE = '';
this.container.innerHTML = '';
this.RESULTS = []
this.CURRENT = null
this.CACHE = ''
this.container.innerHTML = ''
},
hide: function() {
this.clear();
this.container.style.display = 'none';
this.input.value = '';
hide: function () {
this.clear()
this.container.style.display = 'none'
this.input.value = ''
},
setChoice: function (choice) {
choice = choice || this.RESULTS[this.CURRENT];
choice = choice || this.RESULTS[this.CURRENT]
if (choice) {
this.input.value = choice.item.label;
this.options.on_select(choice);
this.displaySelected(choice);
this.hide();
this.input.value = choice.item.label
this.options.on_select(choice)
this.displaySelected(choice)
this.hide()
if (this.options.callback) {
L.Util.bind(this.options.callback, this)(choice);
L.Util.bind(this.options.callback, this)(choice)
}
}
},
search: function() {
var val = this.input.value;
search: function () {
var val = this.input.value
if (val.length < this.options.minChar) {
this.clear();
return;
this.clear()
return
}
if( val + '' === this.CACHE + '') return;
else this.CACHE = val;
this._do_search(val, function (data) {
this.handleResults(data.data);
}, this);
if (val + '' === this.CACHE + '') return
else this.CACHE = val
this._do_search(
val,
function (data) {
this.handleResults(data.data)
},
this
)
},
createResult: function (item) {
var el = L.DomUtil.element('li', {}, this.container);
el.textContent = item.label;
var el = L.DomUtil.element('li', {}, this.container)
el.textContent = item.label
var result = {
item: item,
el: el
};
L.DomEvent.on(el, 'mouseover', function () {
this.CURRENT = result;
this.highlight();
}, this);
L.DomEvent.on(el, 'mousedown', function () {
this.setChoice();
}, this);
return result;
el: el,
}
L.DomEvent.on(
el,
'mouseover',
function () {
this.CURRENT = result
this.highlight()
},
this
)
L.DomEvent.on(
el,
'mousedown',
function () {
this.setChoice()
},
this
)
return result
},
resultToIndex: function (result) {
var out = null;
var out = null
this.forEach(this.RESULTS, function (item, index) {
if (item.item.value == result.item.value) {
out = index;
return;
out = index
return
}
});
return out;
})
return out
},
handleResults: function(data) {
var self = this;
this.clear();
this.container.style.display = 'block';
this.resizeContainer();
handleResults: function (data) {
var self = this
this.clear()
this.container.style.display = 'block'
this.resizeContainer()
this.forEach(data, function (item) {
self.RESULTS.push(self.createResult(item));
});
this.CURRENT = 0;
this.highlight();
self.RESULTS.push(self.createResult(item))
})
this.CURRENT = 0
this.highlight()
//TODO manage no results
},
highlight: function () {
var self = this;
var self = this
this.forEach(this.RESULTS, function (result, index) {
if (index === self.CURRENT) L.DomUtil.addClass(result.el, 'on');
else L.DomUtil.removeClass(result.el, 'on');
});
if (index === self.CURRENT) L.DomUtil.addClass(result.el, 'on')
else L.DomUtil.removeClass(result.el, 'on')
})
},
getLeft: function (el) {
var tmp = el.offsetLeft;
el = el.offsetParent;
while(el) {
tmp += el.offsetLeft;
el = el.offsetParent;
var tmp = el.offsetLeft
el = el.offsetParent
while (el) {
tmp += el.offsetLeft
el = el.offsetParent
}
return tmp;
return tmp
},
getTop: function (el) {
var tmp = el.offsetTop;
el = el.offsetParent;
while(el) {
tmp += el.offsetTop;
el = el.offsetParent;
var tmp = el.offsetTop
el = el.offsetParent
while (el) {
tmp += el.offsetTop
el = el.offsetParent
}
return tmp;
return tmp
},
forEach: function (els, callback) {
Array.prototype.forEach.call(els, callback);
}
});
Array.prototype.forEach.call(els, callback)
},
})
L.U.AutoComplete.Ajax = L.U.AutoComplete.extend({
initialize: function (el, options) {
L.U.AutoComplete.prototype.initialize.call(this, el, options);
if (!this.el) return this;
this.createInput();
this.createContainer();
this.selected_container = this.initSelectedContainer();
L.U.AutoComplete.prototype.initialize.call(this, el, options)
if (!this.el) return this
this.createInput()
this.createContainer()
this.selected_container = this.initSelectedContainer()
},
optionToResult: function (option) {
return {
value: option.value,
label: option.innerHTML
};
label: option.innerHTML,
}
},
_do_search: function (val, callback, context) {
val = val.toLowerCase();
this.xhr.get('/agnocomplete/AutocompleteUser/?q=' + encodeURIComponent(val), {callback: callback, context: context || this});
}
});
val = val.toLowerCase()
this.xhr.get('/agnocomplete/AutocompleteUser/?q=' + encodeURIComponent(val), {
callback: callback,
context: context || this,
})
},
})
L.U.AutoComplete.Ajax.SelectMultiple = L.U.AutoComplete.Ajax.extend({
initSelectedContainer: function () {
return L.DomUtil.after(this.input, L.DomUtil.element('ul', {className: 'umap-multiresult'}));
return L.DomUtil.after(
this.input,
L.DomUtil.element('ul', { className: 'umap-multiresult' })
)
},
displaySelected: function (result) {
var result_el = L.DomUtil.element('li', {}, this.selected_container);
result_el.textContent = result.item.label;
var close = L.DomUtil.element('span', {className: 'close'}, result_el);
close.textContent = '×';
L.DomEvent.on(close, 'click', function () {
this.selected_container.removeChild(result_el);
this.options.on_unselect(result);
}, this);
this.hide();
}
});
var result_el = L.DomUtil.element('li', {}, this.selected_container)
result_el.textContent = result.item.label
var close = L.DomUtil.element('span', { className: 'close' }, result_el)
close.textContent = '×'
L.DomEvent.on(
close,
'click',
function () {
this.selected_container.removeChild(result_el)
this.options.on_unselect(result)
},
this
)
this.hide()
},
})
L.U.AutoComplete.Ajax.Select = L.U.AutoComplete.Ajax.extend({
initSelectedContainer: function () {
return L.DomUtil.after(this.input, L.DomUtil.element('div', {className: 'umap-singleresult'}));
return L.DomUtil.after(
this.input,
L.DomUtil.element('div', { className: 'umap-singleresult' })
)
},
displaySelected: function (result) {
var result_el = L.DomUtil.element('div', {}, this.selected_container);
result_el.textContent = result.item.label;
var close = L.DomUtil.element('span', {className: 'close'}, result_el);
close.textContent = '×';
this.input.style.display = 'none';
L.DomEvent.on(close, 'click', function () {
this.selected_container.innerHTML = '';
this.input.style.display = 'block';
}, this);
this.hide();
}
});
var result_el = L.DomUtil.element('div', {}, this.selected_container)
result_el.textContent = result.item.label
var close = L.DomUtil.element('span', { className: 'close' }, result_el)
close.textContent = '×'
this.input.style.display = 'none'
L.DomEvent.on(
close,
'click',
function () {
this.selected_container.innerHTML = ''
this.input.style.display = 'block'
},
this
)
this.hide()
},
})

File diff suppressed because it is too large Load diff

View file

@ -1,304 +1,319 @@
/* Poor man pub/sub handler, enough for now */
L.UmapSingleton = L.Evented.extend({});
L.U = new L.UmapSingleton();
L.U.Map = L.Map.extend({});
L.UmapSingleton = L.Evented.extend({})
L.U = new L.UmapSingleton()
L.U.Map = L.Map.extend({})
/*
* Utils
*/
* Utils
*/
L.Util.queryString = function (name, fallback) {
var decode = function (s) { return decodeURIComponent(s.replace(/\+/g, ' ')); };
var qs = window.location.search.slice(1).split('&'), qa = {};
for (var i in qs) {
var key = qs[i].split('=');
if (!key) continue;
qa[decode(key[0])] = key[1] ? decode(key[1]) : 1;
var decode = function (s) {
return decodeURIComponent(s.replace(/\+/g, ' '))
}
return qa[name] || fallback;
};
var qs = window.location.search.slice(1).split('&'),
qa = {}
for (var i in qs) {
var key = qs[i].split('=')
if (!key) continue
qa[decode(key[0])] = key[1] ? decode(key[1]) : 1
}
return qa[name] || fallback
}
L.Util.booleanFromQueryString = function (name) {
var value = L.Util.queryString(name);
return value === '1' || value === 'true';
};
var value = L.Util.queryString(name)
return value === '1' || value === 'true'
}
L.Util.setFromQueryString = function (options, name) {
var value = L.Util.queryString(name);
if (typeof value !== 'undefined') options[name] = value;
};
var value = L.Util.queryString(name)
if (typeof value !== 'undefined') options[name] = value
}
L.Util.setBooleanFromQueryString = function (options, name) {
var value = L.Util.queryString(name);
if (typeof value !== 'undefined') options[name] = value == '1' || value == 'true';
};
var value = L.Util.queryString(name)
if (typeof value !== 'undefined') options[name] = value == '1' || value == 'true'
}
L.Util.setNullableBooleanFromQueryString = function (options, name) {
var value = L.Util.queryString(name);
var value = L.Util.queryString(name)
if (typeof value !== 'undefined') {
if (value === 'null') value = null;
else if (value === '0' || value === 'false') value = false;
else value = true;
options[name] = value;
if (value === 'null') value = null
else if (value === '0' || value === 'false') value = false
else value = true
options[name] = value
}
};
}
L.Util.escapeHTML = function (s) {
s = s? s.toString() : '';
return s.replace(/</gm, '&lt;');
};
s = s ? s.toString() : ''
return s.replace(/</gm, '&lt;')
}
L.Util.toHTML = function (r) {
if (!r) return '';
var ii;
if (!r) return ''
var ii
// detect newline format
var newline = r.indexOf('\r\n') != -1 ? '\r\n' : r.indexOf('\n') != -1 ? '\n' : '';
var newline = r.indexOf('\r\n') != -1 ? '\r\n' : r.indexOf('\n') != -1 ? '\n' : ''
// Escape tags
r = r.replace(/</gm, '&lt;');
r = r.replace(/</gm, '&lt;')
// headings and hr
r = r.replace(/^### (.*)/gm, '<h5>$1</h5>');
r = r.replace(/^## (.*)/gm, '<h4>$1</h4>');
r = r.replace(/^# (.*)/gm, '<h3>$1</h3>');
r = r.replace(/^---/gm, '<hr>');
r = r.replace(/^### (.*)/gm, '<h5>$1</h5>')
r = r.replace(/^## (.*)/gm, '<h4>$1</h4>')
r = r.replace(/^# (.*)/gm, '<h3>$1</h3>')
r = r.replace(/^---/gm, '<hr>')
// bold, italics
r = r.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
r = r.replace(/\*(.*?)\*/g, '<em>$1</em>');
r = r.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
r = r.replace(/\*(.*?)\*/g, '<em>$1</em>')
// unordered lists
r = r.replace(/^\*\* (.*)/gm, '<ul><ul><li>$1</li></ul></ul>');
r = r.replace(/^\* (.*)/gm, '<ul><li>$1</li></ul>');
for (ii = 0; ii < 3; ii++) r = r.replace(new RegExp('</ul>' + newline + '<ul>', 'g'), newline);
r = r.replace(/^\*\* (.*)/gm, '<ul><ul><li>$1</li></ul></ul>')
r = r.replace(/^\* (.*)/gm, '<ul><li>$1</li></ul>')
for (ii = 0; ii < 3; ii++)
r = r.replace(new RegExp('</ul>' + newline + '<ul>', 'g'), newline)
// links
r = r.replace(/(\[\[http)/g, '[[h_t_t_p'); // Escape for avoiding clash between [[http://xxx]] and http://xxx
r = r.replace(/({{http)/g, '{{h_t_t_p');
r = r.replace(/(=http)/g, '=h_t_t_p'); // http://xxx as query string, see https://github.com/umap-project/umap/issues/607
r = r.replace(/(https?:[^ \<)\n]*)/g, '<a target="_blank" href="$1">$1</a>');
r = r.replace(/\[\[(h_t_t_ps?:[^\]|]*?)\]\]/g, '<a target="_blank" href="$1">$1</a>');
r = r.replace(/\[\[(h_t_t_ps?:[^|]*?)\|(.*?)\]\]/g, '<a target="_blank" href="$1">$2</a>');
r = r.replace(/\[\[([^\]|]*?)\]\]/g, '<a href="$1">$1</a>');
r = r.replace(/\[\[([^|]*?)\|(.*?)\]\]/g, '<a href="$1">$2</a>');
r = r.replace(/(\[\[http)/g, '[[h_t_t_p') // Escape for avoiding clash between [[http://xxx]] and http://xxx
r = r.replace(/({{http)/g, '{{h_t_t_p')
r = r.replace(/(=http)/g, '=h_t_t_p') // http://xxx as query string, see https://github.com/umap-project/umap/issues/607
r = r.replace(/(https?:[^ \<)\n]*)/g, '<a target="_blank" href="$1">$1</a>')
r = r.replace(/\[\[(h_t_t_ps?:[^\]|]*?)\]\]/g, '<a target="_blank" href="$1">$1</a>')
r = r.replace(
/\[\[(h_t_t_ps?:[^|]*?)\|(.*?)\]\]/g,
'<a target="_blank" href="$1">$2</a>'
)
r = r.replace(/\[\[([^\]|]*?)\]\]/g, '<a href="$1">$1</a>')
r = r.replace(/\[\[([^|]*?)\|(.*?)\]\]/g, '<a href="$1">$2</a>')
// iframe
r = r.replace(/{{{(h_t_t_ps?[^ |{]*)}}}/g, '<div><iframe frameborder="0" src="$1" width="100%" height="300px"></iframe></div>');
r = r.replace(/{{{(h_t_t_ps?[^ |{]*)\|(\d*)(px)?}}}/g, '<div><iframe frameborder="0" src="$1" width="100%" height="$2px"></iframe></div>');
r = r.replace(/{{{(h_t_t_ps?[^ |{]*)\|(\d*)(px)?\*(\d*)(px)?}}}/g, '<div><iframe frameborder="0" src="$1" width="$4px" height="$2px"></iframe></div>');
r = r.replace(
/{{{(h_t_t_ps?[^ |{]*)}}}/g,
'<div><iframe frameborder="0" src="$1" width="100%" height="300px"></iframe></div>'
)
r = r.replace(
/{{{(h_t_t_ps?[^ |{]*)\|(\d*)(px)?}}}/g,
'<div><iframe frameborder="0" src="$1" width="100%" height="$2px"></iframe></div>'
)
r = r.replace(
/{{{(h_t_t_ps?[^ |{]*)\|(\d*)(px)?\*(\d*)(px)?}}}/g,
'<div><iframe frameborder="0" src="$1" width="$4px" height="$2px"></iframe></div>'
)
// images
r = r.replace(/{{([^\]|]*?)}}/g, '<img src="$1">');
r = r.replace(/{{([^|]*?)\|(\d*?)}}/g, '<img src="$1" width="$2">');
r = r.replace(/{{([^\]|]*?)}}/g, '<img src="$1">')
r = r.replace(/{{([^|]*?)\|(\d*?)}}/g, '<img src="$1" width="$2">')
//Unescape http
r = r.replace(/(h_t_t_p)/g, 'http');
r = r.replace(/(h_t_t_p)/g, 'http')
// Preserver line breaks
if (newline) r = r.replace(new RegExp(newline + '(?=[^]+)', 'g'), '<br>' + newline);
if (newline) r = r.replace(new RegExp(newline + '(?=[^]+)', 'g'), '<br>' + newline)
return r;
};
return r
}
L.Util.isObject = function (what) {
return typeof what === 'object' && what !== null;
};
return typeof what === 'object' && what !== null
}
L.Util.CopyJSON = function (geojson) {
return JSON.parse(JSON.stringify(geojson));
};
return JSON.parse(JSON.stringify(geojson))
}
L.Util.detectFileType = function (f) {
var filename = f.name ? escape(f.name.toLowerCase()) : '';
var filename = f.name ? escape(f.name.toLowerCase()) : ''
function ext(_) {
return filename.indexOf(_) !== -1;
return filename.indexOf(_) !== -1
}
if (f.type === 'application/vnd.google-earth.kml+xml' || ext('.kml')) {
return 'kml';
return 'kml'
}
if (ext('.gpx')) return 'gpx';
if (ext('.geojson') || ext('.json')) return 'geojson';
if (ext('.gpx')) return 'gpx'
if (ext('.geojson') || ext('.json')) return 'geojson'
if (f.type === 'text/csv' || ext('.csv') || ext('.tsv') || ext('.dsv')) {
return 'csv';
return 'csv'
}
if (ext('.xml') || ext('.osm')) return 'osm';
if (ext('.umap')) return 'umap';
};
if (ext('.xml') || ext('.osm')) return 'osm'
if (ext('.umap')) return 'umap'
}
L.Util.usableOption = function (options, option) {
return options[option] !== undefined && options[option] !== '';
};
return options[option] !== undefined && options[option] !== ''
}
L.Util.greedyTemplate = function (str, data, ignore) {
function getValue(data, path) {
var value = data
for (var i = 0; i < path.length; i++) {
value = value[path[i]]
if (value === undefined) break;
if (value === undefined) break
}
return value;
return value
}
return str.replace(/\{ *([\w_\:\.\|]+)(?:\|("[^"]*"))? *\}/g, function (str, key, staticFallback) {
var vars = key.split('|'), value, path;
return str.replace(
/\{ *([\w_\:\.\|]+)(?:\|("[^"]*"))? *\}/g,
function (str, key, staticFallback) {
var vars = key.split('|'),
value,
path
if (staticFallback !== undefined) {
vars.push(staticFallback);
vars.push(staticFallback)
}
for (var i = 0; i < vars.length; i++) {
path = vars[i];
if (path.startsWith('"') && path.endsWith('"')) value = path.substring(1, path.length -1); // static default value.
else value = getValue(data, path.split('.'));
if (value !== undefined) break;
path = vars[i]
if (path.startsWith('"') && path.endsWith('"'))
value = path.substring(1, path.length - 1) // static default value.
else value = getValue(data, path.split('.'))
if (value !== undefined) break
}
if (value === undefined) {
if (ignore) value = str;
else value = '';
if (ignore) value = str
else value = ''
}
return value;
});
};
return value
}
)
}
L.Util.sortFeatures = function (features, sortKey) {
var sortKeys = (sortKey || 'name').split(',');
var sortKeys = (sortKey || 'name').split(',')
var sort = function (a, b, i) {
var sortKey = sortKeys[i], score,
var sortKey = sortKeys[i],
score,
valA = a.properties[sortKey] || '',
valB = b.properties[sortKey] || '';
valB = b.properties[sortKey] || ''
if (!valA) {
score = -1;
score = -1
} else if (!valB) {
score = 1;
score = 1
} else {
score = valA.toString().toLowerCase().localeCompare(valB.toString().toLowerCase());
score = valA.toString().toLowerCase().localeCompare(valB.toString().toLowerCase())
}
if (score === 0 && sortKeys[i + 1]) return sort(a, b, i + 1)
return score
}
if (score === 0 && sortKeys[i + 1]) return sort(a, b, i + 1);
return score;
};
features.sort(function (a, b) {
if (!a.properties || !b.properties) {
return 0;
return 0
}
return sort(a, b, 0);
});
return sort(a, b, 0)
})
return features;
};
return features
}
L.Util.flattenCoordinates = function (coords) {
while (coords[0] && typeof coords[0][0] !== 'number') coords = coords[0];
return coords;
};
while (coords[0] && typeof coords[0][0] !== 'number') coords = coords[0]
return coords
}
L.Util.buildQueryString = function (params) {
var query_string = [];
var query_string = []
for (var key in params) {
query_string.push(encodeURIComponent(key) + '=' + encodeURIComponent(params[key]));
query_string.push(encodeURIComponent(key) + '=' + encodeURIComponent(params[key]))
}
return query_string.join('&');
};
return query_string.join('&')
}
L.Util.getBaseUrl = function () {
return '//' + window.location.host + window.location.pathname;
};
return '//' + window.location.host + window.location.pathname
}
L.DomUtil.add = function (tagName, className, container, content) {
var el = L.DomUtil.create(tagName, className, container);
var el = L.DomUtil.create(tagName, className, container)
if (content) {
if (content.nodeType && content.nodeType === 1) {
el.appendChild(content);
}
else {
el.innerHTML = content;
el.appendChild(content)
} else {
el.innerHTML = content
}
}
return el;
};
return el
}
L.DomUtil.createFieldset = function (container, legend, options) {
options = options || {};
var fieldset = L.DomUtil.create('div', 'fieldset toggle', container);
var legendEl = L.DomUtil.add('h5', 'legend style_options_toggle', fieldset, legend);
var fieldsEl = L.DomUtil.add('div', 'fields with-transition', fieldset);
options = options || {}
var fieldset = L.DomUtil.create('div', 'fieldset toggle', container)
var legendEl = L.DomUtil.add('h5', 'legend style_options_toggle', fieldset, legend)
var fieldsEl = L.DomUtil.add('div', 'fields with-transition', fieldset)
L.DomEvent.on(legendEl, 'click', function () {
if (L.DomUtil.hasClass(fieldset, 'on')) {
L.DomUtil.removeClass(fieldset, 'on');
L.DomUtil.removeClass(fieldset, 'on')
} else {
L.DomUtil.addClass(fieldset, 'on');
if (options.callback) options.callback.call(options.context || this);
L.DomUtil.addClass(fieldset, 'on')
if (options.callback) options.callback.call(options.context || this)
}
});
return fieldsEl;
};
})
return fieldsEl
}
L.DomUtil.classIf = function (el, className, bool) {
if (bool) L.DomUtil.addClass(el, className);
else L.DomUtil.removeClass(el, className);
};
if (bool) L.DomUtil.addClass(el, className)
else L.DomUtil.removeClass(el, className)
}
L.DomUtil.element = function (what, attrs, parent) {
var el = document.createElement(what);
var el = document.createElement(what)
for (var attr in attrs) {
el[attr] = attrs[attr];
el[attr] = attrs[attr]
}
if (typeof parent !== 'undefined') {
parent.appendChild(el);
parent.appendChild(el)
}
return el;
};
return el
}
L.DomUtil.before = function (target, el) {
target.parentNode.insertBefore(el, target);
return el;
};
target.parentNode.insertBefore(el, target)
return el
}
L.DomUtil.after = function (target, el)
{
target.parentNode.insertBefore(el, target.nextSibling);
return el;
};
L.DomUtil.after = function (target, el) {
target.parentNode.insertBefore(el, target.nextSibling)
return el
}
L.DomUtil.RGBRegex = /rgb *\( *([0-9]{1,3}) *, *([0-9]{1,3}) *, *([0-9]{1,3}) *\)/;
L.DomUtil.RGBRegex = /rgb *\( *([0-9]{1,3}) *, *([0-9]{1,3}) *, *([0-9]{1,3}) *\)/
L.DomUtil.TextColorFromBackgroundColor = function (el) {
var out = '#000000';
if (!window.getComputedStyle) {return out;}
var rgb = window.getComputedStyle(el).getPropertyValue('background-color');
rgb = L.DomUtil.RGBRegex.exec(rgb);
if (!rgb || rgb.length !== 4) {return out;}
rgb = parseInt(rgb[1], 10) + parseInt(rgb[2], 10) + parseInt(rgb[3], 10);
if (rgb < (255 * 3 / 2)) {
out = '#ffffff';
var out = '#000000'
if (!window.getComputedStyle) {
return out
}
return out;
};
var rgb = window.getComputedStyle(el).getPropertyValue('background-color')
rgb = L.DomUtil.RGBRegex.exec(rgb)
if (!rgb || rgb.length !== 4) {
return out
}
rgb = parseInt(rgb[1], 10) + parseInt(rgb[2], 10) + parseInt(rgb[3], 10)
if (rgb < (255 * 3) / 2) {
out = '#ffffff'
}
return out
}
L.DomEvent.once = function (el, types, fn, context) {
// cf https://github.com/Leaflet/Leaflet/pull/3528#issuecomment-134551575
if (typeof types === 'object') {
for (var type in types) {
L.DomEvent.once(el, type, types[type], fn);
L.DomEvent.once(el, type, types[type], fn)
}
return L.DomEvent;
return L.DomEvent
}
var handler = L.bind(function () {
L.DomEvent
.off(el, types, fn, context)
.off(el, types, handler, context);
}, L.DomEvent);
L.DomEvent.off(el, types, fn, context).off(el, types, handler, context)
}, L.DomEvent)
// add a listener that's executed once and removed after that
return L.DomEvent
.on(el, types, fn, context)
.on(el, types, handler, context);
};
return L.DomEvent.on(el, types, fn, context).on(el, types, handler, context)
}
/*
* Global events
*/
* Global events
*/
L.U.Keys = {
LEFT: 37,
UP: 38,
@ -319,43 +334,45 @@ L.U.Keys = {
M: 77,
P: 80,
S: 83,
Z: 90
};
Z: 90,
}
L.U.Help = L.Class.extend({
initialize: function (map) {
this.map = map;
this.box = L.DomUtil.create('div', 'umap-help-box with-transition dark', document.body);
var closeLink = L.DomUtil.create('a', 'umap-close-link', this.box);
closeLink.href = '#';
L.DomUtil.add('i', 'umap-close-icon', closeLink);
var label = L.DomUtil.create('span', '', closeLink);
label.title = label.textContent = L._('Close');
this.content = L.DomUtil.create('div', 'umap-help-content', this.box);
L.DomEvent.on(closeLink, 'click', this.hide, this);
this.map = map
this.box = L.DomUtil.create(
'div',
'umap-help-box with-transition dark',
document.body
)
var closeLink = L.DomUtil.create('a', 'umap-close-link', this.box)
closeLink.href = '#'
L.DomUtil.add('i', 'umap-close-icon', closeLink)
var label = L.DomUtil.create('span', '', closeLink)
label.title = label.textContent = L._('Close')
this.content = L.DomUtil.create('div', 'umap-help-content', this.box)
L.DomEvent.on(closeLink, 'click', this.hide, this)
},
onKeyDown: function (e) {
var key = e.keyCode,
ESC = 27;
ESC = 27
if (key === ESC) {
this.hide();
this.hide()
}
},
show: function () {
this.content.innerHTML = '';
this.content.innerHTML = ''
for (var i = 0, name; i < arguments.length; i++) {
name = arguments[i];
L.DomUtil.add('div', 'umap-help-entry', this.content, this.resolve(name));
name = arguments[i]
L.DomUtil.add('div', 'umap-help-entry', this.content, this.resolve(name))
}
L.DomUtil.addClass(document.body, 'umap-help-on');
L.DomUtil.addClass(document.body, 'umap-help-on')
},
hide: function () {
L.DomUtil.removeClass(document.body, 'umap-help-on');
L.DomUtil.removeClass(document.body, 'umap-help-on')
},
visible: function () {
@ -363,89 +380,141 @@ L.U.Help = L.Class.extend({
},
resolve: function (name) {
return typeof this[name] === 'function' ? this[name]() : this[name];
return typeof this[name] === 'function' ? this[name]() : this[name]
},
button: function (container, entries) {
var helpButton = L.DomUtil.create('a', 'umap-help-button', container);
helpButton.href = '#';
var helpButton = L.DomUtil.create('a', 'umap-help-button', container)
helpButton.href = '#'
if (entries) {
L.DomEvent
.on(helpButton, 'click', L.DomEvent.stop)
.on(helpButton, 'click', function (e) {
var args = typeof entries === 'string' ? [entries] : entries;
this.show.apply(this, args);
}, this);
L.DomEvent.on(helpButton, 'click', L.DomEvent.stop).on(
helpButton,
'click',
function (e) {
var args = typeof entries === 'string' ? [entries] : entries
this.show.apply(this, args)
},
this
)
}
return helpButton;
return helpButton
},
edit: function () {
var container = L.DomUtil.create('div', ''),
self = this,
title = L.DomUtil.create('h3', '', container),
actionsContainer = L.DomUtil.create('ul', 'umap-edit-actions', container);
actionsContainer = L.DomUtil.create('ul', 'umap-edit-actions', container)
var addAction = function (action) {
var actionContainer = L.DomUtil.add('li', '', actionsContainer);
var actionContainer = L.DomUtil.add('li', '', actionsContainer)
L.DomUtil.add('i', action.options.className, actionContainer),
L.DomUtil.add('span', '', actionContainer, action.options.tooltip);
L.DomEvent.on(actionContainer, 'click', action.addHooks, action);
L.DomEvent.on(actionContainer, 'click', self.hide, self);
};
title.textContent = L._('Where do we go from here?');
for (var id in this.map.helpMenuActions) {
addAction(this.map.helpMenuActions[id]);
L.DomUtil.add('span', '', actionContainer, action.options.tooltip)
L.DomEvent.on(actionContainer, 'click', action.addHooks, action)
L.DomEvent.on(actionContainer, 'click', self.hide, self)
}
return container;
title.textContent = L._('Where do we go from here?')
for (var id in this.map.helpMenuActions) {
addAction(this.map.helpMenuActions[id])
}
return container
},
importFormats: function () {
var container = L.DomUtil.create('div');
L.DomUtil.add('h3', '', container, 'GeojSON');
L.DomUtil.add('p', '', container, L._('All properties are imported.'));
L.DomUtil.add('h3', '', container, 'GPX');
L.DomUtil.add('p', '', container, L._('Properties imported:') + 'name, desc');
L.DomUtil.add('h3', '', container, 'KML');
L.DomUtil.add('p', '', container, L._('Properties imported:') + 'name, description');
L.DomUtil.add('h3', '', container, 'CSV');
L.DomUtil.add('p', '', container, L._('Comma, tab or semi-colon separated values. SRS WGS84 is implied. Only Point geometries are imported. The import will look at the column headers for any mention of «lat» and «lon» at the begining of the header, case insensitive. All other column are imported as properties.'));
L.DomUtil.add('h3', '', container, 'uMap');
L.DomUtil.add('p', '', container, L._('Imports all umap data, including layers and settings.'));
return container;
var container = L.DomUtil.create('div')
L.DomUtil.add('h3', '', container, 'GeojSON')
L.DomUtil.add('p', '', container, L._('All properties are imported.'))
L.DomUtil.add('h3', '', container, 'GPX')
L.DomUtil.add('p', '', container, L._('Properties imported:') + 'name, desc')
L.DomUtil.add('h3', '', container, 'KML')
L.DomUtil.add('p', '', container, L._('Properties imported:') + 'name, description')
L.DomUtil.add('h3', '', container, 'CSV')
L.DomUtil.add(
'p',
'',
container,
L._(
'Comma, tab or semi-colon separated values. SRS WGS84 is implied. Only Point geometries are imported. The import will look at the column headers for any mention of «lat» and «lon» at the begining of the header, case insensitive. All other column are imported as properties.'
)
)
L.DomUtil.add('h3', '', container, 'uMap')
L.DomUtil.add(
'p',
'',
container,
L._('Imports all umap data, including layers and settings.')
)
return container
},
textFormatting: function () {
var container = L.DomUtil.create('div'),
title = L.DomUtil.add('h3', '', container, L._('Text formatting')),
elements = L.DomUtil.create('ul', '', container);
L.DomUtil.add('li', '', elements, L._('*simple star for italic*'));
L.DomUtil.add('li', '', elements, L._('**double star for bold**'));
L.DomUtil.add('li', '', elements, L._('# one hash for main heading'));
L.DomUtil.add('li', '', elements, L._('## two hashes for second heading'));
L.DomUtil.add('li', '', elements, L._('### three hashes for third heading'));
L.DomUtil.add('li', '', elements, L._('Simple link: [[http://example.com]]'));
L.DomUtil.add('li', '', elements, L._('Link with text: [[http://example.com|text of the link]]'));
L.DomUtil.add('li', '', elements, L._('Image: {{http://image.url.com}}'));
L.DomUtil.add('li', '', elements, L._('Image with custom width (in px): {{http://image.url.com|width}}'));
L.DomUtil.add('li', '', elements, L._('Iframe: {{{http://iframe.url.com}}}'));
L.DomUtil.add('li', '', elements, L._('Iframe with custom height (in px): {{{http://iframe.url.com|height}}}'));
L.DomUtil.add('li', '', elements, L._('Iframe with custom height and width (in px): {{{http://iframe.url.com|height*width}}}'));
L.DomUtil.add('li', '', elements, L._('--- for an horizontal rule'));
return container;
elements = L.DomUtil.create('ul', '', container)
L.DomUtil.add('li', '', elements, L._('*simple star for italic*'))
L.DomUtil.add('li', '', elements, L._('**double star for bold**'))
L.DomUtil.add('li', '', elements, L._('# one hash for main heading'))
L.DomUtil.add('li', '', elements, L._('## two hashes for second heading'))
L.DomUtil.add('li', '', elements, L._('### three hashes for third heading'))
L.DomUtil.add('li', '', elements, L._('Simple link: [[http://example.com]]'))
L.DomUtil.add(
'li',
'',
elements,
L._('Link with text: [[http://example.com|text of the link]]')
)
L.DomUtil.add('li', '', elements, L._('Image: {{http://image.url.com}}'))
L.DomUtil.add(
'li',
'',
elements,
L._('Image with custom width (in px): {{http://image.url.com|width}}')
)
L.DomUtil.add('li', '', elements, L._('Iframe: {{{http://iframe.url.com}}}'))
L.DomUtil.add(
'li',
'',
elements,
L._('Iframe with custom height (in px): {{{http://iframe.url.com|height}}}')
)
L.DomUtil.add(
'li',
'',
elements,
L._(
'Iframe with custom height and width (in px): {{{http://iframe.url.com|height*width}}}'
)
)
L.DomUtil.add('li', '', elements, L._('--- for an horizontal rule'))
return container
},
dynamicProperties: function () {
var container = L.DomUtil.create('div');
L.DomUtil.add('h3', '', container, L._('Dynamic properties'));
L.DomUtil.add('p', '', container, L._('Use placeholders with feature properties between brackets, eg. &#123;name&#125;, they will be dynamically replaced by the corresponding values.'));
return container;
var container = L.DomUtil.create('div')
L.DomUtil.add('h3', '', container, L._('Dynamic properties'))
L.DomUtil.add(
'p',
'',
container,
L._(
'Use placeholders with feature properties between brackets, eg. &#123;name&#125;, they will be dynamically replaced by the corresponding values.'
)
)
return container
},
formatURL: L._('Supported variables that will be dynamically replaced') + ': {bbox}, {lat}, {lng}, {zoom}, {east}, {north}..., {left}, {top}...',
formatIconSymbol: L._('Symbol can be either a unicode character or an URL. You can use feature properties as variables: ex.: with "http://myserver.org/images/{name}.png", the {name} variable will be replaced by the "name" value of each marker.'),
formatURL:
L._('Supported variables that will be dynamically replaced') +
': {bbox}, {lat}, {lng}, {zoom}, {east}, {north}..., {left}, {top}...',
formatIconSymbol: L._(
'Symbol can be either a unicode character or an URL. You can use feature properties as variables: ex.: with "http://myserver.org/images/{name}.png", the {name} variable will be replaced by the "name" value of each marker.'
),
colorValue: L._('Must be a valid CSS value (eg.: DarkBlue or #123456)'),
smoothFactor: L._('How much to simplify the polyline on each zoom level (more = better performance and smoother look, less = more accurate)'),
dashArray: L._('A comma separated list of numbers that defines the stroke dash pattern. Ex.: "5, 10, 15".'),
smoothFactor: L._(
'How much to simplify the polyline on each zoom level (more = better performance and smoother look, less = more accurate)'
),
dashArray: L._(
'A comma separated list of numbers that defines the stroke dash pattern. Ex.: "5, 10, 15".'
),
zoomTo: L._('Zoom level for automatic zooms'),
labelKey: L._('The name of the property to use as feature label (ex.: "nom")'),
stroke: L._('Whether to display or not polygons paths.'),
@ -453,82 +522,86 @@ L.U.Help = L.Class.extend({
fillColor: L._('Optional. Same as color if not set.'),
shortCredit: L._('Will be displayed in the bottom right corner of the map'),
longCredit: L._('Will be visible in the caption of the map'),
permanentCredit: L._('Will be permanently visible in the bottom left corner of the map'),
permanentCredit: L._(
'Will be permanently visible in the bottom left corner of the map'
),
sortKey: L._('Property to use for sorting features'),
slugKey: L._('The name of the property to use as feature unique identifier.'),
filterKey: L._('Comma separated list of properties to use when filtering features'),
advancedFilterKey: L._('Comma separated list of properties to use for checkbox filtering'),
advancedFilterKey: L._(
'Comma separated list of properties to use for checkbox filtering'
),
advancedFiltersNoResults: L._('No results for these filters'),
interactive: L._('If false, the polygon will act as a part of the underlying map.'),
outlink: L._('Define link to open in a new window on polygon click.'),
dynamicRemoteData: L._('Fetch data each time map view changes.'),
proxyRemoteData: L._('To use if remote server doesn\'t allow cross domain (slower)'),
browsable: L._('Set it to false to hide this layer from the slideshow, the data browser, the popup navigation…')
});
proxyRemoteData: L._("To use if remote server doesn't allow cross domain (slower)"),
browsable: L._(
'Set it to false to hide this layer from the slideshow, the data browser, the popup navigation…'
),
})
L.U.Orderable = L.Evented.extend({
options: {
selector: 'li',
color: '#374E75'
color: '#374E75',
},
initialize: function (parent, options) {
L.Util.setOptions(this, options);
this.parent = parent;
this.src = null;
this.dst = null;
this.els = this.parent.querySelectorAll(this.options.selector);
for (var i = 0; i < this.els.length; i++) this.makeDraggable(this.els[i]);
L.Util.setOptions(this, options)
this.parent = parent
this.src = null
this.dst = null
this.els = this.parent.querySelectorAll(this.options.selector)
for (var i = 0; i < this.els.length; i++) this.makeDraggable(this.els[i])
},
makeDraggable: function (node) {
node.draggable = true;
L.DomEvent.on(node, 'dragstart', this.onDragStart, this);
L.DomEvent.on(node, 'dragenter', this.onDragEnter, this);
L.DomEvent.on(node, 'dragover', this.onDragOver, this);
L.DomEvent.on(node, 'dragleave', this.onDragLeave, this);
L.DomEvent.on(node, 'drop', this.onDrop, this);
L.DomEvent.on(node, 'dragend', this.onDragEnd, this);
node.draggable = true
L.DomEvent.on(node, 'dragstart', this.onDragStart, this)
L.DomEvent.on(node, 'dragenter', this.onDragEnter, this)
L.DomEvent.on(node, 'dragover', this.onDragOver, this)
L.DomEvent.on(node, 'dragleave', this.onDragLeave, this)
L.DomEvent.on(node, 'drop', this.onDrop, this)
L.DomEvent.on(node, 'dragend', this.onDragEnd, this)
},
nodeIndex: function (node) {
return Array.prototype.indexOf.call(this.parent.children, node);
return Array.prototype.indexOf.call(this.parent.children, node)
},
findTarget: function (node) {
while (node) {
if (this.nodeIndex(node) !== -1) return node;
node = node.parentNode;
if (this.nodeIndex(node) !== -1) return node
node = node.parentNode
}
},
onDragStart: function (e) {
// e.target is the source node.
this.src = e.target;
this.initialIndex = this.nodeIndex(this.src);
this.srcBackgroundColor = this.src.style.backgroundColor;
this.src.style.backgroundColor = this.options.color;
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text/html', this.src.innerHTML);
this.src = e.target
this.initialIndex = this.nodeIndex(this.src)
this.srcBackgroundColor = this.src.style.backgroundColor
this.src.style.backgroundColor = this.options.color
e.dataTransfer.effectAllowed = 'move'
e.dataTransfer.setData('text/html', this.src.innerHTML)
},
onDragOver: function (e) {
if (e.preventDefault) e.preventDefault(); // Necessary. Allows us to drop.
e.dataTransfer.dropEffect = 'move';
return false;
if (e.preventDefault) e.preventDefault() // Necessary. Allows us to drop.
e.dataTransfer.dropEffect = 'move'
return false
},
onDragEnter: function (e) {
// e.target is the current hover target.
var dst = this.findTarget(e.target);
if (!dst || dst === this.src) return;
this.dst = dst;
var dst = this.findTarget(e.target)
if (!dst || dst === this.src) return
this.dst = dst
var targetIndex = this.nodeIndex(this.dst),
srcIndex = this.nodeIndex(this.src);
if (targetIndex > srcIndex) this.parent.insertBefore(this.dst, this.src);
else this.parent.insertBefore(this.src, this.dst);
srcIndex = this.nodeIndex(this.src)
if (targetIndex > srcIndex) this.parent.insertBefore(this.dst, this.src)
else this.parent.insertBefore(this.src, this.dst)
},
onDragLeave: function (e) {
@ -537,24 +610,23 @@ L.U.Orderable = L.Evented.extend({
onDrop: function (e) {
// e.target is current target element.
if (e.stopPropagation) e.stopPropagation(); // Stops the browser from redirecting.
if (!this.dst) return;
if (e.stopPropagation) e.stopPropagation() // Stops the browser from redirecting.
if (!this.dst) return
this.fire('drop', {
src: this.src,
initialIndex: this.initialIndex,
finalIndex: this.nodeIndex(this.src),
dst: this.dst
});
return false;
dst: this.dst,
})
return false
},
onDragEnd: function (e) {
// e.target is the source node.
this.src.style.backgroundColor = this.srcBackgroundColor;
}
});
this.src.style.backgroundColor = this.srcBackgroundColor
},
})
L.LatLng.prototype.isValid = function () {
return !isNaN(this.lat) && !isNaN(this.lng);
return !isNaN(this.lat) && !isNaN(this.lng)
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,189 +1,199 @@
L.U.Icon = L.DivIcon.extend({
initialize: function(map, options) {
this.map = map;
initialize: function (map, options) {
this.map = map
var default_options = {
iconSize: null, // Made in css
iconUrl: this.map.getDefaultOption('iconUrl'),
feature: null
};
options = L.Util.extend({}, default_options, options);
L.Icon.prototype.initialize.call(this, options);
this.feature = this.options.feature;
feature: null,
}
options = L.Util.extend({}, default_options, options)
L.Icon.prototype.initialize.call(this, options)
this.feature = this.options.feature
if (this.feature && this.feature.isReadOnly()) {
this.options.className += ' readonly';
this.options.className += ' readonly'
}
},
_getIconUrl: function (name) {
var url;
if(this.feature && this.feature._getIconUrl(name)) url = this.feature._getIconUrl(name);
else url = this.options[name + 'Url'];
return this.formatUrl(url, this.feature);
var url
if (this.feature && this.feature._getIconUrl(name))
url = this.feature._getIconUrl(name)
else url = this.options[name + 'Url']
return this.formatUrl(url, this.feature)
},
_getColor: function () {
var color;
if(this.feature) color = this.feature.getOption('color');
else if (this.options.color) color = this.options.color;
else color = this.map.getDefaultOption('color');
return color;
var color
if (this.feature) color = this.feature.getOption('color')
else if (this.options.color) color = this.options.color
else color = this.map.getDefaultOption('color')
return color
},
formatUrl: function (url, feature) {
return L.Util.greedyTemplate(url || '', feature ? feature.extendedProperties() : {});
}
});
return L.Util.greedyTemplate(url || '', feature ? feature.extendedProperties() : {})
},
})
L.U.Icon.Default = L.U.Icon.extend({
default_options: {
iconAnchor: new L.Point(16, 40),
popupAnchor: new L.Point(0, -40),
tooltipAnchor: new L.Point(16, -24),
className: 'umap-div-icon'
className: 'umap-div-icon',
},
initialize: function(map, options) {
options = L.Util.extend({}, this.default_options, options);
L.U.Icon.prototype.initialize.call(this, map, options);
initialize: function (map, options) {
options = L.Util.extend({}, this.default_options, options)
L.U.Icon.prototype.initialize.call(this, map, options)
},
_setColor: function() {
var color = this._getColor();
this.elements.container.style.backgroundColor = color;
this.elements.arrow.style.borderTopColor = color;
_setColor: function () {
var color = this._getColor()
this.elements.container.style.backgroundColor = color
this.elements.arrow.style.borderTopColor = color
},
createIcon: function() {
this.elements = {};
this.elements.main = L.DomUtil.create('div');
this.elements.container = L.DomUtil.create('div', 'icon_container', this.elements.main);
this.elements.arrow = L.DomUtil.create('div', 'icon_arrow', this.elements.main);
var src = this._getIconUrl('icon');
createIcon: function () {
this.elements = {}
this.elements.main = L.DomUtil.create('div')
this.elements.container = L.DomUtil.create(
'div',
'icon_container',
this.elements.main
)
this.elements.arrow = L.DomUtil.create('div', 'icon_arrow', this.elements.main)
var src = this._getIconUrl('icon')
if (src) {
// An url.
if (src.indexOf('http') === 0 || src.indexOf('/') === 0 || src.indexOf('data:image') === 0) {
this.elements.img = L.DomUtil.create('img', null, this.elements.container);
this.elements.img.src = src;
if (
src.indexOf('http') === 0 ||
src.indexOf('/') === 0 ||
src.indexOf('data:image') === 0
) {
this.elements.img = L.DomUtil.create('img', null, this.elements.container)
this.elements.img.src = src
} else {
this.elements.span = L.DomUtil.create('span', null, this.elements.container)
this.elements.span.textContent = src;
this.elements.span.textContent = src
}
}
this._setColor();
this._setIconStyles(this.elements.main, 'icon');
return this.elements.main;
}
});
this._setColor()
this._setIconStyles(this.elements.main, 'icon')
return this.elements.main
},
})
L.U.Icon.Circle = L.U.Icon.extend({
initialize: function(map, options) {
initialize: function (map, options) {
var default_options = {
iconAnchor: new L.Point(6, 6),
popupAnchor: new L.Point(0, -6),
tooltipAnchor: new L.Point(6, 0),
className: 'umap-circle-icon'
};
options = L.Util.extend({}, default_options, options);
L.U.Icon.prototype.initialize.call(this, map, options);
},
_setColor: function() {
this.elements.main.style.backgroundColor = this._getColor();
},
createIcon: function() {
this.elements = {};
this.elements.main = L.DomUtil.create('div');
this.elements.main.innerHTML = '&nbsp;';
this._setColor();
this._setIconStyles(this.elements.main, 'icon');
return this.elements.main;
className: 'umap-circle-icon',
}
options = L.Util.extend({}, default_options, options)
L.U.Icon.prototype.initialize.call(this, map, options)
},
});
_setColor: function () {
this.elements.main.style.backgroundColor = this._getColor()
},
createIcon: function () {
this.elements = {}
this.elements.main = L.DomUtil.create('div')
this.elements.main.innerHTML = '&nbsp;'
this._setColor()
this._setIconStyles(this.elements.main, 'icon')
return this.elements.main
},
})
L.U.Icon.Drop = L.U.Icon.Default.extend({
default_options: {
iconAnchor: new L.Point(16, 42),
popupAnchor: new L.Point(0, -42),
tooltipAnchor: new L.Point(16, -24),
className: 'umap-drop-icon'
}
});
className: 'umap-drop-icon',
},
})
L.U.Icon.Ball = L.U.Icon.Default.extend({
default_options: {
iconAnchor: new L.Point(8, 30),
popupAnchor: new L.Point(0, -28),
tooltipAnchor: new L.Point(8, -23),
className: 'umap-ball-icon'
className: 'umap-ball-icon',
},
createIcon: function() {
this.elements = {};
this.elements.main = L.DomUtil.create('div');
this.elements.container = L.DomUtil.create('div', 'icon_container', this.elements.main);
this.elements.arrow = L.DomUtil.create('div', 'icon_arrow', this.elements.main);
this._setColor();
this._setIconStyles(this.elements.main, 'icon');
return this.elements.main;
createIcon: function () {
this.elements = {}
this.elements.main = L.DomUtil.create('div')
this.elements.container = L.DomUtil.create(
'div',
'icon_container',
this.elements.main
)
this.elements.arrow = L.DomUtil.create('div', 'icon_arrow', this.elements.main)
this._setColor()
this._setIconStyles(this.elements.main, 'icon')
return this.elements.main
},
_setColor: function() {
_setColor: function () {
var color = this._getColor('color'),
background;
background
if (L.Browser.ielt9) {
background = color;
}
else if (L.Browser.webkit) {
background = '-webkit-gradient( radial, 6 38%, 0, 6 38%, 8, from(white), to(' + color + ') )';
}
else {
background = 'radial-gradient(circle at 6px 38% , white -4px, ' + color + ' 8px) repeat scroll 0 0 transparent';
}
this.elements.container.style.background = background;
background = color
} else if (L.Browser.webkit) {
background =
'-webkit-gradient( radial, 6 38%, 0, 6 38%, 8, from(white), to(' + color + ') )'
} else {
background =
'radial-gradient(circle at 6px 38% , white -4px, ' +
color +
' 8px) repeat scroll 0 0 transparent'
}
this.elements.container.style.background = background
},
})
});
var _CACHE_COLOR = {};
var _CACHE_COLOR = {}
L.U.Icon.Cluster = L.DivIcon.extend({
options: {
iconSize: [40, 40]
iconSize: [40, 40],
},
initialize: function (datalayer, cluster) {
this.datalayer = datalayer;
this.cluster = cluster;
this.datalayer = datalayer
this.cluster = cluster
},
createIcon: function () {
var container = L.DomUtil.create('div', 'leaflet-marker-icon marker-cluster'),
div = L.DomUtil.create('div', '', container),
span = L.DomUtil.create('span', '', div),
backgroundColor = this.datalayer.getColor();
span.textContent = this.cluster.getChildCount();
div.style.backgroundColor = backgroundColor;
return container;
backgroundColor = this.datalayer.getColor()
span.textContent = this.cluster.getChildCount()
div.style.backgroundColor = backgroundColor
return container
},
computeTextColor: function (el) {
var color,
backgroundColor = this.datalayer.getColor();
backgroundColor = this.datalayer.getColor()
if (this.datalayer.options.cluster && this.datalayer.options.cluster.textColor) {
color = this.datalayer.options.cluster.textColor;
color = this.datalayer.options.cluster.textColor
}
if (!color) {
if (typeof _CACHE_COLOR[backgroundColor] === 'undefined') {
color = L.DomUtil.TextColorFromBackgroundColor(el);
_CACHE_COLOR[backgroundColor] = color;
color = L.DomUtil.TextColorFromBackgroundColor(el)
_CACHE_COLOR[backgroundColor] = color
} else {
color = _CACHE_COLOR[backgroundColor];
color = _CACHE_COLOR[backgroundColor]
}
}
return color;
}
});
return color
},
})

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,143 +1,196 @@
// Dedicated object so we can deal with a separate dirty status, and thus
// call the endpoint only when needed, saving one call at each save.
L.U.MapPermissions = L.Class.extend({
options: {
owner: null,
editors: [],
share_status: null,
edit_status: null
edit_status: null,
},
initialize: function (map) {
this.setOptions(map.options.permissions);
this.map = map;
this.setOptions(map.options.permissions)
this.map = map
var isDirty = false,
self = this;
self = this
try {
Object.defineProperty(this, 'isDirty', {
get: function () {
return isDirty;
return isDirty
},
set: function (status) {
isDirty = status;
if (status) self.map.isDirty = status;
}
});
}
catch (e) {
isDirty = status
if (status) self.map.isDirty = status
},
})
} catch (e) {
// Certainly IE8, which has a limited version of defineProperty
}
},
setOptions: function (options) {
this.options = L.Util.setOptions(this, options);
this.options = L.Util.setOptions(this, options)
},
isOwner: function () {
return this.map.options.user && this.map.options.permissions.owner && this.map.options.user.id == this.map.options.permissions.owner.id;
return (
this.map.options.user &&
this.map.options.permissions.owner &&
this.map.options.user.id == this.map.options.permissions.owner.id
)
},
isAnonymousMap: function () {
return !this.map.options.permissions.owner;
return !this.map.options.permissions.owner
},
getMap: function () {
return this.map;
return this.map
},
edit: function () {
if (!this.map.options.umap_id) return this.map.ui.alert({content: L._('Please save the map first'), level: 'info'});
if (!this.map.options.umap_id)
return this.map.ui.alert({
content: L._('Please save the map first'),
level: 'info',
})
var container = L.DomUtil.create('div', 'permissions-panel'),
fields = [],
title = L.DomUtil.create('h4', '', container);
title = L.DomUtil.create('h4', '', container)
if (this.isAnonymousMap()) {
if (this.options.anonymous_edit_url) {
var helpText = L._('Secret edit link is:<br>{link}', {link: this.options.anonymous_edit_url});
fields.push(['options.edit_status', {handler: 'IntSelect', label: L._('Who can edit'), selectOptions: this.map.options.anonymous_edit_statuses, helpText: helpText}]);
var helpText = L._('Secret edit link is:<br>{link}', {
link: this.options.anonymous_edit_url,
})
fields.push([
'options.edit_status',
{
handler: 'IntSelect',
label: L._('Who can edit'),
selectOptions: this.map.options.anonymous_edit_statuses,
helpText: helpText,
},
])
}
} else {
if (this.isOwner()) {
fields.push(['options.edit_status', {handler: 'IntSelect', label: L._('Who can edit'), selectOptions: this.map.options.edit_statuses}]);
fields.push(['options.share_status', {handler: 'IntSelect', label: L._('Who can view'), selectOptions: this.map.options.share_statuses}]);
fields.push(['options.owner', {handler: 'ManageOwner', label: L._("Map's owner")}]);
fields.push([
'options.edit_status',
{
handler: 'IntSelect',
label: L._('Who can edit'),
selectOptions: this.map.options.edit_statuses,
},
])
fields.push([
'options.share_status',
{
handler: 'IntSelect',
label: L._('Who can view'),
selectOptions: this.map.options.share_statuses,
},
])
fields.push([
'options.owner',
{ handler: 'ManageOwner', label: L._("Map's owner") },
])
}
fields.push(['options.editors', {handler: 'ManageEditors', label: L._("Map's editors")}]);
fields.push([
'options.editors',
{ handler: 'ManageEditors', label: L._("Map's editors") },
])
}
title.textContent = L._('Update permissions');
var builder = new L.U.FormBuilder(this, fields);
var form = builder.build();
container.appendChild(form);
title.textContent = L._('Update permissions')
var builder = new L.U.FormBuilder(this, fields)
var form = builder.build()
container.appendChild(form)
if (this.isAnonymousMap() && this.map.options.user) {
// We have a user, and this user has come through here, so they can edit the map, so let's allow to own the map.
// Note: real check is made on the back office anyway.
var advancedActions = L.DomUtil.createFieldset(container, L._('Advanced actions'));
var advancedButtons = L.DomUtil.create('div', 'button-bar', advancedActions);
var download = L.DomUtil.create('a', 'button', advancedButtons);
download.href = '#';
download.textContent = L._('Attach the map to my account');
L.DomEvent
.on(download, 'click', L.DomEvent.stop)
.on(download, 'click', this.attach, this);
var advancedActions = L.DomUtil.createFieldset(container, L._('Advanced actions'))
var advancedButtons = L.DomUtil.create('div', 'button-bar', advancedActions)
var download = L.DomUtil.create('a', 'button', advancedButtons)
download.href = '#'
download.textContent = L._('Attach the map to my account')
L.DomEvent.on(download, 'click', L.DomEvent.stop).on(
download,
'click',
this.attach,
this
)
}
this.map.ui.openPanel({data: {html: container}, className: 'dark'});
this.map.ui.openPanel({ data: { html: container }, className: 'dark' })
},
attach: function () {
this.map.post(this.getAttachUrl(), {
callback: function () {
this.options.owner = this.map.options.user;
this.map.ui.alert({content: L._("Map has been attached to your account"), level: 'info'});
this.map.ui.closePanel();
this.options.owner = this.map.options.user
this.map.ui.alert({
content: L._('Map has been attached to your account'),
level: 'info',
})
this.map.ui.closePanel()
},
context: this
context: this,
})
},
save: function () {
if (!this.isDirty) return this.map.continueSaving();
var formData = new FormData();
if (!this.isDirty) return this.map.continueSaving()
var formData = new FormData()
if (!this.isAnonymousMap() && this.options.editors) {
var editors = this.options.editors.map(function (u) {return u.id});
for (var i = 0; i < this.options.editors.length; i++) formData.append('editors', this.options.editors[i].id);
var editors = this.options.editors.map(function (u) {
return u.id
})
for (var i = 0; i < this.options.editors.length; i++)
formData.append('editors', this.options.editors[i].id)
}
if (this.isOwner() || this.isAnonymousMap()) formData.append('edit_status', this.options.edit_status);
if (this.isOwner() || this.isAnonymousMap())
formData.append('edit_status', this.options.edit_status)
if (this.isOwner()) {
formData.append('owner', this.options.owner && this.options.owner.id);
formData.append('share_status', this.options.share_status);
formData.append('owner', this.options.owner && this.options.owner.id)
formData.append('share_status', this.options.share_status)
}
this.map.post(this.getUrl(), {
data: formData,
context: this,
callback: function (data) {
this.commit();
this.isDirty = false;
this.map.continueSaving();
}
});
this.commit()
this.isDirty = false
this.map.continueSaving()
},
})
},
getUrl: function () {
return L.Util.template(this.map.options.urls.map_update_permissions, {'map_id': this.map.options.umap_id});
return L.Util.template(this.map.options.urls.map_update_permissions, {
map_id: this.map.options.umap_id,
})
},
getAttachUrl: function () {
return L.Util.template(this.map.options.urls.map_attach_owner, {'map_id': this.map.options.umap_id});
return L.Util.template(this.map.options.urls.map_attach_owner, {
map_id: this.map.options.umap_id,
})
},
addOwnerLink: function (element, container) {
if (this.options.owner && this.options.owner.name && this.options.owner.url) {
var ownerContainer = L.DomUtil.add(element, 'umap-map-owner', container, ' ' + L._('by') + ' '),
owner = L.DomUtil.create('a');
owner.href = this.options.owner.url;
owner.textContent = this.options.owner.name;
ownerContainer.appendChild(owner);
var ownerContainer = L.DomUtil.add(
element,
'umap-map-owner',
container,
' ' + L._('by') + ' '
),
owner = L.DomUtil.create('a')
owner.href = this.options.owner.url
owner.textContent = this.options.owner.name
ownerContainer.appendChild(owner)
}
},
commit: function () {
L.Util.extend(this.map.options.permissions, this.options);
}
});
L.Util.extend(this.map.options.permissions, this.options)
},
})

View file

@ -1,93 +1,97 @@
/* Shapes */
L.U.Popup = L.Popup.extend({
options: {
parseTemplate: true
parseTemplate: true,
},
initialize: function (feature) {
this.feature = feature;
this.container = L.DomUtil.create('div', 'umap-popup');
this.format();
L.Popup.prototype.initialize.call(this, {}, feature);
this.setContent(this.container);
this.feature = feature
this.container = L.DomUtil.create('div', 'umap-popup')
this.format()
L.Popup.prototype.initialize.call(this, {}, feature)
this.setContent(this.container)
},
format: function () {
var mode = this.feature.getOption('popupTemplate') || 'Default',
klass = L.U.PopupTemplate[mode] || L.U.PopupTemplate.Default;
this.content = new klass(this.feature, this.container);
this.content.render();
var els = this.container.querySelectorAll('img,iframe');
klass = L.U.PopupTemplate[mode] || L.U.PopupTemplate.Default
this.content = new klass(this.feature, this.container)
this.content.render()
var els = this.container.querySelectorAll('img,iframe')
for (var i = 0; i < els.length; i++) {
this.onElementLoaded(els[i]);
this.onElementLoaded(els[i])
}
if (!els.length && this.container.textContent.replace('\n', '') === '') {
this.container.innerHTML = '';
L.DomUtil.add('h3', '', this.container, this.feature.getDisplayName());
this.container.innerHTML = ''
L.DomUtil.add('h3', '', this.container, this.feature.getDisplayName())
}
},
onElementLoaded: function (el) {
L.DomEvent.on(el, 'load', function () {
this._updateLayout();
this._updatePosition();
this._adjustPan();
}, this);
}
});
L.DomEvent.on(
el,
'load',
function () {
this._updateLayout()
this._updatePosition()
this._adjustPan()
},
this
)
},
})
L.U.Popup.Large = L.U.Popup.extend({
options: {
maxWidth: 500,
className: 'umap-popup-large'
}
});
className: 'umap-popup-large',
},
})
L.U.Popup.Panel = L.U.Popup.extend({
options: {
zoomAnimation: false
zoomAnimation: false,
},
allButton: function () {
var button = L.DomUtil.create('li', '');
L.DomUtil.create('i', 'umap-icon-16 umap-list', button);
var label = L.DomUtil.create('span', '', button);
label.textContent = label.title = L._('See all');
L.DomEvent.on(button, 'click', this.feature.map.openBrowser, this.feature.map);
return button;
var button = L.DomUtil.create('li', '')
L.DomUtil.create('i', 'umap-icon-16 umap-list', button)
var label = L.DomUtil.create('span', '', button)
label.textContent = label.title = L._('See all')
L.DomEvent.on(button, 'click', this.feature.map.openBrowser, this.feature.map)
return button
},
update: function () {
this.feature.map.ui.openPanel({data: {html: this._content}, actions: [this.allButton()]});
this.feature.map.ui.openPanel({
data: { html: this._content },
actions: [this.allButton()],
})
},
onRemove: function (map) {
map.ui.closePanel();
L.U.Popup.prototype.onRemove.call(this, map);
map.ui.closePanel()
L.U.Popup.prototype.onRemove.call(this, map)
},
_initLayout: function () {this._container = L.DomUtil.create('span');},
_initLayout: function () {
this._container = L.DomUtil.create('span')
},
_updateLayout: function () {},
_updatePosition: function () {},
_adjustPan: function () {}
});
L.U.Popup.SimplePanel = L.U.Popup.Panel; // Retrocompat.
_adjustPan: function () {},
})
L.U.Popup.SimplePanel = L.U.Popup.Panel // Retrocompat.
/* Content templates */
L.U.PopupTemplate = {};
L.U.PopupTemplate = {}
L.U.PopupTemplate.Default = L.Class.extend({
initialize: function (feature, container) {
this.feature = feature;
this.container = container;
this.feature = feature
this.container = container
},
renderTitle: function () {},
@ -95,130 +99,141 @@ L.U.PopupTemplate.Default = L.Class.extend({
renderBody: function () {
var template = this.feature.getOption('popupContentTemplate'),
container = L.DomUtil.create('div', 'umap-popup-container'),
content = '', properties, center;
properties = this.feature.extendedProperties();
content = '',
properties,
center
properties = this.feature.extendedProperties()
// Resolve properties inside description
properties.description = L.Util.greedyTemplate(this.feature.properties.description || '', properties);
content = L.Util.greedyTemplate(template, properties);
content = L.Util.toHTML(content);
container.innerHTML = content;
return container;
properties.description = L.Util.greedyTemplate(
this.feature.properties.description || '',
properties
)
content = L.Util.greedyTemplate(template, properties)
content = L.Util.toHTML(content)
container.innerHTML = content
return container
},
renderFooter: function () {
if (this.feature.hasPopupFooter()) {
var footerContainer = L.DomUtil.create('div', 'umap-footer-container', this.container),
var footerContainer = L.DomUtil.create(
'div',
'umap-footer-container',
this.container
),
footer = L.DomUtil.create('ul', 'umap-popup-footer', footerContainer),
previousLi = L.DomUtil.create('li', 'previous', footer),
zoomLi = L.DomUtil.create('li', 'zoom', footer),
nextLi = L.DomUtil.create('li', 'next', footer),
next = this.feature.getNext(),
prev = this.feature.getPrevious();
if (next) nextLi.title = L._('Go to «{feature}»', {feature: next.properties.name || L._('next')});
if (prev) previousLi.title = L._('Go to «{feature}»', {feature: prev.properties.name || L._('previous')});
zoomLi.title = L._('Zoom to this feature');
prev = this.feature.getPrevious()
if (next)
nextLi.title = L._('Go to «{feature}»', {
feature: next.properties.name || L._('next'),
})
if (prev)
previousLi.title = L._('Go to «{feature}»', {
feature: prev.properties.name || L._('previous'),
})
zoomLi.title = L._('Zoom to this feature')
L.DomEvent.on(nextLi, 'click', function () {
if (next) next.zoomTo({callback: next.view});
});
if (next) next.zoomTo({ callback: next.view })
})
L.DomEvent.on(previousLi, 'click', function () {
if (prev) prev.zoomTo({callback: prev.view});
});
L.DomEvent.on(zoomLi, 'click', function () {
this.zoomTo();
}, this.feature);
if (prev) prev.zoomTo({ callback: prev.view })
})
L.DomEvent.on(
zoomLi,
'click',
function () {
this.zoomTo()
},
this.feature
)
}
},
render: function () {
var title = this.renderTitle();
if (title) this.container.appendChild(title);
var body = this.renderBody();
if (body) L.DomUtil.add('div', 'umap-popup-content', this.container, body);
this.renderFooter();
}
});
var title = this.renderTitle()
if (title) this.container.appendChild(title)
var body = this.renderBody()
if (body) L.DomUtil.add('div', 'umap-popup-content', this.container, body)
this.renderFooter()
},
})
L.U.PopupTemplate.BaseWithTitle = L.U.PopupTemplate.Default.extend({
renderTitle: function () {
var title;
var title
if (this.feature.getDisplayName()) {
title = L.DomUtil.create('h3', 'popup-title');
title.textContent = this.feature.getDisplayName();
title = L.DomUtil.create('h3', 'popup-title')
title.textContent = this.feature.getDisplayName()
}
return title;
}
});
return title
},
})
L.U.PopupTemplate.Table = L.U.PopupTemplate.BaseWithTitle.extend({
formatRow: function (key, value) {
if (value.indexOf('http') === 0) {
value = '<a href="' + value + '" target="_blank">' + value + '</a>';
value = '<a href="' + value + '" target="_blank">' + value + '</a>'
}
return value;
return value
},
addRow: function (container, key, value) {
var tr = L.DomUtil.create('tr', '', container);
L.DomUtil.add('th', '', tr, key);
L.DomUtil.add('td', '', tr, this.formatRow(key, value));
var tr = L.DomUtil.create('tr', '', container)
L.DomUtil.add('th', '', tr, key)
L.DomUtil.add('td', '', tr, this.formatRow(key, value))
},
renderBody: function () {
var table = L.DomUtil.create('table');
var table = L.DomUtil.create('table')
for (var key in this.feature.properties) {
if (typeof this.feature.properties[key] === 'object' || key === 'name') continue;
if (typeof this.feature.properties[key] === 'object' || key === 'name') continue
// TODO, manage links (url, mailto, wikipedia...)
this.addRow(table, key, L.Util.escapeHTML(this.feature.properties[key]).trim());
this.addRow(table, key, L.Util.escapeHTML(this.feature.properties[key]).trim())
}
return table;
}
});
return table
},
})
L.U.PopupTemplate.GeoRSSImage = L.U.PopupTemplate.BaseWithTitle.extend({
options: {
minWidth: 300,
maxWidth: 500,
className: 'umap-popup-large umap-georss-image'
className: 'umap-popup-large umap-georss-image',
},
renderBody: function () {
var container = L.DomUtil.create('a');
container.href = this.feature.properties.link;
container.target = '_blank';
var container = L.DomUtil.create('a')
container.href = this.feature.properties.link
container.target = '_blank'
if (this.feature.properties.img) {
var img = L.DomUtil.create('img', '', container);
img.src = this.feature.properties.img;
var img = L.DomUtil.create('img', '', container)
img.src = this.feature.properties.img
// Sadly, we are unable to override this from JS the clean way
// See https://github.com/Leaflet/Leaflet/commit/61d746818b99d362108545c151a27f09d60960ee#commitcomment-6061847
img.style.maxWidth = this.options.maxWidth + 'px';
img.style.maxHeight = this.options.maxWidth + 'px';
this.onElementLoaded(img);
img.style.maxWidth = this.options.maxWidth + 'px'
img.style.maxHeight = this.options.maxWidth + 'px'
this.onElementLoaded(img)
}
return container;
}
});
return container
},
})
L.U.PopupTemplate.GeoRSSLink = L.U.PopupTemplate.Default.extend({
options: {
className: 'umap-georss-link'
className: 'umap-georss-link',
},
renderBody: function () {
var title = this.renderTitle(this),
a = L.DomUtil.add('a');
a.href = this.feature.properties.link;
a.target = '_blank';
a.appendChild(title);
return a;
}
});
a = L.DomUtil.add('a')
a.href = this.feature.properties.link
a.target = '_blank'
a.appendChild(title)
return a
},
})

View file

@ -1,136 +1,140 @@
L.U.Slideshow = L.Class.extend({
statics: {
CLASSNAME: 'umap-slideshow-active'
CLASSNAME: 'umap-slideshow-active',
},
options: {
delay: 5000,
autoplay: false
autoplay: false,
},
initialize: function (map, options) {
this.setOptions(options);
this.map = map;
this._id = null;
this.setOptions(options)
this.map = map
this._id = null
var current = null, // current feature
self = this;
self = this
try {
Object.defineProperty(this, 'current', {
get: function () {
if (!current) {
var datalayer = this.defaultDatalayer();
if (datalayer) current = datalayer.getFeatureByIndex(0);
var datalayer = this.defaultDatalayer()
if (datalayer) current = datalayer.getFeatureByIndex(0)
}
return current;
return current
},
set: function (feature) {
current = feature;
}
});
}
catch (e) {
current = feature
},
})
} catch (e) {
// Certainly IE8, which has a limited version of defineProperty
}
try {
Object.defineProperty(this, 'next', {
get: function () {
if (!current) {
return self.current;
return self.current
}
return current.getNext();
}
});
}
catch (e) {
return current.getNext()
},
})
} catch (e) {
// Certainly IE8, which has a limited version of defineProperty
}
if (this.options.autoplay) {
this.map.onceDataLoaded(function () {
this.play();
}, this);
this.play()
}, this)
}
this.map.on('edit:enabled', function () {
this.stop();
}, this);
this.map.on(
'edit:enabled',
function () {
this.stop()
},
this
)
},
setOptions: function (options) {
L.setOptions(this, options);
this.timeSpinner();
L.setOptions(this, options)
this.timeSpinner()
},
defaultDatalayer: function () {
return this.map.findDataLayer(function (d) { return d.allowBrowse() && d.hasData(); });
return this.map.findDataLayer(function (d) {
return d.allowBrowse() && d.hasData()
})
},
timeSpinner: function () {
var time = parseInt(this.options.delay, 10);
if (!time) return;
var time = parseInt(this.options.delay, 10)
if (!time) return
var css = 'rotation ' + time / 1000 + 's infinite linear',
spinners = document.querySelectorAll('.umap-slideshow-toolbox .play .spinner');
spinners = document.querySelectorAll('.umap-slideshow-toolbox .play .spinner')
for (var i = 0; i < spinners.length; i++) {
spinners[i].style.animation = css;
spinners[i].style['-webkit-animation'] = css;
spinners[i].style['-moz-animation'] = css;
spinners[i].style['-o-animation'] = css;
spinners[i].style.animation = css
spinners[i].style['-webkit-animation'] = css
spinners[i].style['-moz-animation'] = css
spinners[i].style['-o-animation'] = css
}
},
resetSpinners: function () {
// Make that animnation is coordinated with user actions
var spinners = document.querySelectorAll('.umap-slideshow-toolbox .play .spinner'),
el, newOne;
el,
newOne
for (var i = 0; i < spinners.length; i++) {
el = spinners[i];
newOne = el.cloneNode(true);
el.parentNode.replaceChild(newOne, el);
el = spinners[i]
newOne = el.cloneNode(true)
el.parentNode.replaceChild(newOne, el)
}
},
play: function () {
if (this._id) return;
if (this.map.editEnabled || !this.map.options.slideshow.active) return;
L.DomUtil.addClass(document.body, L.U.Slideshow.CLASSNAME);
this._id = window.setInterval(L.bind(this.loop, this), this.options.delay);
this.resetSpinners();
this.loop();
if (this._id) return
if (this.map.editEnabled || !this.map.options.slideshow.active) return
L.DomUtil.addClass(document.body, L.U.Slideshow.CLASSNAME)
this._id = window.setInterval(L.bind(this.loop, this), this.options.delay)
this.resetSpinners()
this.loop()
},
loop: function () {
this.current = this.next;
this.step();
this.current = this.next
this.step()
},
pause: function () {
if (this._id) {
L.DomUtil.removeClass(document.body, L.U.Slideshow.CLASSNAME);
window.clearInterval(this._id);
this._id = null;
L.DomUtil.removeClass(document.body, L.U.Slideshow.CLASSNAME)
window.clearInterval(this._id)
this._id = null
}
},
stop: function () {
this.pause();
this.current = null;
this.pause()
this.current = null
},
forward: function () {
this.pause();
this.current = this.next;
this.step();
this.pause()
this.current = this.next
this.step()
},
backward: function () {
this.pause();
if (this.current) this.current = this.current.getPrevious();
this.step();
this.pause()
if (this.current) this.current = this.current.getPrevious()
this.step()
},
step: function () {
if(!this.current) return this.stop();
this.current.zoomTo({easing: this.options.easing});
this.current.view();
if (!this.current) return this.stop()
this.current.zoomTo({ easing: this.options.easing })
this.current.view()
},
renderToolbox: function (container) {
@ -138,27 +142,22 @@ L.U.Slideshow = L.Class.extend({
play = L.DomUtil.create('li', 'play', box),
stop = L.DomUtil.create('li', 'stop', box),
prev = L.DomUtil.create('li', 'prev', box),
next = L.DomUtil.create('li', 'next', box);
L.DomUtil.create('div', 'spinner', play);
play.title = L._('Start slideshow');
stop.title = L._('Stop slideshow');
next.title = L._('Zoom to the next');
prev.title = L._('Zoom to the previous');
next = L.DomUtil.create('li', 'next', box)
L.DomUtil.create('div', 'spinner', play)
play.title = L._('Start slideshow')
stop.title = L._('Stop slideshow')
next.title = L._('Zoom to the next')
prev.title = L._('Zoom to the previous')
var toggle = function () {
if (this._id) this.pause();
else this.play();
};
L.DomEvent.on(play, 'click', L.DomEvent.stop)
.on(play, 'click', toggle, this);
L.DomEvent.on(stop, 'click', L.DomEvent.stop)
.on(stop, 'click', this.stop, this);
L.DomEvent.on(prev, 'click', L.DomEvent.stop)
.on(prev, 'click', this.backward, this);
L.DomEvent.on(next, 'click', L.DomEvent.stop)
.on(next, 'click', this.forward, this);
container.appendChild(box);
this.timeSpinner();
return box;
if (this._id) this.pause()
else this.play()
}
});
L.DomEvent.on(play, 'click', L.DomEvent.stop).on(play, 'click', toggle, this)
L.DomEvent.on(stop, 'click', L.DomEvent.stop).on(stop, 'click', this.stop, this)
L.DomEvent.on(prev, 'click', L.DomEvent.stop).on(prev, 'click', this.backward, this)
L.DomEvent.on(next, 'click', L.DomEvent.stop).on(next, 'click', this.forward, this)
container.appendChild(box)
this.timeSpinner()
return box
},
})

View file

@ -1,17 +1,16 @@
L.U.TableEditor = L.Class.extend({
initialize: function (datalayer) {
this.datalayer = datalayer;
this.table = L.DomUtil.create('div', 'table');
this.header = L.DomUtil.create('div', 'thead', this.table);
this.body = L.DomUtil.create('div', 'tbody', this.table);
this.resetProperties();
this.datalayer = datalayer
this.table = L.DomUtil.create('div', 'table')
this.header = L.DomUtil.create('div', 'thead', this.table)
this.body = L.DomUtil.create('div', 'tbody', this.table)
this.resetProperties()
},
renderHeaders: function () {
this.header.innerHTML = '';
this.header.innerHTML = ''
for (var i = 0; i < this.properties.length; i++) {
this.renderHeader(this.properties[i]);
this.renderHeader(this.properties[i])
}
},
@ -19,89 +18,104 @@ L.U.TableEditor = L.Class.extend({
var container = L.DomUtil.create('div', 'tcell', this.header),
title = L.DomUtil.add('span', '', container, property),
del = L.DomUtil.create('i', 'umap-delete', container),
rename = L.DomUtil.create('i', 'umap-edit', container);
del.title = L._('Delete this property on all the features');
rename.title = L._('Rename this property on all the features');
rename = L.DomUtil.create('i', 'umap-edit', container)
del.title = L._('Delete this property on all the features')
rename.title = L._('Rename this property on all the features')
var doDelete = function () {
if (confirm(L._('Are you sure you want to delete this property on all the features?'))) {
if (
confirm(
L._('Are you sure you want to delete this property on all the features?')
)
) {
this.datalayer.eachLayer(function (feature) {
feature.deleteProperty(property);
});
this.datalayer.deindexProperty(property);
this.resetProperties();
this.edit();
feature.deleteProperty(property)
})
this.datalayer.deindexProperty(property)
this.resetProperties()
this.edit()
}
}
};
var doRename = function () {
var newName = prompt(L._('Please enter the new name of this property'), property);
if (!newName || !this.validateName(newName)) return;
var newName = prompt(L._('Please enter the new name of this property'), property)
if (!newName || !this.validateName(newName)) return
this.datalayer.eachLayer(function (feature) {
feature.renameProperty(property, newName);
});
this.datalayer.deindexProperty(property);
this.datalayer.indexProperty(newName);
this.resetProperties();
this.edit();
};
L.DomEvent.on(del, 'click', doDelete, this);
L.DomEvent.on(rename, 'click', doRename, this);
feature.renameProperty(property, newName)
})
this.datalayer.deindexProperty(property)
this.datalayer.indexProperty(newName)
this.resetProperties()
this.edit()
}
L.DomEvent.on(del, 'click', doDelete, this)
L.DomEvent.on(rename, 'click', doRename, this)
},
renderRow: function (feature) {
var builder = new L.U.FormBuilder(feature, this.field_properties,
{
var builder = new L.U.FormBuilder(feature, this.field_properties, {
id: 'umap-feature-properties_' + L.stamp(feature),
className: 'trow',
callback: feature.resetTooltip
}
);
this.body.appendChild(builder.build());
callback: feature.resetTooltip,
})
this.body.appendChild(builder.build())
},
compileProperties: function () {
if (this.properties.length === 0) this.properties = ['name'];
if (this.properties.length === 0) this.properties = ['name']
// description is a forced textarea, don't edit it in a text input, or you lose cariage returns
if (this.properties.indexOf('description') !== -1) this.properties.splice(this.properties.indexOf('description'), 1);
this.properties.sort();
this.field_properties = [];
if (this.properties.indexOf('description') !== -1)
this.properties.splice(this.properties.indexOf('description'), 1)
this.properties.sort()
this.field_properties = []
for (var i = 0; i < this.properties.length; i++) {
this.field_properties.push(['properties.' + this.properties[i], {wrapper: 'div', wrapperClass: 'tcell'}]);
this.field_properties.push([
'properties.' + this.properties[i],
{ wrapper: 'div', wrapperClass: 'tcell' },
])
}
},
resetProperties: function () {
this.properties = this.datalayer._propertiesIndex;
this.properties = this.datalayer._propertiesIndex
},
validateName: function (name) {
if (name.indexOf(".") !== -1) {
this.datalayer.map.ui.alert({content: L._('Invalide property name: {name}', {name: name}), level: 'error'});
return false;
if (name.indexOf('.') !== -1) {
this.datalayer.map.ui.alert({
content: L._('Invalide property name: {name}', { name: name }),
level: 'error',
})
return false
}
return true;
return true
},
edit: function () {
var id = 'tableeditor:edit';
this.datalayer.map.fire('dataloading', {id: id});
this.compileProperties();
this.renderHeaders();
this.body.innerHTML = '';
this.datalayer.eachLayer(this.renderRow, this);
var addButton = L.DomUtil.create('li', 'add-property');
L.DomUtil.create('i', 'umap-icon-16 umap-add', addButton);
var label = L.DomUtil.create('span', '', addButton);
label.textContent = label.title = L._('Add a new property');
var id = 'tableeditor:edit'
this.datalayer.map.fire('dataloading', { id: id })
this.compileProperties()
this.renderHeaders()
this.body.innerHTML = ''
this.datalayer.eachLayer(this.renderRow, this)
var addButton = L.DomUtil.create('li', 'add-property')
L.DomUtil.create('i', 'umap-icon-16 umap-add', addButton)
var label = L.DomUtil.create('span', '', addButton)
label.textContent = label.title = L._('Add a new property')
var addProperty = function () {
var newName = prompt(L._('Please enter the name of the property'));
if (!newName || !this.validateName(newName)) return;
this.datalayer.indexProperty(newName);
this.edit();
};
L.DomEvent.on(addButton, 'click', addProperty, this);
var className = (this.properties.length > 2) ? 'umap-table-editor fullwidth dark' : 'umap-table-editor dark';
this.datalayer.map.ui.openPanel({data: {html: this.table}, className: className, actions: [addButton]});
this.datalayer.map.fire('dataload', {id: id});
var newName = prompt(L._('Please enter the name of the property'))
if (!newName || !this.validateName(newName)) return
this.datalayer.indexProperty(newName)
this.edit()
}
});
L.DomEvent.on(addButton, 'click', addProperty, this)
var className =
this.properties.length > 2
? 'umap-table-editor fullwidth dark'
: 'umap-table-editor dark'
this.datalayer.map.ui.openPanel({
data: { html: this.table },
className: className,
actions: [addButton],
})
this.datalayer.map.fire('dataload', { id: id })
},
})

View file

@ -1,176 +1,209 @@
/*
* Modals
*/
* Modals
*/
L.U.UI = L.Evented.extend({
ALERTS: Array(),
ALERT_ID: null,
TOOLTIP_ID: null,
initialize: function (parent) {
this.parent = parent;
this.container = L.DomUtil.create('div', 'leaflet-ui-container', this.parent);
L.DomEvent.disableClickPropagation(this.container);
L.DomEvent.on(this.container, 'contextmenu', L.DomEvent.stopPropagation); // Do not activate our custom context menu.
L.DomEvent.on(this.container, 'mousewheel', L.DomEvent.stopPropagation);
L.DomEvent.on(this.container, 'MozMousePixelScroll', L.DomEvent.stopPropagation);
this._panel = L.DomUtil.create('div', '', this.container);
this._panel.id = 'umap-ui-container';
this._alert = L.DomUtil.create('div', 'with-transition', this.container);
this._alert.id = 'umap-alert-container';
this._tooltip = L.DomUtil.create('div', '', this.container);
this._tooltip.id = 'umap-tooltip-container';
this.parent = parent
this.container = L.DomUtil.create('div', 'leaflet-ui-container', this.parent)
L.DomEvent.disableClickPropagation(this.container)
L.DomEvent.on(this.container, 'contextmenu', L.DomEvent.stopPropagation) // Do not activate our custom context menu.
L.DomEvent.on(this.container, 'mousewheel', L.DomEvent.stopPropagation)
L.DomEvent.on(this.container, 'MozMousePixelScroll', L.DomEvent.stopPropagation)
this._panel = L.DomUtil.create('div', '', this.container)
this._panel.id = 'umap-ui-container'
this._alert = L.DomUtil.create('div', 'with-transition', this.container)
this._alert.id = 'umap-alert-container'
this._tooltip = L.DomUtil.create('div', '', this.container)
this._tooltip.id = 'umap-tooltip-container'
},
resetPanelClassName: function () {
this._panel.className = 'with-transition';
this._panel.className = 'with-transition'
},
openPanel: function (e) {
this.fire('panel:open');
this.fire('panel:open')
// We reset all because we can't know which class has been added
// by previous ui processes...
this.resetPanelClassName();
this._panel.innerHTML = '';
var actionsContainer = L.DomUtil.create('ul', 'toolbox', this._panel);
var body = L.DomUtil.create('div', 'body', this._panel);
if (e.data.html.nodeType && e.data.html.nodeType === 1) body.appendChild(e.data.html);
else body.innerHTML = e.data.html;
var closeLink = L.DomUtil.create('li', 'umap-close-link', actionsContainer);
L.DomUtil.add('i', 'umap-close-icon', closeLink);
var label = L.DomUtil.create('span', '', closeLink);
label.title = label.textContent = L._('Close');
this.resetPanelClassName()
this._panel.innerHTML = ''
var actionsContainer = L.DomUtil.create('ul', 'toolbox', this._panel)
var body = L.DomUtil.create('div', 'body', this._panel)
if (e.data.html.nodeType && e.data.html.nodeType === 1)
body.appendChild(e.data.html)
else body.innerHTML = e.data.html
var closeLink = L.DomUtil.create('li', 'umap-close-link', actionsContainer)
L.DomUtil.add('i', 'umap-close-icon', closeLink)
var label = L.DomUtil.create('span', '', closeLink)
label.title = label.textContent = L._('Close')
if (e.actions) {
for (var i = 0; i < e.actions.length; i++) {
actionsContainer.appendChild(e.actions[i]);
actionsContainer.appendChild(e.actions[i])
}
}
if (e.className) L.DomUtil.addClass(this._panel, e.className);
if (e.className) L.DomUtil.addClass(this._panel, e.className)
if (L.DomUtil.hasClass(this.parent, 'umap-ui')) {
// Already open.
this.fire('panel:ready');
this.fire('panel:ready')
} else {
L.DomEvent.once(this._panel, 'transitionend', function (e) {
this.fire('panel:ready');
}, this);
L.DomUtil.addClass(this.parent, 'umap-ui');
L.DomEvent.once(
this._panel,
'transitionend',
function (e) {
this.fire('panel:ready')
},
this
)
L.DomUtil.addClass(this.parent, 'umap-ui')
}
L.DomEvent.on(closeLink, 'click', this.closePanel, this);
L.DomEvent.on(closeLink, 'click', this.closePanel, this)
},
closePanel: function () {
this.resetPanelClassName();
L.DomUtil.removeClass(this.parent, 'umap-ui');
this.fire('panel:closed');
this.resetPanelClassName()
L.DomUtil.removeClass(this.parent, 'umap-ui')
this.fire('panel:closed')
},
alert: function (e) {
if (L.DomUtil.hasClass(this.parent, 'umap-alert')) this.ALERTS.push(e);
else this.popAlert(e);
if (L.DomUtil.hasClass(this.parent, 'umap-alert')) this.ALERTS.push(e)
else this.popAlert(e)
},
popAlert: function (e) {
var self = this;
if(!e) {
if (this.ALERTS.length) e = this.ALERTS.pop();
else return;
var self = this
if (!e) {
if (this.ALERTS.length) e = this.ALERTS.pop()
else return
}
var timeoutID,
level_class = e.level && e.level == 'info'? 'info': 'error';
this._alert.innerHTML = '';
L.DomUtil.addClass(this.parent, 'umap-alert');
L.DomUtil.addClass(this._alert, level_class);
level_class = e.level && e.level == 'info' ? 'info' : 'error'
this._alert.innerHTML = ''
L.DomUtil.addClass(this.parent, 'umap-alert')
L.DomUtil.addClass(this._alert, level_class)
var close = function () {
if (timeoutID !== this.ALERT_ID) { return;} // Another alert has been forced
this._alert.innerHTML = '';
L.DomUtil.removeClass(this.parent, 'umap-alert');
L.DomUtil.removeClass(this._alert, level_class);
if (timeoutID) window.clearTimeout(timeoutID);
this.popAlert();
};
var closeLink = L.DomUtil.create('a', 'umap-close-link', this._alert);
closeLink.href = '#';
L.DomUtil.add('i', 'umap-close-icon', closeLink);
var label = L.DomUtil.create('span', '', closeLink);
label.title = label.textContent = L._('Close');
L.DomEvent.on(closeLink, 'click', L.DomEvent.stop)
.on(closeLink, 'click', close, this);
L.DomUtil.add('div', '', this._alert, e.content);
if (timeoutID !== this.ALERT_ID) {
return
} // Another alert has been forced
this._alert.innerHTML = ''
L.DomUtil.removeClass(this.parent, 'umap-alert')
L.DomUtil.removeClass(this._alert, level_class)
if (timeoutID) window.clearTimeout(timeoutID)
this.popAlert()
}
var closeLink = L.DomUtil.create('a', 'umap-close-link', this._alert)
closeLink.href = '#'
L.DomUtil.add('i', 'umap-close-icon', closeLink)
var label = L.DomUtil.create('span', '', closeLink)
label.title = label.textContent = L._('Close')
L.DomEvent.on(closeLink, 'click', L.DomEvent.stop).on(
closeLink,
'click',
close,
this
)
L.DomUtil.add('div', '', this._alert, e.content)
if (e.actions) {
var action, el;
var action, el
for (var i = 0; i < e.actions.length; i++) {
action = e.actions[i];
el = L.DomUtil.element('a', {'className': 'umap-action'}, this._alert);
el.href = '#';
el.textContent = action.label;
L.DomEvent.on(el, 'click', L.DomEvent.stop)
.on(el, 'click', close, this);
if (action.callback) L.DomEvent.on(el, 'click', action.callback, action.callbackContext || this.map);
action = e.actions[i]
el = L.DomUtil.element('a', { className: 'umap-action' }, this._alert)
el.href = '#'
el.textContent = action.label
L.DomEvent.on(el, 'click', L.DomEvent.stop).on(el, 'click', close, this)
if (action.callback)
L.DomEvent.on(
el,
'click',
action.callback,
action.callbackContext || this.map
)
}
}
self.ALERT_ID = timeoutID = window.setTimeout(L.bind(close, this), e.duration || 3000);
self.ALERT_ID = timeoutID = window.setTimeout(
L.bind(close, this),
e.duration || 3000
)
},
tooltip: function (e) {
this.TOOLTIP_ID = Math.random();
var id = this.TOOLTIP_ID;
L.DomUtil.addClass(this.parent, 'umap-tooltip');
if (e.anchor && e.position === 'top') this.anchorTooltipTop(e.anchor);
else if (e.anchor && e.position === 'left') this.anchorTooltipLeft(e.anchor);
else this.anchorTooltipAbsolute();
this._tooltip.innerHTML = e.content;
function closeIt () { this.closeTooltip(id); }
if (e.anchor) L.DomEvent.once(e.anchor, 'mouseout', closeIt, this);
if (e.duration !== Infinity) window.setTimeout(L.bind(closeIt, this), e.duration || 3000);
this.TOOLTIP_ID = Math.random()
var id = this.TOOLTIP_ID
L.DomUtil.addClass(this.parent, 'umap-tooltip')
if (e.anchor && e.position === 'top') this.anchorTooltipTop(e.anchor)
else if (e.anchor && e.position === 'left') this.anchorTooltipLeft(e.anchor)
else this.anchorTooltipAbsolute()
this._tooltip.innerHTML = e.content
function closeIt() {
this.closeTooltip(id)
}
if (e.anchor) L.DomEvent.once(e.anchor, 'mouseout', closeIt, this)
if (e.duration !== Infinity)
window.setTimeout(L.bind(closeIt, this), e.duration || 3000)
},
anchorTooltipAbsolute: function () {
this._tooltip.className = '';
var left = this.parent.offsetLeft + (this.parent.clientWidth / 2) - (this._tooltip.clientWidth / 2),
top = this.parent.offsetTop + 75;
this.setTooltipPosition({top: top, left: left});
this._tooltip.className = ''
var left =
this.parent.offsetLeft +
this.parent.clientWidth / 2 -
this._tooltip.clientWidth / 2,
top = this.parent.offsetTop + 75
this.setTooltipPosition({ top: top, left: left })
},
anchorTooltipTop: function (el) {
this._tooltip.className = 'tooltip-top';
var coords = this.getPosition(el);
this.setTooltipPosition({left: coords.left - 10, bottom: this.getDocHeight() - coords.top + 11});
this._tooltip.className = 'tooltip-top'
var coords = this.getPosition(el)
this.setTooltipPosition({
left: coords.left - 10,
bottom: this.getDocHeight() - coords.top + 11,
})
},
anchorTooltipLeft: function (el) {
this._tooltip.className = 'tooltip-left';
var coords = this.getPosition(el);
this.setTooltipPosition({top: coords.top, right: document.documentElement.offsetWidth - coords.left + 11});
this._tooltip.className = 'tooltip-left'
var coords = this.getPosition(el)
this.setTooltipPosition({
top: coords.top,
right: document.documentElement.offsetWidth - coords.left + 11,
})
},
closeTooltip: function (id) {
if (id && id !== this.TOOLTIP_ID) return;
this._tooltip.innerHTML = '';
L.DomUtil.removeClass(this.parent, 'umap-tooltip');
if (id && id !== this.TOOLTIP_ID) return
this._tooltip.innerHTML = ''
L.DomUtil.removeClass(this.parent, 'umap-tooltip')
},
getPosition: function (el) {
return el.getBoundingClientRect();
return el.getBoundingClientRect()
},
setTooltipPosition: function (coords) {
if (coords.left) this._tooltip.style.left = coords.left + 'px';
else this._tooltip.style.left = 'initial';
if (coords.right) this._tooltip.style.right = coords.right + 'px';
else this._tooltip.style.right = 'initial';
if (coords.top) this._tooltip.style.top = coords.top + 'px';
else this._tooltip.style.top = 'initial';
if (coords.bottom) this._tooltip.style.bottom = coords.bottom + 'px';
else this._tooltip.style.bottom = 'initial';
if (coords.left) this._tooltip.style.left = coords.left + 'px'
else this._tooltip.style.left = 'initial'
if (coords.right) this._tooltip.style.right = coords.right + 'px'
else this._tooltip.style.right = 'initial'
if (coords.top) this._tooltip.style.top = coords.top + 'px'
else this._tooltip.style.top = 'initial'
if (coords.bottom) this._tooltip.style.bottom = coords.bottom + 'px'
else this._tooltip.style.bottom = 'initial'
},
getDocHeight: function () {
var D = document;
var D = document
return Math.max(
D.body.scrollHeight, D.documentElement.scrollHeight,
D.body.offsetHeight, D.documentElement.offsetHeight,
D.body.clientHeight, D.documentElement.clientHeight
);
D.body.scrollHeight,
D.documentElement.scrollHeight,
D.body.offsetHeight,
D.documentElement.offsetHeight,
D.body.clientHeight,
D.documentElement.clientHeight
)
},
});
})

View file

@ -1,146 +1,164 @@
L.U.Xhr = L.Evented.extend({
initialize: function (ui) {
this.ui = ui;
this.ui = ui
},
_wrapper: function () {
var wrapper;
var wrapper
if (window.XMLHttpRequest === undefined) {
wrapper = function() {
wrapper = function () {
try {
return new window.ActiveXObject('Microsoft.XMLHTTP.6.0');
}
catch (e1) {
return new window.ActiveXObject('Microsoft.XMLHTTP.6.0')
} catch (e1) {
try {
return new window.ActiveXObject('Microsoft.XMLHTTP.3.0');
}
catch (e2) {
throw new Error('XMLHttpRequest is not supported');
return new window.ActiveXObject('Microsoft.XMLHTTP.3.0')
} catch (e2) {
throw new Error('XMLHttpRequest is not supported')
}
}
};
}
else {
wrapper = window.XMLHttpRequest;
} else {
wrapper = window.XMLHttpRequest
}
return new wrapper();
return new wrapper()
},
_ajax: function (settings) {
var xhr = this._wrapper(), id = Math.random(), self = this;
this.fire('dataloading', {id: id});
var loaded = function () {self.fire('dataload', {id: id});};
var xhr = this._wrapper(),
id = Math.random(),
self = this
this.fire('dataloading', { id: id })
var loaded = function () {
self.fire('dataload', { id: id })
}
try {
xhr.open(settings.verb, settings.uri, true);
xhr.open(settings.verb, settings.uri, true)
} catch (err) {
// Unknown protocol?
this.ui.alert({content: L._('Error while fetching {url}', {url: settings.uri}), level: 'error'});
loaded();
this.ui.alert({
content: L._('Error while fetching {url}', { url: settings.uri }),
level: 'error',
})
loaded()
return
}
if (settings.uri.indexOf('http') !== 0 || settings.uri.indexOf(window.location.origin) === 0) {
if (
settings.uri.indexOf('http') !== 0 ||
settings.uri.indexOf(window.location.origin) === 0
) {
// "X-" mode headers cause the request to be in preflight mode,
// we don"t want that by default for CORS requests
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest')
}
if (settings.headers) {
for (var name in settings.headers) {
xhr.setRequestHeader(name, settings.headers[name]);
xhr.setRequestHeader(name, settings.headers[name])
}
}
xhr.onreadystatechange = function() {
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status == 200) {
settings.callback.call(settings.context || xhr, xhr.responseText, xhr);
}
else if (xhr.status === 403) {
self.ui.alert({content: xhr.responseText || L._('Action not allowed :('), level: 'error'});
}
else if (xhr.status === 412) {
var msg = L._('Woops! Someone else seems to have edited the data. You can save anyway, but this will erase the changes made by others.');
settings.callback.call(settings.context || xhr, xhr.responseText, xhr)
} else if (xhr.status === 403) {
self.ui.alert({
content: xhr.responseText || L._('Action not allowed :('),
level: 'error',
})
} else if (xhr.status === 412) {
var msg = L._(
'Woops! Someone else seems to have edited the data. You can save anyway, but this will erase the changes made by others.'
)
var actions = [
{
label: L._('Save anyway'),
callback: function () {
delete settings.headers['If-Match'];
self._ajax(settings);
delete settings.headers['If-Match']
self._ajax(settings)
},
callbackContext: self
callbackContext: self,
},
{
label: L._('Cancel')
}
];
self.ui.alert({content: msg, level: 'error', duration: 100000, actions: actions});
}
else {
if (xhr.status !== 0) { // 0 === request cut by user
self.ui.alert({'content': L._('Problem in the response'), 'level': 'error'});
label: L._('Cancel'),
},
]
self.ui.alert({
content: msg,
level: 'error',
duration: 100000,
actions: actions,
})
} else {
if (xhr.status !== 0) {
// 0 === request cut by user
self.ui.alert({ content: L._('Problem in the response'), level: 'error' })
}
}
loaded();
loaded()
}
}
};
try {
xhr.send(settings.data);
xhr.send(settings.data)
} catch (e) {
// Pass
loaded();
console.error('Bad Request', e);
loaded()
console.error('Bad Request', e)
}
},
// supports only JSON as response data type
_json: function (verb, uri, options) {
var args = arguments,
self = this;
self = this
var default_options = {
'async': true,
'callback': null,
'responseType': 'text',
'data': null,
'listen_form': null // optional form to listen in default callback
};
var settings = L.Util.extend({}, default_options, options);
async: true,
callback: null,
responseType: 'text',
data: null,
listen_form: null, // optional form to listen in default callback
}
var settings = L.Util.extend({}, default_options, options)
if (verb === 'POST') {
// find a way not to make this django specific
var token = document.cookie.replace(/(?:(?:^|.*;\s*)csrftoken\s*\=\s*([^;]*).*$)|^.*$/, '$1');
var token = document.cookie.replace(
/(?:(?:^|.*;\s*)csrftoken\s*\=\s*([^;]*).*$)|^.*$/,
'$1'
)
if (token) {
settings.headers = settings.headers || {};
settings.headers['X-CSRFToken'] = token;
settings.headers = settings.headers || {}
settings.headers['X-CSRFToken'] = token
}
}
var callback = function(responseText, response) {
var data;
var callback = function (responseText, response) {
var data
try {
data = JSON.parse(responseText);
}
catch (err) {
console.log(err);
self.ui.alert({content: L._('Problem in the response format'), level: 'error'});
return;
data = JSON.parse(responseText)
} catch (err) {
console.log(err)
self.ui.alert({
content: L._('Problem in the response format'),
level: 'error',
})
return
}
if (data.errors) {
console.log(data.errors);
self.ui.alert({content: L._('An error occured'), level: 'error'});
console.log(data.errors)
self.ui.alert({ content: L._('An error occured'), level: 'error' })
} else if (data.login_required) {
// login_required should be an URL for the login form
if (settings.login_callback) settings.login_callback(data);
else self.login(data, args);
if (settings.login_callback) settings.login_callback(data)
else self.login(data, args)
} else {
if (settings.callback)
L.bind(settings.callback, settings.context || this)(data, response)
else self.default_callback(data, settings, response)
}
else {
if (settings.callback) L.bind(settings.callback, settings.context || this)(data, response);
else self.default_callback(data, settings, response);
}
};
this._ajax({
verb: verb,
@ -148,138 +166,131 @@ L.U.Xhr = L.Evented.extend({
data: settings.data,
callback: callback,
headers: settings.headers,
listener: settings.listener
});
listener: settings.listener,
})
},
get: function(uri, options) {
this._json('GET', uri, options);
get: function (uri, options) {
this._json('GET', uri, options)
},
post: function(uri, options) {
this._json('POST', uri, options);
post: function (uri, options) {
this._json('POST', uri, options)
},
submit_form: function(form_id, options) {
if(typeof options === 'undefined') options = {};
var form = L.DomUtil.get(form_id);
var formData = new FormData(form);
if(options.extraFormData) formData.append(options.extraFormData);
options.data = formData;
this.post(form.action, options);
return false;
submit_form: function (form_id, options) {
if (typeof options === 'undefined') options = {}
var form = L.DomUtil.get(form_id)
var formData = new FormData(form)
if (options.extraFormData) formData.append(options.extraFormData)
options.data = formData
this.post(form.action, options)
return false
},
listen_form: function (form_id, options) {
var form = L.DomUtil.get(form_id), self = this;
if (!form) return;
L.DomEvent
.on(form, 'submit', L.DomEvent.stopPropagation)
var form = L.DomUtil.get(form_id),
self = this
if (!form) return
L.DomEvent.on(form, 'submit', L.DomEvent.stopPropagation)
.on(form, 'submit', L.DomEvent.preventDefault)
.on(form, 'submit', function () {
self.submit_form(form_id, options);
});
self.submit_form(form_id, options)
})
},
listen_link: function (link_id, options) {
var link = L.DomUtil.get(link_id), self = this;
var link = L.DomUtil.get(link_id),
self = this
if (link) {
L.DomEvent
.on(link, 'click', L.DomEvent.stop)
.on(link, 'click', function () {
if (options.confirm && !confirm(options.confirm)) { return;}
self.get(link.href, options);
});
L.DomEvent.on(link, 'click', L.DomEvent.stop).on(link, 'click', function () {
if (options.confirm && !confirm(options.confirm)) {
return
}
self.get(link.href, options)
})
}
},
default_callback: function (data, options) {
// default callback, to avoid boilerplate
if (data.redirect) {
var newPath = data.redirect;
if (window.location.pathname == newPath) window.location.reload(); // Keep the hash, so the current view
else window.location = newPath;
}
else if (data.info) {
this.ui.alert({content: data.info, level: 'info'});
this.ui.closePanel();
}
else if (data.error) {
this.ui.alert({content: data.error, level: 'error'});
}
else if (data.html) {
var ui_options = {'data': data},
listen_options;
if (options.className) ui_options.className = options.className;
this.ui.openPanel(ui_options);
var newPath = data.redirect
if (window.location.pathname == newPath)
window.location.reload() // Keep the hash, so the current view
else window.location = newPath
} else if (data.info) {
this.ui.alert({ content: data.info, level: 'info' })
this.ui.closePanel()
} else if (data.error) {
this.ui.alert({ content: data.error, level: 'error' })
} else if (data.html) {
var ui_options = { data: data },
listen_options
if (options.className) ui_options.className = options.className
this.ui.openPanel(ui_options)
// To low boilerplate, if there is a form, listen it
if (options.listen_form) {
// Listen form again
listen_options = L.Util.extend({}, options, options.listen_form.options);
this.listen_form(options.listen_form.id, listen_options);
listen_options = L.Util.extend({}, options, options.listen_form.options)
this.listen_form(options.listen_form.id, listen_options)
}
if (options.listen_link) {
for (var i=0, l=options.listen_link.length; i<l; i++) {
for (var i = 0, l = options.listen_link.length; i < l; i++) {
// Listen link again
listen_options = L.Util.extend({}, options, options.listen_link[i].options);
this.listen_link(options.listen_link[i].id, listen_options);
listen_options = L.Util.extend({}, options, options.listen_link[i].options)
this.listen_link(options.listen_link[i].id, listen_options)
}
}
}
else if (options.success) {
} else if (options.success) {
// Success is called only if data contain no msg and no html
options.success(data);
options.success(data)
}
},
login: function (data, args) {
// data.html: login form
// args: args of the first _json call, to call again at process end
var self = this;
var self = this
var proceed = function () {
self.ui.closePanel();
if (typeof args !== 'undefined') self._json.apply(self, args);
else self.default_callback(data, {});
};
var ask_for_login = function (data) {
self.ui.openPanel({'data': data, className: 'login-panel'});
self.listen_form('login_form', {
'callback': function (data) {
if (data.html) ask_for_login(data); // Problem in the login - ask again
else proceed();
self.ui.closePanel()
if (typeof args !== 'undefined') self._json.apply(self, args)
else self.default_callback(data, {})
}
});
var ask_for_login = function (data) {
self.ui.openPanel({ data: data, className: 'login-panel' })
self.listen_form('login_form', {
callback: function (data) {
if (data.html) ask_for_login(data) // Problem in the login - ask again
else proceed()
},
})
// Auth links
var links = document.getElementsByClassName('umap-login-popup');
var links = document.getElementsByClassName('umap-login-popup')
Object.keys(links).forEach(function (el) {
var link = links[el];
L.DomEvent
.on(link, 'click', L.DomEvent.stop)
.on(link, 'click', function () {
self.ui.closePanel();
var win = window.open(link.href);
var link = links[el]
L.DomEvent.on(link, 'click', L.DomEvent.stop).on(link, 'click', function () {
self.ui.closePanel()
var win = window.open(link.href)
window.umap_proceed = function () {
proceed();
win.close();
};
});
});
};
proceed()
win.close()
}
})
})
}
if (data.login_required) {
this.get(data.login_required, {
'callback': function (data) {
ask_for_login(data);
}
});
}
else {
ask_for_login(data);
callback: function (data) {
ask_for_login(data)
},
})
} else {
ask_for_login(data)
}
},
logout: function(url) {
this.get(url);
}
});
logout: function (url) {
this.get(url)
},
})