module Ropenlayer module Openlayer class Map attr_reader :js_id attr_reader :div_id attr_reader :js_propierties attr_reader :options attr_reader :layer_names attr_reader :layers attr_reader :js_helper attr_accessor :layers_select attr_accessor :control_names attr_accessor :controls attr_accessor :markers_layer attr_accessor :vectors_layer attr_accessor :js_notification_area attr_accessor :form_localizations_fields attr_accessor :draw_features # used to scope js variables created with the map. Js name will be created with this prefix + plus dom_id argument MAP_JS_PREFIX = 'olObject' DEFAULT_ADD_FEATURE_CALLBACK = 'addFeatureToMap' # == Initialize # # Create a map object with parsed attributes. Ropenlayer manage two ids for each map. # - js_div, use to scope all the variables names to draw js output. # - div_id, the dom_id passed as argument to construtor. For example # # For example # # m = Ropenlayer::Openlayer::Map.new('group_map') # => # m.js_id # => "olObject_group_map" # n.div_id # => "group_map" # # To draw map, just call to_js method. For example, in a rails 3.x application # # <%= raw javascript_tag(Ropenlayer::Openlayer::Map.new('group_map').to_js) %> # # Ropenlayer::Openlayer::Map use this options # # - layers: Select which layers are used in map. For a list of available layers see Ropenlayer::Openlayer::Laye::Baser # - default_layer: Default layer at render. Default layers.first # - layer_select: If true, map will render a control for change between differents layers # - controls: Select which controls are used in map. For a list of available controlse see Ropenlayer::Openlayer::Control # - latitude: Specify default latitude for map. Map will be pointed at this latitude at render. # - longitude: Specify default longitude for map. Map will be pointed at this longitude at render. # - zoom: Specify default zoom for map. Map will be render with this zoom enable. # - edit_map: If true, map will display a custom control what enable edit capabilities with map # # Map object accepts other options scoped in :map_js_options key. # # - theme: CSS theme used to display. By default none is used # - projection: Specify projection. Argument must be a valid OpenLayers.Projection JS object. See more on # - units: Units for measure. By default: "'m'" # - maxResolution: maxResolution of the map, by default word length: "156543.0339" # - meaxExtentd: Bound for projection. Must be valid OpenLayers.Bounds object. By default world length bound. See for more info. # # After display objects, you can, ofc, call methods from openlayers api to instace js variable. For example # # <% map = Ropenlayer::Openlayer::Map.new('group_map') %> # <%= raw javascript_tag map.to_js %> # <%= raw javascript_tag "#{ map.js_id }.setCenter(new OpenLayers.LonLat(0,0), 10);" %> # # Will call the setCenter OpenLayer.Map JS method to map.js_id js instace object # def initialize(dom_id, options = {}) @js_id = "#{ MAP_JS_PREFIX }_#{ dom_id }" @div_id = "#{ dom_id }" options[:add_feature_callback] ||= DEFAULT_ADD_FEATURE_CALLBACK @options = options @js_propierties = map_js_propierties(options[:map_js_options]) @layer_names = @options[:layers] || self.class.default_layers if options[:default_layer] def_layer = @layer_names.delete(options[:default_layer]) @layer_names = @layer_names.push(def_layer).reverse if def_layer end @layers = Ropenlayer::Openlayer::Layer::Base.build_collection(self) @control_names = @options[:controls] || self.class.default_controls @controls = Ropenlayer::Openlayer::Control.build_collection(self) @latitude = @options[:latitude] || self.class.default_latitude @longitude = @options[:longitude] || self.class.default_longitude @zoom = @options[:zoom] || self.class.default_zoom @layers_select = @options[:layer_select].nil? or @options[:layer_select] @edit_map = @options[:edit_map] @markers_layer = Ropenlayer::Openlayer::Layer::ElementsMarker.new(self) @vectors_layer = Ropenlayer::Openlayer::Layer::ElementsVector.new(self) @draw_features = options[:draw_features] || [] @js_notification_area = "#{ @js_id }_notification_area" @form_localizations_fields = {} @js_helper = Ropenlayer.js_helper end def map_js_propierties(map_js_options = {}) map_js_options ||= {} propierties = {} propierties[:div] = "'#{ div_id }'" propierties[:controls] = "[]" propierties[:theme] = map_js_options[:theme] || "'/stylesheets/ropenlayer.css'" propierties[:projection] = map_js_options[:projection] || "#{ Ropenlayer::Openlayer::Js.new_method("OpenLayers.Projection", :args => ["'EPSG:900913'"]) }" propierties[:units] = map_js_options[:units] || "'m'" propierties[:eventListeners] = map_js_options[:eventListeners] if map_js_options[:eventListeners] propierties[:maxResolution] = map_js_options[:units] || "156543.0339" propierties[:maxExtent] = map_js_options[:maxExtent] || "#{ Ropenlayer::Openlayer::Js.new_method("OpenLayers.Bounds", :args => ["-20037508", "-20037508", "20037508", "20037508.34"]) }" propierties end def set_center %(// Setting center #{ Ropenlayer::Openlayer::Js.new("#{ @js_id }.setCenter(#{ Ropenlayer::Openlayer::Js.new_method("OpenLayers.LonLat", :args => [ @longitude, @latitude ]) }, #{ @zoom })").to_js } ) end def add_notification_area %(// Notification area #{ Ropenlayer::Openlayer::Js.new_var(@js_notification_area, Ropenlayer::Openlayer::Js.new(@js_helper.create_xhtml_element('div', { :class => "'olMapNotificationArea'", :style => "'display: none;'", :id => "'#{ @js_notification_area }'" })).to_js) } ) end def self.default_layers [ :google_hybrid, :google_streets, :wms, :google_satellite, :google_physical, :osm ] end def self.default_latitude 4580313.35287 end def self.default_longitude 263274.20626803 end def self.default_zoom 4 end def self.default_controls [ :scale_line, :mouse_position, :pan_panel, :navigation, :zoom_panel ] end # Map to JS OpenLayer construtor def to_js %( // Ropenlayer::Openlayer::Map.to_s OpenLayers Cartographic JS project licensed under BSD~style license. More information can be found at http://openlayers.org/ #{ Ropenlayer::Openlayer::Js.new_var(@js_id, Ropenlayer::Openlayer::Js.new_method("OpenLayers.Map", :propierties => @js_propierties)).to_js } #{ add_notification_area } #{ @layers.map(&:to_js) } #{ @controls.map(&:to_js) } #{ set_center } #{ Ropenlayer::Openlayer::BoxControl::LayersSelect.new(self).to_js if @layers_select } #{ Ropenlayer::Openlayer::BoxControl::EditMap.new(self).to_js if @edit_map } #{ @vectors_layer.to_js } #{ @markers_layer.to_js } #{ Ropenlayer::Openlayer::Feature.draw_collection(self) if @draw_features.any? } ) end end end end