<!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("");
  
}