Your IP : 216.73.216.43


Current Path : /home/cbequiperp/www/plugins/flexicontent_fields/addressint/
Upload File :
Current File : /home/cbequiperp/www/plugins/flexicontent_fields/addressint/addressint.php

<?php
/**
 * @package         FLEXIcontent
 * @version         3.4
 *
 * @author          Emmanuel Danan, Georgios Papadakis, Yannick Berges, others, see contributor page
 * @link            https://flexicontent.org
 * @copyright       Copyright © 2020, FLEXIcontent team, All Rights Reserved
 * @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
 */

defined( '_JEXEC' ) or die( 'Restricted access' );
JLoader::register('FCField', JPATH_ADMINISTRATOR . '/components/com_flexicontent/helpers/fcfield/parentfield.php');

class plgFlexicontent_fieldsAddressint extends FCField
{
	static $field_types = null; // Automatic, do not remove since needed for proper late static binding, define explicitely when a field can render other field types
	var $task_callable = null;  // Field's methods allowed to be called via AJAX

	// ***
	// *** CONSTRUCTOR
	// ***

	public function __construct( &$subject, $params )
	{
		parent::__construct( $subject, $params );
	}



	// ***
	// *** DISPLAY methods, item form & frontend views
	// ***

	// Method to create field's HTML display for item form
	public function onDisplayField(&$field, &$item)
	{
		if ( !in_array($field->field_type, static::$field_types) ) return;

		$field->label = $field->parameters->get('label_form') ? JText::_($field->parameters->get('label_form')) : JText::_($field->label);

		// Set field and item objects
		$this->setField($field);
		$this->setItem($item);

		$use_ingroup = $field->parameters->get('use_ingroup', 0);
		if (!isset($field->formhidden_grp)) $field->formhidden_grp = $field->formhidden;
		if ($use_ingroup) $field->formhidden = 3;
		if ($use_ingroup && empty($field->ingroup)) return;


		// Initialize framework objects and other variables
		$document = JFactory::getDocument();
		$cparams  = JComponentHelper::getParams( 'com_flexicontent' );

		$tooltip_class = 'hasTooltip';
		$add_on_class    = $cparams->get('bootstrap_ver', 2)==2  ?  'add-on' : 'input-group-addon';
		$input_grp_class = $cparams->get('bootstrap_ver', 2)==2  ?  'input-append input-prepend' : 'input-group';
		$form_font_icons = $cparams->get('form_font_icons', 1);
		$font_icon_class = $form_font_icons ? ' fcfont-icon' : '';
		$font_icon_class .= FLEXI_J40GE ? ' icon icon- ' : '';


		/**
		 * Number of values
		 */

		$multiple     = $use_ingroup || (int) $field->parameters->get('allow_multiple', 0);
		$max_values   = $use_ingroup ? 0 : (int) $field->parameters->get('max_values', 0);
		$required     = (int) $field->parameters->get('required', 0);
		$add_position = (int) $field->parameters->get('add_position', 3);

		// Classes for marking field required
		$required_class = $required ? ' required' : '';

		// If we are multi-value and not inside fieldgroup then add the control buttons (move, delete, add before/after)
		$add_ctrl_btns = !$use_ingroup && $multiple;
		$fields_box_placing = (int) $field->parameters->get('fields_box_placing', 0);

		/**
		 * Value handling
		 */

		$values = $this->parseValues($field->value);

		if (empty($values))
		{
			// Default value
			$field->value = array(0 => array(
				'autocomplete' => '',
				'addr_display' => '',
				'addr_formatted' => '',
				'name' => '',
				'addr1' => '',
				'addr2' => '',
				'addr3' => '',
				'city' => '',
				'state' => '',
				'province' => '',
				'zip' => '',
				'zip_suffix' => '',
				'country' => '',
				'lat' => '',
				'lon' => '',
				'url' => '',
				'zoom' => '',
				'custom_marker' => '',
				'marker_anchor' => ''
			));
			$values = $field->value;
		}
		$this->values = & $values;


		// MAP Engine to use in item form
		$mapapi_edit    = $field->parameters->get('mapapi_edit', 'googlemap');

		// Some parameter shortcuts
		$addr_edit_mode = $field->parameters->get('addr_edit_mode', 'plaintext');
		$edit_latlon    = (int) $field->parameters->get('edit_latlon',  1);
		$use_name       = (int) $field->parameters->get('use_name',     1);
		$use_addr2      = (int) $field->parameters->get('use_addr2',    1);
		$use_addr3      = (int) $field->parameters->get('use_addr3',    1);
		$use_usstate    = (int) $field->parameters->get('use_usstate',  1);
		$use_province   = (int) $field->parameters->get('use_province', 1);
		$use_zip_suffix = (int) $field->parameters->get('use_zip_suffix', 1);
		$use_country    = (int) $field->parameters->get('use_country',  1);

		$use_custom_marker   = (int) $field->parameters->get('use_custom_marker', 1);
		$default_marker_file = $field->parameters->get('default_marker_file', '');
		$custom_marker_path  = $field->parameters->get('custom_marker_path', 'modules/mod_flexigooglemap/assets/marker');

		// Map configuration
		$map_type   = $field->parameters->get('map_type', 'roadmap');
		$map_zoom   = (int) $field->parameters->get('map_zoom', 16);
		$map_width  = (int) $field->parameters->get('map_width_form', 350);
		$map_height = (int) $field->parameters->get('map_height_form', 250);

		// Get required properties from field configuration
		$required_props = $addr_edit_mode != 'plaintext'
			? $field->parameters->get('required_props', array())
			: $field->parameters->get('required_props_plaintext', array());

		$required_props = $required && !$required_props
			? array('address')
			: $required_props;

		// Google autocomplete search types drop down list (for geolocation)
		$list_ac_types = array(
			//''=>'PLG_FLEXICONTENT_FIELDS_ADDRESSINT_AC_ALL_SEARCH_TYPES',
			''=>'FLEXI_ALL',
			'address'=>'PLG_FLEXICONTENT_FIELDS_ADDRESSINT_AC_ADDRESS',

			'geocode'=>'PLG_FLEXICONTENT_FIELDS_ADDRESSINT_AC_GEOCODE',
			'establishment'=>'PLG_FLEXICONTENT_FIELDS_ADDRESSINT_AC_BUSINESS',
			'(regions)'=>'PLG_FLEXICONTENT_FIELDS_ADDRESSINT_AC_REGION',
			'(cities)'=>'PLG_FLEXICONTENT_FIELDS_ADDRESSINT_AC_CITY',

			'busStop'=>'PLG_FLEXICONTENT_FIELDS_ADDRESSINT_AC_BUS_STOP',
			'trainStation'=>'PLG_FLEXICONTENT_FIELDS_ADDRESSINT_AC_TRAIN_STATION',
			'townhall'=>'PLG_FLEXICONTENT_FIELDS_ADDRESSINT_AC_TOWN_HALL',
			'airport'=>'PLG_FLEXICONTENT_FIELDS_ADDRESSINT_AC_AIRPORT',
			'country'=>'PLG_FLEXICONTENT_FIELDS_ADDRESSINT_AC_COUNTRY',
			'city'=>'PLG_FLEXICONTENT_FIELDS_ADDRESSINT_AC_CITY_OR_AREA',
		);


		// Load Countries ($list_countries) and US states ($list_states)
		include('tmpl_common' . DS . 'areas.php');

		$api_sfx = $mapapi_edit === 'googlemap' ? '' : '_algolia';

		// GET ALLOWED ac search types, note 'false' may have been saved for 'ac_type_allowed_list' due to legacy bug, so do not use heritage directly
		$ac_types_default     = $field->parameters->get('ac_types_default' . $api_sfx, '');
		$ac_type_allowed_list = $field->parameters->get('ac_type_allowed_list' . $api_sfx, false);

		$ac_type_allowed_list = $ac_type_allowed_list ?:
			($mapapi_edit === 'googlemap'
				? array('','geocode','address','establishment','(regions)','(cities)')
				: array('','address','busStop','trainStation','townhall','airport','country','city')
			);
		$ac_type_allowed_list = FLEXIUtilities::paramToArray($ac_type_allowed_list, false, false, true);


		// CET ALLOWED countries, with special check for single country
		$ac_country_default      = trim($field->parameters->get('ac_country_default', ''));
		$ac_country_allowed_list = trim($field->parameters->get('ac_country_allowed_list', ''));

		if (!strlen($ac_country_allowed_list))
		{
			// Empty array indicates all countries allowed
			$ac_country_allowed_list = array();
		}
		else
		{
			// Add default country and make the list unique
			$ac_country_allowed_list = $ac_country_default . ',' . $ac_country_allowed_list;
			$ac_country_allowed_list = array_unique(FLEXIUtilities::paramToArray($ac_country_allowed_list, "/[\s]*,[\s]*/", false, true));
		}

		$single_country = count($ac_country_allowed_list) === 1 && $ac_country_default === reset($ac_country_allowed_list)
			? $ac_country_default
			: false;

		// CREATE COUNTRY OPTIONS
		$_list = count($ac_country_allowed_list) ? array_flip($ac_country_allowed_list) : $list_countries;

		$allowed_country_names = array();
		$allowed_countries     = array('' => JText::_('FLEXI_SELECT'));

		foreach($_list as $country_code => $k)
		{
			$country_op = new stdClass;
			$country_op->value = $country_code;
			$country_op->text  = JText::_('PLG_FC_ADDRESSINT_CC_' . $country_code);

			$allowed_countries[] = $country_op;

			if (count($ac_country_allowed_list))
			{
				$allowed_country_names[] = $country_op->text;
			}
		}
		$countries_attribs = ''
			. ($single_country ? ' disabled="disabled" readonly="readonly"' : '')
			. ($mapapi_edit === 'googlemap' ? ' onchange="fcfield_addrint.toggle_USA_state(this);" ' : '');


		/**
		 * Create Image marker list
		 */
		if ($use_custom_marker)
		{
			$custom_marker_path_abs = JPATH::clean(JPATH_SITE . DS . $custom_marker_path. DS);
			$custom_marker_url_base = str_replace('\\', '/', JURI::root() . $custom_marker_path . '/');

			// Default marker
			if ($mapapi_edit === 'googlemap')
			{
				$custom_marker_default = 'https://maps.gstatic.com/mapfiles/api-3/images/spotlight-poi2.png';
			}
			elseif ($mapapi_edit === 'algolia')
			{
				$custom_marker_default = 'https://unpkg.com/leaflet@1.5.1/dist/images/marker-icon.png';
			}

			$imgs = JFolder::files($custom_marker_path_abs);

			if ($imgs)
			{
				$custom_markers = array('' => JText::_('FLEXI_SELECT'));
				foreach ($imgs as $custom_marker)
				{
					$custom_markers_op = new stdClass;
					$custom_markers[] = $custom_markers_op;

					// Use full path, this way we can change in the future to other folder ??
					$custom_markers_op->value = $custom_marker;
					$custom_markers_op->text  = $custom_marker;
				}
			}
			$marker_anchors = array(
				(object) array('value'=>'TopL', 'text'=>JText::_('FLEXI_TOP') . ' ' . JText::_('FLEXI_LEFT')),
				(object) array('value'=>'TopC', 'text'=>JText::_('FLEXI_TOP') . ' ' . JText::_('FLEXI_CENTER')),
				(object) array('value'=>'TopR', 'text'=>JText::_('FLEXI_TOP') . ' ' . JText::_('FLEXI_RIGHT')),
				(object) array('value'=>'MidL', 'text'=>JText::_('FLEXI_MIDDLE') . ' ' . JText::_('FLEXI_LEFT')),
				(object) array('value'=>'MidC', 'text'=>JText::_('FLEXI_MIDDLE') . ' ' . JText::_('FLEXI_CENTER')),
				(object) array('value'=>'MidR', 'text'=>JText::_('FLEXI_MIDDLE') . ' ' . JText::_('FLEXI_RIGHT')),
				(object) array('value'=>'BotL', 'text'=>JText::_('FLEXI_BOTTOM') . ' ' . JText::_('FLEXI_LEFT')),
				(object) array('value'=>'BotC', 'text'=>JText::_('FLEXI_BOTTOM') . ' ' . JText::_('FLEXI_CENTER')),
				(object) array('value'=>'BotR', 'text'=>JText::_('FLEXI_BOTTOM') . ' ' . JText::_('FLEXI_RIGHT')),
			);
		}

		// CREATE AC SEARCH TYPE OPTIONS
		$ac_type_options = '';
		foreach($ac_type_allowed_list as $ac_type)
		{
			$lbl = $list_ac_types[$ac_type];
			$ac_type_options .= '<option value="'.htmlspecialchars($ac_type, ENT_COMPAT, 'UTF-8').'"  '.($ac_type == $ac_types_default ? 'selected="selected"' : '').'>'.JText::_($lbl)."</option>\n";
		}

		// CSS classes of value container
		$value_classes  = 'fcfieldval_container valuebox fcfieldval_container_'.$field->id;

		// Field name and HTML TAG id
		$fieldname = 'custom['.$field->name.']';
		$elementid = 'custom_'.$field->name;

		// JS safe Field name
		$field_name_js = str_replace('-', '_', $field->name);

		// JS & CSS of current field
		if ($mapapi_edit === 'googlemap')
		{
			$conf_ops = array();

			if (count($ac_country_allowed_list))
			{
				$conf_ops[] = 'country:[\'' . implode("', '", $ac_country_allowed_list) . '\']';
			}

			$js = '
				fcfield_addrint.allowed_countries["'.$field_name_js.'"] = new Array('.(count($ac_country_allowed_list) ? '"' . implode('", "', $ac_country_allowed_list) . '"' : '').');
				fcfield_addrint.single_country["'.$field_name_js.'"] = "' . $single_country . '";

				fcfield_addrint.map_zoom["'.$field_name_js.'"] = ' . $map_zoom . ';
				fcfield_addrint.map_type["'.$field_name_js.'"] = "' . strtoupper($map_type) . '";

				fcfield_addrint.configure["' . $field_name_js . '"] = function(placesAutocomplete)
				{
					if (' . ($conf_ops ? 1 : 0)  . ') placesAutocomplete.setComponentRestrictions({' . implode(', ', $conf_ops) . '});
				}
			';
			$css = '';
		}
		else // ($mapapi_edit === 'algolia')
		{
			$algolia_api_id  = $field->parameters->get('algolia_edit_api_id', '');
			$algolia_api_key = $field->parameters->get('algolia_edit_api_key', '');

			$js = '
				fcfield_addrint.algolia_api_id["'.$field_name_js.'"]  = "' . $algolia_api_id . '";
				fcfield_addrint.algolia_api_key["'.$field_name_js.'"] = "' . $algolia_api_key . '";
			';

			$conf_ops = array();
			$ac_types_default = $field->parameters->get('ac_types_default_algolia', '');

			if (count($ac_country_allowed_list))
			{
				$conf_ops[] = 'countries:[\'' . implode("', '", $ac_country_allowed_list) . '\']';
			}

			if (!$ac_types_default)
			{
				$conf_ops[] = 'type:[\'' . implode("', '", array_filter($ac_type_allowed_list)) . '\']';
			}
			else
			{
				$conf_ops[] = 'type:\'' . $ac_types_default . '\'';
			}

			$js .= '
				fcfield_addrint.configure["' . $field_name_js . '"] = function(placesAutocomplete)
				{
					placesAutocomplete.configure({' . implode(', ', $conf_ops) . '});
				}
			';

			$css = '
			body .ap-suggestion {
				height: 2em !important;
				font-size: 12px !important;
				line-height: 1em !important;
			}
			';
		}

		// Handle multiple records
		if ($multiple)
		{
			// Add the drag and drop sorting feature
			if ($add_ctrl_btns) $js .= "
			jQuery(document).ready(function(){
				jQuery('#sortables_".$field->id."').sortable({
					handle: '.fcfield-drag-handle',
					cancel: false,
					/*containment: 'parent',*/
					tolerance: 'pointer'
					".($field->parameters->get('fields_box_placing', 1) ? "
					,start: function(e) {
						//jQuery(e.target).children().css('float', 'left');
						//fc_setEqualHeights(jQuery(e.target), 0);
					}
					,stop: function(e) {
						//jQuery(e.target).children().css({'float': 'none', 'min-height': '', 'height': ''});
					}
					" : '')."
				});
			});
			";

			if ($max_values) JText::script("FLEXI_FIELD_MAX_ALLOWED_VALUES_REACHED", true);
			$js .= "
			function addField".$field->id."(el, groupval_box, fieldval_box, params)
			{
				var insert_before   = (typeof params!== 'undefined' && typeof params.insert_before   !== 'undefined') ? params.insert_before   : 0;
				var remove_previous = (typeof params!== 'undefined' && typeof params.remove_previous !== 'undefined') ? params.remove_previous : 0;
				var scroll_visible  = (typeof params!== 'undefined' && typeof params.scroll_visible  !== 'undefined') ? params.scroll_visible  : 1;
				var animate_visible = (typeof params!== 'undefined' && typeof params.animate_visible !== 'undefined') ? params.animate_visible : 1;

				if(!remove_previous && (rowCount".$field->id." >= maxValues".$field->id.") && (maxValues".$field->id." != 0)) {
					alert(Joomla.JText._('FLEXI_FIELD_MAX_ALLOWED_VALUES_REACHED') + maxValues".$field->id.");
					return 'cancel';
				}

				// Find last container of fields and clone it to create a new container of fields
				var lastField = fieldval_box ? fieldval_box : jQuery(el).prev().children().last();
				var newField  = lastField.clone();
				newField.find('.fc-has-value').removeClass('fc-has-value');

				// Destroy any select2 elements
				var sel2_elements = newField.find('div.select2-container');
				if (sel2_elements.length)
				{
					sel2_elements.remove();
					newField.find('select.use_select2_lib, select.has_select2_lib').select2('destroy').show();
				}

				// New element's field name and id
				var uniqueRowN = uniqueRowNum" . $field->id . ";
				var element_id = '" . $elementid . "_' + uniqueRowN;
				var fname_pfx  = '" . $fieldname . "[' + uniqueRowN + ']';
				";

			// NOTE: HTML tag id of this form element needs to match the -for- attribute of label HTML tag of this FLEXIcontent field, so that label will be marked invalid when needed
			$js .=

			/**
			 * Update non-optional properties
			 * Latitude, Longtitude, Directions URL
			 */
				"
				theInput = newField.find('input.addrint_lat').first();
				theInput.val('');
				theInput.attr('name', fname_pfx + '[lat]');
				theInput.attr('id', element_id + '_lat');
				newField.find('.addrint_lat-lbl').first().attr('for', element_id + '_lat');

				theInput = newField.find('input.addrint_lon').first();
				theInput.val('');
				theInput.attr('name', fname_pfx + '[lon]');
				theInput.attr('id', element_id + '_lon');
				newField.find('.addrint_lon-lbl').first().attr('for', element_id + '_lon');

				theInput = newField.find('input.addrint_url').first();
				theInput.val('');
				theInput.attr('name', fname_pfx + '[url]');
				theInput.attr('id', element_id + '_url');
				newField.find('.addrint_url-lbl').first().attr('for', element_id + '_url');
				" .

			/**
			 * Address format: 'plaintext'
			 */
				"
				theArea = newField.find('.addrint_addr_display').first();
				theArea.val('');
				theArea.attr('name', fname_pfx + '[addr_display]');
				theArea.attr('id', element_id + '_addr_display');
				newField.find('.addrint_addr_display-lbl').first().attr('for', element_id + '_addr_display');
				" .

			/**
			 * Address format: 'formatted'
			 */
				"
				theInput = newField.find('.addrint_addr_formatted').first();
				theInput.val('');
				theInput.attr('name', fname_pfx + '[addr_formatted]');
				theInput.attr('id', element_id + '_addr_formatted');
				newField.find('.addrint_addr_formatted-lbl').first().attr('for', element_id + '_addr_formatted');

				theInput = newField.find('.addrint_addr1').first();
				theInput.val('');
				theInput.attr('name', fname_pfx + '[addr1]');
				theInput.attr('id', element_id + '_addr1');
				newField.find('.addrint_addr1-lbl').first().attr('for', element_id + '_addr1');
				" .

			/**
			 * Update optional properties of 'formatted' format
			 */
				"
				theInput = newField.find('.addrint_name').first();
				theInput.val('');
				theInput.attr('name', fname_pfx + '[name]');
				theInput.attr('id', element_id + '_name');
				newField.find('.addrint_name-lbl').first().attr('for', element_id + '_name');

				theInput = newField.find('.addrint_addr2').first();
				theInput.val('');
				theInput.attr('name', fname_pfx + '[addr2]');
				theInput.attr('id', element_id + '_addr2');

				theInput = newField.find('.addrint_addr3').first();
				theInput.val('');
				theInput.attr('name', fname_pfx + '[addr3]');
				theInput.attr('id', element_id + '_addr3');

				theInput = newField.find('.fc_gm_city').first();
				theInput.val('');
				theInput.attr('name', fname_pfx + '[city]');
				theInput.attr('id', element_id + '_city');
				newField.find('.fc_gm_city-lbl').first().attr('for', element_id + '_city');

				theSelect = newField.find('select.fc_gm_usstate').first();
				theSelect.val('');
				theSelect.attr('name', fname_pfx + '[state]');
				theSelect.attr('id', element_id + '_state');
				newField.find('.fc_gm_usstate-lbl').first().attr('for', element_id + '_state');

				theInput = newField.find('.fc_gm_province').first();
				theInput.val('');
				theInput.attr('name', fname_pfx + '[province]');
				theInput.attr('id', element_id + '_province');
				newField.find('.fc_gm_province-lbl').first().attr('for', element_id + '_province');

				theSelect = newField.find('select.fc_gm_country').first();
				theSelect.val('');
				theSelect.attr('name', fname_pfx + '[country]');
				theSelect.attr('id', element_id + '_country');
				newField.find('.fc_gm_country-lbl').first().attr('for', element_id + '_country');

				theInput = newField.find('.addrint_zip').first();
				theInput.val('');
				theInput.attr('name', fname_pfx + '[zip]');
				theInput.attr('id', element_id + '_zip');
				newField.find('.addrint_zip-lbl').first().attr('for', element_id + '_zip');

				theInput = newField.find('.addrint_zip_suffix').first();
				theInput.val('');
				theInput.attr('name', fname_pfx + '[zip_suffix]');
				theInput.attr('id', element_id + '_zip_suffix');
				";

			/**
			 * Update custom marker
			 */
			if ($use_custom_marker) $js .= "
				theSelect = newField.find('select.fc_gm_custom_marker').first();
				theSelect.val('" . $default_marker_file ."');
				theSelect.attr('name', fname_pfx + '[custom_marker]');
				theSelect.attr('id', element_id + '_custom_marker');
				newField.find('.fc_gm_custom_marker-lbl').first().attr('for', element_id + '_custom_marker');

				theSelect = newField.find('select.fc_gm_marker_anchor').first();
				theSelect.val('BotC');
				theSelect.attr('name', fname_pfx + '[marker_anchor]');
				theSelect.attr('id', element_id + '_marker_anchor');
				newField.find('.fc_gm_marker_anchor-lbl').first().attr('for', element_id + '_marker_anchor');
				";

			/**
			 * Update map header information
			 */
			$js .= "
				theInput = newField.find('.addrint_marker_tolerance').first();
				theInput.attr('name', fname_pfx + '[marker_tolerance]');
				theInput.attr('id', element_id + '_marker_tolerance');
				newField.find('.addrint_marker_tolerance-lbl').first().attr('for', element_id + '_marker_tolerance');

				theInput = newField.find('.addrint_zoom').first();
				theInput.attr('value', '" . $map_zoom . "');
				theInput.attr('name', fname_pfx + '[zoom]');
				theInput.attr('id', element_id + '_zoom');
				newField.find('.addrint_zoom-lbl').first().attr('for', element_id + '_zoom');
				";

			// Update messages box
			$js .= "
				theDiv = newField.find('div.addrint_messages');
				theDiv.html('');
				theDiv.attr('id', element_id + '_messages');
				";

			// Clear canvas container and hide outer container of map
			$js .= "
				theDiv = newField.find('div.addrint_map_canvas');
				theDiv.html('').removeClass('has_fc_google_maps_map');
				theDiv.attr('id', 'map_canvas_' + element_id );

				theDiv = newField.find('div.fcfield_addressint_map');
				theDiv.attr('id', element_id + '_addressint_map');
				theDiv.hide();
				";

			// Attach search auto-complete
			$js .= "
				theInput = newField.find('.addrint_autocomplete').first();
				theInput.val('');
				theInput.attr('name', fname_pfx + '[autocomplete]');
				theInput.attr('id', element_id + '_autocomplete');
				newField.find('.addrint_autocomplete-lbl').first().attr('for', element_id + '_autocomplete');

				" . ($mapapi_edit === 'algolia' ? "
				// Remove previous autocomplete algolia container
				theParent = theInput.parent('.algolia-places');
				if (theParent.length)
				{
					theInput.insertAfter(theParent);
					theParent.remove();
				}
				" : "") . "

				theSelect = newField.find('select.addrint_ac_type').first();
				theSelect.val('');
				theSelect.attr('name', fname_pfx + '[ac_type]');
				theSelect.attr('id', element_id + '_ac_type');

				// Re-init any select2 element
				var has_select2 = theSelect.prev().hasClass('.select2-container');
				if (has_select2) {
					theSelect.prev().remove();
					theSelect.select2('destroy').show();
				}
				";

			// Add new field to DOM
			$js .= "
				lastField ?
					(insert_before ? newField.insertBefore( lastField ) : newField.insertAfter( lastField ) ) :
					newField.appendTo( jQuery('#sortables_".$field->id."') ) ;
				if (remove_previous) lastField.remove();

				// Attach form validation on new element
				fc_validationAttach(newField);

				// Re-init any select2 elements
				fc_attachSelect2(newField);
				";

			// Add new element to sortable objects (if field not in group)
			if ($add_ctrl_btns) $js .= "
				//jQuery('#sortables_".$field->id."').sortable('refresh');  // Refresh was done appendTo ?
				";

			// Show new field, increment counters
			$js .="
				//newField.fadeOut({ duration: 400, easing: 'swing' }).fadeIn({ duration: 200, easing: 'swing' });
				if (scroll_visible) fc_scrollIntoView(newField, 1);
				if (animate_visible) newField.css({opacity: 0.1}).animate({ opacity: 1 }, 800, function() { jQuery(this).css('opacity', ''); });

				// Enable tooltips on new element
				newField.find('.hasTooltip').tooltip({html: true, container: newField});
				newField.find('.hasPopover').popover({html: true, container: newField, trigger : 'hover focus'});

				// Initialize maps search autocomplete
				fcfield_addrint.initAutoComplete" . ($mapapi_edit === 'googlemap' ? "" : "_OS") . "(element_id, '" . $field_name_js . "');

				// Initialize marker selector
				fcfield_addrint.initMarkerSelector(element_id, '" . $field_name_js . "');

				rowCount".$field->id."++;       // incremented / decremented
				uniqueRowNum".$field->id."++;   // incremented only
			}


			function deleteField".$field->id."(el, groupval_box, fieldval_box)
			{
				// Disable clicks on remove button, so that it is not reclicked, while we do the field value hide effect (before DOM removal of field value)
				var btn = fieldval_box ? false : jQuery(el);
				if (btn && rowCount".$field->id." > 1) btn.css('pointer-events', 'none').off('click');

				// Find field value container
				var row = fieldval_box ? fieldval_box : jQuery(el).closest('li');

				// Add empty container if last element, instantly removing the given field value container
				if(rowCount".$field->id." == 1)
					addField".$field->id."(null, groupval_box, row, {remove_previous: 1, scroll_visible: 0, animate_visible: 0});

				// Remove if not last one, if it is last one, we issued a replace (copy,empty new,delete old) above
				if (rowCount".$field->id." > 1)
				{
					// Destroy the remove/add/etc buttons, so that they are not reclicked, while we do the field value hide effect (before DOM removal of field value)
					row.find('.fcfield-delvalue').remove();
					row.find('.fcfield-expand-view').remove();
					row.find('.fcfield-insertvalue').remove();
					row.find('.fcfield-drag-handle').remove();
					row.find('.fcfield-enablevalue').remove();
					row.find('.fcfield-disablevalue').remove();
					// Do hide effect then remove from DOM
					row.slideUp(400, function(){ jQuery(this).remove(); });
					rowCount".$field->id."--;
				}
			}
			";

			$css .= '';

			$remove_button = '<span class="' . $add_on_class . ' fcfield-delvalue ' . $font_icon_class . '" title="'.JText::_( 'FLEXI_REMOVE_VALUE' ).'" onclick="deleteField'.$field->id.'(this);"></span>';
			$move2 = '<span class="' . $add_on_class . ' fcfield-drag-handle ' . $font_icon_class . '" title="'.JText::_( 'FLEXI_CLICK_TO_DRAG' ).'"></span>';
			$add_here = '';
			$add_here .= $add_position==2 || $add_position==3 ? '<span class="' . $add_on_class . ' fcfield-insertvalue fc_before ' . $font_icon_class . '" onclick="addField'.$field->id.'(null, jQuery(this).closest(\'ul\'), jQuery(this).closest(\'li\'), {insert_before: 1});" title="'.JText::_( 'FLEXI_ADD_BEFORE' ).'"></span> ' : '';
			$add_here .= $add_position==1 || $add_position==3 ? '<span class="' . $add_on_class . ' fcfield-insertvalue fc_after ' . $font_icon_class . '"  onclick="addField'.$field->id.'(null, jQuery(this).closest(\'ul\'), jQuery(this).closest(\'li\'), {insert_before: 0});" title="'.JText::_( 'FLEXI_ADD_AFTER' ).'"></span> ' : '';
		}

		// Field not multi-value
		else
		{
			$remove_button = '';
			$move2 = '';
			$add_here = '';
			$js .= '';
			$css .= '';
		}


		// Add field's custom CSS / JS
		$js .= "
			function enableField".$field->id."(el, groupval_box, fieldval_box)
			{
				// Find field value container
				var row = fieldval_box ? fieldval_box : jQuery(el).closest('.fcfieldval_container');

				row.find('.fcfield-enablevalue').parent().hide();
				row.find('.fcfield-disablevalue').parent().show();

				row.find('.fc-field-prop-disabled').removeAttr('disabled').prop('disabled', false).removeClass('fc-field-prop-disabled');
				row.find('.fc-field-value-properties-box').removeClass('fc-field-value-disabled');
			}
			function disableField".$field->id."(el, groupval_box, fieldval_box)
			{
				// Find field value container
				var row = fieldval_box ? fieldval_box : jQuery(el).closest('.fcfieldval_container');

				row.find('.fcfield-enablevalue').parent().show();
				row.find('.fcfield-disablevalue').parent().hide();

				row.find(':enabled').attr('disabled', 'disabled').prop('disabled', true).addClass('fc-field-prop-disabled');
				row.find('.fc-field-value-properties-box').addClass('fc-field-value-disabled');
			}
		";

		// Check if not required, and add buttons  Edit / Skip to allow skipping the value block
		$enable_disable_btns = !$required /*&& count($required_props)*/ ? '
			<div class="'.$input_grp_class.' fc-xpended-btns" style="%s">
				<span class="fcfield-enablevalue ' . $font_icon_class . '" title="'.JText::_( 'FLEXI_ENABLE_N_EDIT_VALUE_DATA' ).'" onclick="enableField'.$field->id.'(this);"> '.JText::_( 'FLEXI_EDIT' ).'</span>
			</div>
			<div class="'.$input_grp_class.' fc-xpended-btns" style="%s">
				<span class="fcfield-disablevalue ' . $font_icon_class . '" title="'.JText::_( 'FLEXI_SKIP_VALUE_DATA_ON_SAVE' ).'" onclick="disableField'.$field->id.'(this);"> '.JText::_( 'FLEXI_SKIP' ).'</span>
			</div>
		' : '';


		// Add needed JS/CSS
		static $js_added = array();
		if (!isset($js_added[$mapapi_edit]))
		{
			$js_added[$mapapi_edit] = true;

			if (count($js_added) < 2)
			{
				JText::script('PLG_FLEXICONTENT_FIELDS_ADDRESSINT_MARKER_ADDRESS_NOT_FOUND_WITHIN_TOLERANCE', false);
				JText::script('PLG_FLEXICONTENT_FIELDS_ADDRESSINT_MARKER_ADDRESS_FOUND_WITHIN_TOLERANCE', false);
				JText::script('PLG_FLEXICONTENT_FIELDS_ADDRESSINT_MARKER_ADDRESS_NOT_FOUND_AT_MARKER', false);
				JText::script('PLG_FLEXICONTENT_FIELDS_ADDRESSINT_MARKER_ADDRESS_ONLY_LONG_LAT', false);
				JText::script('PLG_FLEXICONTENT_FIELDS_ADDRESSINT_COUNTRY_NOT_ALLOWED_WARNING', false);
				JText::script('PLG_FLEXICONTENT_FIELDS_ADDRESSINT_PLEASE_USE_COUNTRIES', false);
			}

			// Load form.js (google maps)
			$document->addScript(JUri::root(true) . '/plugins/flexicontent_fields/addressint/js/form.js', array('version' => FLEXI_VHASH));

			// Load google maps library
			if ($mapapi_edit === 'googlemap')
			{
				flexicontent_html::loadFramework('google-maps', 'form', $field->parameters);
			}

			// Load leaflet & form_algolia.js
			// TODO: move js in field to a framework call to support multi values
			elseif ($mapapi_edit === 'algolia')
			{
				$document->addStyleSheet('https://cdn.jsdelivr.net/leaflet/1/leaflet.css');
				$document->addScript('https://cdn.jsdelivr.net/leaflet/1/leaflet.js');
				$document->addScript('https://cdn.jsdelivr.net/npm/places.js@1.17.1');
			}
		}


		// Add field's CSS / JS
		if ($multiple) $js .= "
			var uniqueRowNum".$field->id."	= ".count($field->value).";  // Unique row number incremented only
			var rowCount".$field->id."	= ".count($field->value).";      // Counts existing rows to be able to limit a max number of values
			var maxValues".$field->id." = ".$max_values.";
		";
		if ($js)  $document->addScriptDeclaration($js);
		if ($css) $document->addStyleDeclaration($css);


		/**
		 * Create field's HTML display for item form
		 */

		$field->html = array();

		// Render form field
		$formlayout = $field->parameters->get('formlayout', '');
		$formlayout = $formlayout ? 'field_'.$formlayout : 'field';

		//$this->setField($field);
		//$this->setItem($item);
		//$this->displayField( $formlayout );

		include(self::getFormPath($this->fieldtypes[0], $formlayout));

		foreach($field->html as $n => & $_html_)
		{
			$_html_ = '
				'.(!$add_ctrl_btns ? '' : '
				<div class="'.$input_grp_class.' fc-xpended-btns">
					'.$move2.'
					'.$remove_button.'
					'.(!$add_position ? '' : $add_here).'
				</div>
				')
				. ($enable_disable_btns ? sprintf($enable_disable_btns, !$field->fc_form_data[$n]->value_disabled ? 'display:none' : '',  $field->fc_form_data[$n]->value_disabled ? 'display:none' : '') : '') . '
				<div class="fcclear"></div>
				'.$_html_;
		}
		unset($_html_);

		// Do not convert the array to string if field is in a group
		if ($use_ingroup);

		// Handle multiple records
		elseif ($multiple)
		{
			$field->html = !count($field->html) ? '' :
				'<li class="'.$value_classes.'">'.
					implode('</li><li class="'.$value_classes.'">', $field->html).
				'</li>';
			$field->html = '<ul class="fcfield-sortables" id="sortables_'.$field->id.'">' .$field->html. '</ul>';
			if (!$add_position) $field->html .= '
				<div class="input-append input-prepend fc-xpended-btns">
					<span class="fcfield-addvalue ' . $font_icon_class . ' fccleared" onclick="addField'.$field->id.'(jQuery(this).closest(\'.fc-xpended-btns\').get(0));" title="'.JText::_( 'FLEXI_ADD_TO_BOTTOM' ).'">
						'.JText::_( 'FLEXI_ADD_VALUE' ).'
					</span>
				</div>';
		}

		// Handle single values
		else
		{
			$field->html = '<div class="fcfieldval_container valuebox fcfieldval_container_'.$field->id.'">
				' . (isset($field->html[-1]) ? $field->html[-1] : '') . $field->html[0] . '
			</div>';
		}
	}



