<!DOCTYPE html>
<html>
<head>
<link data-require="openlayers@*" data-semver="3.2.1" rel="stylesheet" href="http://openlayers.org/en/v3.2.1/css/ol.css" />
<script data-require="openlayers@*" data-semver="3.2.1" src="http://openlayers.org/en/v3.2.1/build/ol.js"></script>
<script data-require="jquery@*" data-semver="3.0.0" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.js"></script>
<link rel="stylesheet" href="ol3-contextmenu.css" />
<script src="ol3-contextmenu-debug.js"></script>
<script src="olContextMenu.js"></script>
<script src="utility.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
<title>Openlayer3 draw, edit and save data </title>
</head>
<body>
<h1>Openlayer3 draw, edit and save data </h1>
<div id="map" class="map"></div>
</body>
</html>
// Code goes here
var map;
var contextmenu;
var source = new ol.source.Vector({ wrapX: false });
var view = new ol.View({
center: [11560106.846765194,148975.76812780878],
zoom: 14
});
window.addEventListener('load', function () {
map = initMap();
});
function initMap() {
var attribution = new ol.control.Attribution({
collapsible: false
});
// create a vector layer used for editing
var stroke = new ol.style.Stroke({
color: 'red'
});
var textStroke = new ol.style.Stroke({
color: '#fff',
width: 3
});
var textFill = new ol.style.Fill({
color: '#000'
});
var vector = new ol.layer.Vector({
name: 'my_vectorlayer',
source: source,
style: (function () {
var textStroke = new ol.style.Stroke({
color: '#fff',
width: 3
});
var textFill = new ol.style.Fill({
color: '#000'
});
return function (feature, resolution) {
return [new ol.style.Style({
cursor: 'pointer',
text: new ol.style.Text({
font: '34px Calibri,sans-serif',
text: getAreaLabel(feature),
fill: textFill,
stroke: textStroke
}),
image: new ol.style.Circle({
radius: 7,
fill: new ol.style.Fill({
color: '#ff7733'
})
}),
fill: new ol.style.Fill({
color: 'rgba(255, 255, 255, 0.2)'
}),
stroke: new ol.style.Stroke({
color: '#ffcc33',
width: 2
})
})];
};
})()
});
// Create a map
map = new ol.Map({
layers: [
new ol.layer.Group({
'title': 'Base map',
layers: [
new ol.layer.Tile({
title: 'Base',
source: new ol.source.OSM(),
}),
vector
],
})
],
controls: ol.control.defaults({ attribution: false }).extend([attribution]),
target: 'map',
view: view
});
//create contextmenu
contextmenu = new ContextMenu({
width: 170,
default_items: true, //default_items are (for now) Zoom In/Zoom Out
items: StandardContextItems
});
map.addControl(contextmenu);
map.getViewport().addEventListener('contextmenu', function (e) {
e.preventDefault();
var offset = $(this).offset();
var mapX = e.x - offset.left;
var mapY = e.y - offset.top;
var clkfeatures = [];
map.forEachFeatureAtPixel([mapX, mapY], function (ft, layer) {
if(typeof ft.get('ModelName') !== 'undefined'){
if (!contains.call(clkfeatures, ft)){
clkfeatures.push(ft);
}
}
});
console.log('length : ' +clkfeatures.length);
if (clkfeatures.length > 1) {
contextmenu.clear();
contextmenu.extend(SelectorContextMenu);
} else if (clkfeatures.length == 1) {
contextmenu.clear();
var ID = clkfeatures[0].get('ID');
var ModelName = clkfeatures[0].get('OpenlayersMapType')
var FeatureContextMenu = [{
text: 'View',
callback: function (obj, map) {
handleFeatureContexMenuEvent2('view', ID, ModelName);
}
},
{
text: 'Edit',
callback: function (obj, map) {
handleFeatureContexMenuEvent2('edit', ID, ModelName);
}
},
{
text: 'EditArea',
callback: function (obj, map) {
handleFeatureContexMenuEvent2('editarea', ID, ModelName, mapX, mapY);
}
}];
contextmenu.extend(FeatureContextMenu);
}
else {
contextmenu.clear();
contextmenu.extend(StandardContextItems);
}
});
return map;
}
var draw; // global so we can remove it later
function addInteraction(value) {
if (value)
map.removeInteraction(draw);
if (value !== 'None') {
var geometryFunction, maxPoints;
if (value === 'Square') {
value = 'Circle';
geometryFunction = ol.interaction.Draw.createRegularPolygon(4);
} else if (value === 'Box') {
value = 'LineString';
maxPoints = 2;
geometryFunction = function (coordinates, geometry) {
if (!geometry) {
geometry = new ol.geom.Polygon(null);
}
var start = coordinates[0];
var end = coordinates[1];
geometry.setCoordinates([
[start, [start[0], end[1]], end, [end[0], start[1]], start]
]);
return geometry;
};
}
draw = new ol.interaction.Draw({
source: source,
type: /** @type {ol.geom.GeometryType} */ (value),
geometryFunction: geometryFunction,
maxPoints: maxPoints
});
map.addInteraction(draw);
draw.on('drawend', function(event) {
map.removeInteraction(draw);
var title = prompt( "Please provide the Area Title:", "untitled" );
event.feature.setProperties({
'id': title + GetID(),
'name': title,
'MapMarkerTitle': title,
'Display': title,
'ModelName': title,
'MapAreaLabelText': title
});
});
}
}
function getLongLatFromPoint(loc) {
return ol.proj.transform(loc, 'EPSG:3857', 'EPSG:4326')
}
function getAreaLabel(feature) {
if(typeof feature.get('ModelName') !== 'undefined') {
var title = feature.get('Display');
return title;
}
}
function handleFeatureContexMenuEvent2(option, ID, ModelName, x, y) {
contextmenu.clear();
if (option == 'edit') {
console.log('edit');
} else if (option == 'view') {
console.log('view');
} else if (option == 'editarea') {
console.log('editarea');
var AreaEditMenu = [
{
text: 'Save',
},
{
text: 'Cancel',
}
];
contextmenu.extend(AreaEditMenu);
}
}
/* Styles go here */
.map {
height: 600px;
width: 100%;
}
/**
* Custom Context Menu for Openlayers 3
* https://github.com/jonataswalker/ol3-contextmenu
* Version: v2.2.2
* Built: 2016-07-29T09:38:39-03:00
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.ContextMenu = factory());
}(this, function () { 'use strict';
var namespace = "ol-ctx-menu";
var container_class = "-container";
var separator_class = "-separator";
var submenu_class = "-submenu";
var hidden_class = "-hidden";
var icon_class = "-icon";
var zoom_in_class = "-zoom-in";
var zoom_out_class = "-zoom-out";
var ol_unselectable_class = "ol-unselectable";
/**
* @module utils
* All the helper functions needed in this project
*/
var utils = {
isNumeric: function isNumeric(str) {
return /^\d+$/.test(str);
},
classRegex: function classRegex(classname) {
return new RegExp(("(^|\\s+) " + classname + " (\\s+|$)"));
},
/**
* @param {Element|Array<Element>} element DOM node or array of nodes.
* @param {String|Array<String>} classname Class or array of classes.
* For example: 'class1 class2' or ['class1', 'class2']
* @param {Number|undefined} timeout Timeout to remove a class.
*/
addClass: function addClass(element, classname, timeout) {
var this$1 = this;
if (Array.isArray(element)) {
element.forEach(function (each) { this$1.addClass(each, classname); });
return;
}
var array = (Array.isArray(classname)) ? classname : classname.split(/\s+/);
var i = array.length;
while(i--) {
if (!this$1.hasClass(element, array[i])) {
this$1._addClass(element, array[i], timeout);
}
}
},
_addClass: function _addClass(el, c, timeout) {
var this$1 = this;
// use native if available
if (el.classList) {
el.classList.add(c);
} else {
el.className = (el.className +' '+ c).trim();
}
if (timeout && this.isNumeric(timeout)) {
window.setTimeout(function () { this$1._removeClass(el, c); }, timeout);
}
},
/**
* @param {Element|Array<Element>} element DOM node or array of nodes.
* @param {String|Array<String>} classname Class or array of classes.
* For example: 'class1 class2' or ['class1', 'class2']
* @param {Number|undefined} timeout Timeout to add a class.
*/
removeClass: function removeClass(element, classname, timeout) {
var this$1 = this;
if (Array.isArray(element)) {
element.forEach(function (each) { this$1.removeClass(each, classname, timeout); });
return;
}
var array = (Array.isArray(classname)) ? classname : classname.split(/\s+/);
var i = array.length;
while(i--) {
if (this$1.hasClass(element, array[i])) {
this$1._removeClass(element, array[i], timeout);
}
}
},
_removeClass: function _removeClass(el, c, timeout) {
var this$1 = this;
if (el.classList) {
el.classList.remove(c);
} else {
el.className = (el.className.replace(this.classRegex(c), ' ')).trim();
}
if (timeout && this.isNumeric(timeout)) {
window.setTimeout(function () {
this$1._addClass(el, c);
}, timeout);
}
},
/**
* @param {Element} element DOM node.
* @param {String} classname Classname.
* @return {Boolean}
*/
hasClass: function hasClass(element, c) {
// use native if available
return (element.classList) ?
element.classList.contains(c) : this.classRegex(c).test(element.className);
},
/**
* @param {Element|Array<Element>} element DOM node or array of nodes.
* @param {String} classname Classe.
*/
toggleClass: function toggleClass(element, classname) {
var this$1 = this;
if (Array.isArray(element)) {
element.forEach(function (each) { this$1.toggleClass(each, classname); });
return;
}
// use native if available
if (element.classList) {
element.classList.toggle(classname);
} else {
if (this.hasClass(element, classname)) {
this._removeClass(element, classname);
} else {
this._addClass(element, classname);
}
}
},
$: function $(id) {
id = (id[0] === '#') ? id.substr(1, id.length) : id;
return document.getElementById(id);
},
isElement: function isElement(obj) {
// DOM, Level2
if ('HTMLElement' in window) {
return (!!obj && obj instanceof HTMLElement);
}
// Older browsers
return (!!obj && typeof obj === 'object' &&
obj.nodeType === 1 && !!obj.nodeName);
},
/**
* Abstraction to querySelectorAll for increased
* performance and greater usability
* @param {String} selector
* @param {Element} context (optional)
* @param {Boolean} find_all (optional)
* @return (find_all) {Element} : {Array}
*/
find: function(selector, context, find_all){
if ( context === void 0 ) context = window.document;
var simpleRe = /^(#?[\w-]+|\.[\w-.]+)$/,
periodRe = /\./g,
slice = Array.prototype.slice,
matches = [];
// Redirect call to the more performant function
// if it's a simple selector and return an array
// for easier usage
if(simpleRe.test(selector)){
switch(selector[0]){
case '#':
matches = [this.$(selector.substr(1))];
break;
case '.':
matches = slice.call(context.getElementsByClassName(
selector.substr(1).replace(periodRe, ' ')));
break;
default:
matches = slice.call(context.getElementsByTagName(selector));
}
} else{
// If not a simple selector, query the DOM as usual
// and return an array for easier usage
matches = slice.call(context.querySelectorAll(selector));
}
return (find_all) ? matches : matches[0];
},
getAllChildren: function getAllChildren(node, tag) {
return [].slice.call(node.getElementsByTagName(tag));
},
isEmpty: function isEmpty(str) {
return (!str || 0 === str.length);
},
emptyArray: function emptyArray(array) {
while(array.length) array.pop();
},
removeAllChildren: function removeAllChildren(node) {
while (node.firstChild) {
node.removeChild(node.firstChild);
}
},
/**
* Overwrites obj1's values with obj2's and adds
* obj2's if non existent in obj1
* @returns obj3 a new object based on obj1 and obj2
*/
mergeOptions: function mergeOptions(obj1, obj2) {
var obj3 = {};
for (var attr1 in obj1) { obj3[attr1] = obj1[attr1]; }
for (var attr2 in obj2) { obj3[attr2] = obj2[attr2]; }
return obj3;
},
createFragment: function createFragment(html) {
var frag = document.createDocumentFragment(),
temp = document.createElement('div');
temp.innerHTML = html;
while (temp.firstChild) {
frag.appendChild(temp.firstChild);
}
return frag;
},
/**
* Does str contain test?
* @param {String} str_test
* @param {String} str
* @returns Boolean
*/
contains: function contains(str_test, str) {
return !!~str.indexOf(str_test);
},
isDefAndNotNull: function isDefAndNotNull(val) {
// Note that undefined == null.
return val != null;
},
assertEqual: function assertEqual(a, b, message) {
if (a != b) {
throw new Error(message + ' mismatch: ' + a + ' != ' + b);
}
},
assert: function assert(condition, message) {
if ( message === void 0 ) message = 'Assertion failed';
if (!condition) {
if (typeof Error !== 'undefined') {
throw new Error(message);
}
throw message; // Fallback
}
},
events: function events() {
var topics = {};
var hOP = topics.hasOwnProperty;
return {
subscribe: function(topic, listener) {
// Create the topic's object if not yet created
if(!hOP.call(topics, topic)) topics[topic] = [];
// Add the listener to queue
var index = topics[topic].push(listener) -1;
// Provide handle back for removal of topic
return {
remove: function() {
delete topics[topic][index];
}
};
},
publish: function(topic, info) {
// If the topic doesn't exist, or there's no listeners
// in queue, just leave
if(!hOP.call(topics, topic)) return;
// Cycle through topics queue, fire!
topics[topic].forEach(function (item) {
item(info !== undefined ? info : {});
});
}
};
}
};
var eventType = {
/**
* Triggered before context menu is openned.
*/
BEFOREOPEN: 'beforeopen',
/**
* Triggered when context menu is openned.
*/
OPEN: 'open',
/**
* Triggered when context menu is closed.
*/
CLOSE: 'close',
/**
* Internal. Triggered when a menu entry is added.
*/
ADD_MENU_ENTRY: 'add-menu-entry'
};
var defaultOptions = {
width: 150,
default_items: true
};
// internal pub/sub
var events = utils.events();
var defaultItems = [
{
text: 'Zoom In',
classname: [
namespace + zoom_in_class,
namespace + icon_class
].join(' '),
callback: function(obj, map){
var
view = map.getView(),
pan = ol.animation.pan({
duration: 1000,
source: view.getCenter()
}),
zoom = ol.animation.zoom({
duration: 1000,
resolution: view.getResolution()
})
;
map.beforeRender(pan, zoom);
view.setCenter(obj.coordinate);
view.setZoom(+view.getZoom() + 1);
}
},
{
text: 'Zoom Out',
classname: [
namespace + zoom_out_class,
namespace + icon_class
].join(' '),
callback: function(obj, map){
var
view = map.getView(),
pan = ol.animation.pan({
duration: 1000,
source: view.getCenter()
}),
zoom = ol.animation.zoom({
duration: 1000,
resolution: view.getResolution()
})
;
map.beforeRender(pan, zoom);
view.setCenter(obj.coordinate);
view.setZoom(+view.getZoom() - 1);
}
}
];
/**
* @class Internal
*/
var Internal = function Internal(base) {
this.Base = base;
this.map = undefined;
this.coordinate_clicked = undefined;
this.pixel_clicked = undefined;
this.counter = 0;
this.lineHeight = 0;
this.items = {};
this.submenu = {
left: this.Base.options.width - 15 + 'px',
last_left: '' // string + px
};
return this;
};
Internal.prototype.init = function init (map) {
this.map = map;
// subscribe
this.setListeners();
// publish
this.Base.constructor.Html.createMenu();
this.lineHeight = this.getItemsLength() > 0 ?
this.Base.container.offsetHeight / this.getItemsLength() :
this.Base.constructor.Html.cloneAndGetLineHeight();
};
Internal.prototype.getItemsLength = function getItemsLength () {
var this$1 = this;
var count = 0;
Object.keys(this.items).forEach(function (k) {
if (this$1.items[k].submenu || this$1.items[k].separator) return;
count++;
});
return count;
};
Internal.prototype.getPixelClicked = function getPixelClicked () {
return this.pixel_clicked;
};
Internal.prototype.getCoordinateClicked = function getCoordinateClicked () {
return this.coordinate_clicked;
};
Internal.prototype.positionContainer = function positionContainer (pixel) {
var this$1 = this;
var map_size = this.map.getSize(),
map_w = map_size[0],
map_h = map_size[1],
// how much (width) space left over
space_left_h = map_h - pixel[1],
// how much (height) space left over
space_left_w = map_w - pixel[0],
menu_size = {
w: this.Base.container.offsetWidth,
// a cheap way to recalculate container height
// since offsetHeight is like cached
h: Math.round(this.lineHeight * this.getItemsLength())
},
// submenus <ul>
uls = utils.find('li.' + namespace + submenu_class + '>ul',
this.Base.container, true);
if (space_left_w >= menu_size.w) {
this.Base.container.style.right = 'auto';
this.Base.container.style.left = (pixel[0] + 5) + "px";
} else {
this.Base.container.style.left = 'auto';
this.Base.container.style.right = '15px';
}
// set top or bottom
if (space_left_h >= menu_size.h) {
this.Base.container.style.bottom = 'auto';
this.Base.container.style.top = (pixel[1] - 10) + "px";
} else {
this.Base.container.style.top = 'auto';
this.Base.container.style.bottom = 0;
}
utils.removeClass(this.Base.container, namespace + hidden_class);
if (uls.length) {
if (space_left_w < (menu_size.w * 2)) {
// no space (at right) for submenu
// position them at left
this.submenu.last_left = "-" + (menu_size.w) + "px";
} else {
this.submenu.last_left = this.submenu.left;
}
uls.forEach(function (ul) {
ul.style.left = this$1.submenu.last_left;
});
}
};
Internal.prototype.openMenu = function openMenu (pixel, coordinate) {
this.positionContainer(pixel);
this.Base.dispatchEvent({
type: eventType.OPEN,
pixel: pixel,
coordinate: coordinate
});
};
Internal.prototype.closeMenu = function closeMenu () {
utils.addClass(this.Base.container, namespace + hidden_class);
this.Base.dispatchEvent({
type: eventType.CLOSE
});
};
Internal.prototype.getNextItemIndex = function getNextItemIndex () {
return ++this.counter;
};
Internal.prototype.setListeners = function setListeners () {
var this_ = this,
map = this.map,
canvas = map.getTargetElement(),
menu = function(evt) {
this_.coordinate_clicked = map.getEventCoordinate(evt);
this_.pixel_clicked = map.getEventPixel(evt);
this_.Base.dispatchEvent({
type: eventType.BEFOREOPEN,
pixel: this_.pixel_clicked,
coordinate: this_.coordinate_clicked
});
if (this_.Base.disabled) {
return;
}
evt.stopPropagation();
evt.preventDefault();
this_.openMenu(this_.pixel_clicked, this_.coordinate_clicked);
//one-time fire
canvas.addEventListener('mousedown', {
handleEvent: function (evt) {
this_.closeMenu();
canvas.removeEventListener(evt.type, this, false);
}
}, false);
};
canvas.addEventListener('contextmenu', menu, false);
// subscribe to later menu entries
events.subscribe(eventType.ADD_MENU_ENTRY, function (obj) {
this_.setItemListener(obj.element, obj.index);
});
};
Internal.prototype.setItemListener = function setItemListener (li, index) {
var this_ = this;
if(li && typeof this.items[index].callback === 'function') {
(function(callback){
li.addEventListener('click', function(evt){
evt.preventDefault();
var obj = {
coordinate: this_.getCoordinateClicked(),
data: this_.items[index].data || null
};
this_.closeMenu();
callback.call(undefined, obj, this_.map);
}, false);
})(this.items[index].callback);
}
};
/**
* @class Html
*/
var Html = function Html(base) {
this.Base = base;
this.Base.container = this.container = this.createContainer();
return this;
};
Html.prototype.createContainer = function createContainer () {
var container = document.createElement('ul');
container.className = [
namespace + container_class,
namespace + hidden_class,
ol_unselectable_class
].join(' ');
container.style.width = parseInt(this.Base.options.width, 10) + 'px';
return container;
};
Html.prototype.createMenu = function createMenu () {
var options = this.Base.options, items = [];
if ('items' in options) {
items = (options.default_items) ?
options.items.concat(defaultItems) : options.items;
} else if (options.default_items) {
items = defaultItems;
}
// no item
if(items.length === 0) return false;
// create entries
items.forEach(this.addMenuEntry, this);
};
Html.prototype.addMenuEntry = function addMenuEntry (item) {
var this$1 = this;
var $internal = this.Base.constructor.Internal;
var index = $internal.getNextItemIndex();
var submenu_class$$ = namespace + submenu_class;
if (item.items && Array.isArray(item.items)) {
// submenu - only a second level
item.classname = item.classname || '';
if (!utils.contains(submenu_class$$, item.classname)) {
item.classname =
item.classname.length > 0 ? ' ' + submenu_class$$ : submenu_class$$;
}
var li = this.generateHtmlAndPublish(this.container, item, index);
var ul = document.createElement('ul');
ul.className = namespace + container_class;
ul.style.left = $internal.submenu.last_left || $internal.submenu.left;
ul.style.width = this.Base.options.width + 'px';
li.appendChild(ul);
item.items.forEach(function (each) {
this$1.generateHtmlAndPublish(ul, each, $internal.getNextItemIndex(), true);
});
} else {
this.generateHtmlAndPublish(this.container, item, index);
}
};
Html.prototype.generateHtmlAndPublish = function generateHtmlAndPublish (parent, item, index, submenu) {
var html, frag, element, separator = false;
var $internal = this.Base.constructor.Internal;
// separator
if (typeof item === 'string' && item.trim() == '-') {
html = [
'<li id="index',
index,
'" class="',
namespace,
separator_class,
'"><hr></li>'
].join('');
frag = utils.createFragment(html);
// http://stackoverflow.com/a/13347298/4640499
element = [].slice.call(frag.childNodes, 0)[0];
parent.appendChild(frag);
// to exclude from lineHeight calculation
separator = true;
} else {
item.classname = item.classname || '';
html = '<span>'+ item.text +'</span>';
frag = utils.createFragment(html);
element = document.createElement('li');
if (item.icon) {
if (item.classname === '') {
item.classname = namespace + icon_class;
} else if (item.classname.indexOf(namespace + icon_class) === -1) {
item.classname += ' ' + namespace + icon_class;
}
element.setAttribute('style', 'background-image:url('+ item.icon +')');
}
element.id = 'index' + index;
element.className = item.classname;
element.appendChild(frag);
parent.appendChild(element);
}
$internal.items[index] = {
id: index,
submenu: submenu || 0,
separator: separator,
callback: item.callback,
data: item.data || null
};
// publish to add listener
events.publish(eventType.ADD_MENU_ENTRY, {
index: index,
element: element
});
return element;
};
Html.prototype.removeMenuEntry = function removeMenuEntry (index) {
var element = utils.find('#index' + index, this.container);
if (element) {
this.container.removeChild(element);
}
delete this.Base.constructor.Internal.items[index];
};
Html.prototype.cloneAndGetLineHeight = function cloneAndGetLineHeight () {
// for some reason I have to calculate with 2 items
var cloned = this.container.cloneNode();
var frag = utils.createFragment('<span>Foo</span>');
var frag2 = utils.createFragment('<span>Foo</span>');
var element = document.createElement('li');
var element2 = document.createElement('li');
element.appendChild(frag);
element2.appendChild(frag2);
cloned.appendChild(element);
cloned.appendChild(element2);
this.container.parentNode.appendChild(cloned);
var height = cloned.offsetHeight / 2;
this.container.parentNode.removeChild(cloned);
return height;
};
/**
* @class Base
* @extends {ol.control.Control}
*/
var Base = (function (superclass) {
function Base(opt_options) {
if ( opt_options === void 0 ) opt_options = {};
utils.assert(typeof opt_options == 'object',
'@param `opt_options` should be object type!'
);
this.options = utils.mergeOptions(defaultOptions, opt_options);
this.disabled = false;
Base.Internal = new Internal(this);
Base.Html = new Html(this);
superclass.call(this, {
element: this.container
});
}
if ( superclass ) Base.__proto__ = superclass;
Base.prototype = Object.create( superclass && superclass.prototype );
Base.prototype.constructor = Base;
/**
* Remove all elements from the menu.
*/
Base.prototype.clear = function clear () {
console.info(Base.Internal.items);
Object.keys(Base.Internal.items).forEach(function (k) {
Base.Html.removeMenuEntry(k);
});
};
/**
* Close the menu programmatically.
*/
Base.prototype.close = function close () {
Base.Internal.closeMenu();
};
/**
* Enable menu
*/
Base.prototype.enable = function enable () {
this.disabled = false;
};
/**
* Disable menu
*/
Base.prototype.disable = function disable () {
this.disabled = true;
};
/**
* @return {Array} Returns default items
*/
Base.prototype.getDefaultItems = function getDefaultItems () {
return defaultItems;
};
/**
* Add items to the menu. This pushes each item in the provided array
* to the end of the menu.
* @param {Array} arr Array.
*/
Base.prototype.extend = function extend (arr) {
utils.assert(Array.isArray(arr), '@param `arr` should be an Array.');
arr.forEach(this.push, this);
};
/**
* Remove the last item of the menu.
*/
Base.prototype.pop = function pop () {
var keys = Object.keys(Base.Internal.items);
Base.Html.removeMenuEntry(keys[keys.length - 1]);
};
/**
* Insert the provided item at the end of the menu.
* @param {Object|String} item Item.
*/
Base.prototype.push = function push (item) {
utils.assert(utils.isDefAndNotNull(item), '@param `item` must be informed.');
Base.Html.addMenuEntry(item, Base.Internal.getNextItemIndex());
};
/**
* Remove the first item of the menu.
*/
Base.prototype.shift = function shift () {
Base.Html.removeMenuEntry(Object.keys(Base.Internal.items)[0]);
};
/**
* Not supposed to be used on app.
*/
Base.prototype.setMap = function setMap (map) {
ol.control.Control.prototype.setMap.call(this, map);
//http://gis.stackexchange.com/a/136850/50718
// let's start since now we have the map
Base.Internal.init(map);
};
return Base;
}(ol.control.Control));
return Base;
}));
/**
* Custom Context Menu for Openlayers 3
* https://github.com/jonataswalker/ol3-contextmenu
* Version: v2.2.2
* Built: 2016-07-29T09:38:39-03:00
*/
.ol-ctx-menu-container {
position: absolute;
padding: 10px;
list-style: none;
background: #fff;
color: #222;
font-size: 13px;
border-radius: 5px;
box-shadow: rgba(0, 0, 0, 0.2) 3px 3px 5px;
box-sizing: border-box; }
.ol-ctx-menu-container div, .ol-ctx-menu-container span, .ol-ctx-menu-container applet, .ol-ctx-menu-container object, .ol-ctx-menu-container iframe,
.ol-ctx-menu-container h1, .ol-ctx-menu-container h2, .ol-ctx-menu-container h3, .ol-ctx-menu-container h4, .ol-ctx-menu-container h5, .ol-ctx-menu-container h6, .ol-ctx-menu-container p, .ol-ctx-menu-container blockquote, .ol-ctx-menu-container pre,
.ol-ctx-menu-container a, .ol-ctx-menu-container abbr, .ol-ctx-menu-container acronym, .ol-ctx-menu-container address, .ol-ctx-menu-container big, .ol-ctx-menu-container cite, .ol-ctx-menu-container code,
.ol-ctx-menu-container del, .ol-ctx-menu-container dfn, .ol-ctx-menu-container em, .ol-ctx-menu-container img, .ol-ctx-menu-container ins, .ol-ctx-menu-container kbd, .ol-ctx-menu-container q, .ol-ctx-menu-container s, .ol-ctx-menu-container samp,
.ol-ctx-menu-container small, .ol-ctx-menu-container strike, .ol-ctx-menu-container strong, .ol-ctx-menu-container sub, .ol-ctx-menu-container sup, .ol-ctx-menu-container tt, .ol-ctx-menu-container var,
.ol-ctx-menu-container b, .ol-ctx-menu-container u, .ol-ctx-menu-container i, .ol-ctx-menu-container center,
.ol-ctx-menu-container dl, .ol-ctx-menu-container dt, .ol-ctx-menu-container dd, .ol-ctx-menu-container ol, .ol-ctx-menu-container ul, .ol-ctx-menu-container li,
.ol-ctx-menu-container fieldset, .ol-ctx-menu-container form, .ol-ctx-menu-container label, .ol-ctx-menu-container legend,
.ol-ctx-menu-container table, .ol-ctx-menu-container caption, .ol-ctx-menu-container tbody, .ol-ctx-menu-container tfoot, .ol-ctx-menu-container thead, .ol-ctx-menu-container tr, .ol-ctx-menu-container th, .ol-ctx-menu-container td,
.ol-ctx-menu-container article, .ol-ctx-menu-container aside, .ol-ctx-menu-container canvas, .ol-ctx-menu-container details, .ol-ctx-menu-container embed,
.ol-ctx-menu-container figure, .ol-ctx-menu-container figcaption, .ol-ctx-menu-container footer, .ol-ctx-menu-container header, .ol-ctx-menu-container hgroup,
.ol-ctx-menu-container menu, .ol-ctx-menu-container nav, .ol-ctx-menu-container output, .ol-ctx-menu-container ruby, .ol-ctx-menu-container section, .ol-ctx-menu-container summary,
.ol-ctx-menu-container time, .ol-ctx-menu-container mark, .ol-ctx-menu-container audio, .ol-ctx-menu-container video {
margin: 0;
padding: 0;
border: 0;
font: inherit;
font-size: 100%;
vertical-align: baseline; }
.ol-ctx-menu-container table {
border-collapse: collapse;
border-spacing: 0; }
.ol-ctx-menu-container caption, .ol-ctx-menu-container th, .ol-ctx-menu-container td {
text-align: left;
font-weight: normal;
vertical-align: middle; }
.ol-ctx-menu-container q, .ol-ctx-menu-container blockquote {
quotes: none; }
.ol-ctx-menu-container q:before, .ol-ctx-menu-container q:after, .ol-ctx-menu-container blockquote:before, .ol-ctx-menu-container blockquote:after {
content: "";
content: none; }
.ol-ctx-menu-container a img {
border: none; }
.ol-ctx-menu-container *,
.ol-ctx-menu-container *::before,
.ol-ctx-menu-container *::after {
box-sizing: inherit; }
.ol-ctx-menu-container.ol-ctx-menu-hidden {
opacity: 0;
visibility: hidden;
-webkit-transition: visibility 0s linear 300ms, opacity 300ms;
transition: visibility 0s linear 300ms, opacity 300ms; }
.ol-ctx-menu-container li {
position: relative;
line-height: 20px;
padding: 2px 5px; }
.ol-ctx-menu-container li:not(.ol-ctx-menu-separator):hover {
cursor: pointer;
background-color: #333;
color: #eee; }
.ol-ctx-menu-container li.ol-ctx-menu-submenu ul {
border: 1px solid #eee;
top: 0;
opacity: 0;
visibility: hidden;
-webkit-transition: visibility 0s linear 300ms, opacity 300ms;
transition: visibility 0s linear 300ms, opacity 300ms; }
.ol-ctx-menu-container li.ol-ctx-menu-submenu:hover ul {
opacity: 1;
visibility: visible;
-webkit-transition-delay: 0s;
transition-delay: 0s; }
.ol-ctx-menu-container li.ol-ctx-menu-submenu::after {
position: absolute;
top: 7px;
right: 10px;
content: "";
display: inline-block;
width: 0.6em;
height: 0.6em;
border-right: 0.3em solid #222;
border-top: 0.3em solid #222;
-webkit-transform: rotate(45deg);
transform: rotate(45deg); }
.ol-ctx-menu-container li.ol-ctx-menu-submenu:hover::after {
border-color: #eee; }
.ol-ctx-menu-container li.ol-ctx-menu-separator {
padding: 0; }
.ol-ctx-menu-container li.ol-ctx-menu-separator hr {
border: 0;
height: 1px;
background-image: -webkit-linear-gradient(right, transparent, rgba(0, 0, 0, 0.75), transparent);
background-image: linear-gradient(to left, transparent, rgba(0, 0, 0, 0.75), transparent); }
.ol-ctx-menu-icon {
text-indent: 20px;
background-size: 20px auto;
background-repeat: no-repeat;
background-position: left center; }
.ol-ctx-menu-zoom-in {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABaUlEQVQ4T72U7VHCQBCGn90GtAMuNGCswFiBWIFQgWMFxg6wArECsQKhArEBiB1Qwa1zgQn5IAYcxv13k71n3919L8KJQ07M47+BzgG9TRfZ/JBuWhS6BJFHRJICYrZGZIz3z5Ct2+B7gG6I6kt+wewdkQVwjtkAkR5mC8yu26A1oItR/cTsOweQBdgutD8G7jGm2PJ2n8oqUKIpIjd4HxTM8gvaT/F+AlmWnyWaIXKF95eNguFzTYFhNsdWu9kFgFlaFMANUH3D8wDLoLgSTSD2il8NCe2ZXQBxWDGwxmyUzzOMBZ7wy7Qb2K0wQfXjMOBuhlFpZtNty5sFaTQBuTusZdymeqs1SpYKcO9HkE3KbTd9WFijMHJQ5hBNEAYNq5Qd0dhyke0GiE4QzjqfW23mHT8Hl4DG4Lce3FPE7AtbBSdsbNqpoJLgYkRnNeUV+xwJDHTnUEkxHGbhBXUs5TjJjew/KPy94g+NRaIVRYmMXwAAAABJRU5ErkJggg=="); }
.ol-ctx-menu-container li:hover.ol-ctx-menu-zoom-in {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABc0lEQVQ4T71U21ECQRDsJgGdvQDECMQIxAjECMQILCPwzAAjECIQI0AiEDPQAPaWCBhrcKHuCUcV5f7dY3v6tUscefHIePhfwBBCF8CZqRCReRs1tQxDCH1VfQLQz4EsSY4AvIjIsgm8AhhCGKrqa9zwrqoLAKckB5HtguR1E2gBMITQU9VPAD8GICIGtl3e+xHJBwBT59xtHcsCYJZlUwA3kcGHbfDep51OZywi3/acZZm9vyJ5WR5o38uACmDunNt6ZwAkUxFZDwghDFT1jeSjiJinhVUBVNVJkiTDKO8CQA+AsbNQ7s1Ps0VVn5MkSfcCtmBoDZi1Bdx4eJ7zbBolrwPy3o9J3rWSHPs3A1BbjVKlYBaIyDgvu9LDXDU2RTZmXVW1oKyLxRD+OrkOrJLy5mVM0iaftDhuhVbsvBzMglzKUNW6IV/OOWtCM8MmVvEkmbwt83LaB19fdgOtVquUZJeknaDdobTwbOcvBzPcN/AXH1DFFWP7u9oAAAAASUVORK5CYII="); }
.ol-ctx-menu-zoom-out {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABU0lEQVQ4T72U7VECMRRFz3sNaAdkacC1AtcKxApcKnCsQOwAK3CtQKxAqEBsANYOqCDPyTIC+8WCw5jfybn33dxEOPGSE/P4b6BzQG89RT47ZJoWhy5B5BGRZAMxWyEyxvtnyFdt8AagS1F9KQ6YvSMyB84xGyDSw2yO2XUbtAJ0MaqfmH0XAPIA2y7tj4F7jAm2uG1yWQZKNEHkBu+Dg2njWBJNEbnC+8uaIFRuWfuG2QxbbrOrUd0A1Tc8D7AIjkur7DAAsVf8MiWMZ3ZR2m02LPIMscATfjHqBnY7TFD9OAy4zTCCPG/MUKMM5O6wkXFr9dZq7FQqqHk/hDzbFa73cFONTZFDdRyiCcKg5rrSiLaXkiI6RjjrfG6VzDs+B5eAxuDXeYpmNRGzL2wZ/wof+du4GNFpBVqqz5HA4MM5VEYYDrOs+1I6Q9u/4Q8O9wN/AGgWjBVqQjjgAAAAAElFTkSuQmCC"); }
.ol-ctx-menu-container li:hover.ol-ctx-menu-zoom-out {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABYklEQVQ4T72U4VHCQBCF36tA91KAWIFYgViBWIFYgWMFYgdYgVCBWAFSgdiBFpAsFWSdxcDkQoBkhnF/ZjbfvX377ogjF4/Mw/8CVbUD4MynEJF5k2lqFapqz8yeAPRKkCXJEYAXEVnugm8BVXVgZq/FD+9mtgBwSrJfqF2QvN4FjYCq2jWzTwA/DhARh20qTdMRyQcA0xDCbZ3KCJhl2RTATaHgo+6HLMv8+xXJy+qB3l8FGoB5CKHsXcRV1b6ZvZF8FBH3NKotoJlNkiQZFONdlLtJ3rufbouZPSdJMjwIbKDQEzBrClx7eC4i33Uepmk6JnnXaOQifzMAtdGoRApugYiMI1uqKkrRWAfZo9MxM1+UZzFewl8mN4nYdVM83L7BkwbXLUrF3sfBLQDQBbDy08x8vOohXyEE71lVq9emuEk+3gZa3XYroCvwFyjP8yHJDsnxwaU08GxvS2uFhw78BbzWrxXgMbsHAAAAAElFTkSuQmCC"); }
var StandardContextItems = [
{
text: 'Center map here',
classname: 'some-style-class', // add some CSS rules,
callback: center
},
'-', // this is a separator,
{
text: 'Draw',
classname: 'some-style-class', // you can add this icon with a CSS class
// instead of `icon` property (see next line)
items: [{
text: 'None',
classname: 'some-style-class', // you can add this icon with a CSS class
// instead of `icon` property (see next line)
callback: function (obj, map) {
addInteraction('None');
}
}, {
text: 'Point',
classname: 'some-style-class', // you can add this icon with a CSS class
// instead of `icon` property (see next line)
callback: function (obj, map) {
addInteraction('Point');
}
}, {
text: 'LineString',
classname: 'some-style-class', // you can add this icon with a CSS class
// instead of `icon` property (see next line)
callback: function (obj, map) {
addInteraction('LineString');
}
}, {
text: 'Polygon',
classname: 'some-style-class', // you can add this icon with a CSS class
// instead of `icon` property (see next line)
callback: function (obj, map) {
addInteraction('Polygon');
}
}, {
text: 'Circle',
classname: 'some-style-class', // you can add this icon with a CSS class
// instead of `icon` property (see next line)
callback: function (obj, map) {
addInteraction('Circle');
}
}, {
text: 'Square',
classname: 'some-style-class', // you can add this icon with a CSS class
// instead of `icon` property (see next line)
callback: function (obj, map) {
addInteraction('Square');
}
}, {
text: 'Box',
classname: 'some-style-class', // you can add this icon with a CSS class
// instead of `icon` property (see next line)
callback: function (obj, map) {
addInteraction('Box');
}
}, {
text: 'Clean',
classname: 'some-style-class', // you can add this icon with a CSS class
// instead of `icon` property (see next line)
callback: function (obj, map) {
clearDraw();
}
},
]
},
];
var SelectorContextMenu = [{
text: 'FeatureA',
callback: function (obj, map) {
var ID = feature.get('ID');
var ModelName = feature.get('ModelName')
handleFeatureContexMenuEvent('view', ID, ModelName);
}
},
{
text: 'FeatureB',
callback: function (obj, map) {
var ID = feature.get('ID');
var ModelName = feature.get('ModelName')
handleFeatureContexMenuEvent('view', ID, ModelName);
}
},
{
text: 'FeatureC',
callback: function (obj, map) {
var ID = feature.get('ID');
var ModelName = feature.get('ModelName')
handleFeatureContexMenuEvent('view', ID, ModelName);
}
}];
function clearDraw() {
map.removeInteraction(draw);
if (source) {
source.clear();
}
}
function center(obj) {
var pan = ol.animation.pan({
duration: 1000,
easing: elastic,
source: view.getCenter()
});
console.log(view.getCenter());
map.beforeRender(pan);
view.setCenter(obj.coordinate);
}
var contains = function(needle) {
// Per spec, the way to identify NaN is that it is not equal to itself
var findNaN = needle !== needle;
var indexOf;
if(!findNaN && typeof Array.prototype.indexOf === 'function') {
indexOf = Array.prototype.indexOf;
} else {
indexOf = function(needle) {
var i = -1, index = -1;
for(i = 0; i < this.length; i++) {
var item = this[i];
if((findNaN && item !== item) || item === needle) {
index = i;
break;
}
}
return index;
};
}
return indexOf.call(this, needle) > -1;
};
function GetID(){
var date = new Date();
var components = [
date.getYear(),
date.getMonth(),
date.getDate(),
date.getHours(),
date.getMinutes(),
date.getSeconds(),
date.getMilliseconds()
];
return components.join("");
}