123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748 |
- {% extends 'SonataAdminBundle:CRUD:base_list.html.twig' %}
- {% block stylesheets %}
- {{ parent() }}
- <style>
- .no_checkbox>i.jstree-checkbox
- {
- display:none
- }
- </style>
- <link rel="stylesheet" href="/css/tree/proton/style.css" />
- {% endblock %}
- {% block actions %}
- {% endblock %}
- {% block tab_menu %}
- {#{{ knp_menu_render(admin.sidemenu(action), {'currentClass' : 'active', 'template': sonata_admin.adminPool.getTemplate('tab_menu_template')}, 'twig') }}#}
- {% endblock %}
- {% block list_filters_actions %}
- {% endblock %}
- {% block list_filters %}
- {% endblock %}
- {% block list_table %}
- {% include 'LeafletBundle:Leaflet:resources.html.twig' %}
- <script type="text/javascript">
- window.SONATA_CONFIG.USE_ICHECK = false;
- window.currentLayer = null; // Almacena el ID del layer actualmente seleccionado.
- var osmUrl = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
- osmAttrib = '© <a href="http://openstreetmap.org/copyright">OpenStreetMap</a> contributors',
- osm = L.tileLayer(osmUrl, { maxZoom: 18, attribution: osmAttrib }),
- map = new L.Map('map', { center: new L.LatLng({{map['lat']}}, {{map['lng']}}), zoom: {{map['zoom']}} });
- var controlLayers = L.control.layers({
- 'OSM': osm.addTo(map),
- "Google": L.tileLayer('http://www.google.cn/maps/vt?lyrs=s@189&gl=cn&x={x}&y={y}&z={z}', {
- attribution: 'google'
- })
- }, {}, { position: 'topleft', collapsed: false });
- addLayersMap();
- controlLayers.addTo(map);
- // Agregar Clase para dibujo de vectores
- window.drawControl = new L.Control.Draw();
- map.on(L.Draw.Event.CREATED, function (event) {
- /* Se dispara tras creación de vector */
- var uuid = guid();
- var layer = event.layer;
- var currentLayer = layers[window.currentLayer];
- layer.layerType = event.layerType;
- layer.layerClass = "vector";
- currentLayer.addLayer(layer);
- currentLayer.eachLayer(function(layer) {
- if (typeof layer._uuid === 'undefined') {
- layer._uuid = uuid + "_" + layer._leaflet_id;
- }
- });
- saveData();
- refresh();
- });
- map.on(L.Draw.Event.DELETED, function (event) {
- /* Se dispara tras borrado de vector */
- var layers = event.layers;
- var deleteLayers = new Array();
- layers.eachLayer(function(layer) {
- deleteLayers.push(layer._uuid);
- });
- sendData = {'layerId' : layerId, 'vectors' : deleteLayers};
- var json = JSON.stringify(sendData);
- saveData();
- refresh()
- });
- function saveData() {
- /*
- * Guarda todos los layers presentes en window.layers
- * y a sus correspondientes vectores
- */
- $.each(window.layers, function(id, myLayer) {
- var vectorData = new Array();
- if (myLayer) {
- myLayer.eachLayer(function(layer) {
- if(layer.layerType == "marker") {
- data = [layer._latlng];
- } else if (layer.layerType == "circle") {
- data = [layer._latlng, layer._mRadius];
- } else if (layer.layerType == "polyline") {
- data = [layer._latlngs];
- } else {
- data = [layer._latlngs[0]];
- }
- object = {'_uuid': layer._uuid, 'layerType': layer.layerType, 'data': data, 'layerId': layer._id};
- vectorData.push(object);
- });
- sendData = {'layerId' : id, 'vectors' : vectorData};
- var json = JSON.stringify(sendData);
- $.ajax({
- type: "POST",
- url: "{{ path('admin_map_vector_create_ajax') }}",
- data: json,
- contentType: "application/json; charset=utf-8",
- dataType: "json",
- error: function(msg) {
- console.log(msg.msg);
- }
- });
- }
- });
- }
- function addLayersMap() {
- /*
- * Obtiene todos los layers y vectores de un mapa.
- * Luego los agrega al control Leaflet
- */
- window.layers = new Array();
- var url = window.location.pathname;
- var id = url.substring(url.lastIndexOf('/') + 1);
- var mapData = getData('maps', id );
- for(var i=0; i < mapData.layers.length; i++) {
- var layer = mapData.layers[i];
- newLayer = L.featureGroup();
- for(var j=0; j < layer.vectors.length; j++ ) {
- var vector = layer.vectors[j];
- _id = vector.id;
- name = vector.name;
- type = vector.type;
- _uuid = vector.uuid;
- data = JSON.parse(vector.data);
- style = JSON.parse(vector.style);
- if(type == "marker") {
- if (typeof style.icon !== 'undefined') {
- icon = style.icon;
- } else {
- icon = "miniBubbleBlueIcon";
- }
- object = new L.marker([data[0]['lat'], data[0]['lng']],{icon: eval(icon)});
- } else if (type == "circle") {
- object = new L.circle([data[0]['lat'], data[0]['lng']], data[1], style);
- } else if (type == "polyline") {
- object = new L.Polyline(data[0], style);
- } else if (type == "rectangle"){
- object = new L.Rectangle(data[0], style);
- } else {
- object = new L.Polygon(data[0], style);
- }
- object._id = _id;
- object.name = name;
- object._uuid = _uuid;
- object.layerType = type;
- object.layerClass = "vector";
- var desc = $("#desc_vector_" + vector.id).html();
- object.on("click", function (e) {
- var layer = e.target
- if (layer.class = 'vector') {
- // Deseleccionar todos los elementos.
- $('#jstree').jstree('deselect_all');
- $('#overlay_tree').jstree('deselect_all');
- for (key in layer._eventParents) {
- var leafletId = key; // Debería iterar una sola vez
- }
- // Seleccionar elementos:
- for (key in window.layers) {
- if (window.layers[key]._leaflet_id == leafletId) {
- $('#jstree').jstree('select_node', key);
- }
- }
- /* Dar 200ms de espera, ya que esta instrucción puede ejecutarse
- incluso antes de que el árbol de vectores haya
- recibido la instrucción de recargarse. */
- setTimeout(function() { selectElement(layer._id) }, 200);
- }
- });
- newLayer.class = 'layer';
- newLayer.addLayer(object);
- }
- window.layers[layer.id] = newLayer.addTo(map);
- }
- }
- </script>
- {% endblock %}
- {% block content %}
- <div class="col-md-10">
- <div class="cms-block cms-block-element">
- <div class="box">
- <div class="box-body">
- <div id="map" style="margin:0 auto; width: 100%; height: calc(100vh - 190px); border: 1px solid #ccc"></div>
- </div>
- </div>
- </div>
- </div>
- <div class="col-md-2">
- <div class="box">
- <div class="box-header">
- <h4>Capas</h4>
- <div class="box-body">
- <div class="jstree-proton" id="jstree" style="max-height: calc(100vh - 250px); overflow-y: auto; overflow-x: hidden;"></div>
- </div>
- <button class="btn btn-default btn-xs" id="btnNewLayer"><i class="fa fa-file-o" data-toggle="modal" data-target="#modalNewLayer"></i></button>
- <button onclick="refresh()" class="btn btn-default btn-xs"><i class="fa fa-refresh" aria-hidden="true"></i></button>
- <button id="btnSave" class="btn btn-default btn-xs"><i class="fa fa-floppy-o" aria-hidden="true"></i></button>
- </div>
- </div>
- <div class="box">
- <div class="box-header">
- <h4>Elementos</h4>
- <br/>
- <div class="btn-group">
- <button class="btn btn-default btn-xs" onclick="new L.Draw.Polyline(map, drawControl.options.polyline).enable();"><i class="fa fa-share-alt" aria-hidden="true"></i></button>
- <button class="btn btn-default btn-xs" onclick="new L.Draw.Polygon(map, drawControl.options.polygon).enable();"><i class="fa fa-star-o" aria-hidden="true"></i></button>
- <button class="btn btn-default btn-xs" onclick="new L.Draw.Rectangle(map, drawControl.options.rectangle).enable();"><i class="fa fa-stop" aria-hidden="true"></i></button>
- <button class="btn btn-default btn-xs" onclick="new L.Draw.Circle(map, drawControl.options.circle).enable();"><i class="fa fa-circle-o" aria-hidden="true"></i></button>
- <button class="btn btn-default btn-xs" onclick="new L.Draw.Marker(map, drawControl.options.marker).enable();"><i class="fa fa-map-marker" aria-hidden="true"></i></button>
- </div>
- </div>
- <div class="box-body">
- <div class="jstree-proton" id="overlay_tree" style="max-height: calc(100vh - 450px); overflow-y: auto; overflow-x: hidden;"></div>
- </div>
- </div>
- </div>
- <!-- Modal Nueva Capa -->
- <div class="modal fade" id="modalNewLayer" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
- <div class="modal-dialog" role="document">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
- <h4 class="modal-title" id="myModalLabel">Nueva Capa</h4>
- </div>
- <div class="modal-body">
- <div class="container-fluid">
- <label class="control-label col-md-3">Nombre</label>
- <input class="form-control col-md-9" name="name" id="newLayerName"></input>
- </div>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default" data-dismiss="modal">Cancelar</button>
- <button onclick="createNewLayer()" type="submit" class="btn btn-primary">Crear</button>
- </div>
- </div>
- </div>
- </div>
- <!-- Fin - Modal Nueva Capa -->
- <!-- Modal Renombrar -->
- <div class="modal fade" id="modalRename" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
- <div class="modal-dialog" role="document">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
- <h4 class="modal-title" id="myModalLabel">Renombrar</h4>
- </div>
- <div class="modal-body">
- <div class="container-fluid">
- <label class="control-label col-md-3">Nombre</label>
- <input class="form-control col-md-9" name="name" id="newName"></input>
- </div>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default" data-dismiss="modal">Cancelar</button>
- <button onclick="renameItem()" type="submit" class="btn btn-primary">Renombrar</button>
- </div>
- </div>
- </div>
- </div>
- <!-- Fin - Modal Renombrar -->
- <!-- Modal Renombrar -->
- <div class="modal fade" id="modalDelete" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
- <div class="modal-dialog modal-danger" role="document">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
- <h4 class="modal-title" id="myModalLabel">Borrar</h4>
- </div>
- <div class="modal-body">
- <p>¿Está seguro de que desea borrar <span id="elementTypeCaption"?></span> "<span id="elementName"></span>"?</p>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-danger" data-dismiss="modal">Cancelar</button>
- <button onclick="deleteItem()" type="submit" class="btn btn-danger">Borrar</button>
- </div>
- </div>
- </div>
- </div>
- <!-- Fin - Modal Renombrar -->
- {% endblock %}
- {% block javascripts %}
- {{ parent() }}
- <script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.4/jstree.min.js"></script>
- <script>
- $(document).ready(function() {
- $('#btnSave').click(function() {
- /*
- * Desactiva la edición en todas las capas,
- * luego postea los datos existentes.
- */
- $.each(window.layers, function(id, myLayer) {
- if (myLayer) {
- myLayer.eachLayer(function(layer) {
- layer.editing.disable();
- });
- }
- });
- saveData();
- });
- // Defaults para el plugin JSTree
- $.jstree.defaults.core.dblclick_toggle = false;
- $.jstree.defaults.core.multiple = false;
- $.jstree.defaults.checkbox.three_state = false;
- $.jstree.defaults.checkbox.whole_node = false;
- $.jstree.defaults.checkbox.tie_selection = false;
- $.jstree.defaults.contextmenu.select_node = true;
- $('#jstree').on('check_node.jstree uncheck_node.jstree', function (e, data) {
- if (data.node.type == 'layer') {
- if (data.node.state.checked) {
- map.addLayer(layers[data.node.id]);
- } else {
- map.removeLayer(layers[data.node.id]);
- }
- }
- });
- $('#jstree').on('select_node.jstree', function (e, data) {
- if (data.node.type == 'layer') {
- window.currentLayer = data.selected;
- $('#overlay_tree').jstree(true).settings.core.data = makeOverlayTree(layers[data.selected]);
- $('#overlay_tree').jstree(true).refresh();
- }
- toggleControls();
- });
- $('#overlay_tree').on('select_node.jstree', function (e, data) {
- var vectorData = getData('vectors', data.node.id);
- map.eachLayer(function(layer){
- if (layer._id == data.node.id) {
- var popupContent = "<b>" + vectorData.name + "</b><br/>" + vectorData.description + " <div style='text-align:center;margin-top:5px'><a target='_blank' href='/admin/map/vector/" + vectorData.id + "/edit'>EDITAR</a></div>";
- layer.bindPopup(popupContent);
- if (!layer._popup.isOpen()) {
- layer.openPopup();
- }
- }
- });
- })
- initializeTrees();
- });
- function getData(entity, id=null) {
- /*
- * Dadas una entidad y opcionalmente un id, devuelve un JSON obtenido
- * mediante una llamada AJAX a la API REST.
- */
- var result = null;
- if (id == null) {
- var url = "/api/" + entity
- } else {
- var url = "/api/" + entity + "/" + id
- }
- $.ajax({
- type: "GET",
- dataType: "json",
- async: false,
- cache: false,
- url: url,
- success: function(data){
- result = data;
- },
- error: function(XMLHttpRequest, textStatus, errorThrown) {
- console.log("Status: " + textStatus); alert("Error: " + errorThrown);
- }
- });
- return result;
- }
- function makeTree() {
- /*
- * Función que obtiene la información de las capas y se la entrega
- * procesada al JSTree de capas.
- */
- var url = window.location.pathname;
- var id = url.substring(url.lastIndexOf('/') + 1);
- var mapData = getData('maps', id );
- var result = [];
- result.push({ "id" : "map_" + mapData.id, "parent" : "#", "text" : mapData.name,
- "type": "map", a_attr: {class: "no_checkbox"}, state: { opened : true } });
- for(var i = 0; i < mapData.layers.length; i++) {
- var layer = mapData.layers[i];
- result.push({ "id" : layer.id, "parent" : "map_" + mapData.id,
- "text" : layer.name, "type" : "layer", state: { checked : true } });
- }
- return result;
- }
- function makeOverlayTree(layer) {
- /*
- * Función que obtiene los vectores dentro de una capa y se los
- * entrega procesados al JSTree de elementos.
- */
- result = [];
- if (layer) {
- var layerss = layer.getLayers();
- for(var j = 0; j < layerss.length; j++) {
- var vector = layerss[j];
- result.push({ "id" :vector._id, "parent" : "#", "text" : vector.name,
- "type": vector.layerType, a_attr: {class: "no_checkbox"} });
- };
- }
- return result;
- }
- function customMenu(node) {
- var items = {
- editItem: {
- label: "Editar",
- action: function () { treeMenuEdit(node) } // No pasar la función directamente, sino la ejecuta al hacer click.
- },
- renameItem: {
- label: "Renombrar",
- action: function () {
- if (node.type == 'layer') {
- window.activeType = 'layer';
- } else {
- window.activeType = 'vector';
- }
- window.activeId = node.id;
- $("#newName").val(node.text);
- $("#modalRename").modal();
- }
- },
- deleteItem: {
- label: "Borrar",
- action: function () {
- if (node.type == 'layer') {
- $("#elementTypeCaption").text('la capa');
- window.activeType = 'layer';
- } else {
- $("#elementTypeCaption").text('el elemento');
- window.activeType = 'vector';
- }
- window.activeId = node.id;
- $("#elementName").text(node.text);
- $("#modalDelete").modal();
- }
- }
- };
- return items;
- }
- function treeMenuEdit(node) {
- if (node.type == "layer") {
- var editor = new L.EditToolbar.Edit(map, {
- featureGroup: drawControl.options.featureGroup,
- selectedPathOptions: drawControl.options.edit.selectedPathOptions
- })
- } else {
- var currentlayer = layers[[$('#jstree').jstree(true).get_selected()[0]]];
- currentlayer.eachLayer(function(layer) {
- if (layer._id == node.id) {
- var vector = layer;
- vector.editing.enable();
- }
- });
- }
- }
- function guid() {
- return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
- s4() + '-' + s4() + s4() + s4();
- }
- function s4() {
- return Math.floor((1 + Math.random()) * 0x10000)
- .toString(16)
- .substring(1);
- }
- function initializeTrees() {
- /*
- * Inicializa los controles JSTree
- */
- $('#jstree').jstree({
- 'core' : {
- "animation" : 200,
- "check_callback" : true,
- "data" : makeTree(),
- "strings" : { 'Loading ...' : 'Cargando...' },
- },
- "types" : {
- "map" : {
- "icon" : "/images/tree/16x16/Map.png",
- "valid_children" : ["layer"]
- },
- "layer" : {
- "icon" : "/images/tree/16x16/Layers.png",
- "valid_children" : ["vector","object"]
- },
- "#" : {
- "valid_children" : []
- }
- },
- "plugins" : [ "dnd", "contextmenu", "checkbox", "types", "changed", "wholerow" ],
- contextmenu: {items: customMenu}
- });
- $('#overlay_tree').jstree({
- 'core' : {
- "animation" : 0,
- "check_callback" : false,
- "data" : makeOverlayTree(),
- "themes" : { "dots": false },
- "strings" : { 'Loading ...' : 'Cargando...' },
- },
- "types" : {
- "polygon" : {
- "icon" : "/images/tree/16x16/Polygon.png",
- "valid_children" : []
- },
- "circle" : {
- "icon" : "/images/tree/16x16/Circle.png",
- "valid_children" : []
- },
- "rectangle" : {
- "icon" : "/images/tree/16x16/Rectangle.png",
- "valid_children" : []
- },
- "polyline" : {
- "icon" : "/images/tree/16x16/Polyline.png",
- "valid_children" : []
- },
- "marker" : {
- "icon" : "/images/tree/16x16/Marker.png",
- "valid_children" : []
- },
- "#" : {
- "valid_children" : []
- }
- },
- "plugins" : [ "dnd", "contextmenu", "checkbox", "types", "changed", "wholerow" ],
- contextmenu: {items: customMenu}
- });
- }
- function createNewLayer() {
- var url = window.location.pathname;
- var mapid = parseInt(url.substring(url.lastIndexOf('/') + 1));
- var name = $('#newLayerName').val();
- sendData = {name: name, map: mapid};
- $.ajax({
- type: "POST",
- url: "{{ path('post_layer') }}",
- async: false,
- data: JSON.stringify(sendData),
- contentType: "application/json; charset=utf-8",
- dataType: "json",
- error: function(msg) {
- console.log(msg.msg);
- }
- });
- $('#modalNewLayer').modal('hide');
- refresh();
- }
- function deleteItem() {
- /*
- * Dados el tipo de elemento y el id del mismo, realiza una petición HTTP
- * a la API para que realice el borrado del mismo.
- */
- var itemId = window.activeId
- var itemType = window.activeType
- if (itemType == 'layer') {
- var url = '/api/layers/' + itemId;
- } else if (itemType == 'vector') {
- var url = '/api/vectors/' + itemId;
- }
- $.ajax({
- type: "DELETE",
- url: url,
- async: false,
- contentType: "application/json; charset=utf-8",
- dataType: "json",
- error: function(msg) {
- console.log(msg.msg);
- }
- });
- $('#modalDelete').modal('hide');
- refresh();
- }
- function renameItem() {
- /*
- * Dados el tipo de elemento y el id del mismo, realiza una petición HTTP
- * a la API para cambiar el nombre.
- */
- var itemId = window.activeId
- var itemType = window.activeType
- if (itemType == 'layer') {
- var url = '/api/layers/' + itemId;
- } else if (itemType == 'vector') {
- var url = '/api/vectors/' + itemId;
- }
- sendData = {id: itemId, name: $('#newName').val()};
- $.ajax({
- type: "PATCH",
- url: url,
- async: false,
- data: JSON.stringify(sendData),
- contentType: "application/json; charset=utf-8",
- dataType: "json",
- error: function(msg) {
- console.log(msg.msg);
- }
- });
- $('#modalRename').modal('hide');
- refresh();
- }
- function refresh() {
- /* Recarga todos los elementos */
- map.eachLayer(function (layer) {
- if (layer._url != "http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png") { //TODO: Buscar otra manera de matchear el mapa base.
- map.removeLayer(layer);
- }
- });
- window.layers = null; /* Destruir global */
- addLayersMap();
- $('#jstree').jstree(true).settings.core.data = makeTree();
- $('#overlay_tree').jstree(true).settings.core.data = makeOverlayTree(null);
- $('#jstree').jstree(true).refresh();
- }
- function selectElement(elementId) {
- /*
- * Espera (preventivamente) a que los elementos se carguen e intenta
- * seleccionar el elemento en cuestión
- */
- if ($('#overlay_tree').jstree().is_loading()) {
- window.setTimeout(waitForLoad, 100); /* Reintenta en 100ms si está cargando */
- } else {
- $('#overlay_tree').jstree('select_node', elementId);
- }
- }
- function toggleControls() {
- if ($('#overlay_tree').jstree('get_selected') == '[]') {
- $('#btnSave').prop('disabled', 'disabled');
- } else {
- $('#btnSave').removeProp('disabled');
- }
- }
- </script>
- {% endblock %}
|