	// ***
	// *** METHODS HANDLING before & after saving / deleting field events
	// ***

	// Method to handle field's values before they are saved into the DB
	public function onBeforeSaveField( &$field, &$post, &$file, &$item )
	{
		if ( !in_array($field->field_type, static::$field_types) ) return;

		// Check if field has posted data
		if ( empty($post) || !is_array($post)) return;

		// Make sure posted data is an array
		$v = reset($post);
		$post = !is_array($v) ? array($post) : $post;

		// Enforce configuration so that user does not manipulate form to add disabled data
		$use_name          = (int) $field->parameters->get('use_name', 1);
		$use_addr2         = (int) $field->parameters->get('use_addr2', 1);
		$use_addr3         = (int) $field->parameters->get('use_addr3', 1);
		$use_usstate       = (int) $field->parameters->get('use_usstate', 1);
		$use_province      = (int) $field->parameters->get('use_province', 1);
		$use_country       = (int) $field->parameters->get('use_country', 1);
		$use_zip_suffix    = (int) $field->parameters->get('use_zip_suffix', 1);
		$map_zoom          = (int) $field->parameters->get('map_zoom', 16);
		$use_custom_marker = (int) $field->parameters->get('use_custom_marker', 0);

		// Get allowed countries
		$ac_country_default      = $field->parameters->get('ac_country_default', '');
		$ac_country_allowed_list = $field->parameters->get('ac_country_allowed_list', '');
		$ac_country_allowed_list = array_unique(FLEXIUtilities::paramToArray($ac_country_allowed_list, "/[\s]*,[\s]*/", false, true));
		$ac_country_allowed_list = array_flip($ac_country_allowed_list);

		$new=0;
		$newpost = array();
		foreach ($post as $n => $v)
		{
			if (empty($v)) continue;

			// Skip value if both address and formated address are empty
			if (
				empty($v['addr_display']) && empty($v['addr_formatted']) &&
				empty($v['addr1']) && empty($v['city']) && empty($v['state']) &&
				empty($v['province']) && empty($v['zip']) &&
				(empty($v['lat']) || empty($v['lon'])) && empty($v['url'])
			) continue;

			// validate data or empty/set default values
			$newpost[$new] = array();

			// Skip value if non-allowed country was passed
			if ($use_country)
			{
				if (!empty($v['country']) && count($ac_country_allowed_list) && !isset($ac_country_allowed_list[$v['country']]))
				{
					$continue;
				}
			}

			$newpost[$new]['addr_display']  = !isset($v['addr_display']) ? '' : flexicontent_html::dataFilter($v['addr_display'],   4000, 'STRING', '');
			$newpost[$new]['addr_formatted']= !isset($v['addr_formatted']) ? '' : flexicontent_html::dataFilter($v['addr_formatted'], 4000, 'STRING', '');
			$newpost[$new]['addr1'] = !isset($v['addr1']) ? '' : flexicontent_html::dataFilter($v['addr1'],  4000, 'STRING', '');
			$newpost[$new]['city']  = !isset($v['city']) ? '' : flexicontent_html::dataFilter($v['city'],   4000, 'STRING', '');
			$newpost[$new]['zip']   = !isset($v['zip']) ? '' : flexicontent_html::dataFilter($v['zip'],    10,   'STRING', '');
			$newpost[$new]['lat']   = !isset($v['lat']) ? '' : flexicontent_html::dataFilter(str_replace(',', '.', $v['lat']),  100, 'DOUBLE', 0);
			$newpost[$new]['lon']   = !isset($v['lon']) ? '' : flexicontent_html::dataFilter(str_replace(',', '.', $v['lon']),  100, 'DOUBLE', 0);
			$newpost[$new]['url']   = !isset($v['url']) ? '' : flexicontent_html::dataFilter($v['url'],    4000,   'URL', '');
			$newpost[$new]['zoom']  = !isset($v['zoom']) ? '' : flexicontent_html::dataFilter($v['zoom'],  2, 'INTEGER', $map_zoom);

			$newpost[$new]['lat']   = $newpost[$new]['lat'] ? $newpost[$new]['lat'] : '';  // clear if zero
			$newpost[$new]['lon']   = $newpost[$new]['lon'] ? $newpost[$new]['lon'] : '';  // clear if zero

			// Allow saving these into the DB, so that they can be enabled later
			$newpost[$new]['name']          = /*!$use_name       ||*/ !isset($v['name'])          ? '' : flexicontent_html::dataFilter($v['name'],          4000,  'STRING', 0);
			$newpost[$new]['addr2']         = /*!$use_addr2      ||*/ !isset($v['addr2'])         ? '' : flexicontent_html::dataFilter($v['addr2'],         4000,  'STRING', 0);
			$newpost[$new]['addr3']         = /*!$use_addr3      ||*/ !isset($v['addr3'])         ? '' : flexicontent_html::dataFilter($v['addr3'],         4000,  'STRING', 0);
			$newpost[$new]['state']         = /*!$use_usstate    ||*/ !isset($v['state'])         ? '' : flexicontent_html::dataFilter($v['state'],          200,  'STRING', 0);
			$newpost[$new]['country']       = /*!$use_country    ||*/ !isset($v['country'])       ? '' : flexicontent_html::dataFilter($v['country'],          2,  'STRING', 0);
			$newpost[$new]['province']      = /*!$use_province   ||*/ !isset($v['province'])      ? '' : flexicontent_html::dataFilter($v['province'],       200,  'STRING', 0);
			$newpost[$new]['zip_suffix']    = /*!$use_zip_suffix ||*/ !isset($v['zip_suffix'])    ? '' : flexicontent_html::dataFilter($v['zip_suffix'],      10,  'STRING', 0);
			$newpost[$new]['custom_marker'] = /*!$custom_marker  ||*/ !isset($v['custom_marker']) ? '' : flexicontent_html::dataFilter($v['custom_marker'], 4000,  'PATH', 0);
			$newpost[$new]['marker_anchor'] = /*!$marker_anchor  ||*/ !isset($v['marker_anchor']) ? '' : flexicontent_html::dataFilter($v['marker_anchor'], 4000,  'WORD', 0);

			$new++;
		}
		$post = $newpost;

		// Serialize multi-property data before storing them into the DB, also map some properties as fields
		$props_to_fields = array('name', 'addr1', 'addr2', 'addr3', 'city', 'zip', 'country', 'lon', 'lat', 'custom_marker', 'marker_anchor');
		$_fields = array();
		$byIds = FlexicontentFields::indexFieldsByIds($item->fields, $item);
		foreach($post as $i => $v)
		{
			foreach($props_to_fields as $propname)
			{
				$to_fieldid = $field->parameters->get('field_'.$propname);
				if ( $to_fieldid && isset($byIds[$to_fieldid]) )
				{
					$to_fieldname = $byIds[$to_fieldid]->name;
					$item->calculated_fieldvalues[$to_fieldname][$i] = $v[$propname];
				}
			}

			$post[$i] = serialize($v);
		}
	}


