'300px', 'height' => '200px', 'zoom' => 3, 'maxzoom' => 14, 'controltype' => 'Small', 'align' => 'None', 'latlong' => '40,0', 'maptype' => 'Map', 'mtc' => 'standard', 'baselayers' => array('Map', 'Satellite', 'Hybrid'), 'styles' => array( 'line_default' => array('0000ff', 5, 45, '', 0, 0), 'poly_default' => array('000000', 3, 25, 'ff0000', 45), ), 'line_colors' => array('#00cc00', '#ff0000', '#0000ff'), ); $defaults['behavior'] = array(); $m = array(); $behaviors = module_invoke_all('gmap', 'behaviors', $m); foreach ($behaviors as $k => $v) { $defaults['behavior'][$k] = $v['default']; } $defaults = array_merge($defaults, variable_get('gmap_default', array())); return $defaults; } /** * Implementation of hook_theme(). */ function gmap_theme() { return array( 'views_view_gmap' => array('arguments' => array('element')), 'gmap_views_marker_label' => array('arguments' => array('element')), 'gmap_marker_popup' => array('arguments' => array('label')), 'gmap_overlay_edit' => array('arguments' => array('element')), 'gmap_macrotext' => array('arguments' => array('element')), 'gmap_dimension' => array('arguments' => array('element')), 'gmap_address' => array('arguments' => array('element')), 'gmap_align' => array('arguments' => array('element')), 'gmap_style' => array('arguments' => array('element')), 'gmap' => array('arguments' => array('element')), ); } /** * Implementation of hook_gmap(). */ function gmap_gmap($op, &$map) { switch ($op) { case 'macro': return array( 'points' => array( 'multiple' => TRUE, ), 'markers' => array( 'multiple' => TRUE, ), 'feed' => array( 'multiple' => TRUE, ), 'style' => array( 'multiple' => TRUE, ), ); case 'pre_theme_map': $path = drupal_get_path('module', 'gmap') .'/js/'; // Activate markers if needed. if ((isset($map['behavior']['dynmarkers']) && $map['behavior']['dynmarkers']) || !empty($map['markers'])) { static $header_set = FALSE; if (!$header_set) { $header_set = TRUE; // If the user is using private download method, it's up to them to get the path set up. if (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) != FILE_DOWNLOADS_PUBLIC) { $markerpath = variable_get('gmap_private_markerfile', ''); if (empty($markerpath) || !file_exists($markerpath)) { drupal_set_message(t('GMap marker file settings are not configured properly for Private download method, markers will not work!'), 'error'); } else { drupal_add_js($markerpath, 'module', 'header', FALSE, TRUE, FALSE); } } // With public method, we can handle all bookkeeping ourselves. else { $markerpath = file_create_path('js'); if (!$markerpath || !file_exists("$markerpath/gmap_markers.js")) { gmap_regenerate_markers(); $markerpath = file_create_path('js'); } drupal_add_js("$markerpath/gmap_markers.js", 'module', 'header', FALSE, TRUE, FALSE); } } drupal_add_js($path .'icon.js'); drupal_add_js($path .'marker.js'); $mm = variable_get('gmap_mm_type', 'gmap'); // If you really really want to override the marker manager, implement // this, take $mm by ref, and have fun. --Bdragon if (function_exists('_gmap_markermanager_override')) { _gmap_markermanager_override($mm); } drupal_add_js($path . $mm .'_marker.js'); } if (isset($map['behavior']['locpick']) && $map['behavior']['locpick']) { drupal_add_js($path .'locpick.js'); } if (!empty($map['markers']) || !empty($map['lines'])) { drupal_add_js($path .'markerloader_static.js'); } if (!empty($map['shapes'])) { drupal_add_js($path .'shapeloader_static.js'); drupal_add_js($path .'gmap_shapes.js'); } if (isset($map['feed']) && is_array($map['feed'])) { drupal_add_js($path .'markerloader_georss.js'); } break; case 'macro_multiple': return array('points', 'markers', 'feed', 'circle', 'rpolygon', 'polygon', 'line', 'style'); case 'behaviors': return array( 'locpick' => array( 'title' => t('Location chooser'), 'default' => FALSE, 'help' => t('Used to activate location choosing using a gmap.'), 'internal' => TRUE, ), 'nodrag' => array( 'title' => t('Disable dragging'), 'default' => FALSE, 'help' => t('Remove the ability for the user to drag the map. If dragging is disabled, keyboard shortcuts are implicitly disabled.'), ), 'nokeyboard' => array( 'title' => t('Disable keyboard'), 'default' => TRUE, 'help' => t('Disable the keyboard shortcuts.'), ), 'nomousezoom' => array( 'title' => t('Disable mousezoom'), 'default' => FALSE, 'help' => t('Disable using the scroll wheel to zoom the map.'), ), 'nocontzoom' => array( 'title' => t('Disable Continuous Zoom'), 'default' => FALSE, 'help' => t('Disable dynamically resizing images while waiting for tiles to load when zooming.'), ), 'autozoom' => array( 'title' => t('Use AutoZoom'), 'default' => FALSE, 'help' => t('Automatically zoom the map to fit all markers when markers are added.'), ), 'dynmarkers' => array( 'title' => t('Unconditionally enable marker interface'), 'default' => FALSE, 'help' => t('Load the marker loader system even if no markers to load are detected. Useful if you are injecting markers from somewhere else.'), ), 'overview' => array( 'title' => t('Enable Overview Map'), 'default' => FALSE, 'help' => t('Enable the "overview map" in the bottom right corner.'), 'previewable' => TRUE, ), /* 'notype' => array( 'title' => t('Disable map type control'), 'default' => FALSE, 'help' => t('Removes the map type control from the upper right corner. Recommended for very narrow maps.'), 'previewable' => TRUE, ), */ 'collapsehack' => array( 'title' => t('Work around bugs when maps appear in collapsible fieldsets'), 'default' => FALSE, 'help' => t('Enabling this will work around some issues that can occur when maps appear inside collapsible fieldsets.'), ), // Note to myself, who keeps forgetting what a scale control actually IS.: // |------------ 1mi ------------| 'scale' => array( 'title' => t('Add scale control to map.'), 'default' => FALSE, 'help' => t('Adds a scale control to the map in the default position.'), 'previewable' => TRUE, ), 'extramarkerevents' => array( 'title' => t('Enable extra marker events.'), 'default' => FALSE, 'help' => t('Used for advanced javascript work, this will enable the mouseovermarker, mouseoutmarker, and dblclickmarker events.'), 'internal' => TRUE, ), 'clickableshapes' => array( 'title' => t('Enable clickable shapes.'), 'default' => FALSE, 'help' => t('Used for advanced javascript work, this will enable the clickshape event.'), 'internal' => TRUE, ), ); break; case 'baselayers': $map['Google']['Map'] = array( 'title' => t('Map: Standard street map.'), 'default' => TRUE, 'help' => t('The standard default street map. Internal name: G_NORMAL_MAP'), ); $map['Google']['Satellite'] = array( 'title' => t('Satellite: Standard satellite map.'), 'default' => TRUE, 'help' => t('Satellite view without street overlay. Internal name: G_SATELLITE_MAP'), ); $map['Google']['Hybrid'] = array( 'title' => t('Hybrid: Hybrid satellite map.'), 'default' => TRUE, 'help' => t('Satellite view with street overlay. Internal name: G_HYBRID_MAP'), ); $map['Google']['Physical'] = array( 'title' => t('Terrain: Physical feature map.'), 'default' => FALSE, 'help' => t('Map with physical data (terrain, vegetation.) Internal name: G_PHYSICAL_MAP'), ); break; } } /** * Set up the HTML header for GMap. * If you are going to include a custom JS file that extends GMap, you probabaly * want to call this first to ensure that the core js files have been added. */ function _gmap_doheader() { static $gmap_initialized = FALSE; if ($gmap_initialized) { return; } $gmap_path = drupal_get_path('module', 'gmap'); drupal_add_css($gmap_path .'/gmap.css'); drupal_add_js($gmap_path .'/js/gmap.js'); $mm = variable_get('gmap_mm_type', 'gmap'); $mms = variable_get('gmap_markermanager', array()); if (empty($mms[$mm])) { $mms[$mm] = array(); } // If you really really want to override the marker manager, implement // this, take $mm by ref, and have fun. --Bdragon if (function_exists('_gmap_markermanager_override')) { _gmap_markermanager_override($mm, $mms); } if ($mm == 'clusterer' || $mm == 'clustermarker') { // Needed for access to clusterer marker. drupal_add_js($gmap_path .'/js/icon.js'); } if (isset($mms[$mm]['filename'])) { drupal_add_js($gmap_path .'/thirdparty/'. $mms[$mm]['filename']); } drupal_add_js($gmap_path .'/js/marker.js'); drupal_add_js($gmap_path .'/js/'. $mm .'_marker.js'); drupal_add_js(array('gmap_markermanager' => $mms[$mm]), 'setting'); // @@@ drupal_add_js($gmap_path .'/js/poly.js'); global $language; $query = array( 'file' => 'api', 'v' => variable_get('gmap_api_version', GMAP_API_VERSION), 'key' => gmap_get_key(), 'hl' => $language->language, ); drupal_set_html_head(''); $gmap_initialized = TRUE; } /** * Convert a macro string into a GMap array. * * @param $instring * Macro to process. * @param $ver * Version to treat macro as. * Set to 1 when processing very old macros, otherwise leave as is. * @return * A GMap array. */ function gmap_parse_macro($instring, $ver = 2) { require_once drupal_get_path('module', 'gmap') .'/gmap_parse_macro.inc'; return _gmap_parse_macro($instring, $ver); } /** * Theme a marker popup. * This will get called for markers embedded in macros. * @ingroup themeable */ function theme_gmap_marker_popup($label) { return $label; } /** * Location chooser utility function. * * Creates a map that can be interactively used to fill a form with a * location (latitude, longitude and zoom level). * * Note: This is a utility function designed for location.module, there is no * guarantee it will not be removed eventually. * * @param $map * Either a macro to use as the base map for setting a location, or an already set map associative array. * @param $form * A formset associative array. Cannot be more than one deep. * @param $fields * An associative array for the field names. 'latitude', 'longitude'=>name of respective array, 'address' is optional. * @return * A string with the google map code to be inserted onto the page. * */ function gmap_set_location($map, &$form, $fields) { static $ctr = 0; $ctr++; if (!is_array($map)) { $map = array_merge(gmap_defaults(), gmap_parse_macro($map)); } $id = 'loc'. $ctr; $map['id'] = $id; // This is a locpick map. $map['behavior']['locpick'] = TRUE; $element = array( '#type' => 'gmap', '#map' => $map['id'], '#settings' => $map, ); $form[$fields['latitude']]['#map']=$id; gmap_widget_setup($form[$fields['latitude']], 'locpick_latitude'); $form[$fields['longitude']]['#map']=$id; gmap_widget_setup($form[$fields['longitude']], 'locpick_longitude'); if (isset($fields['address'])) { $form[$fields['address']]['#map'] = $id; gmap_widget_setup($form[$fields['address']], 'locpick_address'); } return theme('gmap', $element); } /** * Handle filter preparation. */ function _gmap_prepare($intext) { $out = FALSE; $matches = array(); preg_match_all('/\[gmap([^\[\]]+ )* \] /x', $intext, $matches); $i = 0; while (isset($matches[1][$i])) { $out[0][$i] = $matches[0][$i]; if ($matches[1][$i][0] == '1') { $ver = 1; $matches[1][$i] = substr($matches[0][$i], 1); } else { $ver = 2; } $map = array('#settings' => gmap_parse_macro($matches[1][$i], $ver)); $out[1][$i] = theme('gmap', $map); $i++; } // endwhile process macro return $out; } /** * Make sure a string is a valid css dimension. */ function gmap_todim($instring) { if (!is_string($instring)) { return FALSE; } $s = strtolower(trim($instring)); $matches = array(); if (preg_match('/^([\d.]+)\s*(em|ex|px|in|cm|mm|pt|pc|%)$/', $s, $matches)) { return $matches[1] . $matches[2]; } else { return FALSE; } } /** * Ensure a textfield is a valid css dimension string. */ function gmap_dimension_validate(&$elem, &$form_state) { $value = gmap_todim($elem['#value']); if ($value) { // Normalize the css dimension string. form_set_value($elem, $value, $form_state); } else { form_error($elem, t('The specified value is not a valid CSS dimension.')); } } /** * Implementation of hook_filter(). */ function gmap_filter($op, $delta = 0, $format = -1, $text = '') { switch ($op) { case 'list': return (array(0 => t('GMap macro expander'))); case 'name': return t('Google map filter'); case 'description': return t('Converts a Google Map macro into the HTML required for inserting a Google Map.'); case 'process': $gmaps = _gmap_prepare($text); //returns an array of $tables[0] = table macro $table[1]= table html if ($gmaps) { // there are table macros in this node return str_replace($gmaps[0], $gmaps[1], $text); } else { return $text; } case 'prepare': return $text; case 'no cache': return TRUE; // @@@ Possibly improve efficiency in the future? } } /** * Implementation of hook_filter_tips(). */ function gmap_filter_tips($delta, $format, $long = FALSE) { if (user_access('create gmap macro')) { // only display macro if user can create one return t('Insert Google Map macro.') .''. t('Create a macro') .''; } else { return t('Insert Google Map macro.'); } } /** * Implementation of hook_menu(). */ function gmap_menu() { $items['admin/settings/gmap'] = array( 'title' => 'GMap', 'description' => 'Configure GMap settings', 'page callback' => 'drupal_get_form', 'page arguments' => array('gmap_admin_settings'), 'file' => 'gmap_settings_ui.inc', 'access arguments' => array('administer site configuration'), 'type' => MENU_NORMAL_ITEM, ); return $items; } /** * Regenerate the markerdata file. */ function gmap_regenerate_markers() { $contents = ''; // Create the js/ within the files folder. $jspath = file_create_path('js'); file_check_directory($jspath, FILE_CREATE_DIRECTORY); $contents .= "// GMap marker image data.\n"; $contents .= "Drupal.gmap.iconpath = ". drupal_to_js(base_path() . variable_get('gmap_markerfiles', drupal_get_path('module', 'gmap') .'/markers')) .";\n"; $contents .= "Drupal.gmap.icondata = ". drupal_to_js(gmap_get_icondata(TRUE)) .";\n"; file_save_data($contents, "$jspath/gmap_markers.js", FILE_EXISTS_REPLACE); // Also regenerate the cached marker titles array gmap_get_marker_titles(TRUE); } /** * Implementation of hook_flush_caches(). */ function gmap_flush_caches() { gmap_regenerate_markers(); } /** * Implementation of hook_elements(). */ function gmap_elements() { return array( 'gmap' => array( '#input' => FALSE, // This isn't a *form* input!! '#settings' => array_merge(gmap_defaults(), array( 'points' => array(), 'pointsOverlays' => array(), 'lines' => array(), )), ), 'gmap_macrotext' => array( '#input' => TRUE, '#gmap_newtype' => 'textarea', '#theme' => 'gmap_macrotext', '#process' => array('process_gmap_control'), ), 'gmap_overlay_edit' => array('#input' => TRUE, '#process' => array('process_gmap_overlay_edit')), 'gmap_style' => array('#input' => TRUE, '#tree' => TRUE, '#gmap_style_type' => 'poly', '#process' => array('process_gmap_style')), 'gmap_address' => array('#input' => TRUE, '#process' => array('process_gmap_address')), 'gmap_align' => array('#input' => TRUE, '#process' => array('process_gmap_align')), 'gmap_latitude' => array('#input' => TRUE, '#gmap_newtype' => 'textfield', '#process' => array('process_gmap_control')), 'gmap_longitude' => array('#input' => TRUE, '#gmap_newtype' => 'textfield', '#process' => array('process_gmap_control')), 'gmap_latlon' => array('#input' => TRUE, '#gmap_newtype' => 'textfield', '#process' => array('process_gmap_control')), 'gmap_markerchooser' => array('#input' => TRUE, '#process' => array('process_gmap_markerchooser')), 'gmap_dimension' => array('#input' => TRUE, '#gmap_newtype' => 'textfield', '#process' => array('process_gmap_control'), '#element_validate' => array('gmap_dimension_validate')), ); } /** * Generic gmap control #process function. */ function process_gmap_control($element, $edit, &$form_state, $complete_form) { $control = substr($element['#type'], 5); $element['#type'] = $element['#gmap_newtype']; unset($element['#gmap_newtype']); gmap_widget_setup($element, $control); // Attempt to run any #process handlers of our transmogrified type. // However, if we aren't the only #process handler, we assume someone else // is taking care of setting up any default handlers. $chain = FALSE; if (count($element['#process']) == 1) { // Unset #process so we can pull in the default. unset($element['#process']); $chain = TRUE; } // Inherit #input from the new type. unset($element['#input']); // Merge in the defaults for the target element type. $element += _element_info($element['#type']); if (isset($element['#input']) && $element['#input']) { if (isset($element['#process']) && $chain) { // Chain process. foreach ($element['#process'] as $process) { if (function_exists($process)) { $form = $process($element, $edit, $form_state, $complete_form); } } } } return $element; } /** * Style fieldset #process function. */ function process_gmap_style($element) { $isline = ($element['#gmap_style_type'] == 'line'); // Stroke color $element[0] = array( '#type' => 'textfield', '#size' => 6, '#maxlength' => 6, '#field_prefix' => '#', '#title' => t('Stroke color'), '#value' => $element['#value'][0], '#attributes' => array('class' => 'gmap_style'), ); // Stroke weight $element[1] = array( '#type' => 'textfield', '#title' => t('Stroke weight'), '#description' => t('Thickness of line, in pixels.'), '#size' => 3, '#maxlength' => 3, '#field_suffix' => t('px'), '#value' => $element['#value'][1], '#attributes' => array('class' => 'gmap_style'), ); // Stroke opacity $element[2] = array( '#type' => 'textfield', '#title' => t('Stroke opacity'), '#size' => 3, '#maxlength' => 3, '#field_suffix' => '%', '#value' => $element['#value'][2], '#attributes' => array('class' => 'gmap_style'), ); // Fill color $element[3] = array( '#type' => 'textfield', '#title' => t('Fill color'), '#description' => t('Hex color value for fill color. Example: #00AA33'), '#size' => 6, '#maxlength' => 6, '#field_prefix' => '#', '#value' => $isline ? '' : $element['#value'][3], '#disabled' => $isline, '#attributes' => array('class' => 'gmap_style'), ); $element[4] = array( '#type' => 'textfield', '#title' => t('Fill opacity'), '#description' => t('Opacity of fill, from 0 to 100%.'), '#size' => 3, '#maxlength' => 3, '#field_suffix' => '%', '#value' => $isline ? '' : $element['#value'][4], '#disabled' => $isline, '#attributes' => array('class' => 'gmap_style'), ); unset($element['#input']); $element += _element_info('fieldset'); return $element; } /** * Theme a gmap_style fieldset. * @ingroup themeable */ function theme_gmap_style($element) { // Fieldsets print #value at the end, so we need to empty it out. // Otherwise, it puts "Array" at the end of the fieldset. $element['#value'] = ''; return theme('fieldset', $element, $element['#children']); } /** * Overlay editor #process function. */ function process_gmap_overlay_edit($element) { // Conver the root element into a fieldset. $element['#type'] = 'fieldset'; if (!isset($element['#title'])) { $element['#title'] = t('Overlay editor'); } $element['#tree'] = TRUE; $element['mapclicktype'] = array( '#type' => 'select', '#title' => t('Click map'), '#map' => $element['#map'], '#options' => array( 'Points' => t('Points'), 'Lines' => t('Lines'), 'Circles' => t('Circles'), 'GPolygon' => t('Filled Polygons'), ), ); gmap_widget_setup($element['mapclicktype'], 'overlayedit_mapclicktype'); $element['markerclicktype'] = array( '#type' => 'select', '#title' => t('Click marker / segment'), '#map' => $element['#map'], '#options' => array( 'Remove' => t('Remove'), // 'updatestyle' => t('Update Styles'), // 'removestyle' => t('Remove Styles'), 'Edit Info' => t('Edit Info'), ), ); gmap_widget_setup($element['markerclicktype'], 'overlayedit_markerclicktype'); $element['marker'] = array( '#type' => 'select', '#map' => $element['#map'], '#options' => gmap_get_marker_titles(), '#title' => t('Marker'), '#theme' => 'gmap_overlay_edit', ); gmap_widget_setup($element['marker'], 'overlayedit'); $element['linestyle'] = array( '#type' => 'gmap_style', '#title' => t('Line style'), '#gmap_style_type' => 'line', '#default_value' => array('0000ff', 5, 45, '', ''), // @@@ ); gmap_widget_setup($element['linestyle'], 'overlayedit_linestyle', $element['#map']); $element['linestyle']['linestyle_apply'] = array( '#tree' => FALSE, '#type' => 'checkbox', '#title' => t('Use for new and changed lines'), '#default_value' => FALSE, ); gmap_widget_setup($element['linestyle']['linestyle_apply'], 'overlayedit_linestyle_apply', $element['#map']); $element['polystyle'] = array( '#type' => 'gmap_style', '#title' => t('Polygon style'), '#gmap_style_type' => 'poly', '#default_value' => array('000000', 3, 25, 'ff0000', 45), // @@@ ); gmap_widget_setup($element['polystyle'], 'overlayedit_polystyle', $element['#map']); $element['polystyle']['polystyle_apply'] = array( '#tree' => FALSE, '#type' => 'checkbox', '#title' => t('Use for new and changed polygons'), '#default_value' => FALSE, ); gmap_widget_setup($element['polystyle']['polystyle_apply'], 'overlayedit_polystyle_apply', $element['#map']); $element += _element_info('fieldset'); return $element; } /** * Alignment selector #process function. */ function process_gmap_align($element) { $element['#type'] = 'select'; gmap_widget_setup($element, 'align'); $element['#options'] = drupal_map_assoc(array('None', 'Right', 'Left', 'Center')); $element['#theme'] = 'gmap_align'; $element += _element_info('select'); return $element; } /** * Address widget #process function. */ function process_gmap_address($element) { $element['#type'] = 'textfield'; gmap_widget_setup($element, 'address'); $element['#theme'] = 'gmap_address'; $element += _element_info('textfield'); return $element; } /** * Marker chooser #process function. */ function process_gmap_markerchooser($element) { $element['#type'] = 'select'; $options = gmap_get_marker_titles(); if (!isset($element['#required']) || !$element['#required']) { $options = array('' => t('Default')) + $options; } $element['#options'] = $options; $element += _element_info('select'); return $element; } /** * Overlay editor theme function. * @ingroup themeable */ function theme_gmap_overlay_edit($element) { $path = drupal_get_path('module', 'gmap'); drupal_add_js($path .'/js/gmap.js'); drupal_add_js($path .'/js/gmap_shapes.js'); drupal_add_js($path .'/js/overlay_edit.js'); return theme('select', $element); } /** * Perform some normalization on the map object * to prevent errors. */ function gmap_map_cleanup(&$map) { // Google is picky about this one. $map['zoom'] = (int)$map['zoom']; // Normalize latitude / longitude if ($map['latlong']) { $map['latlon'] = $map['latlong']; unset($map['latlong']); } if (isset($map['latlon']) && (!isset($map['latitude']) || !isset($map['longitude']))) { list($map['latitude'], $map['longitude']) = explode(',', $map['latlon']); } unset($map['latlon']); foreach ($map['baselayers'] as $k => $v) { if (!$v) { unset($map['baselayers'][$k]); } } } function theme_gmap_macrotext($element) { drupal_add_js(drupal_get_path('module', 'gmap') .'/js/macro.js'); // @@@ drupal_add_js(drupal_get_path('module', 'gmap') .'/js/macrobuilder.js'); return theme('textarea', $element); } function theme_gmap_address($element) { drupal_add_js(drupal_get_path('module', 'gmap') .'/js/address.js'); $element['#autocomplete_path'] = ''; return theme('textfield', $element); } function theme_gmap_align($element) { drupal_add_js(drupal_get_path('module', 'gmap') .'/js/align.js'); $element['#multiple'] = FALSE; return theme('select', $element); } /** * Gmap element theme hook */ function theme_gmap($element) { // Track the mapids we've used already. static $mapids = array(); _gmap_doheader(); // Convert from raw map array if needed. if (!isset($element['#settings'])) { $element = array( '#settings' => $element, ); } $mapid = FALSE; if (isset($element['#map']) && $element['#map']) { // The default mapid is #map. $mapid = $element['#map']; } if (isset($element['#settings']['id'])) { // Settings overrides it. $mapid = $element['#settings']['id']; } if (!$mapid) { // Hmm, no mapid. Generate one. $mapid = gmap_get_auto_mapid(); } // Push the mapid back into #map. $element['#map'] = $mapid; gmap_widget_setup($element, 'gmap', $mapid); if (!$element['#settings']) { $element['#settings'] = array(); } // Push the mapid back into #settings. $element['#settings']['id'] = $mapid; $mapdefaults = gmap_defaults(); $map = array_merge($mapdefaults, $element['#settings']); // Styles is a subarray. if (isset($element['#settings']['styles'])) { $map['styles'] = array_merge($mapdefaults['styles'], $element['#settings']['styles']); } gmap_map_cleanup($map); // Add a class around map bubble contents. // @@@ Bdragon sez: Becw, this doesn't belong here. Theming needs to get fixed instead.. if (isset($map['markers'])) { foreach ($map['markers'] as $i => $marker) { $map['markers'][$i]['text'] = '