diff options
| -rw-r--r-- | chimere/settings.sample.py | 11 | ||||
| -rw-r--r-- | chimere/static/chimere/js/jquery.chimere-leaflet.js | 371 | ||||
| -rw-r--r-- | chimere/static/chimere/js/jquery.chimere-ol.js | 67 | ||||
| -rw-r--r-- | chimere/templates/chimere/blocks/head_chimere.html | 7 | ||||
| -rw-r--r-- | chimere/templates/chimere/blocks/map.html | 3 | ||||
| -rw-r--r-- | chimere/templatetags/chimere_tags.py | 4 | 
6 files changed, 429 insertions, 34 deletions
| diff --git a/chimere/settings.sample.py b/chimere/settings.sample.py index 2e5ad40..391c6e5 100644 --- a/chimere/settings.sample.py +++ b/chimere/settings.sample.py @@ -290,7 +290,8 @@ if 'MAP_JS_URLS' not in globals():              STATIC_URL + "openlayers/OpenLayers.js",              STATIC_URL + "openlayers/SimplePanZoom.js",              "http://www.openstreetmap.org/openlayers/OpenStreetMap.js", -            STATIC_URL + "chimere/js/jquery.chimere-ol.js"], +            STATIC_URL + "chimere/js/jquery.chimere-ol.js" +            ],          'leaflet':[              STATIC_URL + "leaflet/leaflet.js",              STATIC_URL + "chimere/js/jquery.chimere-leaflet.js" @@ -299,11 +300,13 @@ if 'MAP_JS_URLS' not in globals():  if 'MAP_CSS_URLS' not in globals():      global MAP_CSS_URLS +    # key: [(url, condition)]      MAP_CSS_URLS = { -        'openlayers':["http://www.openlayers.org/api/theme/default/style.css"], +        'openlayers':[("http://www.openlayers.org/api/theme/default/style.css", +                       None)],          'leaflet':[ -            STATIC_URL + "leaflet/leaflet.css", -            STATIC_URL + "leaflet/leaflet.ie.css" +            (STATIC_URL + "leaflet/leaflet.css", None), +            (STATIC_URL + "leaflet/leaflet.ie.css", 'lte IE 8')          ]      } diff --git a/chimere/static/chimere/js/jquery.chimere-leaflet.js b/chimere/static/chimere/js/jquery.chimere-leaflet.js index 75a0fc3..569f9f5 100644 --- a/chimere/static/chimere/js/jquery.chimere-leaflet.js +++ b/chimere/static/chimere/js/jquery.chimere-leaflet.js @@ -106,9 +106,380 @@ See the file COPYING for details.          * Plugin init function          */          init: function ( options ) { +            settings = $.extend({}, defaults); +            if ( options ) $.extend(settings, options); +            var map_element = $(this).attr('id'); + +            settings.map = map = L.map(map_element); +            for (idx in settings.map_layers){ +                map.addLayer(settings.map_layers[idx]); +            } +            if(settings.zoom && settings.lat && settings.lon){ +                map.setView([settings.lat, settings.lon], settings.zoom); +            } else { +                map.fitWorld(); +            } +            settings.icons = new Object(); +            settings.layerMarkers = L.geoJson(null, { +                onEachFeature: function (feature, layer) { +                    layer.bindPopup(feature.properties.name); +                }, +                pointToLayer: function (feature, latlng) { +                    if (feature.properties.weigthed){ +                        var geojsonMarkerOptions = { +                            radius: 8, +                            fillColor: "#ff7800", +                            color: "#000", +                            weight: 1, +                            opacity: 1, +                            fillOpacity: 0.8 +                        }; +                        return L.circleMarker(latlng, geojsonMarkerOptions); +                    } +                    var icon_path = MEDIA_URL + feature.properties.icon_path; +                    if (!settings.icons.hasOwnProperty(icon_path)){ +                        var icon_offset = null; +                        if (feature.properties.icon_offset){ +                            icon_offset = feature.properties.icon_offset; +                        } else { +                            icon_offset = [feature.properties.icon_width/2, +                                           feature.properties.icon_height]; +                        } +                        var popup_anchor = null; +                        if (feature.properties.popup_anchor){ +                            popup_anchor = feature.properties.popup_anchor; +                        } else { +                            popup_anchor = [0, +                                            -feature.properties.icon_height]; +                        } +                        settings.icons[icon_path] = L.icon({ +                            iconUrl: icon_path, +                            iconSize: [feature.properties.icon_width, +                                       feature.properties.icon_height], +                            iconAnchor: icon_offset, +                            popupAnchor: popup_anchor +                        }); +                    } +                    return L.marker(latlng, {icon: settings.icons[icon_path]}); +                } +            }).addTo(map); +            settings.layerVectors = L.geoJson().addTo(map); + +            methods.loadCategories(); +            methods.loadGeoObjects(); +        }, +        hidePopup: function (evt) { +            settings.map.closePopup(); +            return true; +        }, +        /* +        * Update the categories div in ajax +        */ +        loadCategories: function () { +            var current_extent = settings.map.getBounds(); +            current_extent = current_extent.toBBoxString(); +            current_extent = current_extent.split(',').join('_'); +            current_extent = current_extent.replace(/\./g, 'D'); +            current_extent = current_extent.replace(/-/g, 'M'); +            var uri = extra_url +            if (settings.area_id) uri += settings.area_id + "/"; +            uri += "getAvailableCategories/"; +            var params = {"current_extent": current_extent} +            if (settings.display_submited) params["status"] = "A_S"; +            $.ajax({url: uri, +                    data: params, +                    cache: false, +                    success: function (data) { +                            $('#categories').empty(); +                            $('#categories').html(data); +                            _init_categories(); +                            _reCheckCategories(); +                            if (settings.current_category) { +                                // TODO : add a force mode  +                                // (in case the category is yet visible in HTML...) +                                methods.toggle_category(); +                            } +                        } +                   }); +            var _toggle_subcategories = function (category_element) { +                // Check subcategories only if unchecked +                var val = category_element.is(":checked") ? true : false; +                category_element.parent().find("li input").attr("checked", val); +            } +            var _toggle_categories = function (subcategory_element) { +                var parent = subcategory_element.closest('ul'); +                var parent_label = parent.parent().find("> span"); +                if (parent.find('input[type=checkbox]:checked').length){ +                    parent_label.addClass('category-selected'); +                } else { +                    parent_label.removeClass('category-selected'); +                } +                var master_check = parent.find("> input"); +                if (parent.find('.subcategories input[type=checkbox]').length == +                    parent.find('.subcategories input[type=checkbox]:checked').length){ +                    master_check.attr('checked', 'checked'); +                } else { +                    master_check.removeAttr('checked'); +                } + +                if($('#action-categories').length){ +                    if ($('#categories input[type=checkbox]:checked').length){ +                        $('#action-categories').addClass('category-selected'); +                    } else { +                        $('#action-categories').removeClass('category-selected'); +                    } +                } +                return master_check; +            }; +            var _init_categories = function () { +                /* +                * Add event listener in categories DOM elements +                */ +                $('#categories #ul_categories > li > input').bind("click", +                function (e) { +                    methods.hidePopup(e); +                    _toggle_subcategories($(this)); +                    methods.loadGeoObjects(); +                    //settings.permalink.updateLink(); +                }); +                $('.subcategories li input').bind("click", function (e) { +                    var c_name = $(this).attr('name'); +                    c_name = c_name.substr(c_name.lastIndexOf("_")+1); +                    if($(this).is(':checked')){ +                        methods.subcategory_detail(c_name); +                    } +                    var par = $(this).parent(); +                    if ($(this).attr('checked')){ +                        par.addClass('selected'); +                    } else { +                        par.removeClass('selected'); +                    } +                    methods.hidePopup(e); +                    methods.loadGeoObjects(); +                    _toggle_categories($(this)); +                    //settings.permalink.updateLink(); +                    if ($('#layer_cat_'+c_name).length){ +                        $('#layer_cat_'+c_name).prop("checked", +                                                     this.checked); +                    } +                }); +                $('#display_submited_check').bind("click", function () { +                    methods.loadGeoObjects(); +                    //settings.permalink.updateLink(); +                }); +                // Zoom to category +                $(".zoom_to_category").bind("click", function (e) { +                    var id = this.id.substr(this.id.lastIndexOf("_")+1); +                    helpers.zoom_to_category(id); +                }); +                $(".zoom_to_subcategory").bind("click", function (e) { +                    var id = this.id.substr(this.id.lastIndexOf("_")+1); +                    helpers.zoom_to_subcategories([id]); +                }); +                $(".toggle_category").parent().bind("click", function (e) { +                    var item = $(this).children('.toggle_category'); +                    var id = item.attr('id').substr(item.attr('id').lastIndexOf("_")+1); +                    methods.toggle_category(id); +                }); +            } +            var _reCheckCategories = function (){ +                /* recheck categories on init or when a redraw occurs */ +                if (!settings.checked_categories){ +                    return; +                } +                $('#frm_categories .subcategories input:checkbox').each(function(index){ +                    cat_id = $(this).attr('id').split('_').pop(); +                    if (settings.checked_categories.indexOf(parseInt(cat_id)) != -1) { +                        $(this).attr("checked", "checked"); +                        _toggle_categories($(this)); +                        methods.toggle_category(); +                    } else { +                        $(this).attr("checked", false); +                    } +                }); +                if (settings.display_submited == true){ +                    $('#display_submited_check').attr("checked", "checked"); +                } +            } +        }, +        /* +        * Load markers and route from DB +        */ +        loadGeoObjects: function () { +            if ($('#waiting').length){ +                $('#waiting').show(); +            } +            helpers.retrieve_checked_categories(); +            var ids = settings.checked_categories.join('_'); +            if (!ids) ids = '0'; +            var uri = extra_url + "getGeoObjects/" + ids; +            if (settings.display_submited) uri += "/A_S"; +            $.ajax({url: uri, +                    dataType: "json", +                    success: function (data) { +                        settings.layerMarkers.clearLayers(); +                        settings.layerVectors.clearLayers(); +                        settings.layerMarkers.addData(data); +                        /* +                        for (var i = 0; i < data.features.length; i++) { +                            var feature = data.features[i]; +                            if (feature.geometry.type == 'Point'){ +                                methods.addMarker(feature); +                            } else if (feature.geometry.type == 'LineString') { +                                methods.addRoute(feature); +                            } else if (feature.geometry.type == 'MultiLineString') { +                                methods.addMultiLine(feature); +                            } +                        }*/ +                    }, +                    error: function (data, textStatus, errorThrown) { +                        settings.layerMarkers.clearLayers(); +                        settings.layerVectors.clearLayers(); +                    }, +                    complete: function () { +                        if($('#waiting').length){$('#waiting').hide();} +                    } +                }); +        }, +        subcategory_detail: function(category_id){ +            var uri = extra_url + "getCategory/" + category_id; + +            $.ajax({url: uri, +                    dataType: "json", +                    success: function (data) { +                        if (!data.description){return} +                        $('#category_description').html(data.description); +                        $("#category_description").dialog("option", "title", +                                                          data.name); +                        $('#category_description').dialog('open'); +                    }, +                    error: function (data) { +                        // fail silently +                    } +                }); +        }, +        toggle_category: function (id) { +            // TODO make this id DOM element customisable +            // Check if element is currently visible or not +            var was_visible = $("#maincategory_" + id).is(":visible"); +            // Close all categories +            var category_plus = STATIC_URL + "chimere/img/plus.png"; +            var category_minus = STATIC_URL + "chimere/img/minus.png"; +            if (settings.category_accordion){ +                $("#categories ul.subcategories").hide(); +                $("#categories img.toggle_category").attr("src", category_plus); +                $("#categories .main_category").addClass("toggle_plus"); +                $("#categories .main_category").removeClass("toggle_minus"); +            } +            // Put a minus image +            if (!was_visible) +            { +                // Show the subcategories +                $("#maincategory_" + id).toggle(); +                $("#maincategory_" + id).parent().addClass("toggle_minus"); +                $("#maincategory_" + id).parent().removeClass("toggle_plus"); +                // Put a plus image +                $("#maincategory_img_" + id).attr("src", category_minus); +                settings.current_category = id; +            } +            if (!settings.category_accordion && was_visible) +            { +                $("#maincategory_" + id).toggle(); +                $("#maincategory_" + id).parent().addClass("toggle_plus"); +                $("#maincategory_" + id).parent().removeClass("toggle_minus"); +                // Put a minus image +                $("#maincategory_img_" + id).attr("src", category_plus); +            } +        }, +        zoom: function (options) { +            if ($.hasattr("category", options)) { +                helpers.zoom_to_category(options["category"]); +            } else if ($.hasattr("subcategories", options)) { +                helpers.zoom_to_subcategories(options["subcategories"]); +            } else if ($.hasattr("area", options)) { +                helpers.zoom_to_area(options["area"]); +            }          } // end of init      }; // End of public methods      var helpers = { +        getSubcategories: function (category_id) { +            if(settings.get_subcategories_fx) { +                return settings.get_subcategories_fx(category_id, settings); +            } +            else { +                var ul = document.getElementById('maincategory_'+category_id); +                var subcats = new Array(); +                for (i in ul.children){ +                    var li = ul.children[i]; +                    if (li.id){ +                        subcats.push(li.id.split('_').pop()); +                    } +                } +                return subcats; +            } +        }, +        retrieve_checked_categories: function () { +            /* +            * Retrieve checked_categories, and store it in settings  +            */ +            var initialized = false; +            $('#frm_categories .subcategories input:checkbox').each( +                function(index){ +                    if (!initialized){ +                        initialized = true; +                        settings.checked_categories = []; +                        settings.display_submited = false; +                    } +                    if ($(this).attr('checked') == 'checked' || $(this).attr('checked') == true){ +                        cat_id = $(this).attr('id').split('_').pop(); +                        settings.checked_categories.push(parseInt(cat_id)); +                    } +            }); +            if(initialized && ($('#display_submited_check').attr("checked") == "checked" || $('#display_submited_check').attr("checked") == true)){ +                settings.display_submited = true; +            } +        }, +        zoom_to: function (bounds) { +            settings.map.fitBounds(bounds); +        }, +        zoom_to_subcategories: function (ids) { +            // TODO add markers and check the subcategory, if not yet checked/displayed +            var ids = ids.join('_'); +            if (!ids) ids = '0'; +            var uri = extra_url + "getGeoObjects/" + ids; +            if (settings.display_submited) uri += "/A_S"; +            $.ajax({url: uri,  +                    dataType: "json", +                    success: function (data) { +                        // Create a generic bounds +                        var lon, lat, feature; +                        var points = new Array(); +                        for (var i = 0; i < data.features.length; i++) { +                            feature = data.features[i]; +                            if (feature.geometry.type == 'Point') { +                                lat = feature.geometry.coordinates[1]; +                                lon = feature.geometry.coordinates[0]; +                                points.push(settings.map.latLngToLayerPoint([lat, lon])); +                            } else if (feature.geometry.type == 'LineString') { +                                // TODO +                            } +                        } +                        var bound = L.Bounds(points); +                        helpers.zoom_to(bounds); +                   } +               }); +        }, +        zoom_to_category: function (id) { +            helpers.zoom_to_subcategories(helpers.getSubcategories(id)); +        }, +        zoom_to_area: function (coords) { +            /* zoom to an area */ +            helpers.zoom_to([[coords[1], coords[0]], +                             [coords[3], coords[2]]]); +            if (settings.dynamic_categories) { +                methods.loadCategories(); +            } +        }      }; // End of helpers      $.fn.chimere = function (thing) { diff --git a/chimere/static/chimere/js/jquery.chimere-ol.js b/chimere/static/chimere/js/jquery.chimere-ol.js index 2e2d238..6660b2e 100644 --- a/chimere/static/chimere/js/jquery.chimere-ol.js +++ b/chimere/static/chimere/js/jquery.chimere-ol.js @@ -17,20 +17,22 @@ See the file COPYING for details.  */  /* Add OpenLayers MapQuest layer management */ -OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { -    name: "MapQuestOSM", -    sphericalMercator: true, -    url: ' http://otile1.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png', -    clone: function(obj) { -        if (obj == null) { -            obj = new OpenLayers.Layer.OSM( -            this.name, this.url, this.getOptions()); -        } -        obj = OpenLayers.Layer.XYZ.prototype.clone.apply(this, [obj]); -        return obj; -    }, -    CLASS_NAME: "OpenLayers.Layer.MapQuestOSM" -}); +if (typeof(OpenLayers) != 'undefined'){ +    OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { +        name: "MapQuestOSM", +        sphericalMercator: true, +        url: ' http://otile1.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png', +        clone: function(obj) { +            if (obj == null) { +                obj = new OpenLayers.Layer.OSM( +                this.name, this.url, this.getOptions()); +            } +            obj = OpenLayers.Layer.XYZ.prototype.clone.apply(this, [obj]); +            return obj; +        }, +        CLASS_NAME: "OpenLayers.Layer.MapQuestOSM" +    }); +};  /*  * Little hasattr helper @@ -82,16 +84,13 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, {              hide_popup_fx: null,              // if leave to false every click on the map hide the pop-up              explicit_popup_hide: false, -            controls:[new OpenLayers.Control.Navigation(), -                      new OpenLayers.Control.PanPanel(), -                      new OpenLayers.Control.ZoomPanel(), -                      new OpenLayers.Control.ScaleLine()], -            popupClass: OpenLayers.Popup.FramedCloud, +            controls: null, +            popupClass: null,              popupContentFull: false, // if true the detail is inside the popup              category_accordion: true, // category opening behave like an accordion              maxResolution: 156543.0399,              units: 'm', -            projection: new OpenLayers.Projection('EPSG:4326'), +            projection: null,              theme: null,              enable_clustering: false,              routing: false, // enable routing management @@ -104,13 +103,10 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, {              current_category: null, // To store the current category clicked in list              current_route_feature: null, // To store the current route find by routing              itinerary_step_number:0, // current step number -            icon_offset: new OpenLayers.Pixel(0, 0), +            icon_offset: null,              edition: false, // edition mode              edition_type_is_route: false, // route or POI edition -            default_icon: new OpenLayers.Icon( -                    'http://www.openlayers.org/dev/img/marker-green.png', -                    new OpenLayers.Size(21, 25), -                    new OpenLayers.Pixel(-(21/2), -25)), +            default_icon: null,              cluster_icon: null,              marker_hover_id:'marker_hover',              marker_hover_content_id:'marker_hover_content', @@ -129,6 +125,27 @@ OpenLayers.Layer.MapQuestOSM = OpenLayers.Class(OpenLayers.Layer.XYZ, {          */          init: function ( options ) {              /* Manage parameters */ +            if (defaults.controls == null){ +                defaults.controls = [new OpenLayers.Control.Navigation(), +                                     new OpenLayers.Control.PanPanel(), +                                     new OpenLayers.Control.ZoomPanel(), +                                     new OpenLayers.Control.ScaleLine()]; +            } +            if (defaults.popupClass == null){ +                defaults.popupClass = OpenLayers.Popup.FramedCloud; +            } +            if (defaults.projection == null){ +                defaults.projection = new OpenLayers.Projection('EPSG:4326'); +            } +            if (defaults.icon_offset == null){ +                defaults.icon_offset = new OpenLayers.Pixel(0, 0); +            } +            if (defaults.default_icon == null){ +                defaults.default_icon = new OpenLayers.Icon( +                    'http://www.openlayers.org/dev/img/marker-green.png', +                    new OpenLayers.Size(21, 25), +                    new OpenLayers.Pixel(-(21/2), -25)); +            }              // not staticaly in default because of STATIC_URL init              if (defaults.cluster_icon == null && typeof STATIC_URL != 'undefined'){                  defaults.cluster_icon = new OpenLayers.Icon( diff --git a/chimere/templates/chimere/blocks/head_chimere.html b/chimere/templates/chimere/blocks/head_chimere.html index 099a044..dea92ec 100644 --- a/chimere/templates/chimere/blocks/head_chimere.html +++ b/chimere/templates/chimere/blocks/head_chimere.html @@ -1,5 +1,5 @@ -{% for css_url in MAP_CSS_URLS %} -<link rel="stylesheet" href="{{ css_url }}" />{% endfor %} +{% for css_url, condition in MAP_CSS_URLS %} +{% if condition %}<!--[if {{condition}}]>{%endif%}<link rel="stylesheet" href="{{ css_url }}" />{% if condition %}<![endif]-->{%endif%}{% endfor %}  {% for js_url in MAP_JS_URLS %}  <script src="{{ js_url }}" type="text/javascript"></script>{% endfor %}  {% if routing %}<script src="{{ STATIC_URL }}chimere/js/routing-widget.js" type="text/javascript"></script>{% endif %} @@ -13,11 +13,12 @@  <script src="{{ STATIC_URL }}chimere/js/base.js" type="text/javascript"></script>  <script type="text/javascript">      var DEFAULT_ZOOM = {{ DEFAULT_ZOOM }}; +    {% ifequal CHIMERE_VIEW_RENDERER 'openlayers' %}      var EPSG_DISPLAY_PROJECTION = epsg_display_projection = new OpenLayers.Projection('EPSG:{{ EPSG_DISPLAY_PROJECTION }}');      OpenLayers.ImgPath = '{{ STATIC_URL }}chimere/img/';      var EPSG_PROJECTION = epsg_projection = new OpenLayers.Projection('EPSG:{{ EPSG_PROJECTION }}');      var CENTER_LONLAT = centerLonLat = new OpenLayers.LonLat{{ DEFAULT_CENTER }}.transform(epsg_display_projection, epsg_projection); -    /*var map_layer = {{ MAP_LAYER|safe }};*/ +    {% endifequal %}      var restricted_extent;      {% if area_name %}      var area_name = '{{ area_name }}';{% endif %} diff --git a/chimere/templates/chimere/blocks/map.html b/chimere/templates/chimere/blocks/map.html index e00ff8b..6d4508d 100644 --- a/chimere/templates/chimere/blocks/map.html +++ b/chimere/templates/chimere/blocks/map.html @@ -36,8 +36,9 @@      {% if p_routing_end_lon %}chimere_init_options["routing_end_lon"] = {{ p_routing_end_lon }};{% endif %}      {% if p_routing_end_lat %}chimere_init_options["routing_end_lat"] = {{ p_routing_end_lat }};{% endif %}      {% if p_routing_steps %}chimere_init_options["routing_steps_lonlat"] = [{{ p_routing_steps }}];{% endif %} +    {% ifequal map_renderer 'openlayers' %}      chimere_init_options["icon_offset"] = new OpenLayers.Pixel({{icon_offset_x}}, -                                                            {{icon_offset_y}}); +                                                            {{icon_offset_y}});{% endifequal %}      chimere_init_options["dynamic_categories"] = {{ dynamic_categories }};      {% if p_display_submited %}chimere_init_options["display_submited"] = {{ p_display_submited }};{% endif %}      chimere_init_options["checked_categories"] = [{% for cc in checked_categories %}{% if forloop.counter0 > 0 %}, {% endif %}{{cc}}{% endfor %}]; diff --git a/chimere/templatetags/chimere_tags.py b/chimere/templatetags/chimere_tags.py index f086251..90252a1 100644 --- a/chimere/templatetags/chimere_tags.py +++ b/chimere/templatetags/chimere_tags.py @@ -143,6 +143,7 @@ def head_chimere(context, view=True):              "DEFAULT_CENTER": settings.CHIMERE_DEFAULT_CENTER,              "DEFAULT_ZOOM": settings.CHIMERE_DEFAULT_ZOOM,              "MAP_LAYER": settings.CHIMERE_DEFAULT_MAP_LAYER, +            "CHIMERE_VIEW_RENDERER": settings.CHIMERE_VIEW_RENDERER,              "MAP_CSS_URLS": settings.MAP_CSS_URLS[map_renderer],              "MAP_JS_URLS": settings.MAP_JS_URLS[map_renderer],              'routing': settings.CHIMERE_ENABLE_ROUTING \ @@ -183,7 +184,8 @@ def routing(context):  @register.inclusion_tag('chimere/blocks/map.html', takes_context=True)  def map(context, map_id='map'):      context_data =  {'map_id':map_id, -                     "STATIC_URL": settings.STATIC_URL} +                     "STATIC_URL": settings.STATIC_URL, +                     "map_renderer":settings.CHIMERE_VIEW_RENDERER}      context_data['icon_offset_x'] = settings.CHIMERE_ICON_OFFSET_X      context_data['icon_offset_y'] = settings.CHIMERE_ICON_OFFSET_Y      context_data['icon_width'] = settings.CHIMERE_ICON_WIDTH | 