	// Method to create field's HTML display for frontend views
	public function onDisplayFieldValue(&$field, $item, $values = null, $prop = 'display')
	{
		if ( !in_array($field->field_type, static::$field_types) ) return;

		$field->label = JText::_($field->label);

		// Set field and item objects
		$this->setField($field);
		$this->setItem($item);


		/**
		 * One time initialization
		 */

		static $initialized = null;
		static $app, $document, $option, $format, $realview;

		if ($initialized === null)
		{
			$initialized = 1;

			$app       = JFactory::getApplication();
			$document  = JFactory::getDocument();
			$option    = $app->input->getCmd('option', '');
			$format    = $app->input->getCmd('format', 'html');
			$realview  = $app->input->getCmd('view', '');
		}

		// Current view variable
		$view = $app->input->getCmd('flexi_callview', ($realview ?: 'item'));
		$sfx = $view === 'item' ? '' : '_cat';

		// Check if field should be rendered according to configuration
		if (!$this->checkRenderConds($prop, $view))
		{
			return;
		}

		// Use the custom field values, if these were provided
		$values = $values !== null ? $values : $this->field->value;

		// Parse field values
		$this->values = $this->parseValues($values);


		// CSV export: Create customized output and return
		if ($prop === 'csv_export')
		{
			$separatorf = ' | ';
			$itemprop = false;

			$csv_export_text = $field->parameters->get('csv_export_text', '{{addr1}} {{city}} ZIP: {{zip}}');
			$field_matches = null;

			$result = preg_match_all("/\{\{([a-zA-Z_0-9-]+)\}\}/", $csv_export_text, $field_matches);
			$propertyNames = $result ? $field_matches[1] : array();

			$field->{$prop} = array();

			foreach ($this->values as $value)
			{
				$output = $csv_export_text;

				foreach ($propertyNames as $pname)
				{
					$output = str_replace('{{' . $pname . '}}', (isset($value[$pname]) ? $value[$pname] : ''), $output);
				}

				$field->{$prop}[] = $output;
			}

			// Apply values separator, creating a non-array output regardless of fieldgrouping, as fieldgroup CSV export is not supported
			$field->{$prop} = implode($separatorf, $field->{$prop});

			return;
		}

		// TODO Implement a static image for google maps "img" display
		//$this->getCachedStaticMapImage();


		// Get layout name
		$viewlayout = $field->parameters->get('viewlayout', '');
		$viewlayout = $viewlayout && $viewlayout !== 'value' ? 'value_'.$viewlayout : 'value';

		// Create field's display
		$this->displayFieldValue($prop, $viewlayout);
	}



