Skip to content

Instantly share code, notes, and snippets.

@torounit
Last active January 29, 2021 16:04
Show Gist options
  • Save torounit/5213223 to your computer and use it in GitHub Desktop.
Save torounit/5213223 to your computer and use it in GitHub Desktop.
Fixed Repeater x location fields.
<?php
/*
* Plugin Name: Advanced Custom Fields - Location Field add-on
* Plugin URI: https://github.com/julienbechade/acf-location-field
* Description: This plugin is an add-on for Advanced Custom Fields. It allows you to find coordinates and/or address of a location with Google Maps.
* Author: Julien Bechade
* Author URI: http://julienbechade.com/
* Version: 1.0
* Text Domain: acf-location-field
* Domain Path: /lang/
*/
if( !class_exists( 'ACF_Location_Field' ) && class_exists( 'acf_Field' ) ) :
/*
* Advanced Custom Fields - Location Field add-on
*
* @author Julien Bechade <julien.bechade@gmail.com>
* @contributor Brian Zoetewey <brian.zoetewey@ccci.org>
* @version 1.0
*
*/
class ACF_Location_Field extends acf_Field
{
/*
* WordPress Localization Text Domain
*
* The textdomain for the field is controlled by the helper class.
* @var string
*
*/
private $l10n_domain;
/*--------------------------------------------------------------------------------------
*
* Constructor
* - This function is called when the field class is initalized on each page.
* - Here you can add filters / actions and setup any other functionality for your field
*
* @author Elliot Condon
* @since 2.2.0
*
*-------------------------------------------------------------------------------------*/
public function __construct($parent)
{
//Call parent constructor
parent::__construct($parent);
//Get the textdomain from the Helper class
$this->l10n_domain = ACF_Location_Field_Helper::L10N_DOMAIN;
// set name / title
$this->name = 'location-field'; // variable name (no spaces / special characters / etc)
$this->title = __( 'Location', $this->l10n_domain ); // field label (Displayed in edit screens)
add_action( 'admin_print_scripts', array( &$this, 'admin_print_scripts' ), 12, 0 );
add_action( 'admin_print_styles', array( &$this, 'admin_print_styles' ), 12, 0 );
}
/*--------------------------------------------------------------------------------------
*
* admin_head
* - this function is called in the admin_head of the edit screen where your field
* is created. Use this function to create css and javascript to assist your
* create_field() function.
*
* @author Elliot Condon
* @since 2.2.0
*
*-------------------------------------------------------------------------------------*/
public function admin_head()
{
echo '<script src="https://maps.googleapis.com/maps/api/js?sensor=false" type="text/javascript"></script>';
}
/*--------------------------------------------------------------------------------------
*
* admin_print_scripts / admin_print_styles
* - this function is called in the admin_print_scripts / admin_print_styles where
* your field is created. Use this function to register css and javascript to assist
* your create_field() function.
*
* @author Elliot Condon
* @since 3.0.0
*
*-------------------------------------------------------------------------------------*/
public function admin_print_styles()
{
global $pagenow;
wp_register_style( 'acf-location-field', plugins_url( 'style.css', __FILE__ ) );
if( in_array( $pagenow, array( 'post.php', 'post-new.php', 'admin.php' ) ) )
{
wp_enqueue_style( 'acf-location-field' );
}
}
public function admin_print_scripts()
{
global $pagenow;
//wp_register_script( 'acf-location-field', $this->base_uri_abs . '/js/script.js', array( 'jquery' ) );
if( in_array( $pagenow, array( 'post.php', 'post-new.php' ) ) )
{
//wp_enqueue_script( 'acf-location-field' );
}
}
/*--------------------------------------------------------------------------------------
*
* set_field_defaults
* - populates the fields array with defaults for this field type
*
* @param array $field
* @return array
*
*-------------------------------------------------------------------------------------*/
private function set_field_defaults(&$field)
{
$field['center'] = isset($field['center']) ? $field['center'] : '48.856614,2.3522219000000177';
$field['zoom'] = isset($field['zoom']) ? $field['zoom'] : '2';
$field['val'] = isset($field['val']) ? $field['val'] : 'address';
$field['scrollwheel'] = isset($field['scrollwheel']) ? $field['scrollwheel'] : '1';
}
/*--------------------------------------------------------------------------------------
*
* create_options
* - this function is called from core/field_meta_box.php to create extra options
* for your field
*
* @params
* - $key (int) - the $_POST obejct key required to save the options to the field
* - $field (array) - the field object
*
* @author Elliot Condon
* @since 2.2.0
*
*-------------------------------------------------------------------------------------*/
public function create_options($key, $field)
{
$this->set_field_defaults($field);
?>
<tr class="field_option field_option_<?php echo $this->name; ?>">
<td class="label">
<label><?php _e('Map address','acf-location-field'); ?></label>
<p class="description"><?php _e('Return the address along with the coordinates.','acf-location-field'); ?></p>
</td>
<td>
<?php
$this->parent->create_field(array(
'type' => 'radio',
'name' => 'fields['.$key.'][val]',
'value' => $field['val'],
'layout' => 'horizontal',
'choices' => array(
'address' => __('Yes', 'acf-location-field'),
'coordinates' => __('No', 'acf-location-field')
)
));
?>
</td>
</tr>
<tr class="field_option field_option_<?php echo $this->name; ?>">
<td class="label">
<label><?php _e('Map center','acf-location-field'); ?></label>
<p class="description"><?php _e('Latitude and longitude to center the initial map.','acf-location-field'); ?></p>
</td>
<td>
<?php
$this->parent->create_field(array(
'type' => 'text',
'name' => 'fields['.$key.'][center]',
'value' => $field['center']
));
?>
</td>
</tr>
<tr class="field_option field_option_<?php echo $this->name; ?>">
<td class="label">
<label><?php _e('Map zoom','acf-location-field'); ?></label>
<p class="description"><?php _e('','acf-location-field'); ?></p>
</td>
<td>
<?php
$this->parent->create_field(array(
'type' => 'text',
'name' => 'fields['.$key.'][zoom]',
'value' => $field['zoom']
));
?>
</td>
</tr>
<tr class="field_option field_option_<?php echo $this->name; ?>">
<td class="label">
<label><?php _e('Map Scrollwheel','acf-location-field'); ?></label>
<p class="description"><?php _e('Allows scrollwheel zooming on the map field','acf-location-field'); ?></p>
</td>
<td>
<?php
$this->parent->create_field(array(
'type' => 'radio',
'name' => 'fields['.$key.'][scrollwheel]',
'value' => $field['scrollwheel'],
'layout' => 'horizontal',
'choices' => array(
'1' => __('Yes', 'acf-location-field'),
'0' => __('No', 'acf-location-field')
)
));
?>
</td>
</tr>
<?php
}
/*--------------------------------------------------------------------------------------
*
* pre_save_field
* - this function is called when saving your acf object. Here you can manipulate the
* field object and it's options before it gets saved to the database.
*
* @author Elliot Condon
* @since 2.2.0
*
*-------------------------------------------------------------------------------------*/
public function pre_save_field($field)
{
// do stuff with field (mostly format options data)
return parent::pre_save_field($field);
}
/*--------------------------------------------------------------------------------------
*
* create_field
* - this function is called on edit screens to produce the html for this field
*
* @author Elliot Condon
* @since 2.2.0
*
*-------------------------------------------------------------------------------------*/
public function create_field($field)
{
$this->set_field_defaults($field);
// Build an unique id based on ACF's one.
$pattern = array('/\[/', '/\]/');
$replace = array('_', '');
$uid = preg_replace($pattern, $replace, $field['name']);
// Retrieve options value
$zoom = $field['zoom'];
$center = explode(',', $field['center']);
$scrollwheel = $field['scrollwheel'];
?>
<script type="text/javascript">
function location_init(uid){
function addMarker(position,address){
if(marker){marker.setMap(null)}
marker=new google.maps.Marker({map:map,position:position,title:address,draggable:true});
map.setCenter(position);
dragdropMarker()
}
function dragdropMarker(){
google.maps.event.addListener(marker,'dragend',function(mapEvent){
coordinates=mapEvent.latLng.lat()+','+mapEvent.latLng.lng();locateByCoordinates(coordinates)})
}
function locateByAddress(address){
geocoder.geocode({'address':address},function(results,status){
if(status==google.maps.GeocoderStatus.OK){
addMarker(results[0].geometry.location,address);
coordinates=results[0].geometry.location.lat()+','+results[0].geometry.location.lng();
coordinatesAddressInput.value=address+'|'+coordinates;ddAddress.innerHTML=address;
ddCoordinates.innerHTML=coordinates
}
else{
alert("<?php _e("This address could not be found: ",'acf-location-field');?>"+status)
}
})
}
function locateByCoordinates(coordinates){
latlngTemp=coordinates.split(',',2);
lat=parseFloat(latlngTemp[0]);
lng=parseFloat(latlngTemp[1]);
latlng=new google.maps.LatLng(lat,lng);
geocoder.geocode({'latLng':latlng},function(results,status){
if(status==google.maps.GeocoderStatus.OK){
address=results[0].formatted_address;addMarker(latlng,address);
coordinatesAddressInput.value=address+'|'+coordinates;ddAddress.innerHTML=address;ddCoordinates.innerHTML=coordinates
}
else{
alert("<?php _e("This place could not be found: ",'acf-location-field');?>"+status)
}
})
}
var map,lat,lng,latlng,marker,coordinates,address,val;
var geocoder=new google.maps.Geocoder();
var ddAddress=document.getElementById('location_dd-address_'+uid);
var dtAddress=document.getElementById('location_dt-address_'+uid);
var ddCoordinates=document.getElementById('location_dd-coordinates_'+uid);
var locationInput=document.getElementById('location_input_'+uid);
var location=locationInput.value;
var coordinatesAddressInput=document.getElementById('location_coordinates-address_'+uid);
var coordinatesAddress=coordinatesAddressInput.value;
if(coordinatesAddress){
var coordinatesAddressTemp=coordinatesAddress.split('|',2);
coordinates=coordinatesAddressTemp[1];
address=coordinatesAddressTemp[0]
}if(address){
ddAddress.innerHTML=address
}
if(coordinates){
ddCoordinates.innerHTML=coordinates;
var latlngTemp=coordinates.split(',',2);
lat=parseFloat(latlngTemp[0]);
lng=parseFloat(latlngTemp[1])
}else{
lat=<?php echo $center[0];?>;
lng=<?php echo $center[1];?>
}
latlng=new google.maps.LatLng(lat,lng);
var mapOptions={
zoom:<?php echo $zoom;?>,
center:latlng,
mapTypeId:google.maps.MapTypeId.ROADMAP,scrollwheel: <?php echo $scrollwheel; ?>
};
map=new google.maps.Map(document.getElementById('location_map_'+uid),mapOptions);
if(coordinates){
addMarker(map.getCenter())
}
google.maps.event.addListener(map,'click',function(point){
locateByCoordinates(point.latLng.lat()+','+point.latLng.lng())
});
locationInput.addEventListener('keypress',function(event){
if(event.keyCode==13){
location=locationInput.value;
var regexp=new RegExp('^\-?[0-9]{1,3}\.[0-9]{6,},\-?[0-9]{1,3}\.[0-9]{6,}$');
if(location){
if(regexp.test(location)){
locateByCoordinates(location)
}
else{
locateByAddress(location)}
}
event.stopPropagation();
event.preventDefault();
return false
}
},false);
dtAddress.addEventListener('click',function(){
if(coordinates){
locateByCoordinates(coordinates)
}
},false)
};
jQuery(document).ready(function(){
location_init("<?php echo $uid;?>");
});
var mapids = Array();
jQuery(document).live('acf/setup_fields',function(e){
var fid = jQuery(".repeater .row input[id*=location_coordinates]").not(".exsist").last().attr("id");
if(fid) {
fid = fid.replace("location_coordinates-address_","");
location_init(fid);
jQuery(".repeater .row input[id*=location_coordinates]").addClass("exsist");
}
});
</script>
<input type="hidden" value="<?php echo $field['value']; ?>" id="location_coordinates-address_<?php echo $uid; ?>" name="<?php echo $field['name']; ?>"/>
<input type="text" id="location_input_<?php echo $uid; ?>" placeholder="<?php _e('Search for a location','acf-location-field'); ?>" />
<dl class="location_dl">
<dt class="location_dt-address" id="location_dt-address_<?php echo $uid; ?>" role="button" title="<?php _e('Find the complete address','acf-location-field'); ?>"><?php _e('Address: ','acf-location-field'); ?></dt>
<dd class="location_dd" id="location_dd-address_<?php echo $uid; ?>">&nbsp;</dd>
<dt class="location_dt-coordinates"><?php _e('Coordinates: ','acf-location-field'); ?></dt>
<dd class="location_dd" id="location_dd-coordinates_<?php echo $uid; ?>">&nbsp;</dd>
</dl>
<div class="location_map-container">
<div class="location_map" id="location_map_<?php echo $uid; ?>"></div>
</div>
<?php
}
/*--------------------------------------------------------------------------------------
*
* update_value
* - this function is called when saving a post object that your field is assigned to.
* the function will pass through the 3 parameters for you to use.
*
* @params
* - $post_id (int) - usefull if you need to save extra data or manipulate the current
* post object
* - $field (array) - usefull if you need to manipulate the $value based on a field option
* - $value (mixed) - the new value of your field.
*
* @author Elliot Condon
* @since 2.2.0
*
*-------------------------------------------------------------------------------------*/
public function update_value($post_id, $field, $value)
{
// do stuff with value
// save value
parent::update_value($post_id, $field, $value);
}
/*--------------------------------------------------------------------------------------
*
* get_value
* - called from the edit page to get the value of your field. This function is useful
* if your field needs to collect extra data for your create_field() function.
*
* @params
* - $post_id (int) - the post ID which your value is attached to
* - $field (array) - the field object.
*
* @author Elliot Condon
* @since 2.2.0
*
*-------------------------------------------------------------------------------------*/
public function get_value($post_id, $field)
{
// get value
$value = parent::get_value($post_id, $field);
// format value
// return value
return $value;
}
/*--------------------------------------------------------------------------------------
*
* get_value_for_api
* - called from your template file when using the API functions (get_field, etc).
* This function is useful if your field needs to format the returned value
*
* @params
* - $post_id (int) - the post ID which your value is attached to
* - $field (array) - the field object.
*
* @author Elliot Condon
* @since 3.0.0
*
*-------------------------------------------------------------------------------------*/
public function get_value_for_api($post_id, $field)
{
// get value
$value = $this->get_value($post_id, $field);
// format value
$value = explode('|', $value);
if ($field['val'] == 'address')
{
$value = array( 'coordinates' => $value[1], 'address' => $value[0] );
}
else {
$value = $value[1];
}
// return value
return $value;
}
}
endif; //class_exists 'ACF_Location_Field'
if( !class_exists( 'ACF_Location_Field_Helper' ) ) :
/*
* Advanced Custom Fields - Location Field Helper
*
* @author Brian Zoetewey <brian.zoetewey@ccci.org>
*
*/
class ACF_Location_Field_Helper {
/*
* Singleton instance
* @var ACF_Location_Field_Helper
*
*/
private static $instance;
/*
* Returns the ACF_Location_Field_Helper singleton
*
* <code>$obj = ACF_Location_Field_Helper::singleton();</code>
* @return ACF_Location_Field_Helper
*
*/
public static function singleton()
{
if( !isset( self::$instance ) )
{
$class = __CLASS__;
self::$instance = new $class();
}
return self::$instance;
}
/*
* Prevent cloning of the ACF_Location_Field_Helper object
* @internal
*
*/
private function __clone()
{
}
/*
* WordPress Localization Text Domain
*
* Used in wordpress localization and translation methods.
* @var string
*
*/
const L10N_DOMAIN = 'acf-location-field';
/*
* Language directory path
*
* Used to build the path for WordPress localization files.
* @var string
*
*/
private $lang_dir;
/*
* Constructor
*
*/
private function __construct()
{
$this->lang_dir = rtrim( dirname( realpath( __FILE__ ) ), '/' ) . '/lang';
add_action( 'init', array( &$this, 'register_field' ), 5, 0 );
add_action( 'init', array( &$this, 'load_textdomain' ), 2, 0 );
}
/*
* Registers the Field with Advanced Custom Fields
*
*/
public function register_field()
{
if( function_exists( 'register_field' ) )
{
register_field( 'ACF_Location_Field', __FILE__ );
}
}
/*
* Loads the textdomain for the current locale if it exists
*
*/
public function load_textdomain()
{
$locale = get_locale();
$mofile = $this->lang_dir . '/' . self::L10N_DOMAIN . '-' . $locale . '.mo';
load_textdomain( self::L10N_DOMAIN, $mofile );
}
}
endif; //class_exists 'ACF_Location_Field_Helper'
//Instantiate the Addon Helper class
ACF_Location_Field_Helper::singleton();
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment