/* default variables */ var default_pointer = "/media/images/default-pointer.png"; var marker_cluster = "/media/images/marker-cluster.png"; var view_projection = 'EPSG:3857'; var animation_duration = 250; var cluster_threshold_1 = 8; var cluster_threshold_2 = 25; var base_color_R = 111; var base_color_V = 66; var base_color_B = 193; var base_color_rvb; var map_default_center = 'SRID=4326;POINT (2.4397 46.5528)'; var map_default_zoom = '7'; var min_auto_zoom_on_cluster = 13; /* custom control */ var track_me_msg = "Geolocalize me"; var geoloc_activated_msg = "Geolocation activated"; var geoloc_disabled_msg = "Geolocation disabled"; var geolocation = {}; var geoloc_feature = {}; var geoloc_activated = {}; var fetching_msg = "Fetching data..."; var _map_submit_search = function(query_vars, name, source){ var modal_base_text = $('.modal-progress .modal-header').html(); $('.modal-progress .modal-header').html(fetching_msg); $('.modal-progress').modal('show'); var data = search_get_query_data(query_vars, name); var nb_select = jQuery("#id_" + name + "-length_map").val(); if (!nb_select) nb_select = 10; var url = source + "json-map?length=" + nb_select + "&submited=1&" + data; var use_map_limit = false; if(data.indexOf("no_limit=true") == -1){ url += "&limit=" + current_map_limit; use_map_limit = true; } $.getJSON(url, function(data) { var timestamp = Math.floor(Date.now() / 1000); var map_id = "map-" + timestamp; $('.modal-progress .modal-header').html("{% trans 'Render map...' %}"); var html = render_map(map_id, use_map_limit); $("#tab-content-map-" + name).html(html); $("#id_" + name + "-length_map").change(map_submit_search); if ($('.modal-progress').length > 0){ $('.modal-progress').modal('hide'); $('.modal-progress .modal-header').html(modal_base_text); } register_map(map_id, data); }); return false; }; var geoloc_activated_message = function(map_id){ setTimeout(function(){ navigator.geolocation.watchPosition(function(position) { if(!geoloc_activated[map_id]){ if (display_info) display_info(geoloc_activated_msg); geoloc_activated[map_id] = true; } }, function (error) { if (error.code == error.PERMISSION_DENIED) if (display_info) display_info(geoloc_disabled_msg); }); }, 200); }; var set_geoloc_source = function(map_id){ geolocation[map_id] = new ol.Geolocation({ projection: view_projection }); geolocation[map_id].setTracking(true); geoloc_feature[map_id] = new ol.Feature(); geoloc_feature[map_id].setStyle(new ol.style.Style({ image: new ol.style.Circle({ radius: 6, fill: new ol.style.Fill({color: '#3399CC'}), stroke: new ol.style.Stroke({color: '#fff', width: 2}) }) })); var accuracy_feature = new ol.Feature(); geolocation[map_id].on('change:accuracyGeometry', function() { accuracy_feature.setGeometry(geolocation[map_id].getAccuracyGeometry()); }); geolocation[map_id].on('change:position', function() { var coordinates = geolocation[map_id].getPosition(); geoloc_feature[map_id].setGeometry( coordinates ? new ol.geom.Point(coordinates) : null); var v = map[map_id].getView(); v.animate({center: coordinates, duration: animation_duration * 2}); }); new ol.layer.Vector({ map: map[map_id], source: new ol.source.Vector({ features: [geoloc_feature[map_id], accuracy_feature] }) }); geoloc_activated_message(map_id); }; var TrackPositionControl = (function (Control) { function TrackPositionControl(opt_options) { var options = opt_options || {}; this.map_id = options['map_id']; var button = document.createElement('button'); button.type = "button"; button.innerHTML = ''; button.title = track_me_msg; var element = document.createElement('div'); element.className = 'track-position ol-unselectable ol-control'; element.appendChild(button); Control.call(this, { element: element, target: options.target }); button.addEventListener( 'click', this.handleTrackPosition.bind(this), false ); } if ( Control ) TrackPositionControl.__proto__ = Control; TrackPositionControl.prototype = Object.create( Control && Control.prototype ); TrackPositionControl.prototype.constructor = TrackPositionControl; TrackPositionControl.prototype.handleTrackPosition = function handleTrackPosition () { if (!geolocation[this.map_id]){ set_geoloc_source(this.map_id); } else { if (!geoloc_activated[this.map_id]) return; if (geolocation[this.map_id].getTracking()){ geolocation[this.map_id].setTracking(false); if (display_info) display_info(geoloc_disabled_msg); } else { geolocation[this.map_id].setTracking(true); if (display_info) display_info(geoloc_activated_msg); } } return false; }; return TrackPositionControl; }(ol.control.Control)); /* base layers */ var source_osm = function(options){ return new ol.layer.Tile({ source: new ol.source.OSM() }); }; var default_map_layers = { 'osm': source_osm }; var get_layers = function(layers){ if (!layers){ layers = [{'type': 'osm', 'options': null}]; } var ol_layers = []; for (idx in layers){ var layer_attr = layers[idx]; ol_layers.push( default_map_layers[layer_attr['type']](layer_attr['options']) ); } return ol_layers; }; /* styles */ var get_icon_style = function(feature){ return new ol.style.Style({ image: new ol.style.Icon({ anchor: [17, 50], anchorXUnits: 'pixels', anchorYUnits: 'pixels', size: [35, 50], src: static_path + default_pointer }) }); }; var get_vector_style = function(feature){ return new ol.style.Style({ stroke: new ol.style.Stroke({ color: 'rgba(' + base_color_rvb + ', 1)', width: 2 }), fill: new ol.style.Fill({ color: 'rgba(' + base_color_rvb + ', 0.2)' }) }); }; var cluster_get_style = function(feature, resolution){ feature.set('key', 'cluster'); var cluster_features = feature.get('features'); var size = cluster_features.length; feature.set('size', size); var style = _styleCache[size]; if (!style && size == 1){ style = _styleCache[size] = [get_icon_style()]; } else if (!style && size > 1){ var color = size > cluster_threshold_2 ? "192,0,0" : size > cluster_threshold_1 ? "255,128,0" : "0,128,0"; var radius = Math.max(8, Math.min(size * 0.75, 20)); var lbl = size.toString(); style = _styleCache[size] = [ new ol.style.Style({ image: new ol.style.Circle({ radius: radius, stroke: new ol.style.Stroke({ color:"rgba("+color+",0.5)", width: 15 }), fill: new ol.style.Fill({ color:"rgba("+color+",1)" }) }), text: new ol.style.Text({ text: lbl, fill: new ol.style.Fill({ color: '#fff' }) }) }) ]; } return style; } /* clustering */ var _styleCache; var cluster_source = {}; var cluster_layer = {}; var enable_clustering = function(map_id){ // cache for styles _styleCache = {}; // cluster Source cluster_source[map_id] = new ol.source.Cluster({ distance: 40, source: new ol.source.Vector() }); // animated cluster layer cluster_layer[map_id] = new ol.layer.Vector({ name: 'Cluster', source: cluster_source[map_id], // cluster style style: cluster_get_style }); map[map_id].addLayer(cluster_layer[map_id]); }; var reinit_clustering = function(map_id){ cluster_source[map_id].getSource().clear(); _styleCache = {}; }; /* manage clicks */ var current_feature; var animate_in_progress = false; var animate_end = function(){animate_in_progress = false}; var wait_animation_end = function(callback, retry){ if (!retry) retry = 1; setTimeout(function(){ retry += 1 if (retry < 5 && animate_in_progress){ wait_animation_end(callback) } else { callback(); } }, 100); }; var manage_click_on_map = function(map_id){ return function(e) { var feature = map[map_id].forEachFeatureAtPixel( e.pixel, function(feature, layer) { return feature; } ); click_on_feature(map_id, feature, e); }; }; var current_event; var click_on_feature = function(map_id, feature, e){ // console.log("click_on_feature"); current_event = e; if (!$(e.target).is($(popup_item[map_id])) && !$.contains($(popup_item[map_id])[0], e.target) ) { $(popup_item[map_id]).hide(); $('#ishtar-map-window-' + map_id).hide(); } if (typeof feature == 'undefined'){ current_feature = null; return; } current_feature = feature; if (!feature) return; var timeout = 10; setTimeout(function(){ // zoom on aggregated var key = feature.get('key'); if (feature.get('name') || feature.get('key')){ feature = click_on_cluster(map_id, feature); } }, timeout); }; var auto_zoom = false; var click_on_cluster = function(map_id, feature, zoom_level, duration, nb_zoom, current_nb_items){ // console.log("click_on_cluster"); if (!duration){ // zoom animation must be slower duration = animation_duration * 2; } if (!nb_zoom) nb_zoom = 0; var props = feature.getProperties(); if (!'features' in props) return feature; if (!auto_zoom || props['features'].length == 1){ return display_cluster_detail(map_id, feature); } if (!current_nb_items){ current_nb_items = props['features'].length; } else if(current_nb_items != props['features'].length) { // stop zooming there less item in the cluster return feature; } var v = map[map_id].getView(); if (!zoom_level) zoom_level = v.getZoom() + 1; // center var new_center = feature.getGeometry().getCoordinates(); // max zoom reached if (zoom_level >= min_auto_zoom_on_cluster){ animate_in_progress = true; v.animate({center: new_center, duration: duration}, animate_end); return display_cluster_detail(map_id, feature); } // zoom animate_in_progress = true; v.animate({center: new_center, zoom: zoom_level, duration: duration}, animate_end); nb_zoom += 1; // something wrong stop zoom! if (nb_zoom > v.getMaxZoom()) return feature; // wait for the animation to finish before rezoom return setTimeout( function(){ // our cluster must be at the center (if it exists after zoom) var pixel = map[map_id].getPixelFromCoordinate(v.getCenter()); var new_feature; map.forEachFeatureAtPixel( pixel, function(feat, layer){ if (layer == cluster_layer[map_id]){ new_feature = feat; return true } } ); if (new_feature){ if (zoom_level < min_auto_zoom_on_cluster){ return display_cluster_detail(map_id, new_feature); } return click_on_cluster( map_id, new_feature, zoom_level + 1, duration, nb_zoom, current_nb_items); } // no more cluster feature here or min auto zoom reach: stop zooming return feature; }, duration + 200); }; /* display info */ var display_cluster_detail = function(map_id, cluster){ // console.log("display_cluster_detail"); var features = cluster.getProperties()['features'] var offset_x = 0; var offset_y = -21; if (!features){ features = [cluster]; offset_y = -7; } else if (features.length == 1){ offset_y = -54; } display_items(map_id, features, offset_x, offset_y); }; var display_items = function(map_id, features, offset_x, offset_y){ wait_animation_end(function() {_display_items(map_id, features, offset_x, offset_y)}); }; var open_map_window = function(map_id){ return function(){ $('#ishtar-map-window-' + map_id).show(); }; }; var complete_list_label = "complete list..."; var _display_items = function(map_id, features, offset_x, offset_y){ // console.log("display_items"); var feature = features[0]; var geom = feature.getGeometry(); var ul_class = "map-list-" + map_id; var popup_content = "