	// ***
	// *** SEARCH INDEX METHODS
	// ***

	// Method to create (insert) advanced search index DB records for the field values
	public function onIndexAdvSearch(&$field, &$post, &$item)
	{
		if ( !in_array($field->field_type, static::$field_types) ) return;
		if ( !$field->isadvsearch && !$field->isadvfilter ) return;

		FlexicontentFields::onIndexAdvSearch($field, $post, $item, $required_properties=array(), $search_properties=array('addr1','addr2','addr3','city','state','province','zip','country'), $properties_spacer=' ', $filter_func=null);
		return true;
	}


	// Method to create basic search index (added as the property field->search)
	public function onIndexSearch(&$field, &$post, &$item)
	{
		if ( !in_array($field->field_type, static::$field_types) ) return;
		if ( !$field->issearch ) return;

		FlexicontentFields::onIndexSearch($field, $post, $item, $required_properties=array(), $search_properties=array('addr1','addr2','addr3','city','state','province','zip','country'), $properties_spacer=' ', $filter_func=null);
		return true;
	}



	// ***
	// *** VARIOUS HELPER METHODS
	// ***


	// !!!UNFINISHED !!!
	// TODO Implement a static image for google maps "img" display
	protected function getCachedStaticMapImage()
	{
		$field = $this->field;
		$item  = $this->item;

		// Get Map Engine
		$map_api = $field->parameters->get('mapapi', 'googlemap');

		// Get Embeed type
		$map_embed_type = $field->parameters->get('map_embed_type','img'); // defaults to img for backward compatibility

		if ($map_api !== 'googlemap' || $map_embed_type !== 'int')
		{
			return;
		}

		// Get API Key for viewing, falling back to edit key
		$google_maps_js_api_key = trim($field->parameters->get('google_maps_js_api_key', ''));
		$google_maps_static_api_key = trim($field->parameters->get('google_maps_static_api_key', $google_maps_js_api_key));

		// Get parameters
		$show_address = $field->parameters->get('show_address','both');
		$show_address = $show_address === 'both' || ($view !== 'item' && $show_address === 'category') || ($view === 'item' && $show_address === 'item');

		$addr_display_mode = $field->parameters->get('addr_display_mode','plaintext');
		$addr_format_tmpl = $field->parameters->get('addr_format_tmpl',	'
		 [[name|<h3 class="fc-addrint business-name">{{name}}</h3>]]
		 [[addr1|<span class="fc-addrint street-address">{{addr1}}</span><br/>]]
		 [[addr2|<span class="fc-addrint street-address2">{{addr2}}</span><br/>]]
		 [[addr3|<span class="fc-addrint street-address3">{{addr3}}</span><br/>]]
		 [[city|<span class="fc-addrint city">{{city}}</span>]]
		 <span class="fc-addrint state">[[state|{{state}}]][[province|{{province}},]]</span>
		 <span class="fc-addrint postal-code">{{zip}}[[zip_suffix|-{{zip_suffix}}]]</span><br/>
		 <span class="fc-addrint country">{{country}}</span>
		');

		$directions_position = $field->parameters->get('directions_position','after');
		$directions_link_label = $field->parameters->get('directions_link_label', JText::_('PLG_FC_ADDRESSINT_GET_DIRECTIONS'));

		$show_map = $field->parameters->get('show_map','');
		$show_map = $show_map === 'both' || ($view !== 'item' && $show_map === 'category') || ($view === 'item' && $show_map === 'item');

		$map_type     = $field->parameters->get('map_type','roadmap');
		$map_zoom     = (int) $field->parameters->get('map_zoom', 16);
		$link_map     = (int) $field->parameters->get('link_map', 1);

		$map_position = (int) $field->parameters->get('map_position', 0);
		$marker_color = $field->parameters->get('marker_color', 'red');
		$marker_size  = $field->parameters->get('marker_size', 'mid');

		$map_width  = (int) $field->parameters->get('map_width', 200);
		$map_height = (int) $field->parameters->get('map_height', 150);

		$use_custom_marker = (int) $field->parameters->get('use_custom_marker', 1);
		$defaut_icon_url   = $map_api === 'googlemap'
			? 'https://maps.gstatic.com/mapfiles/api-3/images/spotlight-poi2.png'
			: 'https://unpkg.com/leaflet@1.5.1/dist/images/marker-icon.png';
	}
}