403Webshell
Server IP : 146.59.209.152  /  Your IP : 216.73.216.46
Web Server : Apache
System : Linux webm005.cluster131.gra.hosting.ovh.net 5.15.167-ovh-vps-grsec-zfs-classid #1 SMP Tue Sep 17 08:14:20 UTC 2024 x86_64
User : infrafs ( 43850)
PHP Version : 8.2.29
Disable Function : _dyuweyrj4,_dyuweyrj4r,dl
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /home/i/n/f/infrafs/INFRABIKEIT/wp-content/plugins/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /home/i/n/f/infrafs/INFRABIKEIT/wp-content/plugins/wp-store-locator.tar
inc/wpsl-functions.php000064400000050341151327220640011026 0ustar00<?php

/**
 * Collect all the parameters ( language, key, region )
 * we need before making a request to the Google Maps API.
 *
 * @since 1.0.0
 * @param  string  $api_key_type   The type of API key we need to include ( server_key or browser_key ).
 * @param  boolean $geocode_params
 * @return string  $api_params     The API parameters.
 */
function wpsl_get_gmap_api_params( $api_key_type, $geocode_params = false ) {

    global $wpsl, $wpsl_settings;

    $api_params = '';
    $param_keys = array( 'language', 'region', 'key' );

    /*
     * The geocode params are included after the address so we need to
     * use a '&' as the first char, but when the maps script is included on
     * the front-end it does need to start with a '?'.
     */
    $first_sep = ( $geocode_params ) ? '&' : '?';

    foreach ( $param_keys as $param_key ) {
        $option_key = ( $param_key == 'key' ) ? $api_key_type : $param_key;

        /*
         * Get the current language code if WPML or qTranslate-X is active.
         * Otherwise get the param value from the settings var.
         */
        if ( $option_key == 'language' && ( $wpsl->i18n->wpml_exists() || $wpsl->i18n->qtrans_exists() ) ) {
            $param_val = $wpsl->i18n->check_multilingual_code();
        } else {
            $param_val = $wpsl_settings['api_' . $option_key];
        }

        if ( !empty( $param_val ) ) {
            $api_params .= $param_key . '=' . $param_val . '&';
        }
    }

    if ( $api_params ) {
        $api_params = $first_sep . rtrim( $api_params, '&' );
    }

    // Do we need to include the autocomplete library?
    if ( ( $wpsl_settings['autocomplete'] && $api_key_type == 'browser_key' ) || is_admin() ) {
        $api_params .= '&libraries=places';
    }

    if ( $api_key_type == 'browser_key' ) {
        $api_version = apply_filters( 'wpsl_gmap_api_version', 'quarterly' );
        $api_params .= '&v=' . $api_version;
    }

    return apply_filters( 'wpsl_gmap_api_params', $api_params );
}

/**
 * Get the default plugin settings.
 *
 * @since 1.0.0
 * @return array $default_settings The default settings
 */
function wpsl_get_default_settings() {

    $default_settings = array(
        'api_browser_key'           => '',
        'api_server_key'            => '',
        'api_language'              => 'en',
        'api_region'                => '',
        'api_geocode_component'     => 0,
        'distance_unit'             => 'km',
        'max_results'               => '[25],50,75,100',
        'search_radius'             => '10,25,[50],100,200,500',
        'force_postalcode'          => 0,
        'marker_effect'             => 'bounce',
        'address_format'            => 'city_state_zip',
        'hide_distance'             => 0,
        'hide_country'              => 0,
        'show_contact_details'      => 0,
        'clickable_contact_details' => 0,
        'auto_locate'               => 1,
        'autocomplete'              => 0,
        'autoload'                  => 1,
        'autoload_limit'            => 50,
        'run_fitbounds'             => 1,
        'zoom_level'                => 3,
        'auto_zoom_level'           => 15,
        'start_name'                => '',
        'start_latlng'              => '',
        'height'                    => 350,
        'map_type'                  => 'roadmap',
        'map_style'                 => '',
        'type_control'              => 0,
        'streetview'                => 0,
        'results_dropdown'          => 1,
        'radius_dropdown'           => 1,
        'category_filter'           => 0,
        'category_filter_type'      => 'dropdown',
        'infowindow_width'          => 225,
        'search_width'              => 179,
        'label_width'               => 95,
        'control_position'          => 'left',
        'scrollwheel'               => 1,
        'marker_clusters'           => 0,
        'cluster_zoom'              => 0,
        'cluster_size'              => 0,
        'new_window'                => 0,
        'reset_map'                 => 0,
        'template_id'               => 'default',
        'listing_below_no_scroll'   => 0,
        'direction_redirect'        => 0,
        'more_info'                 => 0,
        'store_url'                 => 0,
        'phone_url'                 => 0,
        'marker_streetview'         => 0,
        'marker_zoom_to'            => 0,
        'more_info_location'        => 'info window',
        'mouse_focus'               => 0,
        'start_marker'              => 'red.png',
        'store_marker'              => 'blue.png',
        'editor_country'            => '',
        'editor_hours'              => wpsl_default_opening_hours(),
        'editor_hour_input'         => 'dropdown',
        'editor_hour_format'        => 12,
        'editor_map_type'           => 'roadmap',
        'hide_hours'                => 0,
        'permalinks'                => 0,
        'permalink_remove_front'    => 0,
        'permalink_slug'            => __( 'stores', 'wpsl' ),
        'category_slug'             => __( 'store-category', 'wpsl' ),
        'infowindow_style'          => 'default',
        'show_credits'              => 0,
        'debug'                     => 0,
        'deregister_gmaps'          => 0,
        'delay_loading'             => 0,
        'start_label'               => __( 'Start location', 'wpsl' ),
        'search_label'              => __( 'Your location', 'wpsl' ),
        'search_btn_label'          => __( 'Search', 'wpsl' ),
        'preloader_label'           => __( 'Searching...', 'wpsl' ),
        'radius_label'              => __( 'Search radius', 'wpsl' ),
        'no_results_label'          => __( 'No results found', 'wpsl' ),
        'results_label'             => __( 'Results', 'wpsl' ),
        'more_label'                => __( 'More info', 'wpsl' ),
        'directions_label'          => __( 'Directions', 'wpsl' ),
        'no_directions_label'       => __( 'No route could be found between the origin and destination', 'wpsl' ),
        'back_label'                => __( 'Back', 'wpsl' ),
        'street_view_label'         => __( 'Street view', 'wpsl' ),
        'zoom_here_label'           => __( 'Zoom here', 'wpsl' ),
        'error_label'               => __( 'Something went wrong, please try again!', 'wpsl' ),
        'limit_label'               => __( 'API usage limit reached', 'wpsl' ),
        'phone_label'               => __( 'Phone', 'wpsl' ),
        'fax_label'                 => __( 'Fax', 'wpsl' ),
        'email_label'               => __( 'Email', 'wpsl' ),
        'url_label'                 => __( 'Url', 'wpsl' ),
        'hours_label'               => __( 'Hours', 'wpsl' ),
        'category_label'            => __( 'Category filter', 'wpsl' ),
        'category_default_label'    => __( 'Any', 'wpsl' )
    );

    return $default_settings;
}

/**
 * Get the current plugin settings.
 *
 * @since 1.0.0
 * @return array $setting The current plugin settings
 */
function wpsl_get_settings() {

    $settings = get_option( 'wpsl_settings' );

    if ( !$settings ) {
        update_option( 'wpsl_settings', wpsl_get_default_settings() );
        $settings = wpsl_get_default_settings();
    }

    return $settings;
}

/**
 * Get a single value from the default settings.
 *
 * @since 1.0.0
 * @param  string $setting               The value that should be restored
 * @return string $wpsl_default_settings The default setting value
 */
function wpsl_get_default_setting( $setting ) {

    global $wpsl_default_settings;

    return $wpsl_default_settings[$setting];
}

/**
 * Set the default plugin settings.
 *
 * @since 1.0.0
 * @return void
 */
function wpsl_set_default_settings() {

    $settings = get_option( 'wpsl_settings' );

    if ( !$settings ) {
        update_option( 'wpsl_settings', wpsl_get_default_settings() );
    }
}

/**
 * Return a list of the store templates.
 *
 * @since 1.2.20
 * @return array $templates The list of default store templates
 */
function wpsl_get_templates() {

    $templates = array(
        array(
            'id'   => 'default',
            'name' => __( 'Default', 'wpsl' ),
            'path' => WPSL_PLUGIN_DIR . 'frontend/templates/default.php'
        ),
        array(
            'id'   => 'below_map',
            'name' => __( 'Show the store list below the map', 'wpsl' ),
            'path' => WPSL_PLUGIN_DIR . 'frontend/templates/store-listings-below.php'
        )
    );

    return apply_filters( 'wpsl_templates', $templates );
}

/**
 * Return the days of the week.
 *
 * @since 2.0.0
 * @return array $weekdays The days of the week
 */
function wpsl_get_weekdays() {

   $weekdays = array(
       'monday'    => __( 'Monday', 'wpsl' ),
       'tuesday'   => __( 'Tuesday', 'wpsl' ),
       'wednesday' => __( 'Wednesday', 'wpsl' ),
       'thursday'  => __( 'Thursday', 'wpsl' ),
       'friday'    => __( 'Friday', 'wpsl' ),
       'saturday'  => __( 'Saturday', 'wpsl' ),
       'sunday'    => __( 'Sunday' , 'wpsl' )
   );

   return $weekdays;
}

/**
 * Get the default opening hours.
 *
 * @since 2.0.0
 * @return array $opening_hours The default opening hours
 */
function wpsl_default_opening_hours() {

   $current_version = get_option( 'wpsl_version' );

   $opening_hours = array(
       'dropdown' => array(
           'monday'    => array( '9:00 AM,5:00 PM' ),
           'tuesday'   => array( '9:00 AM,5:00 PM' ),
           'wednesday' => array( '9:00 AM,5:00 PM' ),
           'thursday'  => array( '9:00 AM,5:00 PM' ),
           'friday'    => array( '9:00 AM,5:00 PM' ),
           'saturday'  => '',
           'sunday'    => ''
        )
    );

   /* Only add the textarea defaults for users that upgraded from 1.x */
   if ( version_compare( $current_version, '2.0', '<' ) ) {
       $opening_hours['textarea'] = sprintf( __( 'Mon %sTue %sWed %sThu %sFri %sSat Closed %sSun Closed', 'wpsl' ), '9:00 AM - 5:00 PM' . "\n", '9:00 AM - 5:00 PM' . "\n", '9:00 AM - 5:00 PM' . "\n", '9:00 AM - 5:00 PM' . "\n", '9:00 AM - 5:00 PM' . "\n", "\n" ); //cleaner way without repeating it 5 times??
   }

   return $opening_hours;
}

/**
 * Get the available map types.
 *
 * @since 2.0.0
 * @return array $map_types The available map types
 */
function wpsl_get_map_types() {

    $map_types = array(
        'roadmap'   => __( 'Roadmap', 'wpsl' ),
        'satellite' => __( 'Satellite', 'wpsl' ),
        'hybrid'    => __( 'Hybrid', 'wpsl' ),
        'terrain'   => __( 'Terrain', 'wpsl' )
    );

    return $map_types;
}

/**
 * Get the address formats.
 *
 * @since 2.0.0
 * @return array $address_formats The address formats
 */
function wpsl_get_address_formats() {

    $address_formats = array(
        'city_state_zip'       => __( '(city) (state) (zip code)', 'wpsl' ),
        'city_comma_state_zip' => __( '(city), (state) (zip code)', 'wpsl' ),
        'city_zip'             => __( '(city) (zip code)', 'wpsl' ),
        'city_comma_zip'       => __( '(city), (zip code)', 'wpsl' ),
        'zip_city_state'       => __( '(zip code) (city) (state)', 'wpsl' ),
        'zip_city'             => __( '(zip code) (city)', 'wpsl' )
    );

    return apply_filters( 'wpsl_address_formats', $address_formats );
}

/**
 * Make sure the provided map type is valid.
 *
 * If the map type is invalid the default is used ( roadmap ).
 *
 * @since 2.0.0
 * @param  string $map_type The provided map type
 * @return string $map_type A valid map type
 */
function wpsl_valid_map_type( $map_type ) {

    $allowed_map_types = wpsl_get_map_types();

    if ( !array_key_exists( $map_type, $allowed_map_types ) ) {
        $map_type = wpsl_get_default_setting( 'map_type' );
    }

    return $map_type;
}

/**
 * Make sure the provided zoom level is valid.
 *
 * If the zoom level is invalid the default is used ( 3 ).
 *
 * @since 2.0.0
 * @param  string $zoom_level The provided zoom level
 * @return string $zoom_level A valid zoom level
 */
function wpsl_valid_zoom_level( $zoom_level ) {

    $zoom_level = absint( $zoom_level );

    if ( ( $zoom_level < 1 ) || ( $zoom_level > 21 ) ) {
        $zoom_level = wpsl_get_default_setting( 'zoom_level' );
    }

    return $zoom_level;
}

/**
 * Get the max auto zoom levels for the map.
 *
 * @since 2.0.0
 * @return array $max_zoom_levels The array holding the min - max zoom levels
 */
function wpsl_get_max_zoom_levels() {

    $max_zoom_levels = array();
    $zoom_level = array(
        'min' => 10,
        'max' => 21
    );

    $i = $zoom_level['min'];

    while ( $i <= $zoom_level['max'] ) {
        $max_zoom_levels[$i] = $i;
        $i++;
    }

    return $max_zoom_levels;
}

/**
 * The labels and the values that can be set through the settings page.
 *
 * @since 2.0.0
 * @return array $labels The label names from the settings page.
 */
function wpsl_labels() {

    $labels = array(
        'search',
        'search_btn',
        'preloader',
        'radius',
        'no_results',
        'results',
        'more',
        'directions',
        'no_directions',
        'back',
        'street_view',
        'zoom_here',
        'error',
        'phone',
        'fax',
        'email',
        'url',
        'hours',
        'start',
        'limit',
        'category',
        'category_default'
    );

    return $labels;
}

/**
 * Callback for array_walk_recursive, sanitize items in a multidimensional array.
 *
 * @since 2.0.0
 * @param string  $item The value
 * @param integer $key  The key
 */
function wpsl_sanitize_multi_array( &$item, $key ) {
    $item = sanitize_text_field( $item );
}

/**
 * Check whether the array is multidimensional.
 *
 * @since 2.0.0
 * @param  array    $array The array to check
 * @return boolean
 */
function wpsl_is_multi_array( $array ) {

    foreach ( $array as $value ) {
        if ( is_array( $value ) ) return true;
    }

    return false;
}

/**
 * @since 2.1.1
 * @param string $address  The address to geocode.
 * @return array $response Either a WP_Error or the response from the Geocode API.
 */
function wpsl_call_geocode_api( $address ) {

    $url      = 'https://maps.googleapis.com/maps/api/geocode/json?address=' . urlencode( $address ) . wpsl_get_gmap_api_params( 'server_key', true );
    $response = wp_remote_get( $url );

    return $response;
}

/**
 * Get the latlng for the provided address.
 *
 * This is used to geocode the address set as the start point on
 * the settings page in case the autocomplete fails
 * ( only happens when there is a JS error on the page ),
 * or to get the latlng when the 'start_location' attr is set
 * on the wpsl shortcode.
 *
 * @since 2.2
 * @param string      $address The address to geocode.
 * @return array|void $latlng  The returned latlng or nothing if there was an error.
 */
function wpsl_get_address_latlng( $address ) {

    $latlng   = '';
    $response = wpsl_call_geocode_api( $address );

    if ( !is_wp_error( $response ) ) {
        $response = json_decode( $response['body'], true );

        if ( $response['status'] == 'OK' ) {
            $latlng = $response['results'][0]['geometry']['location']['lat'] . ',' . $response['results'][0]['geometry']['location']['lng'];
        }
    }

    return $latlng;
}

/**
 * Check if there's a transient that holds
 * the coordinates for the passed address.
 *
 * If not, then we geocode the address and
 * set the returned value in the transient.
 *
 * @since 2.2.11
 * @param  string $address The location to geocode
 * @return string $latlng  The coordinates of the geocoded location
 */
function wpsl_check_latlng_transient( $address ) {

    $name_section   = explode( ',', $address );
    $transient_name = 'wpsl_' . trim( strtolower( $name_section[0] ) ) . '_latlng';

    if ( false === ( $latlng = get_transient( $transient_name ) ) ) {
        $latlng = wpsl_get_address_latlng( $address );

        if ( $latlng ) {
            set_transient( $transient_name, $latlng, 0 );
        }
    }

    return $latlng;
}

/**
 * Make sure the shortcode attributes are booleans
 * when they are expected to be.
 *
 * @since 2.0.4
 * @param  array $atts Shortcode attributes
 * @return array $atts Shortcode attributes
 */
function wpsl_bool_check( $atts ) {

    foreach ( $atts as $key => $val ) {
        if ( in_array( $val, array( 'true', '1', 'yes', 'on' ) ) ) {
            $atts[$key] = true;
        } else if ( in_array( $val, array( 'false', '0', 'no', 'off' ) ) ) {
            $atts[$key] = false;
        }
    }

    return $atts;
}

/**
 * Create a string with random characters.
 *
 * @since 2.2.4
 * @param  int    $length       Used length
 * @return string $random_chars Random characters
 */
function wpsl_random_chars( $length = 5 ) {

    $random_chars = substr( str_shuffle( "abcdefghijklmnopqrstuvwxyz" ), 0, $length );

    return $random_chars;
}

/**
 * Deregister other Google Maps scripts.
 *
 * If plugins / themes also include the Google Maps library, then it can cause
 * problems with the autocomplete function on the settings page and break
 * the store locator on the front-end.
 *
 * @since 2.2.4
 * @return void
 */
function wpsl_deregister_other_gmaps() {

    global $wp_scripts;

    foreach ( $wp_scripts->registered as $index => $script ) {
        if ( ( strpos( $script->src, 'maps.google.com' ) !== false ) || ( strpos( $script->src, 'maps.googleapis.com' ) !== false ) && ( $script->handle !== 'wpsl-gmap' ) ) {
            wp_deregister_script( $script->handle );
        }
    }
}

/**
 * Return the used distance unit.
 *
 * @since 2.2.8
 * @return string Either km or mi
 */
function wpsl_get_distance_unit() {

    global $wpsl_settings;

    return apply_filters( 'wpsl_distance_unit', $wpsl_settings['distance_unit'] );
}

/**
 * Find the term ids for the provided term slugs.
 *
 * @since 2.2.10
 * @param  array $cat_list List of term slugs
 * @return array $term_ids The term ids
 */
function wpsl_get_term_ids( $cat_list ) {

    $term_ids = array();
    $cats     = explode( ',', $cat_list );

    foreach ( $cats as $key => $term_slug ) {
        $term_data = get_term_by( 'slug', $term_slug, 'wpsl_store_category' );

        if ( isset( $term_data->term_id ) && $term_data->term_id ) {
            $term_ids[] = $term_data->term_id;
        }
    }

    return $term_ids;
}

/**
 * Get the url to the admin-ajax.php
 *
 * @since 2.2.3
 * @return string $ajax_url URL to the admin-ajax.php possibly with the WPML lang param included.
 */
function wpsl_get_ajax_url() {

    $i18n = new WPSL_i18n();

    $param = '';

    if ( $i18n->wpml_exists() && defined( 'ICL_LANGUAGE_CODE' ) ) {
        $param = '?lang=' . ICL_LANGUAGE_CODE;
    }

    $ajax_url = admin_url( 'admin-ajax.php' . $param );

    return $ajax_url;
}

/**
 * Get a list of the used meta fields.
 *
 * Used by add-ons and the REST-API.
 *
 * @since 2.2.14
 * @param array $args Argument to grab the locations field. See the $defaults structure.
 * @return array $fields
 */
function wpsl_get_location_fields( $args = array() ) {

    // Required to make sure it works with API calls.
    if ( !class_exists( 'WPSL_Metaboxes' ) ) {
        require_once( WPSL_PLUGIN_DIR . 'admin/class-metaboxes.php' );
    }

    $metaboxes   = new WPSL_Metaboxes();
    $meta_fields = $metaboxes->meta_box_fields();

    $fields   = array();
    $defaults = array(
        'exclude'    => array( 'country_iso' ),
        'prefix'     => '',
        'set_values' => true
    );

    /**
     * Parse incoming $args into an array and merge it with $defaults
     */
    $args = wp_parse_args( $args, $defaults );

    foreach ( $meta_fields as $k => $field_section ) {
        foreach ( $field_section as $field_name => $field_value ) {
            if ( in_array( $field_name, $args['exclude'] ) ) {
                continue;
            }
            $fields[$args['prefix'] . $field_name] = ( $args['set_values'] ) ? $field_name : '';
        }
    }
    return $fields;
}inc/class-borlabs-cookie.php000064400000014733151327220640012036 0ustar00<?php
/**
 * WPSL / Borlabs Cookie class
 *
 * @author Tijmen Smit
 * @since  2.2.22
 */

if ( !defined( 'ABSPATH' ) ) exit;

if ( !class_exists( 'WPSL_Borlabs_Cookie' ) ) {

    class WPSL_Borlabs_Cookie {

        /**
         * Class constructor
         */
        public function __construct() {

            if ( !is_admin() ) {
                if (defined('BORLABS_COOKIE_VERSION') && version_compare(BORLABS_COOKIE_VERSION, '2.0', '>=')) {
                    add_filter( 'borlabsCookie/contentBlocker/modify/content/wpstorelocator', array( $this, 'update_content_blocker' ), 10, 2 );
                } else {
                    add_filter( 'borlabsCookie/bct/modify_content/wpstorelocator', array( $this, 'update_content_blocker_backwards_compatibility' ), 10, 2 );
                }
            }
        }

        /**
         * Check if the 'wpstorelocator' blocked content type exists.
         * If this is not the case, then we create it.
         *
         * @since 2.2.22
         * @return void
         */
        public function maybe_enable_bct() {

            $wpsl_bct_data = BorlabsCookieHelper()->getBlockedContentTypeDataByTypeId( 'wpstorelocator' );

            if ( !$wpsl_bct_data ) {
                $this->enable();
            }
        }

        /**
         * Add support for the delayed loading of the
         * Google Maps library in the Borlabs Cookies plugin
         * by adding a 'wpstorelocator' blocked content type.
         *
         * @since 2.2.22
         * @return void
         */
        public function enable() {

            /**
             * First, we delete old Blocked Content Types with the id wpstorelocator.
             * If the id doesn't exist, nothing happens.
             *
             * Doing so ensures that both plugins work as intended.
             */
            BorlabsCookieHelper()->deleteBlockedContentType( 'wpstorelocator' );

            // Add new Blocked Content Type wpstorelocator - if the BCT exists nothing happens
            BorlabsCookieHelper()->addBlockedContentType(
                'wpstorelocator',
                'WP Store Locator',
                '',
                [],
                '<div class="borlabs-cookie-bct bc-bct-iframe bc-bct-google-maps">
                    <p class="bc-thumbnail"><img src="%%thumbnail%%" alt="%%name%%"></p>
                    <div class="bc-text">
                        <p>' . _x( 'To protect your personal data, your connection to Google Maps has been blocked.<br>Click on <strong>Load map</strong> to unblock Google Maps.<br>By loading the map you accept the privacy policy of Google.<br>More information about Google\'s privacy policy can be found here <a href="https://policies.google.com/privacy?hl=en&amp;gl=en" target="_blank" rel="nofollow">Google - Privacy &amp; Terms</a> . ', 'Borlabs Cookie', 'wpsl' ) . '</p>
                        <p><label><input type="checkbox" name="unblockAll" value="1" checked> ' . _x( 'Do not block Google Maps in the future anymore.', 'Borlabs Cookie', 'wpsl' ) . '</label>
                        <a role="button" data-borlabs-cookie-unblock>' . _x( 'Load map', 'Borlabs Cookie', 'wpsl' ) . '</a></p>
                    </div>
                </div>',
                '',
                '',
                [
                    'responsiveIframe' => false,
                ],
                true,
                true
            );
        }

        /**
         * Remove the 'wpstorelocator' blocked content type
         * from the Borlabs Cookie plugin.
         *
         * @since 2.2.22
         */
        public function disable() {
            if ( function_exists('BorlabsCookieHelper' ) ) {
                BorlabsCookieHelper()->deleteBlockedContentType( 'wpstorelocator' );
            }
        }

        /**
         * modifyWPStoreLocatorContentBlockerBackwardsCompatibility function.
         *
         * @since 2.2.233
         * @param mixed $id
         * @param mixed $content
         * @return void
         */
        public function update_content_blocker_backwards_compatibility( $id, $content ) {
            return $this->update_content_blocker($content);
        }

        /**
         * modifyWPStoreLocatorContentBlocker function.
         *
         * @since 2.2.22
         * @param mixed $content
         * @param mixed $atts
         * @return void
         */
        public function update_content_blocker( $content, $atts = [] ) {

            // Get settings of the Blocked Content Type
            $wpsl_data = BorlabsCookieHelper()->getBlockedContentTypeDataByTypeId( 'wpstorelocator' );

            // Workaround, fixed in newer versions of Borlabs Cookie
            if ( !isset($wpsl_data['settings']['unblockAll'] ) ) {
                $wpsl_data['settings']['unblockAll'] = false;
            }

            BorlabsCookieHelper()->updateBlockedContentTypeJavaScript(
                'wpstorelocator',
                'var myScriptTag = document.createElement("script"); myScriptTag.type = "text/javascript"; myScriptTag.src = "https://maps.google.com/maps/api/js' . wpsl_get_gmap_api_params( "browser_key" ) .'";jQuery("body").append(myScriptTag);',
                'initWpslMap();',
                $wpsl_data['settings']
            );

            // Default thumbnail
            $thumbnail = BORLABS_COOKIE_PLUGIN_URL.'images/bct-google-maps.png';

            // Get the title which was maybe set via title-attribute in a shortcode
            $title = BorlabsCookieHelper()->getCurrentTitleOfBlockedContentType();

            // If no title was set use the Blocked Content Type name as title
            if ( empty( $title ) ) {
                $title = $wpsl_data['name'];
            }

            // Replace text variables
            if (!empty($atts)) {

                foreach ($atts as $key => $value) {
                    $wpsl_data['previewHTML'] = str_replace('%%'.$key.'%%', $value, $wpsl_data['previewHTML']);
                }
            }

            $wpsl_data['previewHTML'] = str_replace(
                [
                    '%%name%%',
                    '%%thumbnail%%',
                    '%%privacy_policy_url%%',
                ],
                [
                    $title,
                    $thumbnail,
                    $wpsl_data['privacyPolicyURL'],
                ],
                $wpsl_data['previewHTML']
            );

            /* Return the HTML that displays the information, that the original content was blocked */
            return $wpsl_data['previewHTML'];
        }
    }

    new WPSL_Borlabs_Cookie();
}inc/class-templates.php000064400000012627151327220640011141 0ustar00<?php
/**
 * Handle the WPSL and Add-on templates
 *
 * @author Tijmen Smit
 * @since  2.2.11
 */

if ( !defined( 'ABSPATH' ) ) exit;

if ( !class_exists( 'WPSL_Templates' ) ) {

    class WPSL_Templates {

        /**
         * Get the list of available templates
         *
         * @since 2.2.11
         * @param string $type The template type to return
         * @return array|void
         */
        public function get_template_list( $type = 'store_locator' ) {

            $template_list = array();

            // Add the WPSL templates or the add-on templates.
            if ( $type == 'store_locator' ) {
                $template_list['store_locator'] = wpsl_get_templates();
            } else {
                $template_list = apply_filters( 'wpsl_template_list', $template_list );
            }

            if ( isset( $template_list[$type] ) && !empty( $template_list[$type] ) ) {
                return $template_list[$type];
            }
        }

        /**
         * Get the template details
         *
         * @since 2.2.11
         * @param  string $used_template The name of the template
         * @param  string $type          The type of template data to load
         * @return array  $template_data The template data ( id, name, path )
         */
        public function get_template_details( $used_template, $type = 'store_locator' ) {

            $used_template = ( empty( $used_template ) ) ? 'default' : $used_template;
            $templates     = $this->get_template_list( $type );
            $template_data = '';
            $template_path = '';

            if ( $templates ) {
                // Grab the the correct template data from the available templates.
                foreach ( $templates as $template ) {
                    if ( $used_template == $template['id'] ) {
                        $template_data = $template;
                        break;
                    }
                }
            }

            // Old structure ( WPSL only ) was only the path, new structure ( add-ons ) expects the file name as well.
            if ( isset( $template_data['path'] ) && isset( $template_data['file_name'] ) ) {
                $template_path = $template_data['path'] . $template_data['file_name'];
            } else if ( isset( $template_data['path'] ) ) {
                $template_path = $template_data['path'];
            }

            // If no match exists, or the template file doesnt exist, then use the default template.
            if ( !$template_data || ( !file_exists( $template_path ) ) ) {
                $template_data = $this->get_default_template( $type );

                // If no template can be loaded, then show a msg to the admin user.
                if ( !$template_data && current_user_can( 'administrator' ) ) {
                    echo '<p>' . sprintf( __( 'No template found for %s', 'wpsl' ), $type ) . '</p>';
                    echo '<p>' . sprintf( __( 'Make sure you call the %sget_template_details%s function with the correct parameters.', 'wpsl' ), '<code>', '</code>' ) . '</p>';
                }
            }

            return $template_data;
        }

        /**
         * Locate the default template
         *
         * @since 2.2.11
         * @param string $type    The type of default template to return
         * @return array $default The default template data
         */
        public function get_default_template( $type = 'store_locator' ) {

            $template_list = $this->get_template_list( $type );
            $default       = '';

            if ( $template_list ) {
                foreach ( $template_list as $template ) {
                    if ( $template['id'] == 'default' ) {
                        $default = $template;
                        break;
                    }
                }
            }

            return $default;
        }

        /**
         * Include the template file.
         *
         * @since  2.2.11
         * @param  array  $args          The template path details
         * @param  array  $template_data The template data ( address, phone, fax etc ).
         * @return string The location template.
         */
        function get_template( $args, $template_data ) {

            // Don't continue if not path and file name is set.
            if ( !isset( $args['path'] ) || !isset( $args['file_name'] ) ) {
                return;
            }

            ob_start();

            include( $this->find_template_path( $args ) );

            return ob_get_clean();
        }

        /**
         * Locate the template file in either the
         * theme folder or the plugin folder itself.
         *
         * @since 2.2.11
         * @param  array  $args     The template data
         * @return string $template The path to the template.
         */
        function find_template_path( $args ) {

            // Look for the template in the theme folder.
            $template = locate_template(
                array( trailingslashit( 'wpsl-templates' ) . $args['file_name'], $args['file_name'] )
            );

            // If the template doesn't exist in the theme folder load the one from the plugin dir.
            if ( !$template ) {
                $template = $args['path'] . $args['file_name'];
            }

            return $template;
        }
    }
}inc/install.php000064400000002721151327220640007500 0ustar00<?php
/**
 * WPSL Install
 *
 * @author Tijmen Smit
 * @since  2.0.0
 */

if ( !defined( 'ABSPATH' ) ) exit;
        
/**
 * Run the install.
 *
 * @since 1.2.20
 * @return void
 */
function wpsl_install( $network_wide ) {

    global $wpdb;

    if ( function_exists( 'is_multisite' ) && is_multisite() ) {

        if ( $network_wide ) {
            $blog_ids = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs" );

            foreach ( $blog_ids as $blog_id ) {
                switch_to_blog( $blog_id );
                wpsl_install_data();
            }

            restore_current_blog();
        } else {
            wpsl_install_data();
        }
    } else {
        wpsl_install_data();
    }

    if ( function_exists( 'BorlabsCookieHelper' ) ) {
        require_once( 'class-borlabs-cookie.php' );

        $borlabs = New WPSL_Borlabs_Cookie();
        $borlabs->enable();
    }
}

/**
 * Install the required data.
 *
 * @since 1.2.20
 * @return void
 */
function wpsl_install_data() {

    global $wpsl;

    // Register the post type and flush the permalinks.
    $wpsl->post_types->register_post_types();
    flush_rewrite_rules();

    // Create the default settings.
    wpsl_set_default_settings();

    // Set the correct version.
    update_option( 'wpsl_version', WPSL_VERSION_NUM );
    
    // Add user roles.
    wpsl_add_roles();
    
    // Add user capabilities.
    wpsl_add_caps();
} inc/class-post-types.php000064400000025750151327220640011273 0ustar00<?php
/**
 * Store Locator custom post type.
 *
 * @author Tijmen Smit
 * @since  2.0.0
 */

if ( !defined( 'ABSPATH' ) ) exit;

if ( !class_exists( 'WPSL_Post_Types' ) ) {
    
    class WPSL_Post_Types {

        /**
         * Constructor
         */
        public function __construct() {
            add_action( 'init',                                     array( $this, 'maybe_show_in_rest' ) );
            add_action( 'init',                                     array( $this, 'register_post_types' ), 10, 1 );
            add_action( 'init',                                     array( $this, 'register_taxonomies' ), 10, 1 );
            add_action( 'manage_wpsl_stores_posts_custom_column',   array( $this, 'custom_columns' ), 10, 2 );
            
            add_filter( 'enter_title_here',                         array( $this, 'change_default_title' ) );
            add_filter( 'manage_edit-wpsl_stores_columns',          array( $this, 'edit_columns' ) );
            add_filter( 'manage_edit-wpsl_stores_sortable_columns', array( $this, 'sortable_columns' ) );
            add_filter( 'request',                                  array( $this, 'sort_columns' ) );
        }

        /**
         * Check if we need to set 'show_in_rest' to true/false,
         * and thereby enabling the REST API.
         *
         * This needs to be set to true for
         * Gutenberg to be enabled.
         *
         * Full REST API support will come in the 3.0 update.
         *
         * @since 2.2.19
         * @return bool
         */
        public function maybe_show_in_rest() {

            global $wp_version;

            return ( version_compare( $wp_version, '5', '>=' ) ) ? true : false;
        }


        /**
         * Register the WPSL post type.
         * 
         * @since 2.0.0
         * @return void
         */
        public function register_post_types() {

            global $wpsl_settings;

            // Enable permalinks for the post type?
            if ( isset( $wpsl_settings['permalinks'] ) && $wpsl_settings['permalinks'] ) {
                $public              = true;
                $exclude_from_search = false;
                $rewrite             = array( 'slug' => $wpsl_settings['permalink_slug'] );

                if ( $wpsl_settings['permalink_remove_front'] ) {
                    $rewrite['with_front'] = false;
                }
            } else {
                $public              = false;
                $exclude_from_search = true;
                $rewrite             = false;
            }

            // The labels for the wpsl_stores post type.
            $labels = apply_filters( 'wpsl_post_type_labels', array(
                    'name'               => __( 'Store Locator', 'wpsl' ),
                    'all_items'          => __( 'All Stores', 'wpsl' ),
                    'singular_name'      => __( 'Store', 'wpsl' ),
                    'add_new'            => __( 'New Store', 'wpsl' ),
                    'add_new_item'       => __( 'Add New Store', 'wpsl' ),
                    'edit_item'          => __( 'Edit Store', 'wpsl' ),
                    'new_item'           => __( 'New Store', 'wpsl' ),
                    'view_item'          => __( 'View Stores', 'wpsl' ),
                    'search_items'       => __( 'Search Stores', 'wpsl' ),
                    'not_found'          => __( 'No Stores found', 'wpsl' ),
                    'not_found_in_trash' => __( 'No Stores found in trash', 'wpsl' ),
                ) 
            );
            
            // The arguments for the wpsl_stores post type.
            $args = apply_filters( 'wpsl_post_type_args', array(
                    'labels'              => $labels, 
                    'public'              => $public,
                    'exclude_from_search' => $exclude_from_search,
                    'show_ui'             => true,
                    'menu_position'       => apply_filters( 'wpsl_post_type_menu_position', null ),
                    'capability_type'     => 'store',
                    'map_meta_cap'        => true,
                    'rewrite'             => $rewrite,
                    'query_var'           => 'wpsl_stores',
                    'supports'            => array( 'title', 'editor', 'author', 'excerpt', 'revisions', 'thumbnail' ),
                    'show_in_rest'        => $this->maybe_show_in_rest()
                )
            );

            register_post_type( 'wpsl_stores', $args );
        }
        
        /**
         * Register the WPSL custom taxonomy.
         * 
         * @since 2.0.0
         * @return void
         */
        public function register_taxonomies() {
            
            global $wpsl_settings;
                        
            // Enable permalinks for the taxonomy?
            if ( isset( $wpsl_settings['permalinks'] ) && $wpsl_settings['permalinks'] ) {
                $public  = true;
                $rewrite = array( 'slug' => $wpsl_settings['category_slug'] );
            } else {
                $public  = false;
                $rewrite = false;
            }

            $labels = array(
				'name'              => __( 'Store Categories', 'wpsl' ),
				'singular_name'     => __( 'Store Category', 'wpsl' ),
				'search_items'      => __( 'Search Store Categories', 'wpsl' ),
				'all_items'         => __( 'All Store Categories', 'wpsl' ),
				'parent_item'       => __( 'Parent Store Category', 'wpsl' ),
				'parent_item_colon' => __( 'Parent Store Category:', 'wpsl' ),
				'edit_item'         => __( 'Edit Store Category', 'wpsl' ),
				'update_item'       => __( 'Update Store Category', 'wpsl' ),
				'add_new_item'      => __( 'Add New Store Category', 'wpsl' ),
				'new_item_name'     => __( 'New Store Category Name', 'wpsl' ),
				'menu_name'         => __( 'Store Categories', 'wpsl' ),
			);
                        
            $args = apply_filters( 'wpsl_store_category_args', array(
                    'labels'                => $labels,
                    'public'                => $public,
                    'hierarchical'          => true,
                    'show_ui'               => true,
                    'show_admin_column'     => true,
                    'update_count_callback' => '_update_post_term_count',
                    'query_var'             => true,
                    'rewrite'               => $rewrite,
                    'show_in_rest'          => $this->maybe_show_in_rest()
                )
            );

            register_taxonomy( 'wpsl_store_category', 'wpsl_stores', $args );    
        }

        /**
         * Change the default "Enter title here" placeholder.
         *
         * @since 2.0.0
         * @param  string $title The default title placeholder
         * @return string $title The new title placeholder
         */
        public function change_default_title( $title ) {

            $screen = get_current_screen();

            if ( $screen->post_type == 'wpsl_stores' ) {
               $title = __( 'Enter store title here', 'wpsl' );
            }

            return $title;
        }  

        /**
         * Add new columns to the store list table.
         *
         * @since 2.0.0
         * @param  array $columns The default columns
         * @return array $columns Updated column list
         */
        public function edit_columns( $columns ) {
            
            $columns['address'] = __( 'Address', 'wpsl' );
            $columns['city']    = __( 'City', 'wpsl' );
            $columns['state']   = __( 'State', 'wpsl' );
            $columns['zip']     = __( 'Zip', 'wpsl' );

            return $columns;
        }
        
        /**
         * Show the correct store content in the correct custom column.
         *
         * @since 2.0.0
         * @param  string $column  The column name
         * @param  int    $post_id The post id
         * @return void
         */
        public function custom_columns( $column, $post_id ) {
            
            switch ( $column ) {
                case 'address':
                    echo esc_html( get_post_meta( $post_id, 'wpsl_address', true ) );
				break; 
                case 'city':
                    echo esc_html( get_post_meta( $post_id, 'wpsl_city', true ) );
                break;
                case 'state':
                    echo esc_html( get_post_meta( $post_id, 'wpsl_state', true ) );
                break;
                case 'zip':
                    echo esc_html( get_post_meta( $post_id, 'wpsl_zip', true ) );
                break;
            }
        }
        
        /**
         * Define the columns that are sortable.
         *
         * @since 2.0.0
         * @param  array $columns List of sortable columns
         * @return array
         */
        public function sortable_columns( $columns ) {

            $custom = array(
                'address' => 'wpsl_address',
                'city'    => 'wpsl_city',
                'state'   => 'wpsl_state',
                'zip'     => 'wpsl_zip'
            );
           
            return wp_parse_args( $custom, $columns );
        }
        
        /**
         * Set the correct column sort parameters.
         *
         * @since 2.0.0
         * @param  array $vars Column sorting parameters
         * @return array $vars The column sorting parameters inc the correct orderby and wpsl meta_key
         */
        public function sort_columns( $vars ) {
            
            if ( isset( $vars['post_type'] ) && $vars['post_type'] == 'wpsl_stores' ) {
                if ( isset( $vars['orderby'] ) ) {
                    if ( $vars['orderby'] === 'wpsl_address' ) {
                        $vars = array_merge( $vars, array(
                            'meta_key' => 'wpsl_address',
                            'orderby'  => 'meta_value'
                        ) );
                    }
                    
                    if ( $vars['orderby'] === 'wpsl_city' ) {
                        $vars = array_merge( $vars, array(
                            'meta_key' => 'wpsl_city',
                            'orderby'  => 'meta_value'
                        ) );
                    }
                    
                    if ( $vars['orderby'] === 'wpsl_state' ) {
                        $vars = array_merge( $vars, array(
                            'meta_key' => 'wpsl_state',
                            'orderby'  => 'meta_value'
                        ) );
                    }
                    
                    if ( $vars['orderby'] === 'wpsl_zip' ) {
                        $vars = array_merge( $vars, array(
                            'meta_key' => 'wpsl_zip',
                            'orderby'  => 'meta_value'
                        ) );
                    }
                }
            }
            
            return $vars;
        }
    }
       
}inc/class-i18n.php000064400000012750151327220640007717 0ustar00<?php
/**
 * i18n class
 *
 * @author Tijmen Smit
 * @since  2.0.0
 */

if ( !defined( 'ABSPATH' ) ) exit;

if ( !class_exists( 'WPSL_i18n' ) ) {
    
    class WPSL_i18n {
        
        private $wpml_active = null;
        
        private $qtrans_active = null;        
                
        /**
         * Class constructor
         */          
        function __construct() {
            add_action( 'plugins_loaded', array( $this, 'load_plugin_textdomain' ) );    
        }
                
        /**
         * Load the translations from the language folder
         *
         * @since 2.0.0
         * @return void
         */
        public function load_plugin_textdomain() {
            
            $domain = 'wpsl';
            $locale = apply_filters( 'plugin_locale', get_locale(), $domain );
            
            // Load the language file from the /wp-content/languages/wp-store-locator folder, custom + update proof translations.
            load_textdomain( $domain, WP_LANG_DIR . '/wp-store-locator/' . $domain . '-' . $locale . '.mo' );
            
            // Load the language file from the /wp-content/plugins/wp-store-locator/languages/ folder.
            load_plugin_textdomain( $domain, false, dirname( WPSL_BASENAME ) . '/languages/' ); 
        }

        /**
         * Check if WPML is active
         *
         * @since 2.0.0
         * @return boolean|null
         */
        public function wpml_exists() {
            
            if ( $this->wpml_active == null ) {
                $this->wpml_active = function_exists( 'icl_register_string' );
            }

            return $this->wpml_active;
        } 

        /**
         * Check if a qTranslate compatible plugin is active.
         *
         * @since 2.0.0
         * @return boolean|null
         */
        public function qtrans_exists() {
            
            if ( $this->qtrans_active == null ) {
                $this->qtrans_active = ( function_exists( 'qtrans_useCurrentLanguageIfNotFoundUseDefaultLanguage' ) || function_exists( 'qtranxf_useCurrentLanguageIfNotFoundUseDefaultLanguage' ) );
            }
            
            return $this->qtrans_active;
        } 
        
        /**
         * See if there is a translated page available for the provided store ID.
         * 
         * @since 2.0.0
         * @see    https://wpml.org/documentation/support/creating-multilingual-wordpress-themes/language-dependent-ids/#2
         * @param  string $store_id
         * @return string empty or the id of the translated store
         */
        public function maybe_get_wpml_id( $store_id ) {
            
            $return_original_id = apply_filters( 'wpsl_return_original_wpml_id', true );

            // icl_object_id is deprecated as of 3.2
            if ( defined( 'ICL_SITEPRESS_VERSION' ) && version_compare( ICL_SITEPRESS_VERSION, 3.2, '>=' ) ) {
                $translated_id = apply_filters( 'wpml_object_id', $store_id, 'wpsl_stores', $return_original_id, ICL_LANGUAGE_CODE );
            } else {
                $translated_id = icl_object_id( $store_id, 'wpsl_stores', $return_original_id, ICL_LANGUAGE_CODE );
            }

            // If '$return_original_id' is set to false, NULL is returned if no translation exists.
            if ( is_null( $translated_id ) ) {
                $translated_id = '';
            }
                        
            return $translated_id;
        }

        /**
         * Get the correct translation.
         * 
         * Return the translated text from WPML or the translation 
         * that was set on the settings page.
         * 
         * @since 2.0.0
         * @param  string $name        The name of the translated string
         * @param  string $text        The text of the translated string
         * @return string $translation The translation
         */
        public function get_translation( $name, $text ) {

            global $wpsl_settings;

            if ( defined( 'WPML_ST_VERSION' ) ) {
                $translation = $text;
            } elseif ( defined( 'POLYLANG_VERSION' ) && defined( 'POLYLANG_DIR' ) ) {

                if ( ! function_exists( 'pll__' ) ) {
                    require_once POLYLANG_DIR . '/include/api.php';
                }

                $translation = pll__( $text );
            } else {
                $translation = stripslashes( $wpsl_settings[$name] );
            }

            return $translation;
        }

        /**
         * If a multilingual plugin like WPML or qTranslate X is active
         * we return the active language code.
         * 
         * @since 2.0.0
         * @return string Empty or the current language code
         */
        public function check_multilingual_code() {
            
            $language_code = '';
            
            if ( $this->wpml_exists() && defined( 'ICL_LANGUAGE_CODE' ) ) {
                $language_code = ICL_LANGUAGE_CODE;
            } else if ( $this->qtrans_exists() ) {
                
                if ( function_exists( 'qtranxf_getLanguage' ) ) {
                    $language_code = qtranxf_getLanguage();
                } else if ( function_exists( 'qtrans_getLanguage' ) ) {
                    $language_code = qtrans_getLanguage();
                }                
            }    
            
            return $language_code;
        }
        
    }
    
    new WPSL_i18n();
}frontend/underscore-functions.php000064400000033415151327220640013263 0ustar00<?php
/**
 * Create the store data templates.
 * 
 * The templates are created in JS with _.template, see http://underscorejs.org/#template
 * 
 * @since 2.0.0
 * @param string $template The type of template we need to create
 * @return void
 */
function wpsl_create_underscore_templates( $template ) {

    global $wpsl_settings, $wpsl;

    if ( $template == 'wpsl_store_locator' ) {
    ?>
<script id="wpsl-info-window-template" type="text/template">
    <?php
        $info_window_template = '<div data-store-id="<%= id %>" class="wpsl-info-window">' . "\r\n";
        $info_window_template .= "\t\t" . '<p>' . "\r\n";
        $info_window_template .= "\t\t\t" .  wpsl_store_header_template() . "\r\n";  // Check which header format we use
        $info_window_template .= "\t\t\t" . '<span><%= address %></span>' . "\r\n";
        $info_window_template .= "\t\t\t" . '<% if ( address2 ) { %>' . "\r\n";
        $info_window_template .= "\t\t\t" . '<span><%= address2 %></span>' . "\r\n";
        $info_window_template .= "\t\t\t" . '<% } %>' . "\r\n";
        $info_window_template .= "\t\t\t" . '<span>' . wpsl_address_format_placeholders() . '</span>' . "\r\n"; // Use the correct address format
        $info_window_template .= "\t\t" . '</p>' . "\r\n";
        $info_window_template .= "\t\t" . '<% if ( phone ) { %>' . "\r\n";
        $info_window_template .= "\t\t" . '<span><strong>' . esc_html( $wpsl->i18n->get_translation( 'phone_label', __( 'Phone', 'wpsl' ) ) ) . '</strong>: <%= formatPhoneNumber( phone ) %></span>' . "\r\n";
        $info_window_template .= "\t\t" . '<% } %>' . "\r\n";
        $info_window_template .= "\t\t" . '<% if ( fax ) { %>' . "\r\n";
        $info_window_template .= "\t\t" . '<span><strong>' . esc_html( $wpsl->i18n->get_translation( 'fax_label', __( 'Fax', 'wpsl' ) ) ) . '</strong>: <%= fax %></span>' . "\r\n";
        $info_window_template .= "\t\t" . '<% } %>' . "\r\n";
        $info_window_template .= "\t\t" . '<% if ( email ) { %>' . "\r\n";
        $info_window_template .= "\t\t" . '<span><strong>' . esc_html( $wpsl->i18n->get_translation( 'email_label', __( 'Email', 'wpsl' ) ) ) . '</strong>: <%= formatEmail( email ) %></span>' . "\r\n";
        $info_window_template .= "\t\t" . '<% } %>' . "\r\n";
        $info_window_template .= "\t\t" . '<%= createInfoWindowActions( id ) %>' . "\r\n";
        $info_window_template .= "\t" . '</div>';

        echo apply_filters( 'wpsl_info_window_template', $info_window_template . "\n" );
    ?>
</script>
<script id="wpsl-listing-template" type="text/template">
    <?php
        $listing_template = '<li data-store-id="<%= id %>">' . "\r\n";
        $listing_template .= "\t\t" . '<div class="wpsl-store-location">' . "\r\n";
        $listing_template .= "\t\t\t" . '<p><%= thumb %>' . "\r\n";
        $listing_template .= "\t\t\t\t" . wpsl_store_header_template( 'listing' ) . "\r\n"; // Check which header format we use
        $listing_template .= "\t\t\t\t" . '<span class="wpsl-street"><%= address %></span>' . "\r\n";
        $listing_template .= "\t\t\t\t" . '<% if ( address2 ) { %>' . "\r\n";
        $listing_template .= "\t\t\t\t" . '<span class="wpsl-street"><%= address2 %></span>' . "\r\n";
        $listing_template .= "\t\t\t\t" . '<% } %>' . "\r\n";
        $listing_template .= "\t\t\t\t" . '<span>' . wpsl_address_format_placeholders() . '</span>' . "\r\n"; // Use the correct address format

        if ( !$wpsl_settings['hide_country'] ) {
            $listing_template .= "\t\t\t\t" . '<span class="wpsl-country"><%= country %></span>' . "\r\n";
        }
        
        $listing_template .= "\t\t\t" . '</p>' . "\r\n";
        
        // Show the phone, fax or email data if they exist.
        if ( $wpsl_settings['show_contact_details'] ) {
            $listing_template .= "\t\t\t" . '<p class="wpsl-contact-details">' . "\r\n";
            $listing_template .= "\t\t\t" . '<% if ( phone ) { %>' . "\r\n";
            $listing_template .= "\t\t\t" . '<span><strong>' . esc_html( $wpsl->i18n->get_translation( 'phone_label', __( 'Phone', 'wpsl' ) ) ) . '</strong>: <%= formatPhoneNumber( phone ) %></span>' . "\r\n";
            $listing_template .= "\t\t\t" . '<% } %>' . "\r\n";
            $listing_template .= "\t\t\t" . '<% if ( fax ) { %>' . "\r\n";
            $listing_template .= "\t\t\t" . '<span><strong>' . esc_html( $wpsl->i18n->get_translation( 'fax_label', __( 'Fax', 'wpsl' ) ) ) . '</strong>: <%= fax %></span>' . "\r\n";
            $listing_template .= "\t\t\t" . '<% } %>' . "\r\n";
            $listing_template .= "\t\t\t" . '<% if ( email ) { %>' . "\r\n";
            $listing_template .= "\t\t\t" . '<span><strong>' . esc_html( $wpsl->i18n->get_translation( 'email_label', __( 'Email', 'wpsl' ) ) ) . '</strong>: <%= formatEmail( email ) %></span>' . "\r\n";
            $listing_template .= "\t\t\t" . '<% } %>' . "\r\n";
            $listing_template .= "\t\t\t" . '</p>' . "\r\n";
        }
        
        $listing_template .= "\t\t\t" . wpsl_more_info_template() . "\r\n"; // Check if we need to show the 'More Info' link and info
        $listing_template .= "\t\t" . '</div>' . "\r\n";
        $listing_template .= "\t\t" . '<div class="wpsl-direction-wrap">' . "\r\n";
        
        if ( !$wpsl_settings['hide_distance'] ) {
            $listing_template .= "\t\t\t" . '<%= distance %> ' . esc_html( wpsl_get_distance_unit() ) . '' . "\r\n";
        }
        
        $listing_template .= "\t\t\t" . '<%= createDirectionUrl() %>' . "\r\n"; 
        $listing_template .= "\t\t" . '</div>' . "\r\n";
        $listing_template .= "\t" . '</li>';

        echo apply_filters( 'wpsl_listing_template', $listing_template . "\n" );
    ?>
</script>            
    <?php
    } else {
    ?>
<script id="wpsl-cpt-info-window-template" type="text/template">
    <?php
        $cpt_info_window_template = '<div class="wpsl-info-window">' . "\r\n";
        $cpt_info_window_template .= "\t\t" . '<p class="wpsl-no-margin">' . "\r\n";
        $cpt_info_window_template .= "\t\t\t" .  wpsl_store_header_template( 'wpsl_map' ) . "\r\n";
        $cpt_info_window_template .= "\t\t\t" . '<span><%= address %></span>' . "\r\n";
        $cpt_info_window_template .= "\t\t\t" . '<% if ( address2 ) { %>' . "\r\n";
        $cpt_info_window_template .= "\t\t\t" . '<span><%= address2 %></span>' . "\r\n";
        $cpt_info_window_template .= "\t\t\t" . '<% } %>' . "\r\n";
        $cpt_info_window_template .= "\t\t\t" . '<span>' . wpsl_address_format_placeholders() . '</span>' . "\r\n"; // Use the correct address format 
        
        if ( !$wpsl_settings['hide_country'] ) {
            $cpt_info_window_template .= "\t\t\t" . '<span class="wpsl-country"><%= country %></span>' . "\r\n"; 
        }
        
        $cpt_info_window_template .= "\t\t" . '</p>' . "\r\n";
        $cpt_info_window_template .= "\t" . '</div>';

        echo apply_filters( 'wpsl_cpt_info_window_template', $cpt_info_window_template . "\n" );
    ?>
</script>
    <?php
    }
}

/**
 * Create the more info template.
 *
 * @since 2.0.0
 * @return string $more_info_template The template that is used to show the "More info" content
 */
function wpsl_more_info_template() {
            
    global $wpsl_settings, $wpsl;

    if ( $wpsl_settings['more_info'] ) {
        $more_info_url = '#';

        if ( $wpsl_settings['template_id'] == 'default' && $wpsl_settings['more_info_location'] == 'info window' ) {
            $more_info_url = '#wpsl-search-wrap';
        }

        if ( $wpsl_settings['more_info_location'] == 'store listings' ) {
            $more_info_template = '<% if ( !_.isEmpty( phone ) || !_.isEmpty( fax ) || !_.isEmpty( email ) ) { %>' . "\r\n";
            $more_info_template .= "\t\t\t" . '<p><a class="wpsl-store-details wpsl-store-listing" href="#wpsl-id-<%= id %>">' . esc_html( $wpsl->i18n->get_translation( 'more_label', __( 'More info', 'wpsl' ) ) ) . '</a></p>' . "\r\n";
            $more_info_template .= "\t\t\t" . '<div id="wpsl-id-<%= id %>" class="wpsl-more-info-listings">' . "\r\n";
            $more_info_template .= "\t\t\t\t" . '<% if ( description ) { %>' . "\r\n";
            $more_info_template .= "\t\t\t\t" . '<%= description %>' . "\r\n";
            $more_info_template .= "\t\t\t\t" . '<% } %>' . "\r\n";
            
            if ( !$wpsl_settings['show_contact_details'] ) {
                $more_info_template .= "\t\t\t\t" . '<p>' . "\r\n";
                $more_info_template .= "\t\t\t\t" . '<% if ( phone ) { %>' . "\r\n";
                $more_info_template .= "\t\t\t\t" . '<span><strong>' . esc_html( $wpsl->i18n->get_translation( 'phone_label', __( 'Phone', 'wpsl' ) ) ) . '</strong>: <%= formatPhoneNumber( phone ) %></span>' . "\r\n";
                $more_info_template .= "\t\t\t\t" . '<% } %>' . "\r\n";
                $more_info_template .= "\t\t\t\t" . '<% if ( fax ) { %>' . "\r\n";
                $more_info_template .= "\t\t\t\t" . '<span><strong>' . esc_html( $wpsl->i18n->get_translation( 'fax_label', __( 'Fax', 'wpsl' ) ) ) . '</strong>: <%= fax %></span>' . "\r\n";
                $more_info_template .= "\t\t\t\t" . '<% } %>' . "\r\n";
                $more_info_template .= "\t\t\t\t" . '<% if ( email ) { %>' . "\r\n";
                $more_info_template .= "\t\t\t\t" . '<span><strong>' . esc_html( $wpsl->i18n->get_translation( 'email_label', __( 'Email', 'wpsl' ) ) ) . '</strong>: <%= formatEmail( email ) %></span>' . "\r\n";
                $more_info_template .= "\t\t\t\t" . '<% } %>' . "\r\n";
                $more_info_template .= "\t\t\t\t" . '</p>' . "\r\n";
            }

            if ( !$wpsl_settings['hide_hours'] ) {
                $more_info_template .= "\t\t\t\t" . '<% if ( hours ) { %>' . "\r\n";
                $more_info_template .= "\t\t\t\t" . '<div class="wpsl-store-hours"><strong>' . esc_html( $wpsl->i18n->get_translation( 'hours_label', __( 'Hours', 'wpsl' ) ) ) . '</strong><%= hours %></div>' . "\r\n";
                $more_info_template .= "\t\t\t\t" . '<% } %>' . "\r\n";
            }

            $more_info_template .= "\t\t\t" . '</div>' . "\r\n"; 
            $more_info_template .= "\t\t\t" . '<% } %>';

        } else {
            $more_info_template = '<p><a class="wpsl-store-details" href="' . $more_info_url . '">' . esc_html( $wpsl->i18n->get_translation( 'more_label', __( 'More info', 'wpsl' ) ) ) . '</a></p>';
        }

        return apply_filters( 'wpsl_more_info_template', $more_info_template );
    }                 
}

/**
 * Create the store header template.
 *
 * @since 2.0.0
 * @param  string $location        The location where the header is shown ( info_window / listing / wpsl_map shortcode )
 * @return string $header_template The template for the store header
 */
function wpsl_store_header_template( $location = 'info_window' ) {

    global $wpsl_settings;

    if ( $wpsl_settings['new_window'] ) {
        $new_window = ' target="_blank"';
    } else {
        $new_window = '';
    }

    /* 
     * To keep the code readable in the HTML source we ( unfortunately ) need to adjust the 
     * amount of tabs in front of it based on the location were it is shown. 
     */
    if ( $location == 'listing') {
        $tab = "\t\t\t\t";    
    } else {
        $tab = "\t\t\t";                 
    }

    if ( $wpsl_settings['permalinks'] ) {
        
        /**
         * It's possible the permalinks are enabled, but not included in the location data on 
         * pages where the [wpsl_map] shortcode is used. 
         * 
         * So we need to check for undefined, which isn't necessary in all other cases.
         */
        if ( $location == 'wpsl_map') {
            $header_template = '<% if ( typeof permalink !== "undefined" ) { %>' . "\r\n";
            $header_template .= $tab . '<strong><a' . $new_window . ' href="<%= permalink %>"><%= store %></a></strong>' . "\r\n";
            $header_template .= $tab . '<% } else { %>' . "\r\n";
            $header_template .= $tab . '<strong><%= store %></strong>' . "\r\n";
            $header_template .= $tab . '<% } %>';   
        } else {
            $header_template = '<strong><a' . $new_window . ' href="<%= permalink %>"><%= store %></a></strong>';
        }
    } else {
        $header_template = '<% if ( wpslSettings.storeUrl == 1 && url ) { %>' . "\r\n";
        $header_template .= $tab . '<strong><a' . $new_window . ' href="<%= url %>"><%= store %></a></strong>' . "\r\n";
        $header_template .= $tab . '<% } else { %>' . "\r\n";
        $header_template .= $tab . '<strong><%= store %></strong>' . "\r\n";
        $header_template .= $tab . '<% } %>'; 
    }

    return apply_filters( 'wpsl_store_header_template', $header_template );
}
        
/**
 * Create the address placeholders based on the structure defined on the settings page.
 * 
 * @since 2.0.0
 * @return string $address_placeholders A list of address placeholders in the correct order
 */
function wpsl_address_format_placeholders() {

    global $wpsl_settings;

    $address_format = explode( '_', $wpsl_settings['address_format'] );
    $placeholders   = '';
    $part_count     = count( $address_format ) - 1;
    $i              = 0;

    foreach ( $address_format as $address_part ) {
        if ( $address_part != 'comma' ) {

            /* 
             * Don't add a space after the placeholder if the next part 
             * is going to be a comma or if it is the last part. 
             */
            if ( $i == $part_count || $address_format[$i + 1] == 'comma' ) {
                $space = '';    
            } else {
                $space = ' ';      
            }

            $placeholders .= '<%= ' . $address_part . ' %>' . $space;
        } else {
            $placeholders .= ', ';
        }

        $i++;
    }

    return $placeholders;
}frontend/templates/default.php000064400000007003151327220640012520 0ustar00<?php 
global $wpsl_settings, $wpsl;

$output         = $this->get_custom_css(); 
$autoload_class = ( !$wpsl_settings['autoload'] ) ? 'class="wpsl-not-loaded"' : '';

$output .= '<div id="wpsl-wrap">' . "\r\n";
$output .= "\t" . '<div class="wpsl-search wpsl-clearfix ' . $this->get_css_classes() . '">' . "\r\n";
$output .= "\t\t" . '<div id="wpsl-search-wrap">' . "\r\n";
$output .= "\t\t\t" . '<form autocomplete="off">' . "\r\n";
$output .= "\t\t\t" . '<div class="wpsl-input">' . "\r\n";
$output .= "\t\t\t\t" . '<div><label for="wpsl-search-input">' . esc_html( $wpsl->i18n->get_translation( 'search_label', __( 'Your location', 'wpsl' ) ) ) . '</label></div>' . "\r\n";
$output .= "\t\t\t\t" . '<input id="wpsl-search-input" type="text" value="' . apply_filters( 'wpsl_search_input', '' ) . '" name="wpsl-search-input" placeholder="" aria-required="true" />' . "\r\n";
$output .= "\t\t\t" . '</div>' . "\r\n";

if ( $wpsl_settings['radius_dropdown'] || $wpsl_settings['results_dropdown']  ) {
    $output .= "\t\t\t" . '<div class="wpsl-select-wrap">' . "\r\n";

    if ( $wpsl_settings['radius_dropdown'] ) {
        $output .= "\t\t\t\t" . '<div id="wpsl-radius">' . "\r\n";
        $output .= "\t\t\t\t\t" . '<label for="wpsl-radius-dropdown">' . esc_html( $wpsl->i18n->get_translation( 'radius_label', __( 'Search radius', 'wpsl' ) ) ) . '</label>' . "\r\n";
        $output .= "\t\t\t\t\t" . '<select id="wpsl-radius-dropdown" class="wpsl-dropdown" name="wpsl-radius">' . "\r\n";
        $output .= "\t\t\t\t\t\t" . $this->get_dropdown_list( 'search_radius' ) . "\r\n";
        $output .= "\t\t\t\t\t" . '</select>' . "\r\n";
        $output .= "\t\t\t\t" . '</div>' . "\r\n";
    }

    if ( $wpsl_settings['results_dropdown'] ) {
        $output .= "\t\t\t\t" . '<div id="wpsl-results">' . "\r\n";
        $output .= "\t\t\t\t\t" . '<label for="wpsl-results-dropdown">' . esc_html( $wpsl->i18n->get_translation( 'results_label', __( 'Results', 'wpsl' ) ) ) . '</label>' . "\r\n";
        $output .= "\t\t\t\t\t" . '<select id="wpsl-results-dropdown" class="wpsl-dropdown" name="wpsl-results">' . "\r\n";
        $output .= "\t\t\t\t\t\t" . $this->get_dropdown_list( 'max_results' ) . "\r\n";
        $output .= "\t\t\t\t\t" . '</select>' . "\r\n";
        $output .= "\t\t\t\t" . '</div>' . "\r\n";
    } 

    $output .= "\t\t\t" . '</div>' . "\r\n";
}

if ( $this->use_category_filter() ) {
    $output .= $this->create_category_filter();
}

$output .= "\t\t\t\t" . '<div class="wpsl-search-btn-wrap"><input id="wpsl-search-btn" type="submit" value="' . esc_attr( $wpsl->i18n->get_translation( 'search_btn_label', __( 'Search', 'wpsl' ) ) ) . '"></div>' . "\r\n";

$output .= "\t\t" . '</form>' . "\r\n";
$output .= "\t\t" . '</div>' . "\r\n";
$output .= "\t" . '</div>' . "\r\n";
    
$output .= "\t" . '<div id="wpsl-gmap" class="wpsl-gmap-canvas"></div>' . "\r\n";

$output .= "\t" . '<div id="wpsl-result-list">' . "\r\n";
$output .= "\t\t" . '<div id="wpsl-stores" '. $autoload_class .'>' . "\r\n";
$output .= "\t\t\t" . '<ul></ul>' . "\r\n";
$output .= "\t\t" . '</div>' . "\r\n";
$output .= "\t\t" . '<div id="wpsl-direction-details">' . "\r\n";
$output .= "\t\t\t" . '<ul></ul>' . "\r\n";
$output .= "\t\t" . '</div>' . "\r\n";
$output .= "\t" . '</div>' . "\r\n";

if ( $wpsl_settings['show_credits'] ) { 
    $output .= "\t" . '<div class="wpsl-provided-by">'. sprintf( __( "Search provided by %sWP Store Locator%s", "wpsl" ), "<a target='_blank' href='https://wpstorelocator.co'>", "</a>" ) .'</div>' . "\r\n";
}

$output .= '</div>' . "\r\n";

return $output;frontend/templates/store-listings-below.php000064400000007535151327220640015202 0ustar00<?php 
global $wpsl_settings, $wpsl;

$output         = $this->get_custom_css(); 
$autoload_class = ( !$wpsl_settings['autoload'] ) ? 'class="wpsl-not-loaded"' : '';

$output .= '<div id="wpsl-wrap" class="wpsl-store-below">' . "\r\n";
$output .= "\t" . '<div class="wpsl-search wpsl-clearfix ' . $this->get_css_classes() . '">' . "\r\n";
$output .= "\t\t" . '<div id="wpsl-search-wrap">' . "\r\n";
$output .= "\t\t\t" . '<form autocomplete="off">' . "\r\n";
$output .= "\t\t\t" . '<div class="wpsl-input">' . "\r\n";
$output .= "\t\t\t\t" . '<div><label for="wpsl-search-input">' . esc_html( $wpsl->i18n->get_translation( 'search_label', __( 'Your location', 'wpsl' ) ) ) . '</label></div>' . "\r\n";
$output .= "\t\t\t\t" . '<input id="wpsl-search-input" type="text" value="' . apply_filters( 'wpsl_search_input', '' ) . '" name="wpsl-search-input" placeholder="" aria-required="true" />' . "\r\n";
$output .= "\t\t\t" . '</div>' . "\r\n";

if ( $wpsl_settings['radius_dropdown'] || $wpsl_settings['results_dropdown']  ) {
    $output .= "\t\t\t" . '<div class="wpsl-select-wrap">' . "\r\n";

    if ( $wpsl_settings['radius_dropdown'] ) {
        $output .= "\t\t\t\t" . '<div id="wpsl-radius">' . "\r\n";
        $output .= "\t\t\t\t\t" . '<label for="wpsl-radius-dropdown">' . esc_html( $wpsl->i18n->get_translation( 'radius_label', __( 'Search radius', 'wpsl' ) ) ) . '</label>' . "\r\n";
        $output .= "\t\t\t\t\t" . '<select id="wpsl-radius-dropdown" class="wpsl-dropdown" name="wpsl-radius">' . "\r\n";
        $output .= "\t\t\t\t\t\t" . $this->get_dropdown_list( 'search_radius' ) . "\r\n";
        $output .= "\t\t\t\t\t" . '</select>' . "\r\n";
        $output .= "\t\t\t\t" . '</div>' . "\r\n";
    }

    if ( $wpsl_settings['results_dropdown'] ) {
        $output .= "\t\t\t\t" . '<div id="wpsl-results">' . "\r\n";
        $output .= "\t\t\t\t\t" . '<label for="wpsl-results-dropdown">' . esc_html( $wpsl->i18n->get_translation( 'results_label', __( 'Results', 'wpsl' ) ) ) . '</label>' . "\r\n";
        $output .= "\t\t\t\t\t" . '<select id="wpsl-results-dropdown" class="wpsl-dropdown" name="wpsl-results">' . "\r\n";
        $output .= "\t\t\t\t\t\t" . $this->get_dropdown_list( 'max_results' ) . "\r\n";
        $output .= "\t\t\t\t\t" . '</select>' . "\r\n";
        $output .= "\t\t\t\t" . '</div>' . "\r\n";
    }
    
    $output .= "\t\t\t" . '</div>' . "\r\n";
}

if ( $this->use_category_filter() ) {
    $output .= $this->create_category_filter();
}
 
$output .= "\t\t\t\t" . '<div class="wpsl-search-btn-wrap"><input id="wpsl-search-btn" type="submit" value="' . esc_attr( $wpsl->i18n->get_translation( 'search_btn_label', __( 'Search', 'wpsl' ) ) ) . '"></div>' . "\r\n";

$output .= "\t\t" . '</form>' . "\r\n";
$output .= "\t\t" . '</div>' . "\r\n";
$output .= "\t" . '</div>' . "\r\n";
    
if ( $wpsl_settings['reset_map'] ) { 
    $output .= "\t" . '<div class="wpsl-gmap-wrap">' . "\r\n";
    $output .= "\t\t" . '<div id="wpsl-gmap" class="wpsl-gmap-canvas"></div>' . "\r\n";
    $output .= "\t" . '</div>' . "\r\n";
} else {
    $output .= "\t" . '<div id="wpsl-gmap" class="wpsl-gmap-canvas"></div>' . "\r\n";
}

$output .= "\t" . '<div id="wpsl-result-list">' . "\r\n";
$output .= "\t\t" . '<div id="wpsl-stores" '. $autoload_class .'>' . "\r\n";
$output .= "\t\t\t" . '<ul></ul>' . "\r\n";
$output .= "\t\t" . '</div>' . "\r\n";
$output .= "\t\t" . '<div id="wpsl-direction-details">' . "\r\n";
$output .= "\t\t\t" . '<ul></ul>' . "\r\n";
$output .= "\t\t" . '</div>' . "\r\n";
$output .= "\t" . '</div>' . "\r\n";

if ( $wpsl_settings['show_credits'] ) { 
    $output .= "\t" . '<div class="wpsl-provided-by">'. sprintf( __( "Search provided by %sWP Store Locator%s", "wpsl" ), "<a target='_blank' href='https://wpstorelocator.co'>", "</a>" ) .'</div>' . "\r\n";
}

$output .= '</div>' . "\r\n";

return $output;frontend/class-frontend.php000064400000242245151327220640012031 0ustar00<?php
/**
 * Frontend class
 *
 * @author Tijmen Smit
 * @since  1.0.0
 */

if ( !defined( 'ABSPATH' ) ) exit;

if ( !class_exists( 'WPSL_Frontend' ) ) {

    /**
     * Handle the frontend of the store locator
     *
     * @since 1.0.0
     */
    class WPSL_Frontend {

        /**
         * Keep track which scripts we need to load
         *
         * @since 2.0.0
         */
        private $load_scripts = array();

        /**
         * Keep track of the amount of maps on the page
         *
         * @since 2.0.0
         */
        private static $map_count = 0;

        /*
         * Holds the shortcode atts for the [wpsl] shortcode.
         *
         * Used to overwrite the settings just before
         * they are send to wp_localize_script.
         *
         * @since 2.1.1
         */
        public $sl_shortcode_atts;

        private $store_map_data = array();


        /**
         * Class constructor
         */
        public function __construct() {

            $this->includes();

            if ( function_exists( 'BorlabsCookieHelper' ) ) {
                add_action( 'init', array( $this, 'borlabs_cookie' ) );
            }

            add_action( 'wp_ajax_store_search',        array( $this, 'store_search' ) );
            add_action( 'wp_ajax_nopriv_store_search', array( $this, 'store_search' ) );
            add_action( 'wp_enqueue_scripts',          array( $this, 'add_frontend_styles' ) );
            add_action( 'wp_footer',                   array( $this, 'add_frontend_scripts' ) );

            add_filter( 'the_content',                 array( $this, 'cpt_template' ) );

            add_shortcode( 'wpsl',                 array( $this, 'show_store_locator' ) );
            add_shortcode( 'wpsl_address',         array( $this, 'show_store_address' ) );
            add_shortcode( 'wpsl_hours',           array( $this, 'show_opening_hours' ) );
            add_shortcode( 'wpsl_map',             array( $this, 'show_store_map' ) );
        }

        /**
         * Include the required front-end files.
         *
         * @since  2.0.0
         * @return void
         */
        public function includes() {
            require_once( WPSL_PLUGIN_DIR . 'frontend/underscore-functions.php' );
        }


        /**
         * Include the required file for the borlabs cookie plugin to work.
         *
         * @since 2.2.22
         * @return void
         */
        public function borlabs_cookie() {
            require_once( WPSL_PLUGIN_DIR . 'inc/class-borlabs-cookie.php' );
        }

        /**
         * Handle the Ajax search on the frontend.
         *
         * @since 1.0.0
         * @return json A list of store locations that are located within the selected search radius
         */
        public function store_search() {

            global $wpsl_settings;

            /*
             * Check if auto loading the locations on page load is enabled.
             *
             * If so then we save the store data in a transient to prevent a long loading time
             * in case a large amount of locations need to be displayed.
             *
             * The SQL query that selects nearby locations doesn't take that long,
             * but collecting all the store meta data in get_store_meta_data() for hunderds,
             * or thousands of stores can make it really slow.
             */
            if ( $wpsl_settings['autoload'] && isset( $_GET['autoload'] ) && $_GET['autoload'] && !$wpsl_settings['debug'] && !isset( $_GET['skip_cache'] ) ) {
                $transient_name = $this->create_transient_name();

                if ( false === ( $store_data = get_transient( 'wpsl_autoload_' . $transient_name ) ) ) {
                    $store_data = $this->find_nearby_locations();

                    if ( $store_data ) {
                        set_transient( 'wpsl_autoload_' . $transient_name, $store_data, 0 );
                    }
                }
            } else {
                $store_data = $this->find_nearby_locations();
            }

            do_action( 'wpsl_store_search' );

            wp_send_json( $store_data );

            exit();
        }

        /**
         * Create the name used in the wpsl autoload transient.
         *
         * @since 2.1.1
         * @return string $transient_name The transient name.
         */
        public function create_transient_name() {

            global $wpsl, $wpsl_settings;

            $name_section = array();

            // Include the set autoload limit.
            if ( $wpsl_settings['autoload'] && $wpsl_settings['autoload_limit'] ) {
                $name_section[] = absint( $wpsl_settings['autoload_limit'] );
            }

            /*
             * Check if we need to include the cat id(s) in the transient name.
             *
             * This can only happen if the user used the
             * 'category' attr on the wpsl shortcode.
             */
            if ( isset( $_GET['filter'] ) && $_GET['filter'] ) {
                $name_section[] = absint( str_replace( ',', '', $_GET['filter'] ) );
            }

            // Include the lat value from the start location.
            if ( isset( $_GET['lat'] ) && $_GET['lat'] ) {
                $name_section[] = absint( str_replace( '.', '', $_GET['lat'] ) );
            }

            /*
             * If a multilingual plugin ( WPML or qTranslate X ) is active then we have
             * to make sure each language has his own unique transient. We do this by
             * including the lang code in the transient name.
             *
             * Otherwise if the language is for example set to German on page load,
             * and the user switches to Spanish, then he would get the incorrect
             * permalink structure ( /de/.. instead or /es/.. ) and translated
             * store details.
             */
            $lang_code = $wpsl->i18n->check_multilingual_code();

            if ( $lang_code ) {
                $name_section[] = $lang_code;
            }

            $transient_name = implode( '_', $name_section );

            /*
             * If the distance unit filter ( wpsl_distance_unit ) is used to change the km / mi unit based on
             * the location of the IP, then we include the km / mi in the transient name. This is done to
             * prevent users from seeing the wrong distances from the cached data.
             *
             * This way one data set can include the distance in km, and the other one the distance in miles.
             */
            if ( has_filter( 'wpsl_distance_unit' ) ) {
                $transient_name = $transient_name . '_' . wpsl_get_distance_unit();
            }

            return $transient_name;
        }

        /**
         * Find store locations that are located within the selected search radius.
         *
         * This happens by calculating the distance between the
         * latlng of the searched location, and the latlng from
         * the stores in the db.
         *
         * @since 2.0.0
         * @param array       $args       The arguments to use in the SQL query, only used by add-ons
         * @return void|array $store_data The list of stores that fall within the selected range.
         */
        public function find_nearby_locations( $args = array() ) {

            global $wpdb, $wpsl, $wpsl_settings;

            $store_data = array();

            /*
             * Set the correct earth radius in either km or miles.
             * We need this to calculate the distance between two coordinates.
             */
            $placeholder_values[] = ( wpsl_get_distance_unit() == 'km' ) ? 6371 : 3959;

            // The placeholder values for the prepared statement in the SQL query.
            if ( empty( $args ) ) {
                $args = $_GET;
            }

            array_push( $placeholder_values, $args['lat'], $args['lng'], $args['lat'] );

            // Check if we need to filter the results by category.
            if ( isset( $args['filter'] ) && $args['filter'] ) {
                $filter_ids = array_map( 'absint', explode( ',', $args['filter'] ) );
                $cat_filter = "INNER JOIN $wpdb->term_relationships AS term_rel ON posts.ID = term_rel.object_id
                               INNER JOIN $wpdb->term_taxonomy AS term_tax ON term_rel.term_taxonomy_id = term_tax.term_taxonomy_id
                                      AND term_tax.taxonomy = 'wpsl_store_category'
                                      AND term_tax.term_id IN (" . implode( ',', $filter_ids ) . ")";
            } else {
                $cat_filter = '';
            }

            /*
             * If WPML is active we include 'GROUP BY lat' in the sql query
             * to prevent duplicate locations from showing up in the results.
             *
             * This is a problem when a store location for example
             * exists in 4 different languages. They would all fall within
             * the selected radius, but we only need one store ID for the 'icl_object_id'
             * function to get the correct store ID for the current language.
             */
            if ( $wpsl->i18n->wpml_exists() ) {
                $group_by = 'GROUP BY lat';
            } else {
                $group_by = 'GROUP BY posts.ID';
            }

            /*
             * If autoload is enabled we need to check if there is a limit to the
             * amount of locations we need to show.
             *
             * Otherwise include the radius and max results limit in the sql query.
             */
            if ( isset( $args['autoload'] ) && $args['autoload'] ) {
                $limit = '';

                if ( $wpsl_settings['autoload_limit'] ) {
                    $limit = 'LIMIT %d';
                    $placeholder_values[] = $wpsl_settings['autoload_limit'];
                }

                $sql_sort = 'ORDER BY distance '. $limit;
            } else {
                array_push( $placeholder_values, $this->check_store_filter( $args, 'search_radius' ), $this->check_store_filter( $args, 'max_results' ) );
                $sql_sort = 'HAVING distance < %d ORDER BY distance LIMIT 0, %d';
            }

            $placeholder_values = apply_filters( 'wpsl_sql_placeholder_values', $placeholder_values );

            /*
             * The sql that will check which store locations fall within
             * the selected radius based on the lat and lng values.
             */
            $sql = apply_filters( 'wpsl_sql',
                "SELECT post_lat.meta_value AS lat,
                           post_lng.meta_value AS lng,
                           posts.ID,
                           ( %d * acos( cos( radians( %s ) ) * cos( radians( post_lat.meta_value ) ) * cos( radians( post_lng.meta_value ) - radians( %s ) ) + sin( radians( %s ) ) * sin( radians( post_lat.meta_value ) ) ) )
                        AS distance
                      FROM $wpdb->posts AS posts
                INNER JOIN $wpdb->postmeta AS post_lat ON post_lat.post_id = posts.ID AND post_lat.meta_key = 'wpsl_lat'
                INNER JOIN $wpdb->postmeta AS post_lng ON post_lng.post_id = posts.ID AND post_lng.meta_key = 'wpsl_lng'
                    $cat_filter
                     WHERE posts.post_type = 'wpsl_stores'
                       AND posts.post_status = 'publish' $group_by $sql_sort"
            );

            $stores = $wpdb->get_results( $wpdb->prepare( $sql, $placeholder_values ) );

            if ( $stores ) {
                $store_data = apply_filters( 'wpsl_store_data', $this->get_store_meta_data( $stores ) );
            } else {
                $store_data = apply_filters( 'wpsl_no_results_sql', '' );
            }

            return $store_data;
        }

        /**
         * Get the post meta data for the selected stores.
         *
         * @since  2.0.0
         * @param  object $stores
         * @return array  $all_stores The stores that fall within the selected range with the post meta data.
         */
        public function get_store_meta_data( $stores ) {

            global $wpsl_settings, $wpsl;

            $all_stores = array();

            // Get the list of store fields that we need to filter out of the post meta data.
            $meta_field_map = $this->frontend_meta_fields();

            foreach ( $stores as $store_key => $store ) {

                // If WPML is active try to get the id of the translated page.
                if ( $wpsl->i18n->wpml_exists() ) {
                    $store->ID = $wpsl->i18n->maybe_get_wpml_id( $store->ID );

                    if ( !$store->ID ) {
                        continue;
                    }
                }

                // Get the post meta data for each store that was within the range of the search radius.
                $custom_fields = get_post_custom( $store->ID );

                foreach ( $meta_field_map as $meta_key => $meta_value ) {

                    if ( isset( $custom_fields[$meta_key][0] ) ) {
                        if ( ( isset( $meta_value['type'] ) ) && ( !empty( $meta_value['type'] ) ) ) {
                            $meta_type = $meta_value['type'];
                        } else {
                            $meta_type = '';
                        }

                        // If we need to hide the opening hours, and the current meta type is set to hours we skip it.
                        if ( $wpsl_settings['hide_hours'] && $meta_type == 'hours' ) {
                            continue;
                        }

                        // Make sure the data is safe to use on the frontend and in the format we expect it to be.
                        switch ( $meta_type ) {
                            case 'numeric':
                                $meta_data = ( is_numeric( $custom_fields[$meta_key][0] ) ) ? $custom_fields[$meta_key][0] : 0 ;
                                break;
                            case 'email':
                                $meta_data = sanitize_email( $custom_fields[$meta_key][0] );
                                break;
                            case 'url':
                                $meta_data = esc_url( $custom_fields[$meta_key][0] );
                                break;
                            case 'hours':
                                $meta_data = $this->get_opening_hours( $custom_fields[$meta_key][0], apply_filters( 'wpsl_hide_closed_hours', false ) );
                                break;
                            case 'wp_editor':
                            case 'textarea':
                                $meta_data = wp_kses_post( wpautop( $custom_fields[$meta_key][0] ) );
                                break;
                            case 'text':
                            default:
                                $meta_data = sanitize_text_field( stripslashes( $custom_fields[$meta_key][0] ) );
                                break;
                        }

                        $store_meta[$meta_value['name']] = $meta_data;
                    } else {
                        $store_meta[$meta_value['name']] = '';
                    }

                    /*
                     * Include the post content if the "More info" option is enabled on the settings page,
                     * or if $include_post_content is set to true through the 'wpsl_include_post_content' filter.
                     */
                    if ( ( $wpsl_settings['more_info'] && $wpsl_settings['more_info_location'] == 'store listings' ) || apply_filters( 'wpsl_include_post_content', false ) ) {
                        $page_object = get_post( $store->ID );

                        // Check if we need to strip the shortcode from the post content.
                        if ( apply_filters( 'wpsl_strip_content_shortcode', true ) ) {
                            $post_content = strip_shortcodes( $page_object->post_content );
                        } else {
                            $post_content = $page_object->post_content;
                        }

                        $store_meta['description'] = apply_filters( 'the_content', $post_content );
                    }

                    $store_meta['store'] = get_the_title( $store->ID );
                    $store_meta['thumb'] = $this->get_store_thumb( $store->ID, $store_meta['store'] );
                    $store_meta['id']    = $store->ID;

                    if ( !$wpsl_settings['hide_distance'] ) {
                        $store_meta['distance'] = round( $store->distance, 1 );
                    }

                    if ( $wpsl_settings['permalinks'] ) {
                        $store_meta['permalink'] = get_permalink( $store->ID );
                    }
                }

                $all_stores[] = apply_filters( 'wpsl_store_meta', $store_meta, $store->ID );
            }

            return $all_stores;
        }

        /**
         * The store meta fields that are included in the json output.
         *
         * The wpsl_ is the name in db, the name value is used as the key in the json output.
         *
         * The type itself is used to determine how the value should be sanitized.
         * Text will go through sanitize_text_field, email through sanitize_email and so on.
         *
         * If no type is set it will default to sanitize_text_field.
         *
         * @since 2.0.0
         * @return array $store_fields The names of the meta fields used by the store
         */
        public function frontend_meta_fields() {

            $store_fields = array(
                'wpsl_address' => array(
                    'name' => 'address'
                ),
                'wpsl_address2' => array(
                    'name' => 'address2'
                ),
                'wpsl_city' => array(
                    'name' => 'city'
                ),
                'wpsl_state' => array(
                    'name' => 'state'
                ),
                'wpsl_zip' => array(
                    'name' => 'zip'
                ),
                'wpsl_country' => array(
                    'name' => 'country'
                ),
                'wpsl_lat' => array(
                    'name' => 'lat',
                    'type' => 'numeric'
                ),
                'wpsl_lng' => array(
                    'name' => 'lng',
                    'type' => 'numeric'
                ),
                'wpsl_phone' => array(
                    'name' => 'phone'
                ),
                'wpsl_fax' => array(
                    'name' => 'fax'
                ),
                'wpsl_email' => array(
                    'name' => 'email',
                    'type' => 'email'
                ),
                'wpsl_hours' => array(
                    'name' => 'hours',
                    'type' => 'hours'
                ),
                'wpsl_url' => array(
                    'name' => 'url',
                    'type' => 'url'
                )
            );

            return apply_filters( 'wpsl_frontend_meta_fields', $store_fields );
        }

        /**
         * Get the store thumbnail.
         *
         * @since 2.0.0
         * @param string       $post_id    The post id of the store
         * @param string       $store_name The name of the store
         * @return void|string $thumb      The html img tag
         */
        public function get_store_thumb( $post_id, $store_name ) {

            $attr = array(
                'class' => 'wpsl-store-thumb',
                'alt'   => $store_name
            );

            $thumb = get_the_post_thumbnail( $post_id, $this->get_store_thumb_size(), apply_filters( 'wpsl_thumb_attr', $attr ) );

            return $thumb;
        }

        /**
         * Get the store thumbnail size.
         *
         * @since 2.0.0
         * @return array $size The thumb format
         */
        public function get_store_thumb_size() {

            $size = apply_filters( 'wpsl_thumb_size', array( 45, 45 ) );

            return $size;
        }

        /**
         * Get the opening hours in the correct format.
         *
         * Either convert the hour values that are set through
         * a dropdown to a table, or wrap the textarea input in a <p>.
         *
         * Note: The opening hours can only be set in the textarea format by users who upgraded from 1.x.
         *
         * @since 2.0.0
         * @param  array|string $hours       The opening hours
         * @param  boolean      $hide_closed Hide the days were the location is closed
         * @return string       $hours       The formated opening hours
         */
        public function get_opening_hours( $hours, $hide_closed ) {

            $hours = maybe_unserialize( $hours );

            /*
             * If the hours are set through the dropdown then we create a table for the opening hours.
             * Otherwise we output the data entered in the textarea.
             */
            if ( is_array( $hours ) ) {
                $hours = $this->create_opening_hours_tabel( $hours, $hide_closed );
            } else {
                $hours = wp_kses_post( wpautop( $hours ) );
            }

            return $hours;
        }

        /**
         * Create a table for the opening hours.
         *
         * @since  2.0.0
         * @todo   add schema.org support.
         * @param  array   $hours       The opening hours
         * @param  boolean $hide_closed Hide the days where the location is closed
         * @return string  $hour_table  The opening hours sorted in a table
         */
        public function create_opening_hours_tabel( $hours, $hide_closed ) {

            $opening_days = wpsl_get_weekdays();

            // Make sure that we have actual opening hours, and not every day is empty.
            if ( $this->not_always_closed( $hours ) ) {
                $hour_table = '<table role="presentation" class="wpsl-opening-hours">';

                foreach ( $opening_days as $index => $day ) {
                    $i          = 0;
                    $hour_count = count( $hours[$index] );

                    // If we need to hide days that are set to closed then skip them.
                    if ( $hide_closed && !$hour_count ) {
                        continue;
                    }

                    $hour_table .= '<tr>';
                    $hour_table .= '<td>' . esc_html( $day ) . '</td>';

                    // If we have opening hours we show them, otherwise just show 'Closed'.
                    if ( $hour_count > 0 ) {
                        $hour_table .= '<td>';

                        while ( $i < $hour_count ) {
                            $hour        = explode( ',', $hours[$index][$i] );
                            $hour_table .= '<time>' . esc_html( $hour[0] ) . ' - ' . esc_html( $hour[1] ) . '</time>';

                            $i++;
                        }

                        $hour_table .= '</td>';
                    } else {
                        $hour_table .= '<td>' . __( 'Closed', 'wpsl' ) . '</td>';
                    }

                    $hour_table .= '</tr>';
                }

                $hour_table .= '</table>';

                return $hour_table;
            }
        }

        /**
         * Create the wpsl post type output.
         *
         * If you want to create a custom template you need to
         * create a single-wpsl_stores.php file in your theme folder.
         * You can see an example here https://wpstorelocator.co/document/create-custom-store-page-template/
         *
         * @since  2.0.0
         * @param  string $content
         * @return string $content
         */
        public function cpt_template( $content ) {

            global $wpsl_settings, $post;

            $skip_cpt_template = apply_filters( 'wpsl_skip_cpt_template', false );

            if ( isset( $post->post_type ) && $post->post_type == 'wpsl_stores' && is_single() && in_the_loop() && !$skip_cpt_template ) {
                array_push( $this->load_scripts, 'wpsl_base' );

                $content .= '[wpsl_map]';
                $content .= '[wpsl_address]';

                if ( !$wpsl_settings['hide_hours'] ) {
                    $content .= '[wpsl_hours]';
                }
            }

            return $content;
        }

        /**
         * Handle the [wpsl] shortcode attributes.
         *
         * @since 2.1.1
         * @param array $atts Shortcode attributes
         */
        public function check_sl_shortcode_atts( $atts ) {

            /*
             * Use a custom start location?
             *
             * If the provided location fails to geocode,
             * then the start location from the settings page is used.
             */
            if ( isset( $atts['start_location'] ) && $atts['start_location'] ) {
                $start_latlng = wpsl_check_latlng_transient( $atts['start_location'] );

                if ( isset( $start_latlng ) && $start_latlng ) {
                    $this->sl_shortcode_atts['js']['startLatlng'] = $start_latlng;
                }
            }

            if ( isset( $atts['auto_locate'] ) && $atts['auto_locate'] ) {
                $this->sl_shortcode_atts['js']['autoLocate'] = ( $atts['auto_locate'] == 'true' ) ? 1 : 0;
            }

            // Change the category slugs into category ids.
            if ( isset( $atts['category'] ) && $atts['category'] ) {
                $term_ids = wpsl_get_term_ids( $atts['category'] );

                if ( $term_ids ) {
                    $this->sl_shortcode_atts['js']['categoryIds'] = implode( ',', $term_ids );
                }
            }

            if ( isset( $atts['category_selection'] ) && $atts['category_selection'] ) {
                $this->sl_shortcode_atts['category_selection'] = wpsl_get_term_ids( $atts['category_selection'] );
            }

            if ( isset( $atts['category_filter_type'] ) && in_array( $atts['category_filter_type'], array( 'dropdown', 'checkboxes' ) ) ) {
                $this->sl_shortcode_atts['category_filter_type'] = $atts['category_filter_type'];
            }

            if ( isset( $atts['checkbox_columns'] ) && is_numeric( $atts['checkbox_columns'] ) ) {
                $this->sl_shortcode_atts['checkbox_columns'] = $atts['checkbox_columns'];
            }

            if ( isset( $atts['map_type'] ) && array_key_exists( $atts['map_type'], wpsl_get_map_types() ) ) {
                $this->sl_shortcode_atts['js']['mapType'] = $atts['map_type'];
            }

            if ( isset( $atts['start_marker'] ) && $atts['start_marker'] ) {
                $this->sl_shortcode_atts['js']['startMarker'] = $atts['start_marker'] . '@2x.png';
            }

            if ( isset( $atts['store_marker'] ) && $atts['store_marker'] ) {
                $this->sl_shortcode_atts['js']['storeMarker'] = $atts['store_marker'] . '@2x.png';
            }
        }

        /**
         * Handle the [wpsl] shortcode.
         *
         * @since 1.0.0
         * @param  array  $atts   Shortcode attributes
         * @return string $output The wpsl template
         */
        public function show_store_locator( $atts ) {

            global $wpsl, $wpsl_settings;

            $atts = shortcode_atts( array(
                'template'             => $wpsl_settings['template_id'],
                'start_location'       => '',
                'auto_locate'          => '',
                'category'             => '',
                'category_selection'   => '',
                'category_filter_type' => '',
                'checkbox_columns'     => '3',
                'map_type'             => '',
                'start_marker'         => '',
                'store_marker'         => ''
            ), $atts );

            $this->check_sl_shortcode_atts( $atts );

            // Make sure the required scripts are included for the wpsl shortcode.
            array_push( $this->load_scripts, 'wpsl_store_locator' );

            $template_details = $wpsl->templates->get_template_details( $atts['template'] );

            $output = include( $template_details['path'] );

            return $output;
        }

        /**
         * Handle the [wpsl_address] shortcode.
         *
         * @since 2.0.0
         * @todo   add schema.org support.
         * @param  array       $atts   Shortcode attributes
         * @return void|string $output The store address
         */
        public function show_store_address( $atts ) {

            global $post, $wpsl_settings, $wpsl;

            $atts = wpsl_bool_check( shortcode_atts( apply_filters( 'wpsl_address_shortcode_defaults', array(
                'id'                        => '',
                'name'                      => true,
                'address'                   => true,
                'address2'                  => true,
                'city'                      => true,
                'state'                     => true,
                'zip'                       => true,
                'country'                   => true,
                'phone'                     => true,
                'fax'                       => true,
                'email'                     => true,
                'url'                       => true,
                'directions'                => false,
                'clickable_contact_details' => (bool) $wpsl_settings['clickable_contact_details']
            ) ), $atts ) );

            if ( get_post_type() == 'wpsl_stores' ) {
                if ( empty( $atts['id'] ) ) {
                    if ( isset( $post->ID ) ) {
                        $atts['id'] = $post->ID;
                    } else {
                        return;
                    }
                }
            } else if ( empty( $atts['id'] ) ) {
                return __( 'If you use the [wpsl_address] shortcode outside a store page you need to set the ID attribute.', 'wpsl' );
            }

            $content = '<div class="wpsl-locations-details">';

            if ( $atts['name'] && $name = get_the_title( $atts['id'] ) ) {
                $content .= '<span><strong>' . esc_html( $name ) . '</strong></span>';
            }

            $content .= '<div class="wpsl-location-address">';

            if ( $atts['address'] && $address = get_post_meta( $atts['id'], 'wpsl_address', true ) ) {
                $content .= '<span>' . esc_html( $address ) . '</span><br/>';
            }

            if ( $atts['address2'] && $address2 = get_post_meta( $atts['id'], 'wpsl_address2', true ) ) {
                $content .= '<span>' . esc_html( $address2 ) . '</span><br/>';
            }

            $address_format = explode( '_', $wpsl_settings['address_format'] );
            $count = count( $address_format );
            $i = 1;

            // Loop over the address parts to make sure they are shown in the right order.
            foreach ( $address_format as $address_part ) {

                // Make sure the shortcode attribute is set to true for the $address_part, and it's not the 'comma' part.
                if ( $address_part != 'comma' && $atts[$address_part] ) {
                    $post_meta = get_post_meta( $atts['id'], 'wpsl_' . $address_part, true );

                    if ( $post_meta ) {

                        /*
                         * Check if the next part of the address is set to 'comma'.
                         * If so add the, after the current address part, otherwise just show a space
                         */
                        if ( isset( $address_format[$i] ) && ( $address_format[$i] == 'comma' ) ) {
                            $punctuation = ', ';
                        } else {
                            $punctuation = ' ';
                        }

                        // If we have reached the last item add a <br /> behind it.
                        $br = ( $count == $i ) ? '<br />' : '';

                        $content .= '<span>' . esc_html( $post_meta ) . $punctuation . '</span>' . $br;
                    }
                }

                $i++;
            }

            if ( $atts['country'] && $country = get_post_meta( $atts['id'], 'wpsl_country', true ) ) {
                $content .= '<span>' . esc_html( $country ) . '</span>';
            }

            $content .= '</div>';

            // If either the phone, fax, email or url is set to true, then add the wrap div for the contact details.
            if ( $atts['phone'] || $atts['fax'] || $atts['email'] || $atts['url'] ) {
                $phone = get_post_meta( $atts['id'], 'wpsl_phone', true );
                $fax   = get_post_meta( $atts['id'], 'wpsl_fax', true );
                $email = get_post_meta( $atts['id'], 'wpsl_email', true );

                if ( $atts['clickable_contact_details'] ) {
                    $contact_details = array(
                        'phone' => '<a href="tel:' . esc_attr( $phone ) . '">' . esc_html( $phone ) . '</a>',
                        'fax'   => '<a href="tel:' . esc_attr( $fax ) . '">' . esc_html( $fax ) . '</a>',
                        'email' => '<a href="mailto:' . sanitize_email( $email ) . '">' . sanitize_email( $email ) . '</a>'
                    );
                } else {
                    $contact_details = array(
                        'phone' => esc_html( $phone ),
                        'fax'   => esc_html( $fax ),
                        'email' => sanitize_email( $email )
                    );
                }

                $content .= '<div class="wpsl-contact-details">';

                if ( $atts['phone'] && $phone ) {
                    $content .= esc_html( $wpsl->i18n->get_translation( 'phone_label', __( 'Phone', 'wpsl' ) ) ) . ': <span>' . $contact_details['phone'] . '</span><br/>';
                }

                if ( $atts['fax'] && $fax ) {
                    $content .= esc_html( $wpsl->i18n->get_translation( 'fax_label', __( 'Fax', 'wpsl' ) ) ) . ': <span>' . $contact_details['fax'] . '</span><br/>';
                }

                if ( $atts['email'] && $email ) {
                    $content .= esc_html( $wpsl->i18n->get_translation( 'email_label', __( 'Email', 'wpsl' ) ) ) . ': <span>' . $contact_details['email'] . '</span><br/>';
                }

                if ( $atts['url'] && $store_url = get_post_meta( $atts['id'], 'wpsl_url', true ) ) {
                    $new_window = ( $wpsl_settings['new_window'] ) ? 'target="_blank"' : '' ;
                    $content   .= esc_html( $wpsl->i18n->get_translation( 'url_label', __( 'Url', 'wpsl' ) ) ) . ': <a ' . $new_window . ' href="' . esc_url( $store_url ) . '">' . esc_url( $store_url ) . '</a><br/>';
                }

                $content .= '</div>';
            }

            if ( $atts['directions'] && $address ) {
                if ( $wpsl_settings['new_window'] ) {
                    $new_window = ' target="_blank"';
                } else {
                    $new_window = '';
                }

                $content .= '<div class="wpsl-location-directions">';

                $city          = get_post_meta( $atts['id'], 'wpsl_city', true );
                $country       = get_post_meta( $atts['id'], 'wpsl_country', true );
                $destination   = $address . ',' . $city . ',' . $country;
                $direction_url = "https://maps.google.com/maps?saddr=&daddr=" . urlencode( $destination ) . "&travelmode=" . strtolower( $this->get_directions_travel_mode() );

                $content .= '<p><a ' . $new_window . ' href="' . esc_url( $direction_url ) . '">' . __( 'Directions', 'wpsl' ) . '</a></p>';
                $content .= '</div>';
            }

            $content .= '</div>';

            return $content;
        }

        /**
         * Handle the [wpsl_hours] shortcode.
         *
         * @since 2.0.0
         * @param  array       $atts   Shortcode attributes
         * @return void|string $output The opening hours
         */
        public function show_opening_hours( $atts ) {

            global $wpsl_settings, $post;

            // If the hours are set to hidden on the settings page, then respect that and don't continue.
            if ( $wpsl_settings['hide_hours'] ) {
                return;
            }

            $hide_closed = apply_filters( 'wpsl_hide_closed_hours', false );

            $atts = wpsl_bool_check( shortcode_atts( apply_filters( 'wpsl_hour_shortcode_defaults', array(
                'id'          => '',
                'hide_closed' => $hide_closed
            ) ), $atts ) );

            if ( get_post_type() == 'wpsl_stores' ) {
                if ( empty( $atts['id'] ) ) {
                    if ( isset( $post->ID ) ) {
                        $atts['id'] = $post->ID;
                    } else {
                        return;
                    }
                }
            } else if ( empty( $atts['id'] ) ) {
                return __( 'If you use the [wpsl_hours] shortcode outside a store page you need to set the ID attribute.', 'wpsl' );
            }

            $opening_hours = get_post_meta( $atts['id'], 'wpsl_hours' );

            if ( $opening_hours ) {
                $output = $this->get_opening_hours( $opening_hours[0], $atts['hide_closed'] );

                return $output;
            }
        }

        /**
         * Handle the [wpsl_map] shortcode.
         *
         * @since 2.0.0
         * @param  array  $atts   Shortcode attributes
         * @return string $output The html for the map
         */
        public function show_store_map( $atts ) {

            global $wpsl_settings, $post;

            $atts = shortcode_atts( apply_filters( 'wpsl_map_shortcode_defaults', array(
                'id'               => '',
                'category'         => '',
                'width'            => '',
                'height'           => $wpsl_settings['height'],
                'zoom'             => $wpsl_settings['zoom_level'],
                'map_type'         => $wpsl_settings['map_type'],
                'map_type_control' => $wpsl_settings['type_control'],
                'map_style'        => '',
                'street_view'      => $wpsl_settings['streetview'],
                'scrollwheel'      => $wpsl_settings['scrollwheel'],
                'control_position' => $wpsl_settings['control_position']
            ) ), $atts );

            array_push( $this->load_scripts, 'wpsl_base' );

            if ( get_post_type() == 'wpsl_stores' ) {
                if ( empty( $atts['id'] ) ) {
                    if ( isset( $post->ID ) ) {
                        $atts['id'] = $post->ID;
                    } else {
                        return;
                    }
                }
            } else if ( empty( $atts['id'] ) && empty( $atts['category'] ) ) {
                return __( 'If you use the [wpsl_map] shortcode outside a store page, then you need to set the ID or category attribute.', 'wpsl' );
            }

            if ( $atts['category'] ) {
                $store_ids = get_posts( array(
                    'numberposts' => -1,
                    'post_type'   => 'wpsl_stores',
                    'post_status' => 'publish',
                    'tax_query'   => array(
                        array(
                            'taxonomy' => 'wpsl_store_category',
                            'field'    => 'slug',
                            'terms'    => explode( ',', sanitize_text_field( $atts['category'] ) )
                        ),
                    ),
                    'fields'      => 'ids'
                ) );
            } else {
                $store_ids = array_map( 'absint', explode( ',', $atts['id'] ) );
                $id_count  = count( $store_ids );
            }

            /*
             * The location url is included if:
             *
             * - Multiple ids are set.
             * - The category attr is set.
             * - The shortcode is used on a post type other then 'wpsl_stores'. No point in showing a location
             * url to the user that links back to the page they are already on.
             */
            if ( $atts['category'] || isset( $id_count ) && $id_count > 1 || get_post_type() != 'wpsl_stores' && !empty( $atts['id'] ) ) {
                $incl_url = true;
            } else {
                $incl_url = false;
            }

            $store_meta = array();
            $i          = 0;

            foreach ( $store_ids as $store_id ) {
                $lat = get_post_meta( $store_id, 'wpsl_lat', true );
                $lng = get_post_meta( $store_id, 'wpsl_lng', true );

                // Make sure the latlng is numeric before collecting the other meta data.
                if ( is_numeric( $lat ) && is_numeric( $lng ) ) {
                    $store_meta[$i] = apply_filters( 'wpsl_cpt_info_window_meta_fields', array(
                        'store'    => get_the_title( $store_id ),
                        'address'  => get_post_meta( $store_id, 'wpsl_address',  true ),
                        'address2' => get_post_meta( $store_id, 'wpsl_address2', true ),
                        'city'     => get_post_meta( $store_id, 'wpsl_city',     true ),
                        'state'    => get_post_meta( $store_id, 'wpsl_state',    true ),
                        'zip'      => get_post_meta( $store_id, 'wpsl_zip',      true ),
                        'country'  => get_post_meta( $store_id, 'wpsl_country',  true )
                    ), $store_id );

                    // Grab the permalink / url if necessary.
                    if ( $incl_url ) {
                        if ( $wpsl_settings['permalinks'] ) {
                            $store_meta[$i]['permalink'] = get_permalink( $store_id );
                        } else {
                            $store_meta[$i]['url'] = get_post_meta( $store_id, 'wpsl_url', true );
                        }
                    }

                    $store_meta[$i]['lat'] = $lat;
                    $store_meta[$i]['lng'] = $lng;
                    $store_meta[$i]['id']  = $store_id;

                    $i++;
                }
            }

            $output = '<div id="wpsl-base-gmap_' . self::$map_count . '" class="wpsl-gmap-canvas"></div>' . "\r\n";

            // Make sure the shortcode attributes are valid.
            $map_styles = $this->check_map_shortcode_atts( $atts );

            if ( $map_styles ) {
                if ( isset( $map_styles['css'] ) && !empty( $map_styles['css'] ) ) {
                    $output .= '<style>' . $map_styles['css'] . '</style>' . "\r\n";
                    unset( $map_styles['css'] );
                }

                if ( $map_styles ) {
                    $store_data['shortCode'] = $map_styles;
                }
            }

            $store_data['locations'] = $store_meta;

            $this->store_map_data[self::$map_count] = $store_data;

            self::$map_count++;

            return $output;
        }

        /**
         * Make sure the map style shortcode attributes are valid.
         *
         * The values are send to wp_localize_script in add_frontend_scripts.
         *
         * @since 2.0.0
         * @param  array $atts     The map style shortcode attributes
         * @return array $map_atts Validated map style shortcode attributes
         */
        public function check_map_shortcode_atts( $atts ) {

            $map_atts = array();

            if ( isset( $atts['width'] ) && is_numeric( $atts['width'] ) ) {
                $width = 'width:' . $atts['width'] . 'px;';
            } else {
                $width = '';
            }

            if ( isset( $atts['height'] ) && is_numeric( $atts['height'] ) ) {
                $height = 'height:' . $atts['height'] . 'px;';
            } else {
                $height = '';
            }

            if ( $width || $height ) {
                $map_atts['css'] = '#wpsl-base-gmap_' . self::$map_count . ' {' . $width . $height . '}';
            }

            if ( isset( $atts['zoom'] ) && !empty( $atts['zoom'] ) ) {
                $map_atts['zoomLevel'] = wpsl_valid_zoom_level( $atts['zoom'] );
            }

            if ( isset( $atts['map_type'] ) && !empty( $atts['map_type'] ) ) {
                $map_atts['mapType'] = wpsl_valid_map_type( $atts['map_type'] );
            }

            if ( isset( $atts['map_type_control'] ) ) {
                $map_atts['mapTypeControl'] = $this->shortcode_atts_boolean( $atts['map_type_control'] );
            }

            if ( isset( $atts['map_style'] ) && $atts['map_style'] == 'default' ) {
                $map_atts['mapStyle'] = '';
            }

            if ( isset( $atts['street_view'] ) ) {
                $map_atts['streetView'] = $this->shortcode_atts_boolean( $atts['street_view'] );
            }

            if ( isset( $atts['scrollwheel'] ) ) {
                $map_atts['scrollWheel'] = $this->shortcode_atts_boolean( $atts['scrollwheel'] );
            }

            if ( isset( $atts['control_position'] ) && !empty( $atts['control_position'] ) && ( $atts['control_position'] == 'left' || $atts['control_position'] == 'right' ) ) {
                $map_atts['controlPosition'] = $atts['control_position'];
            }

            return $map_atts;
        }

        /**
         * Set the shortcode attribute to either 1 or 0.
         *
         * @since 2.0.0
         * @param  string $att     The shortcode attribute val
         * @return int    $att_val Either 1 or 0
         */
        public function shortcode_atts_boolean( $att ) {

            if ( $att === 'true' || absint( $att ) ) {
                $att_val = 1;
            } else {
                $att_val = 0;
            }

            return $att_val;
        }

        /**
         * Make sure the filter contains a valid value, otherwise use the default value.
         *
         * @since 2.0.0
         * @param  array  $args         The values used in the SQL query to find nearby locations
         * @param  string $filter       The name of the filter
         * @return string $filter_value The filter value
         */
        public function check_store_filter( $args, $filter ) {

            if ( isset( $args[$filter] ) && absint( $args[$filter] ) && $this->check_allowed_filter_value( $args, $filter ) ) {
                $filter_value = $args[$filter];
            } else {
                $filter_value = $this->get_default_filter_value( $filter );
            }

            return $filter_value;
        }

        /**
         * Make sure the used filter value isn't bigger
         * then the value that's set on the settings page.
         *
         * @since 2.2.9
         * @param  array  $args    The values used in the SQL query to find nearby locations
         * @param  string $filter  The name of the filter
         * @return bool   $allowed True if the value is equal or smaller then the value from the settings page
         */
        public function check_allowed_filter_value( $args, $filter ) {

            global $wpsl_settings;

            $allowed = false;

            $max_filter_val = max( explode(',', str_replace( array( '[',']' ), '', $wpsl_settings[$filter] ) ) );

            if ( (int) $args[$filter] <= (int) $max_filter_val ) {
                $allowed = true;
            }

            return $allowed;
        }

        /**
         * Get the default selected value for a dropdown.
         *
         * @since 1.0.0
         * @param  string $type     The request list type
         * @return string $response The default list value
         */
        public function get_default_filter_value( $type ) {

            $settings    = get_option( 'wpsl_settings' );
            $list_values = explode( ',', $settings[$type] );

            foreach ( $list_values as $k => $list_value ) {

                // The default radius has a [] wrapped around it, so we check for that and filter out the [].
                if ( strpos( $list_value, '[' ) !== false ) {
                    $response = filter_var( $list_value, FILTER_SANITIZE_NUMBER_INT );
                    break;
                }
            }

            return $response;
        }

        /**
         * Check if we have a opening day that has an value, if not they are all set to closed.
         *
         * @since 2.0.0
         * @param  array   $opening_hours The opening hours
         * @return boolean True if a day is found that isn't empty
         */
        public function not_always_closed( $opening_hours ) {

            foreach ( $opening_hours as $hours => $hour ) {
                if ( !empty( $hour ) ) {
                    return true;
                }
            }
        }

        /**
         * Create the css rules based on the height / max-width that is set on the settings page.
         *
         * @since 1.0.0
         * @return string $css The custom css rules
         */
        public function get_custom_css() {

            global $wpsl_settings;

            $thumb_size = $this->get_store_thumb_size();

            $css = '<style>' . "\r\n";

            if ( isset( $thumb_size[0] ) && is_numeric( $thumb_size[0] ) && isset( $thumb_size[1] ) && is_numeric( $thumb_size[1] ) ) {
                $css .= "\t" . "#wpsl-stores .wpsl-store-thumb {height:" . esc_attr( $thumb_size[0] ) . "px !important; width:" . esc_attr( $thumb_size[1] ) . "px !important;}" . "\r\n";
            }

            if ( $wpsl_settings['template_id'] == 'below_map' && $wpsl_settings['listing_below_no_scroll'] ) {
                $css .= "\t" . "#wpsl-gmap {height:" . esc_attr( $wpsl_settings['height'] ) . "px !important;}" . "\r\n";
                $css .= "\t" . "#wpsl-stores, #wpsl-direction-details {height:auto !important;}";
            } else {
                $css .= "\t" . "#wpsl-stores, #wpsl-direction-details, #wpsl-gmap {height:" . esc_attr( $wpsl_settings['height'] ) . "px !important;}" . "\r\n";
            }

            /*
             * If the category dropdowns are enabled then we make it
             * the same width as the search input field.
             */
            if ( $wpsl_settings['category_filter'] && $wpsl_settings['category_filter_type'] == 'dropdown' || isset( $this->sl_shortcode_atts['category_filter_type'] ) && $this->sl_shortcode_atts['category_filter_type'] == 'dropdown' ) {
                $cat_elem = ',#wpsl-category .wpsl-dropdown';
            } else {
                $cat_elem = '';
            }

            $css .= "\t" . "#wpsl-gmap .wpsl-info-window {max-width:" . esc_attr( $wpsl_settings['infowindow_width'] ) . "px !important;}" . "\r\n";
            $css .= "\t" . ".wpsl-input label, #wpsl-radius label, #wpsl-category label {width:" . esc_attr( $wpsl_settings['label_width'] ) . "px;}" . "\r\n";
            $css .= "\t" . "#wpsl-search-input " . $cat_elem . " {width:" . esc_attr( $wpsl_settings['search_width'] ) . "px;}" . "\r\n";
            $css .= '</style>' . "\r\n";

            return $css;
        }

        /**
         * Collect the CSS classes that are placed on the outer store locator div.
         *
         * @since 2.0.0
         * @return string $classes The custom CSS rules
         */
        public function get_css_classes() {

            global $wpsl_settings;

            $classes = array();

            if ( $wpsl_settings['category_filter'] && $wpsl_settings['results_dropdown'] && !$wpsl_settings['radius_dropdown'] ) {
                $classes[] = 'wpsl-cat-results-filter';
            } else if ( $wpsl_settings['category_filter'] && ( $wpsl_settings['results_dropdown'] || $wpsl_settings['radius_dropdown'] ) ) {
                $classes[] = 'wpsl-filter';
            }
            // checkboxes class toevoegen?
            if ( !$wpsl_settings['category_filter'] && !$wpsl_settings['results_dropdown'] && !$wpsl_settings['radius_dropdown'] ) {
                $classes[] = 'wpsl-no-filters';
            }

            if ( $wpsl_settings['category_filter'] && $wpsl_settings['category_filter_type'] == 'checkboxes' ) {
                $classes[] = 'wpsl-checkboxes-enabled';
            }

            if ( $wpsl_settings['results_dropdown'] && !$wpsl_settings['category_filter'] && !$wpsl_settings['radius_dropdown'] ) {
                $classes[] = 'wpsl-results-only';
            }

            // Adjust the styling of the store locator for the default WP 5.0 theme.
            if ( get_option( 'template' ) === 'twentynineteen' ) {
                $classes[] = 'wpsl-twentynineteen';
            }

            $classes = apply_filters( 'wpsl_template_css_classes', $classes );

            if ( !empty( $classes ) ) {
                return join( ' ', $classes );
            }
        }

        /**
         * Create a dropdown list holding the search radius or
         * max search results options.
         *
         * @since 1.0.0
         * @param  string $list_type     The name of the list we need to load data for
         * @return string $dropdown_list A list with the available options for the dropdown list
         */
        public function get_dropdown_list( $list_type ) {

            global $wpsl_settings;

            $dropdown_list = '';
            $settings      = explode( ',', $wpsl_settings[$list_type] );

            // Only show the distance unit if we are dealing with the search radius.
            if ( $list_type == 'search_radius' ) {
                $distance_unit = ' '. esc_attr( wpsl_get_distance_unit() );
            } else {
                $distance_unit = '';
            }

            foreach ( $settings as $index => $setting_value ) {

                // The default radius has a [] wrapped around it, so we check for that and filter out the [].
                if ( strpos( $setting_value, '[' ) !== false ) {
                    $setting_value = filter_var( $setting_value, FILTER_SANITIZE_NUMBER_INT );
                    $selected = 'selected="selected" ';
                } else {
                    $selected = '';
                }

                $dropdown_list .= '<option ' . $selected . 'value="'. absint( $setting_value ) .'">'. absint( $setting_value ) . $distance_unit .'</option>';
            }

            return $dropdown_list;
        }

        /**
         * Check if we need to use a dropdown or checkboxes
         * to filter the search results by categories.
         *
         * @since 2.2.10
         * @return bool $use_filter
         */
        public function use_category_filter() {

            global $wpsl_settings;

            $use_filter = false;

            // Is a filter type set through the shortcode, or is the filter option enable on the settings page?
            if ( isset( $this->sl_shortcode_atts['category_filter_type'] ) || $wpsl_settings['category_filter'] ) {
                $use_filter = true;
            }

            return $use_filter;
        }

        /**
         * Create the category filter.
         *
         * @todo create another func that accepts a meta key param to generate
         * a dropdown with unique values. So for example create_filter( 'restaurant' ) will output a
         * filter with all restaurant types. This can be used in a custom theme template.
         *
         * @since 2.0.0
         * @return string|void $category The HTML for the category dropdown, or nothing if no terms exist.
         */
        public function create_category_filter() {

            global $wpsl, $wpsl_settings;

            /*
             * If the category attr is set on the wpsl shortcode, then
             * there is no need to ouput an extra category dropdown.
             */
            if ( isset( $this->sl_shortcode_atts['js']['categoryIds'] ) ) {
                return;
            }

            $terms = get_terms( 'wpsl_store_category' );

            if ( count( $terms ) > 0 ) {

                // Either use the shortcode atts filter type or the one from the settings page.
                if ( isset( $this->sl_shortcode_atts['category_filter_type'] ) ) {
                    $filter_type = $this->sl_shortcode_atts['category_filter_type'];
                } else {
                    $filter_type = $wpsl_settings['category_filter_type'];
                }

                // Check if we need to show the filter as checkboxes or a dropdown list
                if ( $filter_type == 'checkboxes' ) {
                    if ( isset( $this->sl_shortcode_atts['checkbox_columns'] ) ) {
                        $checkbox_columns = absint( $this->sl_shortcode_atts['checkbox_columns'] );
                    }

                    if ( isset( $checkbox_columns ) && $checkbox_columns ) {
                        $column_count = $checkbox_columns;
                    } else {
                        $column_count = 3;
                    }

                    $category = '<ul id="wpsl-checkbox-filter" class="wpsl-checkbox-' . $column_count . '-columns">';

                    foreach ( $terms as $term ) {
                        $category .= '<li>';
                        $category .= '<label>';
                        $category .= '<input type="checkbox" value="' . esc_attr( $term->term_id ) . '" ' . $this->set_selected_category( $filter_type, $term->term_id ) . ' />';
                        $category .= esc_html( $term->name );
                        $category .= '</label>';
                        $category .= '</li>';
                    }

                    $category .= '</ul>';
                } else {
                    $category = '<div id="wpsl-category">' . "\r\n";
                    $category .= '<label for="wpsl-category-list">' . esc_html( $wpsl->i18n->get_translation( 'category_label', __( 'Category', 'wpsl' ) ) ) . '</label>' . "\r\n";

                    $args = apply_filters( 'wpsl_dropdown_category_args', array(
                            'show_option_none'  => $wpsl->i18n->get_translation( 'category_default_label', __( 'Any', 'wpsl' ) ),
                            'option_none_value' => '0',
                            'orderby'           => 'NAME',
                            'order'             => 'ASC',
                            'echo'              => 0,
                            'selected'          => $this->set_selected_category( $filter_type ),
                            'hierarchical'      => 1,
                            'name'              => 'wpsl-category',
                            'id'                => 'wpsl-category-list',
                            'class'             => 'wpsl-dropdown',
                            'taxonomy'          => 'wpsl_store_category',
                            'hide_if_empty'     => true
                        )
                    );

                    $category .= wp_dropdown_categories( $args );

                    $category .= '</div>' . "\r\n";
                }

                return $category;
            }
        }

        /**
         * Set the selected category item.
         *
         * @since 2.1.2
         * @param  string      $filter_type  The type of filter being used ( dropdown or checkbox )
         * @param  int|string  $term_id      The term id ( checkbox only )
         * @return string|void $category     The ID of the selected option, or checked='checked' if it's for a checkbox
         */
        public function set_selected_category( $filter_type, $term_id = '' ) {

            $selected_id = '';

            // Check if the ID for the selected cat is either passed through the widget, or shortcode
            if ( isset( $_REQUEST['wpsl-widget-categories'] ) ) {
                $selected_id = absint( $_REQUEST['wpsl-widget-categories'] );
            } else if ( isset( $this->sl_shortcode_atts['category_selection'] ) ) {

                /*
                 * When the term_id is set, then it's a checkbox.
                 *
                 * Otherwise select the first value from the provided list since
                 * multiple selections are not supported in dropdowns.
                 */
                if ( $term_id ) {

                    // Check if the passed term id exists in the set shortcode value.
                    $key = array_search( $term_id, $this->sl_shortcode_atts['category_selection'] );

                    if ( $key !== false ) {
                        $selected_id = $this->sl_shortcode_atts['category_selection'][$key];
                    }
                } else {
                    $selected_id = $this->sl_shortcode_atts['category_selection'][0];
                }
            }

            if ( $selected_id ) {

                /*
                 * Based on the filter type, either return the ID of the selected category,
                 * or check if the checkbox needs to be set to checked="checked".
                 */
                if ( $filter_type == 'dropdown' ) {
                    return $selected_id;
                } else {
                    return checked( $selected_id, $term_id, false );
                }
            }
        }

        /**
         * Create a filename with @2x in it for the selected marker color.
         *
         * So when a user selected green.png in the admin panel. The JS on the front-end will end up
         * loading green@2x.png to provide support for retina compatible devices.
         *
         * @since 1.0.0
         * @param  string $filename The name of the seleted marker
         * @return string $filename The filename with @2x added to the end
         */
        public function create_retina_filename( $filename ) {

            $filename = explode( '.', $filename );
            $filename = $filename[0] . '@2x.' . $filename[1];

            return $filename;
        }

        /**
         * Get the default values for the max_results and the search_radius dropdown.
         *
         * @since 1.0.2
         * @return array $output The default dropdown values
         */
        public function get_dropdown_defaults() {

            global $wpsl_settings;

            $required_defaults = array(
                'max_results',
                'search_radius'
            );

            // Strip out the default values that are wrapped in [].
            foreach ( $required_defaults as $required_default ) {
                preg_match_all( '/\[([0-9]+?)\]/', $wpsl_settings[$required_default], $match, PREG_PATTERN_ORDER );
                $output[$required_default] = ( isset( $match[1][0] ) ) ? $match[1][0] : '25';
            }

            return $output;
        }

        /**
         * Load the required css styles.
         *
         * @since 2.0.0
         * @return void
         */
        public function add_frontend_styles() {

            global $wpsl_settings;

            /**
             * Check if we need to deregister other Google Maps scripts loaded
             * by other plugins, or the current theme?
             *
             * This in some cases can break the store locator map.
             */
            if ( $wpsl_settings['deregister_gmaps'] ) {
                wpsl_deregister_other_gmaps();
            }

            $min = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';

            wp_enqueue_style( 'wpsl-styles', WPSL_URL . 'css/styles'. $min .'.css', '', WPSL_VERSION_NUM );
        }

        /**
         * Get the HTML for the map controls.
         *
         * The '&#xe800;' and '&#xe801;' code is for the icon font from fontello.com
         *
         * @since 2.0.0
         * @return string The HTML for the map controls
         */
        public function get_map_controls() {

            global $wpsl_settings, $is_IE;

            $classes = array();

            if ( $wpsl_settings['reset_map'] ) {
                $reset_button = '<div class="wpsl-icon-reset"><span>&#xe801;</span></div>';
            } else {
                $reset_button = '';
            }

            /*
             * IE messes up the top padding for the icon fonts from fontello >_<.
             *
             * Luckily it's the same in all IE version ( 8-11 ),
             * so adjusting the padding just for IE fixes it.
             */
            if ( $is_IE ) {
                $classes[] = 'wpsl-ie';
            }

            // If the street view option is enabled, then we need to adjust the right margin for the map control div.
            if ( $wpsl_settings['streetview'] ) {
                $classes[] = 'wpsl-street-view-exists';
            }

            if ( !empty( $classes ) ) {
                $class = 'class="' . join( ' ', $classes ) . '"';
            } else {
                $class = '';
            }

            $map_controls = '<div id="wpsl-map-controls" ' . $class . '>' . $reset_button . '<div class="wpsl-icon-direction"><span>&#xe800;</span></div></div>';

            return apply_filters( 'wpsl_map_controls', $map_controls );
        }

        /**
         * The different geolocation errors.
         *
         * They are shown when the Geolocation API returns an error.
         *
         * @since 2.0.0
         * @return array $geolocation_errors
         */
        public function geolocation_errors() {

            $geolocation_errors = array(
                'denied'       => __( 'The application does not have permission to use the Geolocation API.', 'wpsl' ),
                'unavailable'  => __( 'Location information is unavailable.', 'wpsl' ),
                'timeout'      => __( 'The geolocation request timed out.', 'wpsl' ),
                'generalError' => __( 'An unknown error occurred.', 'wpsl' )
            );

            return $geolocation_errors;
        }

        /**
         * Get the used marker properties.
         *
         * @since 2.1.0
         * @link https://developers.google.com/maps/documentation/javascript/3.exp/reference#Icon
         * @return array $marker_props The marker properties.
         */
        public function get_marker_props() {

            $marker_props = array(
                'scaledSize' => '24,35', // 50% of the normal image to make it work on retina screens.
                'origin'     => '0,0',
                'anchor'     => '12,35'
            );

            /*
             * If this is not defined, the url path will default to
             * the url path of the WPSL plugin folder + /img/markers/
             * in the wpsl-gmap.js.
             */
            if ( defined( 'WPSL_MARKER_URI' ) ) {
                $marker_props['url'] = WPSL_MARKER_URI;
            }

            return apply_filters( 'wpsl_marker_props', $marker_props );
        }

        /**
         * Get the used travel direction mode.
         *
         * @since 2.2.8
         * @return string $travel_mode The used travel mode for the travel direcions
         */
        public function get_directions_travel_mode() {

            $default = 'driving';

            $travel_mode   = apply_filters( 'wpsl_direction_travel_mode', $default );
            $allowed_modes = array( 'driving', 'bicycling', 'transit', 'walking' );

            if ( !in_array( $travel_mode, $allowed_modes ) ) {
                $travel_mode = $default;
            }

            return strtoupper( $travel_mode );
        }

        /**
         * Get the map tab anchors.
         *
         * If the wpsl/wpsl_map shortcode is used in one or more tabs,
         * then a JS fix ( the fixGreyTabMap function ) needs to run
         * to make sure the map doesn't turn grey.
         *
         * For the fix to work need to know the used anchor(s).
         *
         * @since 2.2.10
         * @return string|array $map_tab_anchor One or more anchors used to show the map(s)
         */
        public function get_map_tab_anchor() {

            $map_tab_anchor = apply_filters( 'wpsl_map_tab_anchor', 'wpsl-map-tab' );

            return $map_tab_anchor;
        }

        /**
         * Load the required JS scripts.
         *
         * @since 1.0.0
         * @return void
         */
        public function add_frontend_scripts() {

            global $wpsl_settings, $wpsl, $post;

            // Only load the required js files on the store locator page or individual store pages.
            if ( empty( $this->load_scripts ) ) {
                return;
            }

            $min = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';

            $dropdown_defaults = $this->get_dropdown_defaults();

            /**
             * Check if we need to deregister other Google Maps scripts loaded
             * by other plugins, or the current theme?
             *
             * This in some cases can break the store locator map.
             */
            if ( $wpsl_settings['deregister_gmaps'] ) {
                wpsl_deregister_other_gmaps();
            }

            if ( !function_exists( 'BorlabsCookieHelper' ) ) {
                wp_enqueue_script( 'wpsl-gmap', ( 'https://maps.google.com/maps/api/js' . wpsl_get_gmap_api_params( 'browser_key' ) . '' ), '', null, true );
            } else {
                if ( !$wpsl_settings['delay_loading']
                    ||
                    (
                        stripos( $post->post_content, '[borlabs_cookie_blocked_content type="wpstorelocator"' ) === false
                        &&
                        stripos( $post->post_content, '[borlabs-cookie id="wpstorelocator" type="content-blocker"' ) === false
                    )
                ) {
                    wp_enqueue_script( 'wpsl-gmap', ( 'https://maps.google.com/maps/api/js' . wpsl_get_gmap_api_params( 'browser_key' ) . '' ), '', null, true );
                }
            }

            $base_settings = array(
                'storeMarker'           => $this->create_retina_filename( $wpsl_settings['store_marker'] ),
                'mapType'               => $wpsl_settings['map_type'],
                'mapTypeControl'        => $wpsl_settings['type_control'],
                'zoomLevel'             => $wpsl_settings['zoom_level'],
                'startLatlng'           => $wpsl_settings['start_latlng'],
                'autoZoomLevel'         => $wpsl_settings['auto_zoom_level'],
                'scrollWheel'           => $wpsl_settings['scrollwheel'],
                'controlPosition'       => $wpsl_settings['control_position'],
                'url'                   => WPSL_URL,
                'markerIconProps'       => $this->get_marker_props(),
                'storeUrl'              => $wpsl_settings['store_url'],
                'maxDropdownHeight'     => apply_filters( 'wpsl_max_dropdown_height', 300 ),
                'enableStyledDropdowns' => apply_filters( 'wpsl_enable_styled_dropdowns', true ),
                'mapTabAnchor'          => $this->get_map_tab_anchor(),
                'mapTabAnchorReturn'    => apply_filters( 'wpsl_map_tab_anchor_return', false ),
                'gestureHandling'       => apply_filters( 'wpsl_gesture_handling', 'auto' ),
                'directionsTravelMode'  => $this->get_directions_travel_mode(),
                'runFitBounds'          => $wpsl_settings['run_fitbounds']
            );

            $locator_map_settings = array(
                'startMarker'        => $this->create_retina_filename( $wpsl_settings['start_marker'] ),
                'markerClusters'     => $wpsl_settings['marker_clusters'],
                'streetView'         => $wpsl_settings['streetview'],
                'autoComplete'       => $wpsl_settings['autocomplete'],
                'autoLocate'         => $wpsl_settings['auto_locate'],
                'autoLoad'           => $wpsl_settings['autoload'],
                'markerEffect'       => $wpsl_settings['marker_effect'],
                'markerStreetView'   => $wpsl_settings['marker_streetview'],
                'markerZoomTo'       => $wpsl_settings['marker_zoom_to'],
                'newWindow'          => $wpsl_settings['new_window'],
                'resetMap'           => $wpsl_settings['reset_map'],
                'directionRedirect'  => $wpsl_settings['direction_redirect'],
                'phoneUrl'           => $wpsl_settings['phone_url'],
                'clickableDetails'   => $wpsl_settings['clickable_contact_details'],
                'moreInfoLocation'   => $wpsl_settings['more_info_location'],
                'mouseFocus'         => $wpsl_settings['mouse_focus'],
                'templateId'         => $wpsl_settings['template_id'],
                'maxResults'         => $dropdown_defaults['max_results'],
                'searchRadius'       => $dropdown_defaults['search_radius'],
                'distanceUnit'       => wpsl_get_distance_unit(),
                'geoLocationTimeout' => apply_filters( 'wpsl_geolocation_timeout', 7500 ),
                'ajaxurl'            => wpsl_get_ajax_url(),
                'mapControls'        => $this->get_map_controls()
            );

            /*
             * If no results are found then by default it will just show the
             * "No results found" text. This filter makes it possible to show
             * a custom HTML block instead of the "No results found" text.
             */
            $no_results_msg = apply_filters( 'wpsl_no_results', '' );

            if ( $no_results_msg ) {
                $locator_map_settings['noResults'] = $no_results_msg;
            }

            /**
             * If enabled, include the component filter settings.
             * @todo see https://developers.google.com/maps/documentation/javascript/releases#327
             * See https://developers.google.com/maps/documentation/javascript/geocoding#ComponentFiltering
             */
            if ( $wpsl_settings['api_region'] && $wpsl_settings['api_geocode_component'] ) {
                $geocode_components = array();
                $geocode_components['country'] = strtoupper( $wpsl_settings['api_region'] );

                if ( $wpsl_settings['force_postalcode'] ) {
                    $geocode_components['postalCode'] = '';
                }

                $locator_map_settings['geocodeComponents'] = apply_filters( 'wpsl_geocode_components', $geocode_components );
            }

            /**
             * Reduce the requested data fields with each autocomplete API call.
             *
             * You can see the supported fields here https://developers.google.com/maps/documentation/javascript/reference/places-service#PlaceResult
             * and other possible options to target here https://developers.google.com/maps/documentation/javascript/reference/places-widget#AutocompleteOptions
             */
            if ( $wpsl_settings['autocomplete'] ) {
                $locator_map_settings['autoCompleteOptions'] = apply_filters( 'wpsl_autocomplete_options', array(
                    'fields' => array( 'geometry.location' ),
                    'types'  => array( '(regions)' )
                ) );
            }

            // If the marker clusters are enabled, include the js file and marker settings.
            if ( $wpsl_settings['marker_clusters'] ) {
                wp_enqueue_script( 'wpsl-cluster', WPSL_URL . 'js/markerclusterer'. $min .'.js', array( 'wpsl-js' ), WPSL_VERSION_NUM, true  ); //not minified version is in the /js folder

                $base_settings['clusterZoom']      = $wpsl_settings['cluster_zoom'];
                $base_settings['clusterSize']      = $wpsl_settings['cluster_size'];
                $base_settings['clusterImagePath'] = 'https://cdn.rawgit.com/googlemaps/js-marker-clusterer/gh-pages/images/m';
            }

            // Check if we need to include the infobox script and settings.
            if ( $wpsl_settings['infowindow_style'] == 'infobox' ) {
                wp_enqueue_script( 'wpsl-infobox', WPSL_URL . 'js/infobox'. $min .'.js', array( 'wpsl-gmap' ), WPSL_VERSION_NUM, true  ); // Not minified version is in the /js folder

                $base_settings['infoWindowStyle'] = $wpsl_settings['infowindow_style'];
                $base_settings = $this->get_infobox_settings( $base_settings );
            }

            // Include the map style.
            if ( !empty( $wpsl_settings['map_style'] ) ) {
                $base_settings['mapStyle'] = strip_tags( stripslashes( json_decode( $wpsl_settings['map_style'] ) ) );
            }

            wp_enqueue_script( 'wpsl-js', apply_filters( 'wpsl_gmap_js', WPSL_URL . 'js/wpsl-gmap'. $min .'.js' ), array( 'jquery' ), WPSL_VERSION_NUM, true );
            wp_enqueue_script( 'underscore' );

            // Check if we need to include all the settings and labels or just a part of them.
            if ( in_array( 'wpsl_store_locator', $this->load_scripts ) ) {
                $settings = wp_parse_args( $base_settings, $locator_map_settings );
                $template = 'wpsl_store_locator';
                $labels   = array(
                    'preloader'         => $wpsl->i18n->get_translation( 'preloader_label', __( 'Searching...', 'wpsl' ) ),
                    'noResults'         => $wpsl->i18n->get_translation( 'no_results_label', __( 'No results found', 'wpsl' ) ),
                    'moreInfo'          => $wpsl->i18n->get_translation( 'more_label', __( 'More info', 'wpsl' ) ),
                    'generalError'      => $wpsl->i18n->get_translation( 'error_label', __( 'Something went wrong, please try again!', 'wpsl' ) ),
                    'queryLimit'        => $wpsl->i18n->get_translation( 'limit_label', __( 'API usage limit reached', 'wpsl' ) ),
                    'directions'        => $wpsl->i18n->get_translation( 'directions_label', __( 'Directions', 'wpsl' ) ),
                    'noDirectionsFound' => $wpsl->i18n->get_translation( 'no_directions_label', __( 'No route could be found between the origin and destination', 'wpsl' ) ),
                    'startPoint'        => $wpsl->i18n->get_translation( 'start_label', __( 'Start location', 'wpsl' ) ),
                    'back'              => $wpsl->i18n->get_translation( 'back_label', __( 'Back', 'wpsl' ) ),
                    'streetView'        => $wpsl->i18n->get_translation( 'street_view_label', __( 'Street view', 'wpsl' ) ),
                    'zoomHere'          => $wpsl->i18n->get_translation( 'zoom_here_label', __( 'Zoom here', 'wpsl' ) )
                );

                wp_localize_script( 'wpsl-js', 'wpslLabels', $labels );
                wp_localize_script( 'wpsl-js', 'wpslGeolocationErrors', $this->geolocation_errors() );
            } else {
                $template = '';
                $settings = $base_settings;
            }

            // Check if we need to overwrite JS settings that are set through the [wpsl] shortcode.
            if ( $this->sl_shortcode_atts && isset( $this->sl_shortcode_atts['js'] ) ) {
                foreach ( $this->sl_shortcode_atts['js'] as $shortcode_key => $shortcode_val ) {
                    $settings[$shortcode_key] = $shortcode_val;
                }
            }

            wp_localize_script( 'wpsl-js', 'wpslSettings', apply_filters( 'wpsl_js_settings', $settings ) );

            wpsl_create_underscore_templates( $template );

            if ( !empty( $this->store_map_data ) ) {
                $i = 0;

                foreach ( $this->store_map_data as $map ) {
                    wp_localize_script( 'wpsl-js', 'wpslMap_' . $i, $map );

                    $i++;
                }
            }
        }

        /**
         * Get the infobox settings.
         *
         * @since 2.0.0
         * @see http://google-maps-utility-library-v3.googlecode.com/svn/trunk/infobox/docs/reference.html
         * @param  array $settings The plugin settings used on the front-end in js
         * @return array $settings The plugin settings including the infobox settings
         */
        public function get_infobox_settings( $settings ) {

            $infobox_settings = apply_filters( 'wpsl_infobox_settings', array(
                'infoBoxClass'                  => 'wpsl-infobox',
                'infoBoxCloseMargin'            => '2px', // The margin can be written in css style, so 2px 2px 4px 2px for top, right, bottom, left
                'infoBoxCloseUrl'               => '//www.google.com/intl/en_us/mapfiles/close.gif',
                'infoBoxClearance'              => '40,40',
                'infoBoxDisableAutoPan'         => 0,
                'infoBoxEnableEventPropagation' => 0,
                'infoBoxPixelOffset'            => '-52,-45',
                'infoBoxZindex'                 => 1500
            ) );

            foreach ( $infobox_settings as $infobox_key => $infobox_setting ) {
                $settings[$infobox_key] = $infobox_setting;
            }

            return $settings;
        }
    }
}wpml-config.xml000064400000002157151327220640007517 0ustar00<wpml-config>
    <admin-texts>
        <key name="wpsl_settings">
            <key name="editor_country"/>
            <key name="start_label"/>
            <key name="search_label"/> 
            <key name="search_btn_label"/>
            <key name="preloader_label"/>             
            <key name="radius_label"/>
            <key name="no_results_label"/>             
            <key name="results_label"/>
            <key name="category_label"/>
            <key name="category_default_label"/>
            <key name="more_label"/> 
            <key name="directions_label"/>
            <key name="no_directions_label"/> 
            <key name="back_label"/>
            <key name="street_view_label"/>
            <key name="zoom_here_label"/>             
            <key name="error_label"/>
            <key name="limit_label"/> 
            <key name="phone_label"/>
            <key name="fax_label"/> 
            <key name="email_label"/>
            <key name="url_label"/> 
            <key name="hours_label"/>                                                 
        </key>
    </admin-texts>
</wpml-config>font/fontello.svg000064400000002307151327220640010061 0ustar00<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Copyright (C) 2015 by original authors @ fontello.com</metadata>
<defs>
<font id="fontello" horiz-adv-x="1000" >
<font-face font-family="fontello" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
<missing-glyph horiz-adv-x="1000" />
<glyph glyph-name="direction" unicode="&#xe800;" d="m782 655l-357-714q-10-20-32-20-3 0-8 1-13 3-20 13t-8 22v322h-321q-13 0-22 7t-13 20 2 23 17 17l714 357q7 4 16 4 15 0 25-10 8-8 10-20t-3-22z" horiz-adv-x="785.7" />
<glyph glyph-name="arrows-cw" unicode="&#xe801;" d="m843 261q0-3 0-4-36-150-150-243t-267-93q-81 0-157 31t-136 88l-72-72q-11-11-25-11t-25 11-11 25v250q0 14 11 25t25 11h250q14 0 25-11t10-25-10-25l-77-77q40-37 90-57t105-20q74 0 139 37t104 99q6 10 29 66 5 13 17 13h107q8 0 13-6t5-12z m14 446v-250q0-14-10-25t-26-11h-250q-14 0-25 11t-10 25 10 25l77 77q-82 77-194 77-75 0-140-37t-104-99q-6-10-29-66-5-13-17-13h-111q-7 0-13 6t-5 12v4q36 150 151 243t268 93q81 0 158-31t137-88l72 72q11 11 25 11t26-11 10-25z" horiz-adv-x="857.1" />
</font>
</defs>
</svg>font/fontello.eot000064400000012014151327220640010045 0ustar00d�LP��GfontelloRegularVersion 1.0fontello�`OS/2=�H��Vcmap��DJcvt l
fpgm���Yxpgaspdglyf@��2head��_�6hhea
Q�$hmtx
R loca.�,maxp��4 name̝T�post��-$>prep�k��{q�z��z��1PfEd@��R�jZOD(������������-+	#"'.'!".67632��

��
�	
��6Be
��[$G�?(-+#"&'"&=46;23267676;2+"&6?&#"+"&75>32762K$�Q�<H�	M(d7J�'k
�	MRpK�'o$�Q�<H��>9H�M%(J>
8
��MMJ>
8
��>9HG��_<��Ѷ�Ѷ�����[R�jZ���[�Y.�Hsp�55=DLT_
+g�	j�			-	=	M	c	
Vs	&�Copyright (C) 2015 by original authors @ fontello.comfontelloRegularfontellofontelloVersion 1.0fontelloGenerated by svg2ttf from Fontello project.http://fontello.comCopyright (C) 2015 by original authors @ fontello.comfontelloRegularfontellofontelloVersion 1.0fontelloGenerated by svg2ttf from Fontello project.http://fontello.com
	direction	arrows-cw���, �UXEY  K�QK�SZX�4�(Y`f �UX�%a�cc#b!!�Y�C#D�C`B-�,� `f-�, d ��P�&Z�(
CEcER[X!#!�X �PPX!�@Y �8PX!�8YY �
CEcEad�(PX!�
CEcE �0PX!�0Y ��PX f ��a �
PX` � PX!�
` �6PX!�6``YYY�+YY#�PXeYY-�, E �%ad �CPX�#B�#B!!Y�`-�,#!#! d�bB �#B�
CEc�
C�`Ec�*! �C � ��+�0%�&QX`PaRYX#Y! �@SX�+!�@Y#�PXeY-�,�C+�C`B-�,�#B# �#Ba�bf�c�`�*-�,  E �Cc�b �PX�@`Yf�c`D�`-�,�CEB*!�C`B-�	,�C#D�C`B-�
,  E �+#�C�%` E�#a d � PX!��0PX� �@YY#�PXeY�%#aDD�`-�,  E �+#�C�%` E�#a d�$PX��@Y#�PXeY�%#aDD�`-�, �#B�
EX!#!Y*!-�
,�E�daD-�,�`  �CJ�PX �#BY�
CJ�RX �
#BY-�, �bf�c �c�#a�C` �` �#B#-�,KTX�dDY$�
e#x-�,KQXKSX�dDY!Y$�e#x-�,�CUX�C�aB�+Y�C�%B�%B�
%B�# �%PX�C`�%B�� �#a�*!#�a �#a�*!�C`�%B�%a�*!Y�CG�
CG`�b �PX�@`Yf�c �Cc�b �PX�@`Yf�c`�#D�C�>�C`B-�,�ETX�#B E�#B�
#�`B `�a�BB�`�+�r+"Y-�,�+-�,�+-�,�+-�,�+-�,�+-�,�+-�,�+-�,�+-�,�+-�,�	+-�,�
+�ETX�#B E�#B�
#�`B `�a�BB�`�+�r+"Y-�,�+-� ,�+-�!,�+-�",�+-�#,�+-�$,�+-�%,�+-�&,�+-�',�+-�(,�	+-�), <�`-�*, `�` C#�`C�%a�`�)*!-�+,�*+�**-�,,  G  �Cc�b �PX�@`Yf�c`#a8# �UX G  �Cc�b �PX�@`Yf�c`#a8!Y-�-,�ETX��,*�0"Y-�.,�
+�ETX��,*�0"Y-�/, 5�`-�0,�Ec�b �PX�@`Yf�c�+�Cc�b �PX�@`Yf�c�+��D>#8�/*-�1, < G �Cc�b �PX�@`Yf�c`�Ca8-�2,.<-�3, < G �Cc�b �PX�@`Yf�c`�Ca�Cc8-�4,�% . G�#B�%I��G#G#a Xb!Y�#B�3*-�5,��%�%G#G#a�	C+e�.#  <�8-�6,��%�% .G#G#a �#B�	C+ �`PX �@QX�  �&YBB# �C �#G#G#a#F`�C�b �PX�@`Yf�c` �+ ��a �C`d#�CadPX�Ca�C`Y�%�b �PX�@`Yf�ca#  �&#Fa8#�CF�%�CG#G#a` �C�b �PX�@`Yf�c`# �+#�C`�+�%a�%�b �PX�@`Yf�c�&a �%`d#�%`dPX!#!Y#  �&#Fa8Y-�7,�   �& .G#G#a#<8-�8,� �#B   F#G�+#a8-�9,��%�%G#G#a�TX. <#!�%�%G#G#a �%�%G#G#a�%�%I�%a�cc# Xb!Yc�b �PX�@`Yf�c`#.#  <�8#!Y-�:,� �C .G#G#a `� `f�b �PX�@`Yf�c#  <�8-�;,# .F�%FRX <Y.�++-�<,# .F�%FPX <Y.�++-�=,# .F�%FRX <Y# .F�%FPX <Y.�++-�>,�5+# .F�%FRX <Y.�++-�?,�6+�  <�#B�8# .F�%FRX <Y.�++�C.�++-�@,��%�& .G#G#a�	C+# < .#8�++-�A,�%B��%�% .G#G#a �#B�	C+ �`PX �@QX�  �&YBB# G�C�b �PX�@`Yf�c` �+ ��a �C`d#�CadPX�Ca�C`Y�%�b �PX�@`Yf�ca�%Fa8# <#8!  F#G�+#a8!Y�++-�B,�5+.�++-�C,�6+!#  <�#B#8�++�C.�++-�D,� G�#B�.�1*-�E,� G�#B�.�1*-�F,��2*-�G,�4*-�H,�E# . F�#a8�++-�I,�#B�H+-�J,�A+-�K,�A+-�L,�A+-�M,�A+-�N,�B+-�O,�B+-�P,�B+-�Q,�B+-�R,�>+-�S,�>+-�T,�>+-�U,�>+-�V,�@+-�W,�@+-�X,�@+-�Y,�@+-�Z,�C+-�[,�C+-�\,�C+-�],�C+-�^,�?+-�_,�?+-�`,�?+-�a,�?+-�b,�7+.�++-�c,�7+�;+-�d,�7+�<+-�e,��7+�=+-�f,�8+.�++-�g,�8+�;+-�h,�8+�<+-�i,�8+�=+-�j,�9+.�++-�k,�9+�;+-�l,�9+�<+-�m,�9+�=+-�n,�:+.�++-�o,�:+�;+-�p,�:+�<+-�q,�:+�=+-�r,�	EX!#!YB+�e�$Px�0-K��RX��Y��cp�B�*�B�*�B�*�B�	*�B�	*�D�$�QX�@�X�dD�&�QX��@�cTX�DYYYY�*������Dfont/fontello.woff000064400000005440151327220640010224 0ustar00wOFF dOS/2DDV=�H�cmap�:J��cvt �

fpgm��p���Ygaspdglyfl2@�head�56��_hhea� $
Qhmtx�
Rloca�.�maxp� ��name	w�̝post
�->��-prep
�e{�k�x�c`d.d�����TŴ����B3>`0ddb``b`ef�
�\S^0�`d�������f��x�c```f�`Fp��|
 ���^0��R�DK0B�#Èd��x��VisG��a�6>�6�Y�r�vV����J���B�]Kv�O���^�T�o����`'UT(J����L��^�В�^X���|)��6id�IH7lZ��C��)SL�.��h�Ծ�8$"��u�%����$�C�2Z�%�jRn�Iw�����Q��	%5��C�-�¨E2푒6-��_IZ��+�|�%��$�ƛa��g�V��vE�M�E�D3<�"��Zb�\1A@��R^�4�|��{��
q�v��%?�ο$�z��%�@vd{�+�"��
㦝lG���t}'�#����Q^�h�vE�'���W�X�	e��j�|ʗ<Ւ��Z/sb_��GL�k&Ȃ�N����c����],!�8���J�F)a��$m9���E��zGL��:-�-a�N��Kg�I�;1��������x4��L�N��єQJ:<����$�����ʣil3c$�P��si*�e'�4�<�ћ�a�kעE�<P�=zOon��;=��?k�gu*���0���J|�v�IѺ~z�&�C�*�-6Ô�C�~��cK��kl���+�}�DȤ���/�)L��UPݴֵ,��jV�Td�!M+_�iM9}c_�8���KL	���������%�4��f]��uj�]��l��4�}���~��<��:ak�t��:-��H�cl/hA��;r�\���u�K��B l�"a��@�~�@�.#�����~*i;�E��9��en*WSɥ��F�6�)r���xV�+��7���@�D��I�|T�㏮hy�Ĺ�U{s\�e�X�S�ښ��W�ydry#Г�D�&����G���k�~�EY�
����Q��P
\�33��e���!�~�7܃NYIY�`��׏e���'X�b���[ዌ�J�Ef){>�y�0*�a�
\���{��M�L�e���Ǚ ��c0o�� $L]���)����`�)��CTo��p{�}��kW��M�m�F��P�[���'���@U!MŸ��K#�j�a\��F2N����
˲�G�wJ�e �H�GG?��B�Թ��(n�;��Aib����⠔w��eVmS��Sך�ū�ͣ�{��'r�4�tO��U����Y����L.�����ͥ��e\��v0,0�ߡ�W�q�<W�
��H�����b�8G���1L����{��n���2]�]�������f�pC�
���Z��
|�:=�܎���
�`�b��Z��)��|��s�0h2��sl3g
`�9v��`�9�`�:���a2�A�O�<e�����k�0��9��e��9�0��tk(s�t�mP����8�T���ao�0��?j�=���C�� ��bS�tgH�����AL�� �>�/�r��_F�K��.6����@���x�-�OJ�@��7�L�O[;�)ӘB�Hu��)���dQ�nuՅ�����čw�C<���Ĕ��>�{��3i�O$}i`��О l�x�)�a�v��Փ)��0X}8[�m�/ͨ����6��m���b�m�F��� ���_GQ]��x�A�B�z�	��#H�A��L���lq��=�jEJL���%�T&�L�����xlu�`�L`#�.��mH]՞�&�ʞ�L+y���,f��
*����pl��E��w�If86�mD^1U6E��k6�x�c`d``b�ƃ��m�2p3��0\�v�;�^s��������\&�(��wx�c`d``�������o�h�
`�a�Y.�x�c`d```f�``b)�P$��@�ix�u��J�@F�ik�T�zWR��F
���M�n%�i��f�dZ�k�>�/�5�����̹g�ܹ�8�76W�φ�m��C<8.�?:�����W�U�7�5�"r\�>XAU�M��X�L�:.�D]9.��9���R�8���k��q�ꫯ�+�D��F�F:�vW�+�TI��/l�M.=��̆i��@϶<�E�m�G���I�km�S��Ʒ�z��:�Ndb�L.C�FO�z���f��~�Cc�UA���c-��#cf37Y	2�Hi|,�".fr�=>FmȌ��!�{�燤��SV1{����#)��/���f=��"�/�o�9�ܭCk�jݥ)�vj�c=7�	��T,�=������d�Mx�c`b�.쀙������3%�(5�$3?�3��(��X7���^t�x�c��p"(b##c_�Ɲ�X�620hAhz''2���e�
cG`������).�@�]
�,�! %�@���Gk��
,��\�"�font/fontello.ttf000064400000011544151327220640010062 0ustar00�`OS/2=�H��Vcmap��DJcvt l
fpgm���Yxpgaspdglyf@��2head��_�6hhea
Q�$hmtx
R loca.�,maxp��4 name̝T�post��-$>prep�k��{q�z��z��1PfEd@��R�jZOD(������������-+	#"'.'!".67632��

��
�	
��6Be
��[$G�?(-+#"&'"&=46;23267676;2+"&6?&#"+"&75>32762K$�Q�<H�	M(d7J�'k
�	MRpK�'o$�Q�<H��>9H�M%(J>
8
��MMJ>
8
��>9HG��_<��Ѷ�Ѷ�����[R�jZ���[�Y.�Hsp�55=DLT_
+g�	j�			-	=	M	c	
Vs	&�Copyright (C) 2015 by original authors @ fontello.comfontelloRegularfontellofontelloVersion 1.0fontelloGenerated by svg2ttf from Fontello project.http://fontello.comCopyright (C) 2015 by original authors @ fontello.comfontelloRegularfontellofontelloVersion 1.0fontelloGenerated by svg2ttf from Fontello project.http://fontello.com
	direction	arrows-cw���, �UXEY  K�QK�SZX�4�(Y`f �UX�%a�cc#b!!�Y�C#D�C`B-�,� `f-�, d ��P�&Z�(
CEcER[X!#!�X �PPX!�@Y �8PX!�8YY �
CEcEad�(PX!�
CEcE �0PX!�0Y ��PX f ��a �
PX` � PX!�
` �6PX!�6``YYY�+YY#�PXeYY-�, E �%ad �CPX�#B�#B!!Y�`-�,#!#! d�bB �#B�
CEc�
C�`Ec�*! �C � ��+�0%�&QX`PaRYX#Y! �@SX�+!�@Y#�PXeY-�,�C+�C`B-�,�#B# �#Ba�bf�c�`�*-�,  E �Cc�b �PX�@`Yf�c`D�`-�,�CEB*!�C`B-�	,�C#D�C`B-�
,  E �+#�C�%` E�#a d � PX!��0PX� �@YY#�PXeY�%#aDD�`-�,  E �+#�C�%` E�#a d�$PX��@Y#�PXeY�%#aDD�`-�, �#B�
EX!#!Y*!-�
,�E�daD-�,�`  �CJ�PX �#BY�
CJ�RX �
#BY-�, �bf�c �c�#a�C` �` �#B#-�,KTX�dDY$�
e#x-�,KQXKSX�dDY!Y$�e#x-�,�CUX�C�aB�+Y�C�%B�%B�
%B�# �%PX�C`�%B�� �#a�*!#�a �#a�*!�C`�%B�%a�*!Y�CG�
CG`�b �PX�@`Yf�c �Cc�b �PX�@`Yf�c`�#D�C�>�C`B-�,�ETX�#B E�#B�
#�`B `�a�BB�`�+�r+"Y-�,�+-�,�+-�,�+-�,�+-�,�+-�,�+-�,�+-�,�+-�,�+-�,�	+-�,�
+�ETX�#B E�#B�
#�`B `�a�BB�`�+�r+"Y-�,�+-� ,�+-�!,�+-�",�+-�#,�+-�$,�+-�%,�+-�&,�+-�',�+-�(,�	+-�), <�`-�*, `�` C#�`C�%a�`�)*!-�+,�*+�**-�,,  G  �Cc�b �PX�@`Yf�c`#a8# �UX G  �Cc�b �PX�@`Yf�c`#a8!Y-�-,�ETX��,*�0"Y-�.,�
+�ETX��,*�0"Y-�/, 5�`-�0,�Ec�b �PX�@`Yf�c�+�Cc�b �PX�@`Yf�c�+��D>#8�/*-�1, < G �Cc�b �PX�@`Yf�c`�Ca8-�2,.<-�3, < G �Cc�b �PX�@`Yf�c`�Ca�Cc8-�4,�% . G�#B�%I��G#G#a Xb!Y�#B�3*-�5,��%�%G#G#a�	C+e�.#  <�8-�6,��%�% .G#G#a �#B�	C+ �`PX �@QX�  �&YBB# �C �#G#G#a#F`�C�b �PX�@`Yf�c` �+ ��a �C`d#�CadPX�Ca�C`Y�%�b �PX�@`Yf�ca#  �&#Fa8#�CF�%�CG#G#a` �C�b �PX�@`Yf�c`# �+#�C`�+�%a�%�b �PX�@`Yf�c�&a �%`d#�%`dPX!#!Y#  �&#Fa8Y-�7,�   �& .G#G#a#<8-�8,� �#B   F#G�+#a8-�9,��%�%G#G#a�TX. <#!�%�%G#G#a �%�%G#G#a�%�%I�%a�cc# Xb!Yc�b �PX�@`Yf�c`#.#  <�8#!Y-�:,� �C .G#G#a `� `f�b �PX�@`Yf�c#  <�8-�;,# .F�%FRX <Y.�++-�<,# .F�%FPX <Y.�++-�=,# .F�%FRX <Y# .F�%FPX <Y.�++-�>,�5+# .F�%FRX <Y.�++-�?,�6+�  <�#B�8# .F�%FRX <Y.�++�C.�++-�@,��%�& .G#G#a�	C+# < .#8�++-�A,�%B��%�% .G#G#a �#B�	C+ �`PX �@QX�  �&YBB# G�C�b �PX�@`Yf�c` �+ ��a �C`d#�CadPX�Ca�C`Y�%�b �PX�@`Yf�ca�%Fa8# <#8!  F#G�+#a8!Y�++-�B,�5+.�++-�C,�6+!#  <�#B#8�++�C.�++-�D,� G�#B�.�1*-�E,� G�#B�.�1*-�F,��2*-�G,�4*-�H,�E# . F�#a8�++-�I,�#B�H+-�J,�A+-�K,�A+-�L,�A+-�M,�A+-�N,�B+-�O,�B+-�P,�B+-�Q,�B+-�R,�>+-�S,�>+-�T,�>+-�U,�>+-�V,�@+-�W,�@+-�X,�@+-�Y,�@+-�Z,�C+-�[,�C+-�\,�C+-�],�C+-�^,�?+-�_,�?+-�`,�?+-�a,�?+-�b,�7+.�++-�c,�7+�;+-�d,�7+�<+-�e,��7+�=+-�f,�8+.�++-�g,�8+�;+-�h,�8+�<+-�i,�8+�=+-�j,�9+.�++-�k,�9+�;+-�l,�9+�<+-�m,�9+�=+-�n,�:+.�++-�o,�:+�;+-�p,�:+�<+-�q,�:+�=+-�r,�	EX!#!YB+�e�$Px�0-K��RX��Y��cp�B�*�B�*�B�*�B�	*�B�	*�D�$�QX�@�X�dD�&�QX��@�cTX�DYYYY�*������Djs/markerclusterer.min.js000064400000034205151327220640011520 0ustar00function MarkerClusterer(t,e,r){this.extend(MarkerClusterer,google.maps.OverlayView),this.map_=t,this.markers_=[],this.clusters_=[],this.sizes=[53,56,66,78,90],this.styles_=[],this.ready_=!1;var s=r||{};this.gridSize_=s.gridSize||60,this.minClusterSize_=s.minimumClusterSize||2,this.maxZoom_=s.maxZoom||null,this.styles_=s.styles||[],this.imagePath_=s.imagePath||this.MARKER_CLUSTER_IMAGE_PATH_,this.imageExtension_=s.imageExtension||this.MARKER_CLUSTER_IMAGE_EXTENSION_,this.zoomOnClick_=!0,void 0!=s.zoomOnClick&&(this.zoomOnClick_=s.zoomOnClick),this.averageCenter_=!1,void 0!=s.averageCenter&&(this.averageCenter_=s.averageCenter),this.setupStyles_(),this.setMap(t),this.prevZoom_=this.map_.getZoom();var o=this;google.maps.event.addListener(this.map_,"zoom_changed",function(){var t=o.map_.getZoom(),e=o.map_.minZoom||0,r=Math.min(o.map_.maxZoom||100,o.map_.mapTypes[o.map_.getMapTypeId()].maxZoom);t=Math.min(Math.max(t,e),r),o.prevZoom_!=t&&(o.prevZoom_=t,o.resetViewport())}),google.maps.event.addListener(this.map_,"idle",function(){o.redraw()}),e&&(e.length||Object.keys(e).length)&&this.addMarkers(e,!1)}function Cluster(t){this.markerClusterer_=t,this.map_=t.getMap(),this.gridSize_=t.getGridSize(),this.minClusterSize_=t.getMinClusterSize(),this.averageCenter_=t.isAverageCenter(),this.center_=null,this.markers_=[],this.bounds_=null,this.clusterIcon_=new ClusterIcon(this,t.getStyles(),t.getGridSize())}function ClusterIcon(t,e,r){t.getMarkerClusterer().extend(ClusterIcon,google.maps.OverlayView),this.styles_=e,this.padding_=r||0,this.cluster_=t,this.center_=null,this.map_=t.getMap(),this.div_=null,this.sums_=null,this.visible_=!1,this.setMap(this.map_)}MarkerClusterer.prototype.MARKER_CLUSTER_IMAGE_PATH_=wpslSettings.clusterImagePath,MarkerClusterer.prototype.MARKER_CLUSTER_IMAGE_EXTENSION_="png",MarkerClusterer.prototype.extend=function(t,e){return function(t){for(var e in t.prototype)this.prototype[e]=t.prototype[e];return this}.apply(t,[e])},MarkerClusterer.prototype.onAdd=function(){this.setReady_(!0)},MarkerClusterer.prototype.draw=function(){},MarkerClusterer.prototype.setupStyles_=function(){if(!this.styles_.length)for(var t,e=0;t=this.sizes[e];e++)this.styles_.push({url:this.imagePath_+(e+1)+"."+this.imageExtension_,height:t,width:t})},MarkerClusterer.prototype.fitMapToMarkers=function(){for(var t,e=this.getMarkers(),r=new google.maps.LatLngBounds,s=0;t=e[s];s++)r.extend(t.getPosition());this.map_.fitBounds(r)},MarkerClusterer.prototype.setStyles=function(t){this.styles_=t},MarkerClusterer.prototype.getStyles=function(){return this.styles_},MarkerClusterer.prototype.isZoomOnClick=function(){return this.zoomOnClick_},MarkerClusterer.prototype.isAverageCenter=function(){return this.averageCenter_},MarkerClusterer.prototype.getMarkers=function(){return this.markers_},MarkerClusterer.prototype.getTotalMarkers=function(){return this.markers_.length},MarkerClusterer.prototype.setMaxZoom=function(t){this.maxZoom_=t},MarkerClusterer.prototype.getMaxZoom=function(){return this.maxZoom_},MarkerClusterer.prototype.calculator_=function(t,e){for(var r=0,s=t.length,o=s;0!==o;)o=parseInt(o/10,10),r++;return r=Math.min(r,e),{text:s,index:r}},MarkerClusterer.prototype.setCalculator=function(t){this.calculator_=t},MarkerClusterer.prototype.getCalculator=function(){return this.calculator_},MarkerClusterer.prototype.addMarkers=function(t,e){if(t.length)for(var r,s=0;r=t[s];s++)this.pushMarkerTo_(r);else if(Object.keys(t).length)for(var r in t)this.pushMarkerTo_(t[r]);e||this.redraw()},MarkerClusterer.prototype.pushMarkerTo_=function(t){if(t.isAdded=!1,t.draggable){var e=this;google.maps.event.addListener(t,"dragend",function(){t.isAdded=!1,e.repaint()})}this.markers_.push(t)},MarkerClusterer.prototype.addMarker=function(t,e){this.pushMarkerTo_(t),e||this.redraw()},MarkerClusterer.prototype.removeMarker_=function(t){var e=-1;if(this.markers_.indexOf)e=this.markers_.indexOf(t);else for(var r,s=0;r=this.markers_[s];s++)if(r==t){e=s;break}return-1==e?!1:(t.setMap(null),this.markers_.splice(e,1),!0)},MarkerClusterer.prototype.removeMarker=function(t,e){var r=this.removeMarker_(t);return!e&&r?(this.resetViewport(),this.redraw(),!0):!1},MarkerClusterer.prototype.removeMarkers=function(t,e){for(var r,s=!1,o=0;r=t[o];o++){var i=this.removeMarker_(r);s=s||i}return!e&&s?(this.resetViewport(),this.redraw(),!0):void 0},MarkerClusterer.prototype.setReady_=function(t){this.ready_||(this.ready_=t,this.createClusters_())},MarkerClusterer.prototype.getTotalClusters=function(){return this.clusters_.length},MarkerClusterer.prototype.getMap=function(){return this.map_},MarkerClusterer.prototype.setMap=function(t){this.map_=t},MarkerClusterer.prototype.getGridSize=function(){return this.gridSize_},MarkerClusterer.prototype.setGridSize=function(t){this.gridSize_=t},MarkerClusterer.prototype.getMinClusterSize=function(){return this.minClusterSize_},MarkerClusterer.prototype.setMinClusterSize=function(t){this.minClusterSize_=t},MarkerClusterer.prototype.getExtendedBounds=function(t){var e=this.getProjection(),r=new google.maps.LatLng(t.getNorthEast().lat(),t.getNorthEast().lng()),s=new google.maps.LatLng(t.getSouthWest().lat(),t.getSouthWest().lng()),o=e.fromLatLngToDivPixel(r);o.x+=this.gridSize_,o.y-=this.gridSize_;var i=e.fromLatLngToDivPixel(s);i.x-=this.gridSize_,i.y+=this.gridSize_;var a=e.fromDivPixelToLatLng(o),n=e.fromDivPixelToLatLng(i);return t.extend(a),t.extend(n),t},MarkerClusterer.prototype.isMarkerInBounds_=function(t,e){return e.contains(t.getPosition())},MarkerClusterer.prototype.clearMarkers=function(){this.resetViewport(!0),this.markers_=[]},MarkerClusterer.prototype.resetViewport=function(t){for(var e,r=0;e=this.clusters_[r];r++)e.remove();for(var s,r=0;s=this.markers_[r];r++)s.isAdded=!1,t&&s.setMap(null);this.clusters_=[]},MarkerClusterer.prototype.repaint=function(){var t=this.clusters_.slice();this.clusters_.length=0,this.resetViewport(),this.redraw(),window.setTimeout(function(){for(var e,r=0;e=t[r];r++)e.remove()},0)},MarkerClusterer.prototype.redraw=function(){this.createClusters_()},MarkerClusterer.prototype.distanceBetweenPoints_=function(t,e){if(!t||!e)return 0;var r=6371,s=(e.lat()-t.lat())*Math.PI/180,o=(e.lng()-t.lng())*Math.PI/180,i=Math.sin(s/2)*Math.sin(s/2)+Math.cos(t.lat()*Math.PI/180)*Math.cos(e.lat()*Math.PI/180)*Math.sin(o/2)*Math.sin(o/2),a=2*Math.atan2(Math.sqrt(i),Math.sqrt(1-i)),n=r*a;return n},MarkerClusterer.prototype.addToClosestCluster_=function(t){for(var e,r=4e4,s=null,o=(t.getPosition(),0);e=this.clusters_[o];o++){var i=e.getCenter();if(i){var a=this.distanceBetweenPoints_(i,t.getPosition());r>a&&(r=a,s=e)}}if(s&&s.isMarkerInClusterBounds(t))s.addMarker(t);else{var e=new Cluster(this);e.addMarker(t),this.clusters_.push(e)}},MarkerClusterer.prototype.createClusters_=function(){if(this.ready_)for(var t,e=new google.maps.LatLngBounds(this.map_.getBounds().getSouthWest(),this.map_.getBounds().getNorthEast()),r=this.getExtendedBounds(e),s=0;t=this.markers_[s];s++)!t.isAdded&&this.isMarkerInBounds_(t,r)&&this.addToClosestCluster_(t)},Cluster.prototype.isMarkerAlreadyAdded=function(t){if(this.markers_.indexOf)return-1!=this.markers_.indexOf(t);for(var e,r=0;e=this.markers_[r];r++)if(e==t)return!0;return!1},Cluster.prototype.addMarker=function(t){if(this.isMarkerAlreadyAdded(t))return!1;if(this.center_){if(this.averageCenter_){var e=this.markers_.length+1,r=(this.center_.lat()*(e-1)+t.getPosition().lat())/e,s=(this.center_.lng()*(e-1)+t.getPosition().lng())/e;this.center_=new google.maps.LatLng(r,s),this.calculateBounds_()}}else this.center_=t.getPosition(),this.calculateBounds_();t.isAdded=!0,this.markers_.push(t);var o=this.markers_.length;if(o<this.minClusterSize_&&t.getMap()!=this.map_&&t.setMap(this.map_),o==this.minClusterSize_)for(var i=0;o>i;i++)this.markers_[i].setMap(null);return o>=this.minClusterSize_&&t.setMap(null),this.updateIcon(),!0},Cluster.prototype.getMarkerClusterer=function(){return this.markerClusterer_},Cluster.prototype.getBounds=function(){for(var t,e=new google.maps.LatLngBounds(this.center_,this.center_),r=this.getMarkers(),s=0;t=r[s];s++)e.extend(t.getPosition());return e},Cluster.prototype.remove=function(){this.clusterIcon_.remove(),this.markers_.length=0,delete this.markers_},Cluster.prototype.getSize=function(){return this.markers_.length},Cluster.prototype.getMarkers=function(){return this.markers_},Cluster.prototype.getCenter=function(){return this.center_},Cluster.prototype.calculateBounds_=function(){var t=new google.maps.LatLngBounds(this.center_,this.center_);this.bounds_=this.markerClusterer_.getExtendedBounds(t)},Cluster.prototype.isMarkerInClusterBounds=function(t){return this.bounds_.contains(t.getPosition())},Cluster.prototype.getMap=function(){return this.map_},Cluster.prototype.updateIcon=function(){var t=this.map_.getZoom(),e=this.markerClusterer_.getMaxZoom();if(e&&t>e)for(var r,s=0;r=this.markers_[s];s++)r.setMap(this.map_);else{if(this.markers_.length<this.minClusterSize_)return void this.clusterIcon_.hide();var o=this.markerClusterer_.getStyles().length,i=this.markerClusterer_.getCalculator()(this.markers_,o);this.clusterIcon_.setCenter(this.center_),this.clusterIcon_.setSums(i),this.clusterIcon_.show()}},ClusterIcon.prototype.triggerClusterClick=function(){var t=this.cluster_.getMarkerClusterer();google.maps.event.trigger(t,"clusterclick",this.cluster_),t.isZoomOnClick()&&this.map_.fitBounds(this.cluster_.getBounds())},ClusterIcon.prototype.onAdd=function(){if(this.div_=document.createElement("DIV"),this.visible_){var t=this.getPosFromLatLng_(this.center_);this.div_.style.cssText=this.createCss(t),this.div_.innerHTML=this.sums_.text}var e=this.getPanes();e.overlayMouseTarget.appendChild(this.div_);var r=this;google.maps.event.addDomListener(this.div_,"click",function(){r.triggerClusterClick()})},ClusterIcon.prototype.getPosFromLatLng_=function(t){var e=this.getProjection().fromLatLngToDivPixel(t);return e.x-=parseInt(this.width_/2,10),e.y-=parseInt(this.height_/2,10),e},ClusterIcon.prototype.draw=function(){if(this.visible_){var t=this.getPosFromLatLng_(this.center_);this.div_.style.top=t.y+"px",this.div_.style.left=t.x+"px"}},ClusterIcon.prototype.hide=function(){this.div_&&(this.div_.style.display="none"),this.visible_=!1},ClusterIcon.prototype.show=function(){if(this.div_){var t=this.getPosFromLatLng_(this.center_);this.div_.style.cssText=this.createCss(t),this.div_.style.display=""}this.visible_=!0},ClusterIcon.prototype.remove=function(){this.setMap(null)},ClusterIcon.prototype.onRemove=function(){this.div_&&this.div_.parentNode&&(this.hide(),this.div_.parentNode.removeChild(this.div_),this.div_=null)},ClusterIcon.prototype.setSums=function(t){this.sums_=t,this.text_=t.text,this.index_=t.index,this.div_&&(this.div_.innerHTML=t.text),this.useStyle()},ClusterIcon.prototype.useStyle=function(){var t=Math.max(0,this.sums_.index-1);t=Math.min(this.styles_.length-1,t);var e=this.styles_[t];this.url_=e.url,this.height_=e.height,this.width_=e.width,this.textColor_=e.textColor,this.anchor_=e.anchor,this.textSize_=e.textSize,this.backgroundPosition_=e.backgroundPosition},ClusterIcon.prototype.setCenter=function(t){this.center_=t},ClusterIcon.prototype.createCss=function(t){var e=[];e.push("background-image:url("+this.url_+");");var r=this.backgroundPosition_?this.backgroundPosition_:"0 0";e.push("background-position:"+r+";"),"object"==typeof this.anchor_?("number"==typeof this.anchor_[0]&&this.anchor_[0]>0&&this.anchor_[0]<this.height_?e.push("height:"+(this.height_-this.anchor_[0])+"px; padding-top:"+this.anchor_[0]+"px;"):e.push("height:"+this.height_+"px; line-height:"+this.height_+"px;"),"number"==typeof this.anchor_[1]&&this.anchor_[1]>0&&this.anchor_[1]<this.width_?e.push("width:"+(this.width_-this.anchor_[1])+"px; padding-left:"+this.anchor_[1]+"px;"):e.push("width:"+this.width_+"px; text-align:center;")):e.push("height:"+this.height_+"px; line-height:"+this.height_+"px; width:"+this.width_+"px; text-align:center;");var s=this.textColor_?this.textColor_:"black",o=this.textSize_?this.textSize_:11;return e.push("cursor:pointer; top:"+t.y+"px; left:"+t.x+"px; color:"+s+"; position:absolute; font-size:"+o+"px; font-family:Arial,sans-serif; font-weight:bold"),e.join("")},window.MarkerClusterer=MarkerClusterer,MarkerClusterer.prototype.addMarker=MarkerClusterer.prototype.addMarker,MarkerClusterer.prototype.addMarkers=MarkerClusterer.prototype.addMarkers,MarkerClusterer.prototype.clearMarkers=MarkerClusterer.prototype.clearMarkers,MarkerClusterer.prototype.fitMapToMarkers=MarkerClusterer.prototype.fitMapToMarkers,MarkerClusterer.prototype.getCalculator=MarkerClusterer.prototype.getCalculator,MarkerClusterer.prototype.getGridSize=MarkerClusterer.prototype.getGridSize,MarkerClusterer.prototype.getExtendedBounds=MarkerClusterer.prototype.getExtendedBounds,MarkerClusterer.prototype.getMap=MarkerClusterer.prototype.getMap,MarkerClusterer.prototype.getMarkers=MarkerClusterer.prototype.getMarkers,MarkerClusterer.prototype.getMaxZoom=MarkerClusterer.prototype.getMaxZoom,MarkerClusterer.prototype.getStyles=MarkerClusterer.prototype.getStyles,MarkerClusterer.prototype.getTotalClusters=MarkerClusterer.prototype.getTotalClusters,MarkerClusterer.prototype.getTotalMarkers=MarkerClusterer.prototype.getTotalMarkers,MarkerClusterer.prototype.redraw=MarkerClusterer.prototype.redraw,MarkerClusterer.prototype.removeMarker=MarkerClusterer.prototype.removeMarker,MarkerClusterer.prototype.removeMarkers=MarkerClusterer.prototype.removeMarkers,MarkerClusterer.prototype.resetViewport=MarkerClusterer.prototype.resetViewport,MarkerClusterer.prototype.repaint=MarkerClusterer.prototype.repaint,MarkerClusterer.prototype.setCalculator=MarkerClusterer.prototype.setCalculator,MarkerClusterer.prototype.setGridSize=MarkerClusterer.prototype.setGridSize,MarkerClusterer.prototype.setMaxZoom=MarkerClusterer.prototype.setMaxZoom,MarkerClusterer.prototype.onAdd=MarkerClusterer.prototype.onAdd,MarkerClusterer.prototype.draw=MarkerClusterer.prototype.draw,Cluster.prototype.getCenter=Cluster.prototype.getCenter,Cluster.prototype.getSize=Cluster.prototype.getSize,Cluster.prototype.getMarkers=Cluster.prototype.getMarkers,ClusterIcon.prototype.onAdd=ClusterIcon.prototype.onAdd,ClusterIcon.prototype.draw=ClusterIcon.prototype.draw,ClusterIcon.prototype.onRemove=ClusterIcon.prototype.onRemove,Object.keys=Object.keys||function(t){var e=[];for(var r in t)t.hasOwnProperty(r)&&e.push(r);return e};js/infobox.min.js000064400000013542151327220640007753 0ustar00eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('7 8(a){a=a||{};r.s.1R.2k(2,3d);2.Q=a.1v||"";2.1H=a.1B||J;2.S=a.1G||0;2.H=a.1z||1h r.s.1Y(0,0);2.B=a.U||1h r.s.2E(0,0);2.15=a.13||t;2.1p=a.1t||"2h";2.1m=a.F||{};2.1E=a.1C||"3g";2.P=a.1j||"3b://38.r.33/2Y/2T/2N/1r.2K";3(a.1j===""){2.P=""}2.1f=a.1x||1h r.s.1Y(1,1);3(q a.A==="p"){3(q a.18==="p"){a.A=L}v{a.A=!a.18}}2.w=!a.A;2.17=a.1n||J;2.1I=a.2g||"2e";2.16=a.1l||J;2.4=t;2.z=t;2.14=t;2.V=t;2.E=t;2.R=t}8.9=1h r.s.1R();8.9.25=7(){5 i;5 f;5 a;5 d=2;5 c=7(e){e.20=L;3(e.1i){e.1i()}};5 b=7(e){e.30=J;3(e.1Z){e.1Z()}3(!d.16){c(e)}};3(!2.4){2.4=1e.2S("2Q");2.1d();3(q 2.Q.1u==="p"){2.4.O=2.G()+2.Q}v{2.4.O=2.G();2.4.1a(2.Q)}2.2J()[2.1I].1a(2.4);2.1w();3(2.4.6.D){2.R=L}v{3(2.S!==0&&2.4.Z>2.S){2.4.6.D=2.S;2.4.6.2D="2A";2.R=L}v{a=2.1P();2.4.6.D=(2.4.Z-a.W-a.11)+"12";2.R=J}}2.1F(2.1H);3(!2.16){2.E=[];f=["2t","1O","2q","2p","1M","2o","2n","2m","2l"];1o(i=0;i<f.1L;i++){2.E.1K(r.s.u.19(2.4,f[i],c))}2.E.1K(r.s.u.19(2.4,"1O",7(e){2.6.1J="2j"}))}2.V=r.s.u.19(2.4,"2i",b);r.s.u.T(2,"2f")}};8.9.G=7(){5 a="";3(2.P!==""){a="<2d";a+=" 2c=\'"+2.P+"\'";a+=" 2b=11";a+=" 6=\'";a+=" U: 2a;";a+=" 1J: 29;";a+=" 28: "+2.1E+";";a+="\'>"}K a};8.9.1w=7(){5 a;3(2.P!==""){a=2.4.3n;2.z=r.s.u.19(a,"1M",2.27())}v{2.z=t}};8.9.27=7(){5 a=2;K 7(e){e.20=L;3(e.1i){e.1i()}r.s.u.T(a,"3m");a.1r()}};8.9.1F=7(d){5 m;5 n;5 e=0,I=0;3(!d){m=2.1D();3(m 3l r.s.3k){3(!m.26().3h(2.B)){m.3f(2.B)}n=m.26();5 a=m.3e();5 h=a.Z;5 f=a.24;5 k=2.H.D;5 l=2.H.1k;5 g=2.4.Z;5 b=2.4.24;5 i=2.1f.D;5 j=2.1f.1k;5 o=2.23().3c(2.B);3(o.x<(-k+i)){e=o.x+k-i}v 3((o.x+g+k+i)>h){e=o.x+g+k+i-h}3(2.17){3(o.y<(-l+j+b)){I=o.y+l-j-b}v 3((o.y+l+j)>f){I=o.y+l+j-f}}v{3(o.y<(-l+j)){I=o.y+l-j}v 3((o.y+b+l+j)>f){I=o.y+b+l+j-f}}3(!(e===0&&I===0)){5 c=m.3a();m.39(e,I)}}}};8.9.1d=7(){5 i,F;3(2.4){2.4.37=2.1p;2.4.6.36="";F=2.1m;1o(i 35 F){3(F.34(i)){2.4.6[i]=F[i]}}2.4.6.32="31(0)";3(q 2.4.6.X!=="p"&&2.4.6.X!==""){2.4.6.2Z="\\"2X:2W.2V.2U(2R="+(2.4.6.X*1X)+")\\"";2.4.6.2P="2O(X="+(2.4.6.X*1X)+")"}2.4.6.U="2M";2.4.6.M=\'1c\';3(2.15!==t){2.4.6.13=2.15}}};8.9.1P=7(){5 c;5 a={1b:0,1g:0,W:0,11:0};5 b=2.4;3(1e.1s&&1e.1s.1W){c=b.2L.1s.1W(b,"");3(c){a.1b=C(c.1V,10)||0;a.1g=C(c.1U,10)||0;a.W=C(c.1T,10)||0;a.11=C(c.1S,10)||0}}v 3(1e.2I.N){3(b.N){a.1b=C(b.N.1V,10)||0;a.1g=C(b.N.1U,10)||0;a.W=C(b.N.1T,10)||0;a.11=C(b.N.1S,10)||0}}K a};8.9.2H=7(){3(2.4){2.4.2G.2F(2.4);2.4=t}};8.9.1y=7(){2.25();5 a=2.23().2C(2.B);2.4.6.W=(a.x+2.H.D)+"12";3(2.17){2.4.6.1g=-(a.y+2.H.1k)+"12"}v{2.4.6.1b=(a.y+2.H.1k)+"12"}3(2.w){2.4.6.M="1c"}v{2.4.6.M="A"}};8.9.2B=7(a){3(q a.1t!=="p"){2.1p=a.1t;2.1d()}3(q a.F!=="p"){2.1m=a.F;2.1d()}3(q a.1v!=="p"){2.1Q(a.1v)}3(q a.1B!=="p"){2.1H=a.1B}3(q a.1G!=="p"){2.S=a.1G}3(q a.1z!=="p"){2.H=a.1z}3(q a.1n!=="p"){2.17=a.1n}3(q a.U!=="p"){2.1q(a.U)}3(q a.13!=="p"){2.22(a.13)}3(q a.1C!=="p"){2.1E=a.1C}3(q a.1j!=="p"){2.P=a.1j}3(q a.1x!=="p"){2.1f=a.1x}3(q a.18!=="p"){2.w=a.18}3(q a.A!=="p"){2.w=!a.A}3(q a.1l!=="p"){2.16=a.1l}3(2.4){2.1y()}};8.9.1Q=7(a){2.Q=a;3(2.4){3(2.z){r.s.u.Y(2.z);2.z=t}3(!2.R){2.4.6.D=""}3(q a.1u==="p"){2.4.O=2.G()+a}v{2.4.O=2.G();2.4.1a(a)}3(!2.R){2.4.6.D=2.4.Z+"12";3(q a.1u==="p"){2.4.O=2.G()+a}v{2.4.O=2.G();2.4.1a(a)}}2.1w()}r.s.u.T(2,"2z")};8.9.1q=7(a){2.B=a;3(2.4){2.1y()}r.s.u.T(2,"21")};8.9.22=7(a){2.15=a;3(2.4){2.4.6.13=a}r.s.u.T(2,"2y")};8.9.2x=7(a){2.w=!a;3(2.4){2.4.6.M=(2.w?"1c":"A")}};8.9.2w=7(){K 2.Q};8.9.1A=7(){K 2.B};8.9.2v=7(){K 2.15};8.9.2u=7(){5 a;3((q 2.1D()==="p")||(2.1D()===t)){a=J}v{a=!2.w}K a};8.9.3i=7(){2.w=J;3(2.4){2.4.6.M="A"}};8.9.3j=7(){2.w=L;3(2.4){2.4.6.M="1c"}};8.9.2s=7(c,b){5 a=2;3(b){2.B=b.1A();2.14=r.s.u.2r(b,"21",7(){a.1q(2.1A())})}2.1N(c);3(2.4){2.1F()}};8.9.1r=7(){5 i;3(2.z){r.s.u.Y(2.z);2.z=t}3(2.E){1o(i=0;i<2.E.1L;i++){r.s.u.Y(2.E[i])}2.E=t}3(2.14){r.s.u.Y(2.14);2.14=t}3(2.V){r.s.u.Y(2.V);2.V=t}2.1N(t)};',62,210,'||this|if|div_|var|style|function|InfoBox|prototype||||||||||||||||undefined|typeof|google|maps|null|event|else|isHidden_|||closeListener_|visible|position_|parseInt|width|eventListeners_|boxStyle|getCloseBoxImg_|pixelOffset_|yOffset|false|return|true|visibility|currentStyle|innerHTML|closeBoxURL_|content_|fixedWidthSet_|maxWidth_|trigger|position|contextListener_|left|opacity|removeListener|offsetWidth||right|px|zIndex|moveListener_|zIndex_|enableEventPropagation_|alignBottom_|isHidden|addDomListener|appendChild|top|hidden|setBoxStyle_|document|infoBoxClearance_|bottom|new|stopPropagation|closeBoxURL|height|enableEventPropagation|boxStyle_|alignBottom|for|boxClass_|setPosition|close|defaultView|boxClass|nodeType|content|addClickHandler_|infoBoxClearance|draw|pixelOffset|getPosition|disableAutoPan|closeBoxMargin|getMap|closeBoxMargin_|panBox_|maxWidth|disableAutoPan_|pane_|cursor|push|length|click|setMap|mouseover|getBoxWidths_|setContent|OverlayView|borderRightWidth|borderLeftWidth|borderBottomWidth|borderTopWidth|getComputedStyle|100|Size|preventDefault|cancelBubble|position_changed|setZIndex|getProjection|offsetHeight|createInfoBoxDiv_|getBounds|getCloseClickHandler_|margin|pointer|relative|align|src|img|floatPane|domready|pane|infoBox|contextmenu|default|apply|touchmove|touchend|touchstart|dblclick|mouseup|mouseout|addListener|open|mousedown|getVisible|getZIndex|getContent|setVisible|zindex_changed|content_changed|auto|setOptions|fromLatLngToDivPixel|overflow|LatLng|removeChild|parentNode|onRemove|documentElement|getPanes|gif|ownerDocument|absolute|mapfiles|alpha|filter|div|Opacity|createElement|en_us|Alpha|Microsoft|DXImageTransform|progid|intl|MsFilter|returnValue|translateZ|WebkitTransform|com|hasOwnProperty|in|cssText|className|www|panBy|getCenter|http|fromLatLngToContainerPixel|arguments|getDiv|setCenter|2px|contains|show|hide|Map|instanceof|closeclick|firstChild'.split('|'),0,{}))js/wpsl-gmap.min.js000064400000064441151327220640010222 0ustar00var wpsl=wpsl||{};function initWpslMap(){var e;e=setInterval(function(){"object"==typeof google&&"object"==typeof google.maps&&(clearInterval(e),jQuery(".wpsl-gmap-canvas").each(function(e){var t=jQuery(this).attr("id");wpsl.gmaps.init(t,e)}))},500)}wpsl.gmaps={},jQuery(document).ready(function(e){var t,s,o,n,i,l,a,r,p,c,d,w,g,u,m,f=[],h=[],v=[],S={},b={},C={},y=!1,L=!1,k="undefined"!=typeof wpslSettings?wpslSettings.autoLoad:"",x={},I={enabled:void 0!==wpslSettings.collectStatistics,addressComponents:""};function M(){var e,t,s={};return void 0!==wpslSettings.infoWindowStyle&&"infobox"==wpslSettings.infoWindowStyle?(e=wpslSettings.infoBoxClearance.split(","),t=wpslSettings.infoBoxPixelOffset.split(","),s={alignBottom:!0,boxClass:wpslSettings.infoBoxClass,closeBoxMargin:wpslSettings.infoBoxCloseMargin,closeBoxURL:wpslSettings.infoBoxCloseUrl,content:"",disableAutoPan:!!Number(wpslSettings.infoBoxDisableAutoPan),enableEventPropagation:!!Number(wpslSettings.infoBoxEnableEventPropagation),infoBoxClearance:new google.maps.Size(Number(e[0]),Number(e[1])),pixelOffset:new google.maps.Size(Number(t[0]),Number(t[1])),zIndex:Number(wpslSettings.infoBoxZindex)},a=new InfoBox(s)):a=new google.maps.InfoWindow,a}function E(e,t){G(e,0,"",!0,t),W(e,y,k,t)}function N(){return/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)}function R(t,s){if(navigator.geolocation){var o,n,i=Number(wpslSettings.geoLocationTimeout);o=setInterval(function(){e(".wpsl-icon-direction").toggleClass("wpsl-active-icon")},600),n=setTimeout(function(){O(o),E(t,s)},i),navigator.geolocation.getCurrentPosition(function(i){O(o),clearTimeout(n),X(!1),P(t,i,y,s),e(".wpsl-search").addClass("wpsl-geolocation-run")},function(o){if(e(".wpsl-icon-direction").hasClass("wpsl-user-activated")&&!e(".wpsl-search").hasClass("wpsl-geolocation-run")){switch(o.code){case o.PERMISSION_DENIED:alert(wpslGeolocationErrors.denied);break;case o.POSITION_UNAVAILABLE:alert(wpslGeolocationErrors.unavailable);break;case o.TIMEOUT:alert(wpslGeolocationErrors.timeout);break;default:alert(wpslGeolocationErrors.generalError)}e(".wpsl-icon-direction").removeClass("wpsl-active-icon")}else e(".wpsl-search").hasClass("wpsl-geolocation-run")||(clearTimeout(n),E(t,s))},{maximumAge:6e4,timeout:i,enableHighAccuracy:!0})}else alert(wpslGeolocationErrors.unavailable),E(t,s)}function O(t){clearInterval(t),e(".wpsl-icon-direction").removeClass("wpsl-active-icon")}function P(e,t,o,n){if(void 0===t)E(e,n);else{var i=new google.maps.LatLng(t.coords.latitude,t.coords.longitude);x={position:t,newRequest:!0},s.setCenter(i),G(i,0,"",!0,n),W(i,o,k,n)}}function T(){void 0!==wpslSettings.infoWindowStyle&&"infobox"==wpslSettings.infoWindowStyle&&void 0!==f[0]&&f[0].close()}function z(t,o){e(".wpsl-icon-reset, #wpsl-reset-map").on("click",function(){e(this).hasClass("wpsl-in-progress")||(1==wpslSettings.autoLoad&&(k=1),s.getCenter().lat()===C.centerLatlng.lat()&&s.getCenter().lng()===C.centerLatlng.lng()&&s.getZoom()===C.zoomLevel||(X(!1),e("#wpsl-search-input").val("").removeClass(),e(".wpsl-icon-reset").addClass("wpsl-in-progress"),r&&r.clearMarkers(),U(),function(){var t,s,o,n,i,l,a,r,p=e("#wpsl-wrap").hasClass("wpsl-default-filters"),c=[wpslSettings.searchRadius+" "+wpslSettings.distanceUnit,wpslSettings.maxResults],d=["wpsl-radius","wpsl-results"];for(t=0,s=d.length;t<s;t++)e("#"+d[t]+" select").val(parseInt(c[t])),e("#"+d[t]+" li").removeClass(),"wpsl-radius"==d[t]?o=wpslSettings.searchRadius:"wpsl-results"==d[t]&&(o=wpslSettings.maxResults),e("#"+d[t]+" li").each(function(){e(this).text()===c[t]&&(e(this).addClass("wpsl-selected-dropdown"),e("#"+d[t]+" .wpsl-selected-item").html(c[t]).attr("data-value",o))});e("#wpsl-category").length&&(e("#wpsl-category select").val(0),e("#wpsl-category li").removeClass(),e("#wpsl-category li:first-child").addClass("wpsl-selected-dropdown"),n=e("#wpsl-category li:first-child").text(),e("#wpsl-category .wpsl-selected-item").html(n).attr("data-value",0));e(".wpsl-custom-dropdown").length>0&&e(".wpsl-custom-dropdown").each(function(t){p?e(this).find("option").removeAttr("selected"):(i=e(this).siblings("div"),l=i.find("li:first-child"),a=l.text(),r=l.attr("data-value"),i.find("li").removeClass(),i.prev().html(a).attr("data-value",r))})}(),1==wpslSettings.autoLocate?P(t,x.position,!0,o):E(t,o)),e("#wpsl-stores").show(),e("#wpsl-direction-details").hide())})}function U(){void 0!==p&&""!==p&&(p.setMap(null),p="")}function Z(t){var i,l,a,c,d;for(T(),d=t.parents("li").length>0?t.parents("li").data("store-id"):t.parents(".wpsl-info-window").data("store-id"),void 0!==p&&""!==p&&(l=p.getPosition()),b={centerLatlng:s.getCenter(),zoomLevel:s.getZoom()},i=0,c=h.length;i<c;i++)0!=h[i].storeId||void 0!==l&&""!==l?h[i].storeId==d&&(a=h[i].getPosition()):l=h[i].getPosition();l&&a?(e("#wpsl-direction-details ul").empty(),e(".wpsl-direction-before, .wpsl-direction-after").remove(),function(t,i){var l,a,c,d,w,g,u,m,f,v="";u="km"==wpslSettings.distanceUnit?"METRIC":"IMPERIAL";f={origin:t,destination:i,travelMode:wpslSettings.directionsTravelMode,unitSystem:google.maps.UnitSystem[u]},n.route(f,function(t,n){if(n==google.maps.DirectionsStatus.OK){if(o.setMap(s),o.setDirections(t),t.routes.length>0){for(d=t.routes[0],w=0;w<d.legs.length;w++)for(l=d.legs[w],g=0,a=l.steps.length;g<a;g++)c=l.steps[g],v=v+"<li><div class='wpsl-direction-index'>"+(g+1)+"</div><div class='wpsl-direction-txt'>"+c.instructions+"</div><div class='wpsl-direction-distance'>"+c.distance.text+"</div></li>";for(e("#wpsl-direction-details ul").append(v).before("<div class='wpsl-direction-before'><a class='wpsl-back' id='wpsl-direction-start' href='#'>"+wpslLabels.back+"</a><div><span class='wpsl-total-distance'>"+d.legs[0].distance.text+"</span> - <span class='wpsl-total-durations'>"+d.legs[0].duration.text+"</span></div></div>").after("<p class='wpsl-direction-after'>"+t.routes[0].copyrights+"</p>"),e("#wpsl-direction-details").show(),w=0,a=h.length;w<a;w++)h[w].setMap(null);r&&r.clearMarkers(),void 0!==p&&""!==p&&p.setMap(null),e("#wpsl-stores").hide(),1==wpslSettings.templateId&&(m=e("#wpsl-gmap").offset(),e(window).scrollTop(m.top))}}else!function(e){var t;switch(e){case"NOT_FOUND":case"ZERO_RESULTS":t=wpslLabels.noDirectionsFound;break;case"OVER_QUERY_LIMIT":t=wpslLabels.queryLimit;break;default:t=wpslLabels.generalError}alert(t)}(n)})}(l,a)):alert(wpslLabels.generalError)}function B(e,t){var s,o,n;for(s=0,o=h.length;s<o;s++)h[s].storeId==e&&(n=h[s],"start"==t?n.setAnimation(google.maps.Animation.BOUNCE):n.setAnimation(null))}function $(s){var o={};void 0===wpslSettings.geocodeComponents||e.isEmptyObject(wpslSettings.geocodeComponents)?o.address=e("#wpsl-search-input").val():(o.componentRestrictions=wpslSettings.geocodeComponents,void 0!==o.componentRestrictions.postalCode?o.componentRestrictions.postalCode=e("#wpsl-search-input").val():o.address=e("#wpsl-search-input").val()),t.geocode(o,function(e,t){t==google.maps.GeocoderStatus.OK?(I.enabled&&j(e),A(e[0].geometry.location,s)):ee(t)})}function A(e,t){G(e,0,"",!0,t),W(e,y,!1,t)}function V(s,o){var n,i=s.lat().toFixed(5),l=s.lng().toFixed(5);s.lat=function(){return parseFloat(i)},s.lng=function(){return parseFloat(l)},t.geocode({latLng:s},function(t,s){s==google.maps.GeocoderStatus.OK?(1==wpslSettings.autoLocate&&x.newRequest&&(""!==(n=function(e){var t,s,o,n,i,l={},a=e.length;for(t=0;t<a;t++){for(n=e[t].address_components.length,s=0;s<n;s++){if(o=e[t].address_components[s].types,/^postal_code$/.test(o)||/^postal_code,postal_code_prefix$/.test(o)){l.zip=e[t].address_components[s].long_name;break}/^locality,political$/.test(o)&&(l.locality=e[t].address_components[s].long_name)}if(void 0!==l.zip)break}i=void 0===l.zip&&void 0!==l.locality?l.locality:l.zip;return i}(t))&&e("#wpsl-search-input").val(n),x.newRequest=!1),wpslSettings.directionRedirect&&(c=t[0].formatted_address),I.enabled&&e("#wpsl-search-input").val().length>0&&e.isEmptyObject(I.addressComponents)&&j(t),o()):ee(s)})}function j(t){var s,o,n,i,l,a={},r={};for(s="GB"==(i=function(t){var s="";return e.each(t[0].address_components,function(e){if("country,political"==t[0].address_components[e].types.join(","))return s=t[0].address_components[e].short_name,!1}),s}(t))?{city:"postal_town",city_locality:"locality,political",region:"administrative_area_level_2,political",country:"administrative_area_level_1,political"}:{city:"locality,political",region:"administrative_area_level_1,political",country:"country,political"},o=t[0].address_components.length,u=0;u<o;u++)for(var p in n=t[0].address_components[u].types,s)s[p]==n.join(",")&&(t[0].address_components[u].long_name.length>0?r[p]=t[0].address_components[u].long_name:r[p]=t[0].address_components[u].short_name);for(var p in s)void 0===r[p]&&(a[p]=s[p]);if("GB"==i&&void 0!==a.city_locality&&void 0===a.city&&(a={}),Object.keys(a).length>0)for(l=t.length,u=1;u<l;u++)for(o=t[u].address_components.length,m=0;m<o;m++)for(var p in n=t[u].address_components[m].types,a)s[p]==n.join(",")&&(r[p]=t[u].address_components[m].long_name);void 0!==r.city_locality&&r.city_locality.length>0&&(r.city=r.city_locality,delete r.city_locality),I.addressComponents=r}function W(e,t,s,o){1==wpslSettings.directionRedirect||I.enabled?V(e,function(){D(e,t,s,o)}):D(e,t,s,o)}function D(t,o,n,i){var l,a,r="",p=e("#wpsl-listing-template").html(),c=e("#wpsl-stores ul"),d=wpslSettings.url+"img/ajax-loader.gif";a=function(t,s,o){var n,i,l,a,r,p="",c=e("#wpsl-wrap").hasClass("wpsl-mobile"),d=e("#wpsl-wrap").hasClass("wpsl-default-filters"),w={action:"store_search",lat:t.lat(),lng:t.lng()};s?(w.max_results=wpslSettings.maxResults,w.search_radius=wpslSettings.searchRadius):(c||d?(n=parseInt(e("#wpsl-results .wpsl-dropdown").val()),i=parseInt(e("#wpsl-radius .wpsl-dropdown").val())):(n=parseInt(e("#wpsl-results .wpsl-selected-item").attr("data-value")),i=parseInt(e("#wpsl-radius .wpsl-selected-item").attr("data-value"))),isNaN(n)?w.max_results=wpslSettings.maxResults:w.max_results=n,isNaN(i)?w.search_radius=wpslSettings.searchRadius:w.search_radius=i,void 0!==wpslSettings.categoryIds?w.filter=wpslSettings.categoryIds:e("#wpsl-category").length>0?(p=c||d?parseInt(e("#wpsl-category .wpsl-dropdown").val()):parseInt(e("#wpsl-category .wpsl-selected-item").attr("data-value")),isNaN(p)||0===p||(w.filter=p)):e("#wpsl-checkbox-filter").length>0&&e("#wpsl-checkbox-filter input:checked").length>0&&(w.filter=e("#wpsl-checkbox-filter input:checked").map(function(){return e(this).val()}).get().join(",")),e(".wpsl-custom-dropdown").length>0&&e(".wpsl-custom-dropdown").each(function(t){l="",a="",c||d?(l=e(this).attr("name"),a=e(this).val()):(l=e(this).attr("name"),a=e(this).next(".wpsl-selected-item").attr("data-value")),l&&a&&(w[l]=a)}),e(".wpsl-custom-checkboxes").length>0&&e(".wpsl-custom-checkboxes").each(function(t){(r=e(this).attr("data-name"))&&(w[r]=function(t){var s=e("[data-name="+t+"]"),o=[];return e(s).find("input:checked").each(function(t){o.push(e(this).val())}),o.join()}(r))}));1==o&&(void 0!==x.position?w.skip_cache=1:(w.autoload=1,void 0!==wpslSettings.categoryIds&&(w.filter=wpslSettings.categoryIds)));I.enabled&&0==o&&(w.search=e("#wpsl-search-input").val(),w.statistics=I.addressComponents);return w}(t,o,n),c.empty().append("<li class='wpsl-preloader'><img src='"+d+"'/>"+wpslLabels.preloader+"</li>"),e("#wpsl-wrap").removeClass("wpsl-no-results"),e.get(wpslSettings.ajaxurl,a,function(o){e(".wpsl-preloader").remove(),o.length>0&&void 0===o.addon?(e.each(o,function(e){_.extend(o[e],K),G(new google.maps.LatLng(o[e].lat,o[e].lng),o[e].id,o[e],!1,i),r+=_.template(p)(o[e])}),e("#wpsl-result-list").off("click",".wpsl-directions"),c.empty(),c.append(r),e("#wpsl-result-list").on("click",".wpsl-directions",function(){if(1!=wpslSettings.directionRedirect)return Z(e(this)),!1}),F(),e("#wpsl-result-list p:empty").remove()):(G(t,0,"",!0,i),l=function(){var e;e=void 0!==wpslSettings.noResults&&""!==wpslSettings.noResults?wpslSettings.noResults:wpslLabels.noResults;return e}(),e("#wpsl-wrap").addClass("wpsl-no-results"),c.html("<li class='wpsl-no-results-msg'>"+l+"</li>")),1==wpslSettings.runFitBounds?J():(s.setZoom(Number(wpslSettings.zoomLevel)),s.setCenter(h[0].position)),1==wpslSettings.resetMap&&(e.isEmptyObject(C)&&google.maps.event.addListenerOnce(s,"tilesloaded",function(){C={centerLatlng:s.getCenter(),zoomLevel:s.getZoom()},e("#wpsl-map-controls").addClass("wpsl-reset-exists"),e(".wpsl-icon-reset, #wpsl-reset-map").show()}),e(".wpsl-icon-reset").removeClass("wpsl-in-progress"))}),1!=wpslSettings.mouseFocus||N()||e("#wpsl-search-input").focus()}function F(){if(1==wpslSettings.markerClusters){var e,t=Number(wpslSettings.clusterZoom),o=Number(wpslSettings.clusterSize);isNaN(t)&&(t=""),isNaN(o)&&(o=""),void 0!==wpslSettings.excludeStartFromCluster&&1==wpslSettings.excludeStartFromCluster&&(e=h.slice(0)).splice(0,1),r=new MarkerClusterer(s,void 0===e?h:e,{gridSize:o,maxZoom:t})}}function G(t,o,n,i,l){var a,r,p,c;0===o?(n={store:wpslLabels.startPoint},a=S.url+wpslSettings.startMarker):a=void 0!==n.alternateMarkerUrl&&n.alternateMarkerUrl?n.alternateMarkerUrl:void 0!==n.categoryMarkerUrl&&n.categoryMarkerUrl?n.categoryMarkerUrl:S.url+wpslSettings.storeMarker,r={url:a,scaledSize:new google.maps.Size(Number(S.scaledSize[0]),Number(S.scaledSize[1])),origin:new google.maps.Point(Number(S.origin[0]),Number(S.origin[1])),anchor:new google.maps.Point(Number(S.anchor[0]),Number(S.anchor[1]))},p=new google.maps.Marker({position:t,map:s,optimized:!1,title:H(n.store),draggable:i,storeId:o,icon:r}),h.push(p),google.maps.event.addListener(p,"click",(c=s,function(){0!=o?void 0!==wpslSettings.markerStreetView&&1==wpslSettings.markerStreetView?function(e,t){(new google.maps.StreetViewService).getPanoramaByLocation(e,50,function(e,s){L=s==google.maps.StreetViewStatus.OK,t()})}(t,function(){q(p,Y(n),l,c)}):q(p,Y(n),l,c):q(p,wpslLabels.startPoint,l,c),google.maps.event.clearListeners(l,"domready"),google.maps.event.addListener(l,"domready",function(){!function(t,s){e(".wpsl-info-actions a").on("click",function(o){var n=Number(wpslSettings.autoZoomLevel);if(o.stopImmediatePropagation(),e(this).hasClass("wpsl-directions")){if(1==wpslSettings.directionRedirect)return!0;Z(e(this))}else e(this).hasClass("wpsl-streetview")?function(t,s){var o=s.getStreetView();o.setPosition(t.getPosition()),o.setVisible(!0),e("#wpsl-map-controls").hide(),function(t,s){google.maps.event.addListener(t,"visible_changed",function(){if(!t.getVisible()){var o=s.getZoom();e("#wpsl-map-controls").show(),s.setZoom(o-1),s.setZoom(o)}})}(o,s)}(t,s):e(this).hasClass("wpsl-zoom-here")&&(s.setCenter(t.getPosition()),s.setZoom(n));return!1})}(p,c),Q()})})),i&&google.maps.event.addListener(p,"dragend",function(e){X(!0),s.setCenter(e.latLng),V(e.latLng),W(e.latLng,y,k=!1,l)})}function H(e){if(e)return e.replace(/&#(\d+);/g,function(e,t){return String.fromCharCode(t)})}(_.templateSettings={evaluate:/\<\%(.+?)\%\>/g,interpolate:/\<\%=(.+?)\%\>/g,escape:/\<\%-(.+?)\%\>/g},wpsl.gmaps.init=function(l,a){var r,p,c,d,w,g,u,m,f,h,b=Number(wpslSettings.zoomLevel),C=Number(wpslSettings.autoZoomLevel);c=function(e){var t,s,o,n=["zoomLevel","mapType","mapTypeControl","mapStyle","streetView","scrollWheel","controlPosition"],i={zoomLevel:wpslSettings.zoomLevel,mapType:wpslSettings.mapType,mapTypeControl:wpslSettings.mapTypeControl,mapStyle:wpslSettings.mapStyle,streetView:wpslSettings.streetView,scrollWheel:wpslSettings.scrollWheel,controlPosition:wpslSettings.controlPosition,gestureHandling:wpslSettings.gestureHandling};if(void 0!==window["wpslMap_"+e]&&void 0!==window["wpslMap_"+e].shortCode)for(t=0,s=n.length;t<s;t++)void 0!==(o=window["wpslMap_"+e].shortCode[n[t]])&&(i[n[t]]=o);return i.startLatLng=function(e){var t,s,o="";return void 0!==window["wpslMap_"+e]&&void 0!==window["wpslMap_"+e].locations&&(o=window["wpslMap_"+e].locations[0]),void 0!==o&&void 0!==o.lat&&void 0!==o.lng?t=new google.maps.LatLng(o.lat,o.lng):""!==wpslSettings.startLatlng?(s=wpslSettings.startLatlng.split(","),t=new google.maps.LatLng(s[0],s[1])):t=new google.maps.LatLng(0,0),t}(e),i}(a),(m=Number(c.zoomLevel))!==b&&(C=m),d=M(),t=new google.maps.Geocoder,o=new google.maps.DirectionsRenderer,n=new google.maps.DirectionsService,r={zoom:m,center:c.startLatLng,mapTypeId:google.maps.MapTypeId[c.mapType.toUpperCase()],mapTypeControl:!!Number(c.mapTypeControl),streetViewControl:!!Number(c.streetView),gestureHandling:c.gestureHandling,zoomControlOptions:{position:google.maps.ControlPosition[c.controlPosition.toUpperCase()+"_TOP"]}},"cooperative"!==c.gestureHandling&&(r.scrollwheel=!!Number(c.scrollWheel)),S=function(){var e,t=wpslSettings.markerIconProps,s={};void 0!==t.url?s.url=t.url:void 0!==t.categoryMarkerUrl?s.categoryMarkerUrl=t.categoryMarkerUrl:void 0!==t.alternateMarkerUrl?s.alternateMarkerUrl=t.alternateMarkerUrl:s.url=wpslSettings.url+"img/markers/";for(var o in t)t.hasOwnProperty(o)&&2==(e=t[o].split(",")).length&&(s[o]=e);return s}(),s=new google.maps.Map(document.getElementById(l),r),(f=function(e){try{var t=JSON.parse(e);if(t&&"object"==typeof t&&null!==t)return t}catch(e){}return!1}(f=c.mapStyle))&&s.setOptions({styles:f}),void 0!==window["wpslMap_"+a]&&void 0!==window["wpslMap_"+a].locations&&(g=new google.maps.LatLngBounds,u=window["wpslMap_"+a].locations,e.each(u,function(e){G(w=new google.maps.LatLng(u[e].lat,u[e].lng),u[e].id,u[e],!1,d),g.extend(w)}),u.length>1&&(oe(s,C),s.fitBounds(g)),_.isArray(wpslSettings.mapTabAnchor)&&(p={map:s,bounds:g,maxZoom:C},v.push(p))),e("#wpsl-gmap").length&&(1==wpslSettings.autoComplete&&function(){var t,s,o,n={};e("#wpsl-search-input").keypress(function(e){if(13==e.which)return ne(),$(d),!1}),void 0===wpslSettings.geocodeComponents||e.isEmptyObject(wpslSettings.geocodeComponents)||(n.componentRestrictions=wpslSettings.geocodeComponents,n.componentRestrictions=_.omit(n.componentRestrictions,"postalCode"));if(void 0!==wpslSettings.autoCompleteOptions&&!e.isEmptyObject(wpslSettings.autoCompleteOptions))for(var l in wpslSettings.autoCompleteOptions)wpslSettings.autoCompleteOptions.hasOwnProperty(l)&&(n[l]=wpslSettings.autoCompleteOptions[l]);t=document.getElementById("wpsl-search-input"),(s=new google.maps.places.Autocomplete(t,n)).addListener("place_changed",function(){(o=s.getPlace()).geometry&&(i=o.geometry.location)})}(),!N()&&e(".wpsl-dropdown").length&&1==wpslSettings.enableStyledDropdowns?(h=Number(wpslSettings.maxDropdownHeight),e(".wpsl-dropdown").each(function(t){var s,o,n=e(this);n.$dropdownWrap=n.wrap("<div class='wpsl-dropdown'></div>").parent(),n.$selectedVal=n.val(),n.$dropdownElem=e("<div><ul/></div>").appendTo(n.$dropdownWrap),n.$dropdown=n.$dropdownElem.find("ul"),n.$options=n.$dropdownWrap.find("option"),n.hide().removeClass("wpsl-dropdown"),e.each(n.$options,function(){s=e(this).val()==n.$selectedVal?'class="wpsl-selected-dropdown"':"",n.$dropdown.append("<li data-value="+e(this).val()+" "+s+">"+e(this).text()+"</li>")}),n.$dropdownElem.before("<span data-value="+n.find(":selected").val()+" class='wpsl-selected-item'>"+n.find(":selected").text()+"</span>"),n.$dropdownItem=n.$dropdownElem.find("li"),n.$dropdownWrap.on("click",function(t){e(this).hasClass("wpsl-active")?e(this).removeClass("wpsl-active"):(te(),e(this).toggleClass("wpsl-active"),o=0,e(this).hasClass("wpsl-active")?(n.$dropdownItem.each(function(t){o+=e(this).outerHeight()}),n.$dropdownElem.css("height",o+2+"px")):n.$dropdownElem.css("height",0),o>h&&(e(this).addClass("wpsl-scroll-required"),n.$dropdownElem.css("height",h+"px")),t.stopPropagation())}),n.$dropdownItem.on("click",function(t){n.$dropdownWrap.find(e(".wpsl-selected-item")).html(e(this).text()).attr("data-value",e(this).attr("data-value")),n.$dropdownItem.removeClass("wpsl-selected-dropdown"),e(this).addClass("wpsl-selected-dropdown"),te(),t.stopPropagation()})}),e(document).click(function(){te()})):(e("#wpsl-search-wrap select").show(),N()?e("#wpsl-wrap").addClass("wpsl-mobile"):e("#wpsl-wrap").addClass("wpsl-default-filters")),e(".wpsl-search").hasClass("wpsl-widget")||(1==wpslSettings.autoLocate?R(c.startLatLng,d):1==wpslSettings.autoLoad&&E(c.startLatLng,d)),1!=wpslSettings.mouseFocus||N()||e("#wpsl-search-input").focus(),function(t){e("#wpsl-search-btn").unbind("click").bind("click",function(s){return e("#wpsl-search-input").removeClass(),e("#wpsl-search-input").val()?(ne(),1==wpslSettings.autoComplete&&void 0!==i?A(i,t):$(t)):e("#wpsl-search-input").addClass("wpsl-error").focus(),!1})}(d),function(t,s,o){google.maps.event.addListenerOnce(s,"tilesloaded",function(){e(".gm-style").append(wpslSettings.mapControls),e(".wpsl-icon-reset, #wpsl-reset-map").length>0&&(z(t.startLatLng,o),e(".wpsl-icon-reset").hide()),e(".wpsl-icon-direction").on("click",function(){e(this).addClass("wpsl-user-activated"),R(t.startLatLng,o)})})}(c,s,d),e(".wpsl-search").hasClass("wpsl-widget")&&(e("#wpsl-search-btn").trigger("click"),e(".wpsl-search").removeClass("wpsl-widget"))),void 0!==wpslSettings.markerZoomTo&&1==wpslSettings.markerZoomTo&&google.maps.event.addListener(s,"zoom_changed",function(){Q()})},e(".wpsl-gmap-canvas").length&&(e("<img />").attr("src",wpslSettings.url+"img/ajax-loader.gif"),e(".wpsl-gmap-canvas").each(function(t){var s=e(this).attr("id");wpsl.gmaps.init(s,t)}),function(){var t,o;if(_.isArray(wpslSettings.mapTabAnchor))for(t=0,o=v.length;t<o;t++)se(v[t],wpslSettings.mapTabAnchor[t],t);else e("a[href='#"+wpslSettings.mapTabAnchor+"']").length&&se(s,wpslSettings.mapTabAnchor)}()),e("#wpsl-result-list").on("click",".wpsl-back",function(){var t,n;for(o.setMap(null),t=0,n=h.length;t<n;t++)h[t].setMap(s);return void 0!==p&&""!==p&&p.setMap(s),r&&F(),s.setCenter(b.centerLatlng),s.setZoom(b.zoomLevel),e(".wpsl-direction-before, .wpsl-direction-after").remove(),e("#wpsl-stores").show(),e("#wpsl-direction-details").hide(),!1}),e("#wpsl-gmap").length&&("bounce"==wpslSettings.markerEffect?(e("#wpsl-stores").on("mouseenter","li",function(){B(e(this).data("store-id"),"start")}),e("#wpsl-stores").on("mouseleave","li",function(){B(e(this).data("store-id"),"stop")})):"info_window"==wpslSettings.markerEffect&&e("#wpsl-stores").on("mouseenter","li",function(){var t,o;for(t=0,o=h.length;t<o;t++)h[t].storeId==e(this).data("store-id")&&(google.maps.event.trigger(h[t],"click"),s.setCenter(h[t].position))})),void 0!==wpslSettings.infoWindowStyle&&"infobox"==wpslSettings.infoWindowStyle&&1==wpslSettings.markerClusters)&&google.maps.event.addListener(s,"zoom_changed",function(){google.maps.event.addListenerOnce(s,"idle",function(){if(void 0!==r&&(d=r.clusters_).length)for(u=0,w=d.length;u<w;u++)for(m=0,g=d[u].markers_.length;m<g;m++)if(d[u].markers_[m].storeId==l){a.getVisible()&&null===d[u].markers_[m].map?a.setVisible(!1):a.getVisible()||null===d[u].markers_[m].map||a.setVisible(!0);break}})});function q(e,t,s,o){f.length=0,s.setContent(t),s.open(o,e),f.push(s),void 0!==wpslSettings.infoWindowStyle&&"infobox"==wpslSettings.infoWindowStyle&&1==wpslSettings.markerClusters&&(l=e.storeId,s.setVisible(!0))}function Q(){s.getZoom()>=wpslSettings.autoZoomLevel?e(".wpsl-zoom-here").hide():e(".wpsl-zoom-here").show()}var K={formatPhoneNumber:function(e){return(1==wpslSettings.phoneUrl&&N()||1==wpslSettings.clickableDetails)&&(e="<a href='tel:"+K.formatClickablePhoneNumber(e)+"'>"+e+"</a>"),e},formatClickablePhoneNumber:function(e){return-1!=e.indexOf("+")&&-1!=e.indexOf("(0)")&&(e=e.replace("(0)","")),e.replace(/(-| |\(|\)|\.|)/g,"")},formatEmail:function(e){return 1==wpslSettings.clickableDetails&&(e="<a href='mailto:"+e+"'>"+e+"</a>"),e},createInfoWindowActions:function(t){var s,o="",n="";return e("#wpsl-gmap").length&&(L&&(o="<a class='wpsl-streetview' href='#'>"+wpslLabels.streetView+"</a>"),1==wpslSettings.markerZoomTo&&(n="<a class='wpsl-zoom-here' href='#'>"+wpslLabels.zoomHere+"</a>"),s="<div class='wpsl-info-actions'>"+K.createDirectionUrl(t)+o+n+"</div>"),s},createDirectionUrl:function(t){var s,o,n={};return 1==wpslSettings.directionRedirect?(void 0===c&&(c=""),n.target="target='_blank'",void 0!==t?n.src=e("[data-store-id="+t+"] .wpsl-directions").attr("href"):(o=this.zip?this.zip+", ":"",s=this.address+", "+this.city+", "+o+this.country,n.src="https://www.google.com/maps/dir/?api=1&origin="+K.rfc3986EncodeURIComponent(c)+"&destination="+K.rfc3986EncodeURIComponent(s)+"&travelmode="+wpslSettings.directionsTravelMode.toLowerCase())):n={src:"#",target:""},"<a class='wpsl-directions' "+n.target+" href='"+n.src+"'>"+wpslLabels.directions+"</a>"},rfc3986EncodeURIComponent:function(e){return encodeURIComponent(e).replace(/[!'()*]/g,escape)}};function Y(t){var s;return s=e("#wpsl-base-gmap_0").length?e("#wpsl-cpt-info-window-template").html():e("#wpsl-info-window-template").html(),_.template(s)(t)}function J(){var e,t,o=Number(wpslSettings.autoZoomLevel),n=new google.maps.LatLngBounds;for(oe(s,o),e=0,t=h.length;e<t;e++)n.extend(h[e].position);s.fitBounds(n)}function X(e){var t,s;if(o.setMap(null),h){for(s=0,t=h.length;s<t;s++)e?1!=h[s].draggable?h[s].setMap(null):p=h[s]:h[s].setMap(null);h.length=0}r&&r.clearMarkers()}function ee(e){var t;switch(e){case"ZERO_RESULTS":t=wpslLabels.noResults;break;case"OVER_QUERY_LIMIT":t=wpslLabels.queryLimit;break;default:t=wpslLabels.generalError}alert(t)}function te(){e(".wpsl-dropdown").removeClass("wpsl-active"),e(".wpsl-dropdown div").css("height",0)}function se(t,s,o){var n,i,l,a,r,p=!!Number(wpslSettings.mapTabAnchorReturn),c=e("a[href='#"+s+"']");l=void 0!==t.maxZoom?t.maxZoom:Number(wpslSettings.autoZoomLevel),void 0!==o&&0==o&&c.addClass("wpsl-fitbounds"),c.on("click",function(){return setTimeout(function(){void 0!==t.map?(a=t.bounds,r=t.map):r=t,n=r.getZoom(),i=r.getCenter(),google.maps.event.trigger(r,"resize"),c.hasClass("wpsl-fitbounds")||(oe(r,l),r.setZoom(n),r.setCenter(i),void 0!==a?r.fitBounds(a):J(),c.addClass("wpsl-fitbounds"))},50),p})}function oe(e,t){google.maps.event.addListenerOnce(e,"bounds_changed",function(){google.maps.event.addListenerOnce(e,"idle",function(){this.getZoom()>t&&this.setZoom(t)})})}function ne(){e("#wpsl-result-list ul").empty(),e("#wpsl-stores").show(),e(".wpsl-direction-before, .wpsl-direction-after").remove(),e("#wpsl-direction-details").hide(),y=!1,T(),X(!1),U()}e("#wpsl-stores").on("click",".wpsl-store-details",function(){var t,s,o=e(this).parents("li"),n=o.data("store-id");if("info window"==wpslSettings.moreInfoLocation)for(t=0,s=h.length;t<s;t++)h[t].storeId==n&&google.maps.event.trigger(h[t],"click");else o.find(".wpsl-more-info-listings").is(":visible")?e(this).removeClass("wpsl-active-details"):e(this).addClass("wpsl-active-details"),o.siblings().find(".wpsl-store-details").removeClass("wpsl-active-details"),o.siblings().find(".wpsl-more-info-listings").hide(),o.find(".wpsl-more-info-listings").toggle();if("default"!=wpslSettings.templateId||"store listings"==wpslSettings.moreInfoLocation)return!1})});js/wpsl-gmap.js000064400000254377151327220640007451 0ustar00var wpsl = wpsl || {};

wpsl.gmaps = {};

/**
 * This is only used to init the map after the
 * user agreed to load Google Maps in combination
 * with the Borlabs Cookie plugin.
 *
 * @since 2.2.22
 * @returns {void}
 */
function initWpslMap() {
	var mapsLoaded;

	mapsLoaded = setInterval( function() {
		if ( typeof google === 'object' && typeof google.maps === 'object' ) {
			clearInterval( mapsLoaded );

			jQuery( ".wpsl-gmap-canvas" ).each( function( mapIndex ) {
				var mapId = jQuery( this ).attr( "id" );

				wpsl.gmaps.init( mapId, mapIndex );
			});
		}
	}, 500 );
}

jQuery( document ).ready( function( $ ) {
var geocoder, map, directionsDisplay, directionsService, autoCompleteLatLng,
	activeWindowMarkerId, infoWindow, markerClusterer, startMarkerData, startAddress,
	openInfoWindow = [],
	markersArray = [],
    mapsArray = [],
	markerSettings = {},
	directionMarkerPosition = {},
	mapDefaults = {},
	resetMap = false,
	streetViewAvailable = false,
    autoLoad = ( typeof wpslSettings !== "undefined" ) ? wpslSettings.autoLoad : "",
    userGeolocation = {},
    statistics = {
        enabled: ( typeof wpslSettings.collectStatistics !== "undefined" ) ? true : false,
        addressComponents: ''
	};

/** 
 * Set the underscore template settings.
 * 
 * Defining them here prevents other plugins 
 * that also use underscore / backbone, and defined a
 * different _.templateSettings from breaking the 
 * rendering of the store locator template.
 * 
 * @link	 http://underscorejs.org/#template
 * @requires underscore.js
 * @since	 2.0.0
 */	
_.templateSettings = {
	evaluate: /\<\%(.+?)\%\>/g,
	interpolate: /\<\%=(.+?)\%\>/g,
	escape: /\<\%-(.+?)\%\>/g
};

/**
 * Initialize Google Maps with the correct settings.
 *
 * @since   1.0.0
 * @param   {string} mapId    The id of the map div
 * @param   {number} mapIndex Number of the map
 * @returns {void}
 */
wpsl.gmaps.init = function( mapId, mapIndex ) {
    var mapOptions, mapDetails, settings, infoWindow, latLng,
		bounds, mapData, zoomLevel,
		defaultZoomLevel = Number( wpslSettings.zoomLevel ),
        maxZoom = Number( wpslSettings.autoZoomLevel );

	// Get the settings that belongs to the current map.
	settings = getMapSettings( mapIndex );

	/*
	 * This is the value from either the settings page,
	 * or the zoom level set through the shortcode.
	 */
    zoomLevel = Number( settings.zoomLevel );

    /*
     * If they are not equal, then the zoom value is set through the shortcode.
     * If this is the case, then we use that as the max zoom level.
     */
    if ( zoomLevel !== defaultZoomLevel ) {
        maxZoom = zoomLevel;
	}

	// Create a new infoWindow, either with the infobox libray or use the default one.
	infoWindow = newInfoWindow();

    geocoder	      = new google.maps.Geocoder();
    directionsDisplay = new google.maps.DirectionsRenderer();
    directionsService = new google.maps.DirectionsService();

	// Set the map options.
    mapOptions = {
		zoom: zoomLevel,
		center: settings.startLatLng,
		mapTypeId: google.maps.MapTypeId[ settings.mapType.toUpperCase() ],
		mapTypeControl: Number( settings.mapTypeControl ) ? true : false,
		streetViewControl: Number( settings.streetView ) ? true : false,
        gestureHandling: settings.gestureHandling,
		zoomControlOptions: {
			position: google.maps.ControlPosition[ settings.controlPosition.toUpperCase() + '_TOP' ]
		}
	};

    /**
     * When the gestureHandling is set to cooperative and the scrollWheel
     * options is also set, then the gestureHandling value is ingored.
     *
     * To fix this we only include the scrollWheel options when 'cooperative' isn't used.
     */
    if ( settings.gestureHandling !== 'cooperative' ) {
        mapOptions.scrollwheel = Number( settings.scrollWheel ) ? true : false;
    }

	// Get the correct marker path & properties.
	markerSettings = getMarkerSettings();

	map = new google.maps.Map( document.getElementById( mapId ), mapOptions );

	// Check if we need to apply a map style.
	maybeApplyMapStyle( settings.mapStyle );
	
	if ( ( typeof window[ "wpslMap_" + mapIndex ] !== "undefined" ) && ( typeof window[ "wpslMap_" + mapIndex ].locations !== "undefined" ) ) {
		bounds	= new google.maps.LatLngBounds(),
		mapData = window[ "wpslMap_" + mapIndex ].locations;

		// Loop over the map data, create the infowindow object and add each marker.
		$.each( mapData, function( index ) {
			latLng = new google.maps.LatLng( mapData[index].lat, mapData[index].lng );
			addMarker( latLng, mapData[index].id, mapData[index], false, infoWindow );
			bounds.extend( latLng );
		});

		// If we have more then one location on the map, then make sure to not zoom to far.
		if ( mapData.length > 1 ) {
            // Make sure we don't zoom to far when fitBounds runs.
            attachBoundsChangedListener( map, maxZoom );

            // Make all the markers fit on the map.
            map.fitBounds( bounds );
		}

        /*
         * If we need to apply the fix for the map showing up grey because
         * it's used in a tabbed nav multiple times, then collect the active maps.
         *
         * See the fixGreyTabMap function.
         */
        if ( _.isArray( wpslSettings.mapTabAnchor ) ) {
            mapDetails = {
                map: map,
                bounds: bounds,
				maxZoom: maxZoom
            };

            mapsArray.push( mapDetails );
		}
    }

	// Only run this part if the store locator exist and we don't just have a basic map.
	if ( $( "#wpsl-gmap" ).length ) {
		
		if ( wpslSettings.autoComplete == 1 ) {
			activateAutocomplete();
		}
		
		/*
		 * Not the most optimal solution, but we check the useragent if we should enable the styled dropdowns.
		 * 
		 * We do this because several people have reported issues with the styled dropdowns on
		 * iOS and Android devices. So on mobile devices the dropdowns will be styled according 
		 * to the browser styles on that device.
		 */
		if ( !checkMobileUserAgent() && $( ".wpsl-dropdown" ).length && wpslSettings.enableStyledDropdowns == 1 ) {
			createDropdowns();	
		} else {
			$( "#wpsl-search-wrap select" ).show();
			
			if ( checkMobileUserAgent() ) {
				$( "#wpsl-wrap" ).addClass( "wpsl-mobile" );
			} else {
				$( "#wpsl-wrap" ).addClass( "wpsl-default-filters" );
			}
		}

		// Check if we need to autolocate the user, or autoload the store locations.
		if ( !$( ".wpsl-search" ).hasClass( "wpsl-widget" ) ) {
            if ( wpslSettings.autoLocate == 1 ) {
				checkGeolocation( settings.startLatLng, infoWindow );
			} else if ( wpslSettings.autoLoad == 1 ) {
				showStores( settings.startLatLng, infoWindow );
			}
		}

		// Move the mousecursor to the store search field if the focus option is enabled.
		if ( wpslSettings.mouseFocus == 1 && !checkMobileUserAgent() ) {
			$( "#wpsl-search-input" ).focus();
		}

		// Bind store search button.
		searchLocationBtn( infoWindow );

		// Add the 'reload' and 'find location' icon to the map.
		mapControlIcons( settings, map, infoWindow );

		// Check if the user submitted a search through a search widget.
		checkWidgetSubmit();
	}

	// Bind the zoom_changed listener.
	zoomChangedListener();
};

// Only continue if a map is present.
if ( $( ".wpsl-gmap-canvas" ).length ) {
	$( "<img />" ).attr( "src", wpslSettings.url + "img/ajax-loader.gif" );

	/*
	 * The [wpsl] shortcode can only exist once on a page,
	 * but the [wpsl_map] shortcode can exist multiple times.
	 *
	 * So to make sure we init all the maps we loop over them.
	 */
	$( ".wpsl-gmap-canvas" ).each( function( mapIndex ) {
		var mapId = $( this ).attr( "id" );

		wpsl.gmaps.init( mapId, mapIndex );
	});

	/*
	 * Check if we are dealing with a map that's placed in a tab,
	 * if so run a fix to prevent the map from showing up grey.
	 */
	maybeApplyTabFix();
}


/**
 * Activate the autocomplete for the store search.
 * 
 * @since 2.2.0
 * @link https://developers.google.com/maps/documentation/javascript/places-autocomplete
 * @returns {void}
 */
function activateAutocomplete() {
	var input, autocomplete, place,
		options = {};

	// Handle autocomplete queries submitted by the user using the 'enter' key.
	keyboardAutoCompleteSubmit();

    /**
	 * Check if we need to set the geocode component restrictions.
	 * This is automatically included when a fixed map region is
	 * selected on the WPSL settings page.
     */
	if ( typeof wpslSettings.geocodeComponents !== "undefined" && !$.isEmptyObject( wpslSettings.geocodeComponents ) ) {
		options.componentRestrictions = wpslSettings.geocodeComponents;

		/**
		 * If the postalCode is included in the autocomplete together with '(regions)' ( which is included ),
		 * then it will break it. So we have to remove it.
		 */
		options.componentRestrictions = _.omit( options.componentRestrictions, 'postalCode' );
	}

	// Check if we need to restrict the autocomplete data.
    if ( typeof wpslSettings.autoCompleteOptions !== "undefined" && !$.isEmptyObject( wpslSettings.autoCompleteOptions ) ) {
        for ( var key in wpslSettings.autoCompleteOptions ) {
            if ( wpslSettings.autoCompleteOptions.hasOwnProperty( key ) ) {
                options[key] = wpslSettings.autoCompleteOptions[key];
            }
        }
    }

	input		  = document.getElementById( "wpsl-search-input" );
	autocomplete = new google.maps.places.Autocomplete( input, options );

	autocomplete.addListener( "place_changed", function() {
		place = autocomplete.getPlace();

		/**
		 * Assign the returned latlng to the autoCompleteLatLng var.
		 * This var is used when the users submits the search.
		 */
		if ( place.geometry ) {
            autoCompleteLatLng = place.geometry.location;
		}
    });
}

/**
 * Make sure that the 'Zoom here' link in the info window 
 * doesn't zoom past the max auto zoom level.
 * 
 * The 'max auto zoom level' is set on the settings page.
 *
 * @since   2.0.0
 * @returns {void}
 */
function zoomChangedListener() {
	if ( typeof wpslSettings.markerZoomTo !== "undefined" && wpslSettings.markerZoomTo == 1 ) {
		google.maps.event.addListener( map, "zoom_changed", function() {
			checkMaxZoomLevel();
		});
	}
}

/**
 * Get the correct map settings.
 *
 * @since	2.0.0
 * @param	{number} mapIndex    Number of the map
 * @returns {object} mapSettings The map settings either set through a shortcode or the default settings 
 */
function getMapSettings( mapIndex ) {
	var j, len, shortCodeVal,
		settingOptions = [ "zoomLevel", "mapType", "mapTypeControl", "mapStyle", "streetView", "scrollWheel", "controlPosition" ], 
		mapSettings	= {
			zoomLevel: wpslSettings.zoomLevel,
			mapType: wpslSettings.mapType,
			mapTypeControl: wpslSettings.mapTypeControl,
			mapStyle: wpslSettings.mapStyle,
			streetView: wpslSettings.streetView,
			scrollWheel: wpslSettings.scrollWheel,
			controlPosition: wpslSettings.controlPosition,
            gestureHandling: wpslSettings.gestureHandling
		};	

	// If there are settings that are set through the shortcode, then we use them instead of the default ones.
	if ( ( typeof window[ "wpslMap_" + mapIndex ] !== "undefined" ) && ( typeof window[ "wpslMap_" + mapIndex ].shortCode !== "undefined" ) ) {
		for ( j = 0, len = settingOptions.length; j < len; j++ ) {
			shortCodeVal = window[ "wpslMap_" + mapIndex ].shortCode[ settingOptions[j] ];
			
			// If the value is set through the shortcode, we overwrite the default value.
			if ( typeof shortCodeVal !== "undefined" ) {
				mapSettings[ settingOptions[j] ] = shortCodeVal;
			}
		}
	}

	mapSettings.startLatLng = getStartLatlng( mapIndex );

	return mapSettings;
}

/**
 * Get the latlng coordinates that are used to init the map.
 *
 * @since	2.0.0
 * @param	{number} mapIndex    Number of the map
 * @returns {object} startLatLng The latlng value where the map will initially focus on 
 */
function getStartLatlng( mapIndex ) {
	var startLatLng, latLng, 
		firstLocation = "";
	
	/* 
	 * Maps that are added with the [wpsl_map] shortcode will have the locations key set. 
	 * If it exists we use the coordinates from the first location to center the map on. 
	 */
	if ( ( typeof window[ "wpslMap_" + mapIndex ] !== "undefined" ) && ( typeof window[ "wpslMap_" + mapIndex ].locations !== "undefined" ) ) {
		firstLocation = window[ "wpslMap_" + mapIndex ].locations[0];
	}
		
	/* 
	 * Either use the coordinates from the first location as the start coordinates 
	 * or the default start point defined on the settings page.
	 * 
	 * If both are not available we set it to 0,0 
	 */	
	if ( ( typeof firstLocation !== "undefined" && typeof firstLocation.lat !== "undefined" ) && ( typeof firstLocation.lng !== "undefined" ) ) {
		startLatLng = new google.maps.LatLng( firstLocation.lat, firstLocation.lng );
	} else if ( wpslSettings.startLatlng !== "" ) {
		latLng		= wpslSettings.startLatlng.split( "," );
		startLatLng = new google.maps.LatLng( latLng[0], latLng[1] );
    } else {
		startLatLng = new google.maps.LatLng( 0,0 );
    }
		
	return startLatLng;
}

/**
 * Create a new infoWindow object.
 * 
 * Either use the default infoWindow or use the infobox library.
 * 
 * @since  2.0.0
 * @return {object} infoWindow The infoWindow object
 */
function newInfoWindow() {
	var boxClearance, boxPixelOffset, 
		infoBoxOptions = {};
	
	// Do we need to use the infobox script or use the default info windows?
	if ( ( typeof wpslSettings.infoWindowStyle !== "undefined" ) && ( wpslSettings.infoWindowStyle == "infobox" ) ) {

		// See http://google-maps-utility-library-v3.googlecode.com/svn/trunk/infobox/docs/reference.html.
		boxClearance   = wpslSettings.infoBoxClearance.split( "," );
		boxPixelOffset = wpslSettings.infoBoxPixelOffset.split( "," );
		infoBoxOptions = {
			alignBottom: true,
			boxClass: wpslSettings.infoBoxClass,
			closeBoxMargin: wpslSettings.infoBoxCloseMargin,
			closeBoxURL: wpslSettings.infoBoxCloseUrl,
			content: "",
			disableAutoPan: ( Number( wpslSettings.infoBoxDisableAutoPan ) ) ? true : false,
			enableEventPropagation: ( Number( wpslSettings.infoBoxEnableEventPropagation ) ) ? true : false,
			infoBoxClearance: new google.maps.Size( Number( boxClearance[0] ), Number( boxClearance[1] ) ),
			pixelOffset: new google.maps.Size( Number( boxPixelOffset[0] ), Number( boxPixelOffset[1] ) ),
			zIndex: Number( wpslSettings.infoBoxZindex )
		};

		infoWindow = new InfoBox( infoBoxOptions );	
	} else {
		infoWindow = new google.maps.InfoWindow();
	}

	return infoWindow;
}

/**
 * Get the required marker settings.
 * 
 * @since  2.1.0
 * @return {object} settings The marker settings.
 */
function getMarkerSettings() {
	var markerProp,
		markerProps = wpslSettings.markerIconProps,
		settings	= {};

	// Use the correct marker path.
	if ( typeof markerProps.url !== "undefined" ) {
        settings.url = markerProps.url;
    } else if ( typeof markerProps.categoryMarkerUrl !== "undefined" ) {
        settings.categoryMarkerUrl = markerProps.categoryMarkerUrl;
    } else if ( typeof markerProps.alternateMarkerUrl !== "undefined" ) {
        settings.alternateMarkerUrl = markerProps.alternateMarkerUrl;
	} else {
		settings.url = wpslSettings.url + "img/markers/";
	}

	for ( var key in markerProps ) {
		if ( markerProps.hasOwnProperty( key ) ) {
			markerProp = markerProps[key].split( "," );

			if ( markerProp.length == 2 ) {
				settings[key] = markerProp;
			}
		}
	}
	
	return settings;
}

/**
 * Check if we have a map style that we need to apply to the map.
 * 
 * @since  2.0.0
 * @param  {string} mapStyle The id of the map
 * @return {void}
 */
function maybeApplyMapStyle( mapStyle ) {
	
	// Make sure the JSON is valid before applying it as a map style.
	mapStyle = tryParseJSON( mapStyle );

	if ( mapStyle ) {
		map.setOptions({ styles: mapStyle });
	}
}

/**
 * Make sure the JSON is valid. 
 * 
 * @link   http://stackoverflow.com/a/20392392/1065294 
 * @since  2.0.0
 * @param  {string} jsonString The JSON data
 * @return {object|boolean}	The JSON string or false if it's invalid json.
 */
function tryParseJSON( jsonString ) {
	
    try {
        var o = JSON.parse( jsonString );

        /* 
		 * Handle non-exception-throwing cases:
		 * Neither JSON.parse(false) or JSON.parse(1234) throw errors, hence the type-checking,
		 * but... JSON.parse(null) returns 'null', and typeof null === "object", 
		 * so we must check for that, too.
		 */ 
        if ( o && typeof o === "object" && o !== null ) {
            return o;
        }
    }
    catch ( e ) { }

    return false;
}

/**
 * Add the start marker and call the function that inits the store search.
 *
 * @since	1.1.0
 * @param	{object} startLatLng The start coordinates
 * @param	{object} infoWindow  The infoWindow object
 * @returns {void}
 */
function showStores( startLatLng, infoWindow ) {
	addMarker( startLatLng, 0, '', true, infoWindow ); // This marker is the 'start location' marker. With a storeId of 0, no name and is draggable
	findStoreLocations( startLatLng, resetMap, autoLoad, infoWindow );
}

/**
 * Compare the current useragent to a list of known mobile useragents ( not optimal, I know ).
 *
 * @since	1.2.20
 * @returns {boolean} Whether the useragent is from a known mobile useragent or not.
 */
function checkMobileUserAgent() {
	return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test( navigator.userAgent );	
}

/**
 * Check if Geolocation detection is supported. 
 * 
 * If there is an error / timeout with determining the users 
 * location, then we use the 'start point' value from the settings 
 * as the start location through the showStores function. 
 *
 * @since	1.0.0
 * @param	{object} startLatLng The start coordinates
 * @param	{object} infoWindow  The infoWindow object
 * @returns {void}
 */
function checkGeolocation( startLatLng, infoWindow ) {
		
	if ( navigator.geolocation ) {
		var geolocationInProgress, locationTimeout,
			keepStartMarker = false,
			timeout			= Number( wpslSettings.geoLocationTimeout );
	
		// Make the direction icon flash every 600ms to indicate the geolocation attempt is in progress.
		geolocationInProgress = setInterval( function() {
			$( ".wpsl-icon-direction" ).toggleClass( "wpsl-active-icon" );
		}, 600 );

		/* 
		 * If the user doesn't approve the geolocation request within the value set in 
		 * wpslSettings.geoLocationTimeout, then the default map is loaded.
		 * 
		 * You can increase the timeout value with the wpsl_geolocation_timeout filter. 
		 */
		locationTimeout = setTimeout( function() {
			geolocationFinished( geolocationInProgress );
			showStores( startLatLng, infoWindow );
		}, timeout );

		navigator.geolocation.getCurrentPosition( function( position ) {
			geolocationFinished( geolocationInProgress );
			clearTimeout( locationTimeout );
			
			/* 
			 * If the timeout is triggerd and the user later decides to enable 
			 * the geolocation detection again, it gets messy with multiple start markers. 
			 * 
			 * So we first clear the map before adding new ones.
			 */
			deleteOverlays( keepStartMarker ); 
			handleGeolocationQuery( startLatLng, position, resetMap, infoWindow );
			
			/*
			 * Workaround for this bug in Firefox https://bugzilla.mozilla.org/show_bug.cgi?id=1283563.
			 * to keep track if the geolocation code has already run.
			 * 
			 * Otherwise after the users location is determined succesfully the code 
			 * will also detect the returned error, and triggers showStores() to 
			 * run with the start location set in the incorrect location.
			 */ 
			
			$( ".wpsl-search").addClass( "wpsl-geolocation-run" );
		}, function( error ) {

			/* 
			 * Only show the geocode errors if the user actually clicked on the direction icon. 
			 * 
			 * Otherwise if the "Attempt to auto-locate the user" option is enabled on the settings page, 
			 * and the geolocation attempt fails for whatever reason ( blocked in browser, unavailable etc ). 
			 * Then the first thing the visitor will see on pageload is an alert box, which isn't very userfriendly.
			 * 
			 * If an error occurs on pageload without the user clicking on the direction icon,
			 * the default map is shown without any alert boxes.
			 */
			if ( $( ".wpsl-icon-direction" ).hasClass( "wpsl-user-activated" ) && !$( ".wpsl-search" ).hasClass( "wpsl-geolocation-run" ) ) {
				switch ( error.code ) {
					case error.PERMISSION_DENIED:
						alert( wpslGeolocationErrors.denied );
						break;
					case error.POSITION_UNAVAILABLE:
						alert( wpslGeolocationErrors.unavailable );
						break;
					case error.TIMEOUT:
						alert( wpslGeolocationErrors.timeout );
						break;
					default:
						alert( wpslGeolocationErrors.generalError );
						break;
				}

				$( ".wpsl-icon-direction" ).removeClass( "wpsl-active-icon" );
			} else if ( !$( ".wpsl-search" ).hasClass( "wpsl-geolocation-run" ) ) {
				clearTimeout( locationTimeout );
				showStores( startLatLng, infoWindow );
			}
		},
		{ maximumAge: 60000, timeout: timeout, enableHighAccuracy: true } );
	} else {
		alert( wpslGeolocationErrors.unavailable );
		showStores( startLatLng, infoWindow );
	}
}

/**
 * Clean up after the geolocation attempt finished.
 * 
 * @since	2.0.0
 * @param	{number} geolocationInProgress
 * @returns {void}
 */
function geolocationFinished( geolocationInProgress ) {
	clearInterval( geolocationInProgress );
	$( ".wpsl-icon-direction" ).removeClass( "wpsl-active-icon" );	
}

/**
 * Handle the data returned from the Geolocation API.
 * 
 * If there is an error / timeout determining the users location,
 * then we use the 'start point' value from the settings as the start location through the showStores function. 
 *
 * @since	1.0.0
 * @param	{object}  startLatLng The start coordinates
 * @param	{object}  position    The latlng coordinates from the geolocation attempt
 * @param	{boolean} resetMap    Whether we should reset the map or not
 * @param	{object}  infoWindow  The infoWindow object
 * @returns {void}
 */
function handleGeolocationQuery( startLatLng, position, resetMap, infoWindow ) {

	if ( typeof( position ) === "undefined" ) {
		showStores( startLatLng, infoWindow );
	} else {
		var latLng = new google.maps.LatLng( position.coords.latitude, position.coords.longitude );
		
		/* 
		 * Store the latlng from the geolocation for when the user hits "reset" again 
		 * without having to ask for permission again.
		 */
        userGeolocation = {
            position: position,
			newRequest: true
		};

		map.setCenter( latLng );
		addMarker( latLng, 0, '', true, infoWindow ); // This marker is the 'start location' marker. With a storeId of 0, no name and is draggable
		findStoreLocations( latLng, resetMap, autoLoad, infoWindow );
	}
}

/**
 * Handle clicks on the store locator search button.
 * 
 * @since	1.0.0
 * @todo disable button while AJAX request still runs.
 * @param	{object} infoWindow The infoWindow object
 * @returns {void}
 */
function searchLocationBtn( infoWindow ) {

	$( "#wpsl-search-btn" ).unbind( "click" ).bind( "click", function( e ) {
		$( "#wpsl-search-input" ).removeClass();

		if ( !$( "#wpsl-search-input" ).val() ) {
			$( "#wpsl-search-input" ).addClass( "wpsl-error" ).focus();
		} else {
			resetSearchResults();

			/*
             * Check if we need to geocode the user input,
             * or if autocomplete is enabled and we already
             * have the latlng values.
             */
			if ( wpslSettings.autoComplete == 1 && typeof autoCompleteLatLng !== "undefined" ) {
				prepareStoreSearch( autoCompleteLatLng, infoWindow );
			} else {
				codeAddress( infoWindow );
			}
		}

		return false;
	});
}

/**
 * Force the open InfoBox info window to close
 * 
 * This is required if the user makes a new search, 
 * or clicks on the "Directions" link.
 *
 * @since  2.0.0
 * @return {void}
 */
function closeInfoBoxWindow() {
	if ( ( typeof wpslSettings.infoWindowStyle !== "undefined" ) && ( wpslSettings.infoWindowStyle == "infobox" ) && typeof openInfoWindow[0] !== "undefined" ) {
		openInfoWindow[0].close();
	}	
}

/**
 * Add the 'reload' and 'find location' icon to the map.
 *
 * @since  2.0.0
 * @param  {object} settings   Map settings
 * @param  {object} map		   The map object
 * @param  {object} infoWindow The info window object
 * @return {void}
 */
function mapControlIcons( settings, map, infoWindow ) {

	// Once the map has finished loading include the map control button(s).
	google.maps.event.addListenerOnce( map, "tilesloaded", function() {

		// Add the html for the map controls to the map.
		$( ".gm-style" ).append( wpslSettings.mapControls );

		if ( $( ".wpsl-icon-reset, #wpsl-reset-map" ).length > 0 ) {

			// Bind the reset map button.
			resetMapBtn( settings.startLatLng, infoWindow );

			/* 
			 * Hide it to prevent users from clicking it before 
			 * the store location are placed on the map. 
			 */
			$( ".wpsl-icon-reset" ).hide();
		}

		// Bind the direction button to trigger a new geolocation request.
		$( ".wpsl-icon-direction" ).on( "click", function() {
			$( this ).addClass( "wpsl-user-activated" );
			checkGeolocation( settings.startLatLng, infoWindow );
		});
	});
}

/**
 * Handle clicks on the "Reset" button.
 * 
 * @since	1.0.0
 * @param	{object} startLatLng The start coordinates
 * @param	{object} infoWindow  The infoWindow object
 * @returns {void}
 */
function resetMapBtn( startLatLng, infoWindow ) {
	$( ".wpsl-icon-reset, #wpsl-reset-map" ).on( "click", function() {
		var keepStartMarker = false,
			resetMap	    = true;

		/* 
		 * Check if a map reset is already in progress, 
		 * if so prevent another one from starting. 
		 */
		if ( $( this ).hasClass( "wpsl-in-progress" ) ) {
			return;
		}

		/* 
		 * When the start marker is dragged the autoload value is set to false. 
		 * So we need to check the correct value when the reset button is 
		 * pushed before reloading the stores. 
		 */
		if ( wpslSettings.autoLoad == 1 ) {
			autoLoad = 1;
		}

		// Check if the latlng or zoom has changed since pageload, if so there is something to reset.
		if ( ( ( ( map.getCenter().lat() !== mapDefaults.centerLatlng.lat() ) || ( map.getCenter().lng() !== mapDefaults.centerLatlng.lng() ) || ( map.getZoom() !== mapDefaults.zoomLevel ) ) ) ) {
			deleteOverlays( keepStartMarker );

			$( "#wpsl-search-input" ).val( "" ).removeClass();

			// We use this to prevent multiple reset request.
			$( ".wpsl-icon-reset" ).addClass( "wpsl-in-progress" );

			// If marker clusters exist, remove them from the map.
			if ( markerClusterer ) {
				markerClusterer.clearMarkers();
			}

			// Remove the start marker.
			deleteStartMarker();

			// Reset the dropdown values.
			resetDropdowns();

			if ( wpslSettings.autoLocate == 1 ) {
				handleGeolocationQuery( startLatLng, userGeolocation.position, resetMap, infoWindow );
			} else {
				showStores( startLatLng, infoWindow );
			}
		}

		// Make sure the stores are shown and the direction details are hidden.
		$( "#wpsl-stores" ).show();
		$( "#wpsl-direction-details" ).hide();
	});
}

/**
 * Remove the start marker from the map.
 *
 * @since   1.2.12
 * @returns {void}
 */
function deleteStartMarker() {
	if ( ( typeof( startMarkerData ) !== "undefined" ) && ( startMarkerData !== "" ) ) {
		startMarkerData.setMap( null );
		startMarkerData = "";
	}
}

/**
 * Reset the dropdown values for the max results, 
 * and search radius after the "reset" button is triggerd.
 * 
 * @since   1.1.0
 * @returns {void}
 */
function resetDropdowns() {
	var i, arrayLength, dataValue, catText, $customDiv, $customFirstLi, customSelectedText, customSelectedData,
		defaultFilters = $( "#wpsl-wrap" ).hasClass( "wpsl-default-filters" ),
		defaultValues  = [wpslSettings.searchRadius + ' ' + wpslSettings.distanceUnit, wpslSettings.maxResults],
		dropdowns	   = ["wpsl-radius", "wpsl-results"];

	for ( i = 0, arrayLength = dropdowns.length; i < arrayLength; i++ ) {
		$( "#" + dropdowns[i] + " select" ).val( parseInt( defaultValues[i] ) );
		$( "#" + dropdowns[i] + " li" ).removeClass();

		if ( dropdowns[i] == "wpsl-radius" ) {
			dataValue = wpslSettings.searchRadius;
		} else if ( dropdowns[i] == "wpsl-results" ) {
			dataValue = wpslSettings.maxResults;
		}

		$( "#" + dropdowns[i] + " li" ).each( function() {
			if ( $( this ).text() === defaultValues[i] ) {
				$( this ).addClass( "wpsl-selected-dropdown" );

				$( "#" + dropdowns[i] + " .wpsl-selected-item" ).html( defaultValues[i] ).attr( "data-value", dataValue );
			}
		});
	}

	/** 
	 * Reset the category dropdown.
	 * @todo look for other way to do this in combination with above code. Maybe allow users to define a default cat on the settings page?
	 */
	if ( $( "#wpsl-category" ).length ) {
		$( "#wpsl-category select" ).val( 0 );
		$( "#wpsl-category li" ).removeClass();
		$( "#wpsl-category li:first-child" ).addClass( "wpsl-selected-dropdown" );

		catText = $( "#wpsl-category li:first-child" ).text();

		$( "#wpsl-category .wpsl-selected-item" ).html( catText ).attr( "data-value", 0 );
	}

	// If any custom dropdowns exist, then we reset them as well.
	if ( $( ".wpsl-custom-dropdown" ).length > 0 ) {
		$( ".wpsl-custom-dropdown" ).each( function( index ) {
			
			// Check if we are dealing with the styled dropdowns, or the default select dropdowns.
			if ( !defaultFilters ) {
				$customDiv		   = $( this ).siblings( "div" );
				$customFirstLi	   = $customDiv.find( "li:first-child" );
				customSelectedText = $customFirstLi.text();
				customSelectedData = $customFirstLi.attr( "data-value" );

				$customDiv.find( "li" ).removeClass();
				$customDiv.prev().html( customSelectedText ).attr( "data-value", customSelectedData );	
			} else {
				$( this ).find( "option" ).removeAttr( "selected" );
			}
		});
	}
}

// Handle the click on the back button when the route directions are displayed.
$( "#wpsl-result-list" ).on( "click", ".wpsl-back", function() {	
	var i, len;

    // Remove the directions from the map.
    directionsDisplay.setMap( null );

    // Restore the store markers on the map.
    for ( i = 0, len = markersArray.length; i < len; i++ ) {
		markersArray[i].setMap( map );
    }

	// Restore the start marker on the map.
	if ( ( typeof( startMarkerData ) !== "undefined" )  && ( startMarkerData !== "" ) ) {
		startMarkerData.setMap( map );
	}

	// If marker clusters are enabled, restore them.
	if ( markerClusterer ) {
		checkMarkerClusters();			
	}

	map.setCenter( directionMarkerPosition.centerLatlng );
	map.setZoom( directionMarkerPosition.zoomLevel );	

    $( ".wpsl-direction-before, .wpsl-direction-after" ).remove();
    $( "#wpsl-stores" ).show();
    $( "#wpsl-direction-details" ).hide();

    return false;
});

/**
 * Show the driving directions.
 * 
 * @since	1.1.0
 * @param	{object} e The clicked elemennt
 * @returns {void}
 */
function renderDirections( e ) {
    var i, start, end, len, storeId;
	
	// Force the open InfoBox info window to close.
	closeInfoBoxWindow();

    /* 
     * The storeId is placed on the li in the results list, 
     * but in the marker it will be on the wrapper div. So we check which one we need to target.
     */
    if ( e.parents( "li" ).length > 0 ) {
		storeId = e.parents( "li" ).data( "store-id" );
    } else {
		storeId = e.parents( ".wpsl-info-window" ).data( "store-id" );
    }
	
	// Check if we need to get the start point from a dragged marker.
	if ( ( typeof( startMarkerData ) !== "undefined" )  && ( startMarkerData !== "" ) ) {
		start = startMarkerData.getPosition();
	}
	
	// Used to restore the map back to the state it was in before the user clicked on 'directions'.
	directionMarkerPosition = {
		centerLatlng: map.getCenter(),
		zoomLevel: map.getZoom()	
	};

    // Find the latlng that belongs to the start and end point.
    for ( i = 0, len = markersArray.length; i < len; i++ ) {
		
		// Only continue if the start data is still empty or undefined.
		if ( ( markersArray[i].storeId == 0 ) && ( ( typeof( start ) === "undefined" ) || ( start === "" ) ) ) {
			start = markersArray[i].getPosition();
		} else if ( markersArray[i].storeId == storeId ) {
			end = markersArray[i].getPosition();
		}
    }
	
    if ( start && end ) {
		$( "#wpsl-direction-details ul" ).empty();
		$( ".wpsl-direction-before, .wpsl-direction-after" ).remove();
		calcRoute( start, end );
    } else {
		alert( wpslLabels.generalError );
    } 
}

/**
 * Check what effect is triggerd once a user hovers over the store list. 
 * Either bounce the corresponding marker up and down, open the info window or ignore it.
 */
if ( $( "#wpsl-gmap" ).length ) {	
	if ( wpslSettings.markerEffect == 'bounce' ) {
		$( "#wpsl-stores" ).on( "mouseenter", "li", function() {
			letsBounce( $( this ).data( "store-id" ), "start" );
		});

		$( "#wpsl-stores" ).on( "mouseleave", "li", function() {	
			letsBounce( $( this ).data( "store-id" ), "stop" );
		});
	} else if ( wpslSettings.markerEffect == 'info_window' ) {
		$( "#wpsl-stores" ).on( "mouseenter", "li", function() {
			var i, len;

			for ( i = 0, len = markersArray.length; i < len; i++ ) {
				if ( markersArray[i].storeId == $( this ).data( "store-id" ) ) {
					google.maps.event.trigger( markersArray[i], "click" );
					map.setCenter( markersArray[i].position );
				}
			}
		});	
	}
}

/**
 * Let a single marker bounce.
 * 
 * @since	1.0.0
 * @param	{number} storeId The storeId of the marker that we need to bounce on the map
 * @param	{string} status  Indicates whether we should stop or start the bouncing
 * @returns {void}
 */
function letsBounce( storeId, status ) {
    var i, len, marker;

    // Find the correct marker to bounce based on the storeId.
    for ( i = 0, len = markersArray.length; i < len; i++ ) {
		if ( markersArray[i].storeId == storeId ) {
			marker = markersArray[i];
			
			if ( status == "start" ) {
				marker.setAnimation( google.maps.Animation.BOUNCE );	
			} else {
				marker.setAnimation( null );	
			}
		}
    }	
}

/**
 * Calculate the route from the start to the end.
 * 
 * @since	1.0.0
 * @param	{object} start The latlng from the start point
 * @param	{object} end   The latlng from the end point
 * @returns {void}
 */
function calcRoute( start, end ) {
    var legs, len, step, index, direction, i, j,
		distanceUnit, directionOffset, request,
		directionStops = "";
		
	if ( wpslSettings.distanceUnit == "km" ) {
		distanceUnit = 'METRIC';
	} else {
		distanceUnit = 'IMPERIAL';
	}

	request = {
		origin: start,
		destination: end,
		travelMode: wpslSettings.directionsTravelMode,
		unitSystem: google.maps.UnitSystem[ distanceUnit ] 
	};

    directionsService.route( request, function( response, status ) {
		if ( status == google.maps.DirectionsStatus.OK ) {
			directionsDisplay.setMap( map );
			directionsDisplay.setDirections( response );

			if ( response.routes.length > 0 ) {
				direction = response.routes[0];

				// Loop over the legs and steps of the directions.
				for ( i = 0; i < direction.legs.length; i++ ) {
					legs = direction.legs[i];

					for ( j = 0, len = legs.steps.length; j < len; j++ ) {
						step = legs.steps[j];
						index = j+1;
						directionStops = directionStops + "<li><div class='wpsl-direction-index'>" + index + "</div><div class='wpsl-direction-txt'>" + step.instructions + "</div><div class='wpsl-direction-distance'>" + step.distance.text + "</div></li>";
					}
				}

				$( "#wpsl-direction-details ul" ).append( directionStops ).before( "<div class='wpsl-direction-before'><a class='wpsl-back' id='wpsl-direction-start' href='#'>" + wpslLabels.back + "</a><div><span class='wpsl-total-distance'>" + direction.legs[0].distance.text + "</span> - <span class='wpsl-total-durations'>" + direction.legs[0].duration.text + "</span></div></div>" ).after( "<p class='wpsl-direction-after'>" + response.routes[0].copyrights + "</p>" );
				$( "#wpsl-direction-details" ).show();
				
				// Remove all single markers from the map.
				for ( i = 0, len = markersArray.length; i < len; i++ ) {
					markersArray[i].setMap( null );
				}
			
				// Remove the marker clusters from the map.
				if ( markerClusterer ) {
					markerClusterer.clearMarkers();
				}			
				
				// Remove the start marker from the map.
				if ( ( typeof( startMarkerData ) !== "undefined" ) && ( startMarkerData !== "" ) ) {
					startMarkerData.setMap( null );
				}

				$( "#wpsl-stores" ).hide();		
								
				// Make sure the start of the route directions are visible if the store listings are shown below the map.				
				if ( wpslSettings.templateId == 1 ) {
					directionOffset = $( "#wpsl-gmap" ).offset();
					$( window ).scrollTop( directionOffset.top );
				}
			}
		} else {
			directionErrors( status );
		}
    });
}

/**
 * Geocode the user input.
 * 
 * @since	1.0.0
 * @param	{object} infoWindow The infoWindow object
 * @returns {void}
 */
function codeAddress( infoWindow ) {
    var latLng, request = {};

    // Check if we need to set the geocode component restrictions.
	if ( typeof wpslSettings.geocodeComponents !== "undefined" && !$.isEmptyObject( wpslSettings.geocodeComponents ) ) {
		request.componentRestrictions = wpslSettings.geocodeComponents;

		if ( typeof request.componentRestrictions.postalCode !== "undefined" ) {
            request.componentRestrictions.postalCode = $( "#wpsl-search-input" ).val();
        } else {
            request.address = $( "#wpsl-search-input" ).val();
		}
	} else {
        request.address = $( "#wpsl-search-input" ).val();
	}

    geocoder.geocode( request, function( response, status ) {
		if ( status == google.maps.GeocoderStatus.OK ) {

			if ( statistics.enabled ) {
				collectStatsData( response );
			}

			latLng = response[0].geometry.location;

            prepareStoreSearch( latLng, infoWindow );
		} else {
			geocodeErrors( status );
		}
    });
}

/**
 * Prepare a new location search.
 * 
 * @since	2.2.0
 * @param	{object} latLng 	The coordinates
 * @param	{object} infoWindow The infoWindow object.
 * @returns {void}
 */
function prepareStoreSearch( latLng, infoWindow ) {
	var autoLoad = false;

	// Add a new start marker.
	addMarker( latLng, 0, '', true, infoWindow );

	// Try to find stores that match the radius, location criteria.
	findStoreLocations( latLng, resetMap, autoLoad, infoWindow );
}

/**
 * Reverse geocode the passed coordinates and set the returned zipcode in the input field.
 *
 * @since	1.0.0
 * @param	{object} latLng The coordinates of the location that should be reverse geocoded
 * @returns {object} response The address components if the stats add-on is active.
 */
function reverseGeocode( latLng, callback ) {
    var userLocation,
		lat = latLng.lat().toFixed( 5 ),
		lng = latLng.lng().toFixed( 5 );

    latLng.lat = function() {
        return parseFloat( lat );
    };

    latLng.lng = function() {
        return parseFloat( lng );
    };

    geocoder.geocode( {'latLng': latLng }, function( response, status ) {
        if ( status == google.maps.GeocoderStatus.OK ) {

			if ( wpslSettings.autoLocate == 1 && userGeolocation.newRequest ) {
                userLocation = filterApiResponse( response );

				if ( userLocation !== "" ) {
					$( "#wpsl-search-input" ).val( userLocation );
				}

                /*
                 * Prevent the zip from being placed in the input field
                 * again after the users location is determined.
                 */
                userGeolocation.newRequest = false;
			}

            if ( wpslSettings.directionRedirect ) {
                startAddress = response[0].formatted_address;
            }

            // Prevent it from running on autoload when the input field is empty.
            if ( statistics.enabled && $( "#wpsl-search-input" ).val().length > 0 ) {
                if ( $.isEmptyObject( statistics.addressComponents ) ) {
                    collectStatsData( response );
                }
            }

            callback();
		} else {
			geocodeErrors( status );
		}
	});
}

/**
 * Collect the data for the statistics
 * add-on from the Google Geocode API.
 *
 * @since 2.2.18
 * @param response
 * @returns {void}
 */
function collectStatsData( response ) {
	var requiredFields, addressLength, responseType,
        countryCode, responseLength,
        missingFields = {},
        statsData 	   = {};

    countryCode = findCountryCode( response );

    /**
     * The UK is a special case how the city / town / region / country data
     * is structured in the Geocode API response. So we adjust the structure a bit.
     *
     * We later check which field contained the city / town data
     * and if necessary later move it to the correct one.
     */
    if ( countryCode == "GB" ) {
        requiredFields = {
            'city': 'postal_town',
            'city_locality': 'locality,political',
            'region': 'administrative_area_level_2,political',
            'country': 'administrative_area_level_1,political'
        };
    } else {
        requiredFields = {
            'city': 'locality,political',
            'region': 'administrative_area_level_1,political',
            'country': 'country,political'
        };
    }

    addressLength = response[0].address_components.length;

    // Loop over the first row in the API response.
    for ( i = 0; i < addressLength; i++ ) {
        responseType = response[0].address_components[i].types;

        for ( var key in requiredFields ) {
            if ( requiredFields[key] == responseType.join( "," ) ) {

                // In rare cases the long name is empty.
                if ( response[0].address_components[i].long_name.length > 0 ) {
                    statsData[key] = response[0].address_components[i].long_name;
                } else {
                    statsData[key] = response[0].address_components[i].short_name;
                }
            }
        }
    }

    /**
     * Check if we have the required fields. This is often the case after
     * grabbing the data from the first row, but in some cases we have to loop
     * through all the data to get all the required data.
     */
    for ( var key in requiredFields ) {
        if ( typeof statsData[key] === "undefined" ) {
            missingFields[key] = requiredFields[key];
        }
    }

    /**
     * In the UK the data we want is most of the time in the
     * postal_town ( city ) field, which is often set on the first row.
     *
     * If this field contains data then don't continue and ignore
     * the missing data in the locality field, which is more of a
     * backup in case the 'postal_town' is missing in the API response.
     */
    if ( countryCode == "GB" ) {
        if ( typeof missingFields.city_locality !== "undefined" && typeof missingFields.city === "undefined" ) {
            missingFields = {};
        }
    }

    /**
     * If one or more required fields are missing,
     * then loop through the remaining API data.
     */
    if ( Object.keys( missingFields ).length > 0 ) {
        responseLength = response.length;

        /**
         * Loop over the remaining API results,
         * but skip the first row since we already checked that one.
         */
        for ( i = 1; i < responseLength; i++ ) {
            addressLength = response[i].address_components.length;

            for ( j = 0; j < addressLength; j++ ) {
                responseType = response[i].address_components[j].types;

                for ( var key in missingFields ) {
                    if ( requiredFields[key] == responseType.join( "," ) ) {
                        statsData[key] = response[i].address_components[j].long_name;
                    }
                }
            }
        }
    }

    /**
     * In rare cases, and as far I know this only happens in the UK, the city / town name
     * is often set in the 'postal_town' ( city ) field in the Google API response.
     *
     * But in some cases the 'locality,political' ( city_locality ) field is also
     * set in the first row ( where it's located for locations in the rest of the world ).
     *
     * When both fields are set the 'locality,political' ( city_locality ) will contain more
     * accurate details, so we copy it's value back to the city field.
     */
    if ( typeof statsData.city_locality !== "undefined" && statsData.city_locality.length > 0 ) {
        statsData.city = statsData.city_locality;

        delete statsData.city_locality;
    }

    statistics.addressComponents = statsData;
}

/**
 * Grab the country name from the API response.
 *
 * @since 2.2.18
 * @param {object}  response 	 The API response
 * @return {string} countryCode The country code found in the API response.
 */
function findCountryCode( response ) {
	var responseType, countryCode = '';

    $.each( response[0].address_components, function( index ) {
        responseType = response[0].address_components[index].types;

        if ( responseType.join( ',' ) == 'country,political' ) {
            countryCode = response[0].address_components[index].short_name;

            return false;
        }
    });

	return countryCode;
}

/**
 * Filter out the zip / city name from the API response
 *
 * @since	1.0.0
 * @param	{object} response 	   The complete Google API response
 * @returns {string} userLocation Either the users zip / city name the user is located in
 */
function filterApiResponse( response ) {
    var i, j, responseType, addressLength, userLocation, filteredData = {},
		responseLength = response.length;

	for ( i = 0; i < responseLength; i++ ) {
		addressLength = response[i].address_components.length;

		for ( j = 0; j < addressLength; j++ ) {
			responseType = response[i].address_components[j].types;

			if ( ( /^postal_code$/.test( responseType ) ) || ( /^postal_code,postal_code_prefix$/.test( responseType ) ) ) {
				filteredData.zip = response[i].address_components[j].long_name;

				break;
			}

			if ( /^locality,political$/.test( responseType ) ) {
				filteredData.locality = response[i].address_components[j].long_name;
			}
		}

		if ( typeof filteredData.zip !== "undefined" ) {
			break;
		}
	}

	// If no zip code was found ( it's rare, but it happens ), then we use the city / town name as backup.
	if ( typeof filteredData.zip === "undefined" && typeof filteredData.locality !== "undefined" ) {
		userLocation = filteredData.locality;
	} else {
		userLocation = filteredData.zip;
	}

    return userLocation;
}

/**
 * Call the function to make the ajax request to load the store locations. 
 * 
 * If we need to show the driving directions on maps.google.com itself, 
 * we first need to geocode the start latlng into a formatted address.
 * 
 * @since	1.0.0
 * @param	{object}  startLatLng The coordinates
 * @param	{boolean} resetMap    Whether we should reset the map or not
 * @param	{string}  autoLoad    Check if we need to autoload all the stores
 * @param	{object}  infoWindow  The infoWindow object
 * @returns {void}
 */
function findStoreLocations( startLatLng, resetMap, autoLoad, infoWindow ) {

	if ( wpslSettings.directionRedirect == 1 || statistics.enabled ) {
        reverseGeocode( startLatLng, function() {
			makeAjaxRequest( startLatLng, resetMap, autoLoad, infoWindow );
		});
	} else {
		makeAjaxRequest( startLatLng, resetMap, autoLoad, infoWindow );
	}
}

/**
 * Make the AJAX request to load the store data.
 * 
 * @since	1.2.0
 * @param	{object}  startLatLng The latlng used as the starting point
 * @param	{boolean} resetMap    Whether we should reset the map or not
 * @param	{string}  autoLoad    Check if we need to autoload all the stores
 * @param	{object}  infoWindow  The infoWindow object
 * @returns {void}
 */
function makeAjaxRequest( startLatLng, resetMap, autoLoad, infoWindow ) {
	var latLng, noResultsMsg, ajaxData,
		storeData  = "",
		draggable  = false,
		template   = $( "#wpsl-listing-template" ).html(),
		$storeList = $( "#wpsl-stores ul" ),
		preloader  = wpslSettings.url + "img/ajax-loader.gif";

	ajaxData = collectAjaxData( startLatLng, resetMap, autoLoad );

    // Add the preloader.
	$storeList.empty().append( "<li class='wpsl-preloader'><img src='" + preloader + "'/>" + wpslLabels.preloader + "</li>" );

    $( "#wpsl-wrap" ).removeClass( "wpsl-no-results" );
		
	$.get( wpslSettings.ajaxurl, ajaxData, function( response ) {

	    // Remove the preloaders and no results msg.
        $( ".wpsl-preloader" ).remove();

		if ( response.length > 0 && typeof response.addon == "undefined" ) {

			// Loop over the returned locations.
			$.each( response, function( index ) {
				_.extend( response[index], templateHelpers ); 

				// Add the location maker to the map.
				latLng = new google.maps.LatLng( response[index].lat, response[index].lng );	
				addMarker( latLng, response[index].id, response[index], draggable, infoWindow );	

				// Create the HTML output with help from underscore js.
				storeData = storeData + _.template( template )( response[index] );
			});

			$( "#wpsl-result-list" ).off( "click", ".wpsl-directions" );

			// Remove the old search results.
			$storeList.empty();

			// Add the html for the store listing to the <ul>.
			$storeList.append( storeData );

			$( "#wpsl-result-list" ).on( "click", ".wpsl-directions", function() {

				// Check if we need to render the direction on the map.
				if ( wpslSettings.directionRedirect != 1 ) {
					renderDirections( $( this ) );

					return false;
				}
			});

			// Do we need to create a marker cluster?
			checkMarkerClusters();

			$( "#wpsl-result-list p:empty" ).remove();
		} else {
			addMarker( startLatLng, 0, '', true, infoWindow );
			
			noResultsMsg = getNoResultsMsg();

			$( "#wpsl-wrap" ).addClass( "wpsl-no-results" );
			
			$storeList.html( "<li class='wpsl-no-results-msg'>" + noResultsMsg + "</li>" );
		}
		
		/*
		 * Do we need to adjust the zoom level so that all the markers fit in the viewport,
		 * or just center the map on the start marker.
		 */
        if ( wpslSettings.runFitBounds == 1 ) {
            fitBounds();
		} else {
            map.setZoom( Number( wpslSettings.zoomLevel ) );
            map.setCenter( markersArray[0].position );
        }
		
		/*
		 * Store the default zoom and latlng values the first time 
		 * all the stores are added to the map.
		 * 
		 * This way when a user clicks the reset button we can check if the 
		 * zoom/latlng values have changed, and if they have, then we know we 
		 * need to reload the map.
		 */
		if ( wpslSettings.resetMap == 1 ) {
			if ( $.isEmptyObject( mapDefaults ) ) {
				google.maps.event.addListenerOnce( map, "tilesloaded", function() {
					mapDefaults = {
						centerLatlng: map.getCenter(),
						zoomLevel: map.getZoom()
					};
															
					/*
					 * Because the reset icon exists, we need to adjust 
					 * the styling of the direction icon. 
					 */
					$( "#wpsl-map-controls" ).addClass( "wpsl-reset-exists" );

					/*
					 * The reset initialy is set to hidden to prevent 
					 * users from clicking it before the map is loaded. 
					 */
					$( ".wpsl-icon-reset, #wpsl-reset-map" ).show();
				});
			}
			
			$( ".wpsl-icon-reset" ).removeClass( "wpsl-in-progress" );
		}
	});	
	
	// Move the mousecursor to the store search field if the focus option is enabled.
	if ( wpslSettings.mouseFocus == 1 && !checkMobileUserAgent() ) {
		$( "#wpsl-search-input" ).focus();
	}
}

/**
 * Collect the data we need to include in the AJAX request.
 * 
 * @since	2.2.0
 * @param	{object}  startLatLng The latlng used as the starting point
 * @param	{boolean} resetMap    Whether we should reset the map or not
 * @param	{string}  autoLoad    Check if we need to autoload all the stores
 * @returns {object}  ajaxData	  The collected data.
 */
function collectAjaxData( startLatLng, resetMap, autoLoad ) {
	var maxResult, radius, customDropdownName, customDropdownValue,
        customCheckboxName,
		categoryId	   = "",
		isMobile	   = $( "#wpsl-wrap" ).hasClass( "wpsl-mobile" ),
		defaultFilters = $( "#wpsl-wrap" ).hasClass( "wpsl-default-filters" ),
		ajaxData = {
			action: "store_search",
			lat: startLatLng.lat(),
			lng: startLatLng.lng()
		};
	
	/* 
	 * If we reset the map we use the default dropdown values instead of the selected values. 
	 * Otherwise we first make sure the filter val is valid before including the radius / max_results param
	 */
	if ( resetMap ) {
		ajaxData.max_results   = wpslSettings.maxResults;
		ajaxData.search_radius = wpslSettings.searchRadius;
	} else {
		if ( isMobile || defaultFilters ) {
			maxResult = parseInt( $( "#wpsl-results .wpsl-dropdown" ).val() );
			radius 	  = parseInt( $( "#wpsl-radius .wpsl-dropdown" ).val() );
		} else {
			maxResult = parseInt( $( "#wpsl-results .wpsl-selected-item" ).attr( "data-value" ) );
			radius    = parseInt( $( "#wpsl-radius .wpsl-selected-item" ).attr( "data-value" ) );
		}
		
		// If the max results or radius filter values are NaN, then we use the default value.
		if ( isNaN( maxResult ) ) {
			ajaxData.max_results = wpslSettings.maxResults;
		} else {
			ajaxData.max_results = maxResult;
		}
		
		if ( isNaN( radius ) ) {
			ajaxData.search_radius = wpslSettings.searchRadius;
		} else {
			ajaxData.search_radius = radius;
		}
		
		/* 
		 * If category ids are set through the wpsl shortcode, then we always need to include them.
		 * Otherwise check if the category dropdown exist, or if the checkboxes are used.
		 */
		if ( typeof wpslSettings.categoryIds !== "undefined" ) {
			ajaxData.filter = wpslSettings.categoryIds;
		} else if ( $( "#wpsl-category" ).length > 0 ) {
			if ( isMobile || defaultFilters ) {
				categoryId = parseInt( $( "#wpsl-category .wpsl-dropdown" ).val() );
			} else {
				categoryId = parseInt( $( "#wpsl-category .wpsl-selected-item" ).attr( "data-value" ) );				
			}

			if ( ( !isNaN( categoryId ) && ( categoryId !== 0 ) ) )  {
				ajaxData.filter = categoryId;
			}
		} else if ( $( "#wpsl-checkbox-filter" ).length > 0 ) {
			if ( $( "#wpsl-checkbox-filter input:checked" ).length > 0 ) {
				ajaxData.filter = getCheckboxIds();
			}
		}

		// Include values from custom dropdowns.
		if ( $( ".wpsl-custom-dropdown" ).length > 0 ) {
			$( ".wpsl-custom-dropdown" ).each( function( index ) {
				customDropdownName  = '';
				customDropdownValue = '';

				if ( isMobile || defaultFilters ) {
					customDropdownName  = $( this ).attr( "name" );
					customDropdownValue = $( this ).val();
				} else {
					customDropdownName  = $( this ).attr( "name" );
					customDropdownValue = $( this ).next( ".wpsl-selected-item" ).attr( "data-value" );
				}

				if ( customDropdownName && customDropdownValue ) {
					ajaxData[customDropdownName] = customDropdownValue;
				}
			});	
		}

		// Include values from custom checkboxes
        if ( $( ".wpsl-custom-checkboxes" ).length > 0 ) {
            $( ".wpsl-custom-checkboxes" ).each( function( index ) {
				customCheckboxName = $( this ).attr( "data-name" );

                if ( customCheckboxName ) {
                    ajaxData[customCheckboxName] = getCustomCheckboxValue( customCheckboxName );
                }
			});
        }
	}

   /*
	* If the autoload option is enabled, then we need to check if the included latlng 
	* is based on a geolocation attempt before including the autoload param.
	* 
	* Because if both the geolocation and autoload options are enabled, 
	* and the geolocation attempt was successful, then we need to to include
	* the skip_cache param. 
	* 
	* This makes sure the results don't come from an older transient based on the 
	* start location from the settings page, instead of the users actual location. 
	*/
    if ( autoLoad == 1 ) {
		if ( typeof userGeolocation.position !== "undefined" ) {
			ajaxData.skip_cache = 1;
		} else {
			ajaxData.autoload = 1;
			
			/* 
			 * If the user set the 'category' attr on the wpsl shortcode, then include the cat ids 
			 * to make sure only locations from the set categories are loaded on autoload.
			 */
			if ( typeof wpslSettings.categoryIds !== "undefined" ) {
				ajaxData.filter = wpslSettings.categoryIds;
			}
		}
	}
	
	// If the collection of statistics is enabled, then we include the searched value.
	if ( statistics.enabled && autoLoad == 0 ) {
		ajaxData.search = $( "#wpsl-search-input" ).val();
        ajaxData.statistics = statistics.addressComponents;
    }
	
	return ajaxData;
}

/**
 * Get custom checkbox values by data-name group.
 *
 * If multiple selection are made, then the returned
 * values are comma separated
 *
 * @since  2.2.8
 * @param  {string} customCheckboxName The data-name value of the custom checkbox
 * @return {string} customValue		   The collected checkbox values separated by a comma
 */
function getCustomCheckboxValue( customCheckboxName ) {
	var dataName    = $( "[data-name=" + customCheckboxName + "]" ),
		customValue = [];

	$( dataName ).find( "input:checked" ).each( function( index ) {
        customValue.push( $( this ).val() );
	});

	return customValue.join();
}

/**
 * Check which no results msg we need to show. 
 * 
 * Either the default txt or a longer custom msg.
 * 
 * @since  2.2.0
 * @return string noResults The no results msg to show.
 */
function getNoResultsMsg() {
	var noResults;
	
	if ( typeof wpslSettings.noResults !== "undefined" && wpslSettings.noResults !== "" ) {
		noResults = wpslSettings.noResults;
	} else {
		noResults = wpslLabels.noResults;
	}
	
	return noResults;
}

/**
 * Collect the ids of the checked checkboxes.
 * 
 * @since  2.2.0
 * @return string catIds The cat ids from the checkboxes.
 */
function getCheckboxIds() {
	var catIds = $( "#wpsl-checkbox-filter input:checked" ).map( function() {
		return $( this ).val();
	});
	
	catIds = catIds.get();
	catIds = catIds.join(',');
	
	return catIds;
}

/**
 * Check if cluster markers are enabled.
 * If so, init the marker clustering with the 
 * correct gridsize and max zoom.
 * 
 * @since  1.2.20
 * @return {void}
 */
function checkMarkerClusters() {
	if ( wpslSettings.markerClusters == 1 ) {
		var markers, markersArrayNoStart,
			clusterZoom = Number( wpslSettings.clusterZoom ),
			clusterSize = Number( wpslSettings.clusterSize );

		if ( isNaN( clusterZoom ) ) {
			clusterZoom = "";
		}
		
		if ( isNaN( clusterSize ) ) {
			clusterSize = "";
		}

        /*
         * Remove the start location marker from the cluster so the location
         * count represents the actual returned locations, and not +1 for the start location.
         */
		if ( typeof wpslSettings.excludeStartFromCluster !== "undefined" && wpslSettings.excludeStartFromCluster == 1 ) {
            markersArrayNoStart = markersArray.slice( 0 );
            markersArrayNoStart.splice( 0,1 );
        }

        markers = ( typeof markersArrayNoStart === "undefined" ) ? markersArray : markersArrayNoStart;

        markerClusterer = new MarkerClusterer( map, markers, {
			gridSize: clusterSize,
			maxZoom: clusterZoom
		});
	}
}

/**
 * Add a new marker to the map based on the provided location (latlng).
 * 
 * @since  1.0.0
 * @param  {object}  latLng		    The coordinates
 * @param  {number}  storeId		The store id
 * @param  {object}  infoWindowData The data we need to show in the info window
 * @param  {boolean} draggable      Should the marker be draggable
 * @param  {object}  infoWindow     The infoWindow object
 * @return {void}
 */
function addMarker( latLng, storeId, infoWindowData, draggable, infoWindow ) {
	var url, mapIcon, marker,
		keepStartMarker = true;

    if ( storeId === 0 ) {
        infoWindowData = {
            store: wpslLabels.startPoint
        };

        url = markerSettings.url + wpslSettings.startMarker;
    } else if ( typeof infoWindowData.alternateMarkerUrl !== "undefined" && infoWindowData.alternateMarkerUrl ) {
		url = infoWindowData.alternateMarkerUrl;
	} else if ( typeof infoWindowData.categoryMarkerUrl !== "undefined" && infoWindowData.categoryMarkerUrl ) {
		url = infoWindowData.categoryMarkerUrl;
	} else {
		url = markerSettings.url + wpslSettings.storeMarker;
	}

	mapIcon = {
		url: url,
		scaledSize: new google.maps.Size( Number( markerSettings.scaledSize[0] ), Number( markerSettings.scaledSize[1] ) ), //retina format
		origin: new google.maps.Point( Number( markerSettings.origin[0] ), Number( markerSettings.origin[1] ) ),
		anchor: new google.maps.Point( Number( markerSettings.anchor[0] ), Number( markerSettings.anchor[1] ) )
	};

    marker = new google.maps.Marker({
		position: latLng,
		map: map,
		optimized: false, //fixes markers flashing while bouncing
		title: decodeHtmlEntity( infoWindowData.store ),
		draggable: draggable,
		storeId: storeId,
		icon: mapIcon
	});	

	// Store the marker for later use.
	markersArray.push( marker );

    google.maps.event.addListener( marker, "click",( function( currentMap ) {
		return function() {
			
			// The start marker will have a store id of 0, all others won't.
			if ( storeId != 0 ) {

				// Check if streetview is available at the clicked location.
				if ( typeof wpslSettings.markerStreetView !== "undefined" && wpslSettings.markerStreetView == 1 ) {
					checkStreetViewStatus( latLng, function() {
						setInfoWindowContent( marker, createInfoWindowHtml( infoWindowData ), infoWindow, currentMap );
					});
				} else {
					setInfoWindowContent( marker, createInfoWindowHtml( infoWindowData ), infoWindow, currentMap );
				}
			} else {
				setInfoWindowContent( marker, wpslLabels.startPoint, infoWindow, currentMap );
			}

			google.maps.event.clearListeners( infoWindow, "domready" );
			
			google.maps.event.addListener( infoWindow, "domready", function() {
				infoWindowClickActions( marker, currentMap );
				checkMaxZoomLevel();
			});
		};
    }( map ) ) );
	
	// Only the start marker will be draggable.
	if ( draggable ) {
		google.maps.event.addListener( marker, "dragend", function( event ) {
			deleteOverlays( keepStartMarker );
			map.setCenter( event.latLng );
			reverseGeocode( event.latLng );
			findStoreLocations( event.latLng, resetMap, autoLoad = false, infoWindow );
		}); 
    }
}

/**
 * Decode HTML entities.
 * 
 * @link	https://gist.github.com/CatTail/4174511
 * @since	2.0.4
 * @param	{string} str The string to decode.
 * @returns {string} The string with the decoded HTML entities.
 */
function decodeHtmlEntity( str ) {
	if ( str ) {
		return str.replace( /&#(\d+);/g, function( match, dec) {
			return String.fromCharCode( dec );
		});
	}
};

// Check if we are using both the infobox for the info windows and have marker clusters.
if ( typeof wpslSettings.infoWindowStyle !== "undefined" && wpslSettings.infoWindowStyle == "infobox" && wpslSettings.markerClusters == 1 ) {
	var clusters, clusterLen, markerLen, i, j;
	
	/* 
	 * We need to listen to both zoom_changed and idle. 
	 * 
	 * If the zoom level changes, then the marker clusters either merges nearby 
	 * markers, or changes into individual markers. Which is the moment we 
	 * either show or hide the opened info window.
	 * 
	 * "idle" is necessary to make sure the getClusters() is up 
	 * to date with the correct cluster data.
	 */
	google.maps.event.addListener( map, "zoom_changed", function() {
		google.maps.event.addListenerOnce( map, "idle", function() {

			if ( typeof markerClusterer !== "undefined" ) {		
				clusters = markerClusterer.clusters_;

				if ( clusters.length ) {
					for ( i = 0, clusterLen = clusters.length; i < clusterLen; i++ ) {
						for ( j = 0, markerLen = clusters[i].markers_.length; j < markerLen; j++ ) {

							/* 
							 * Match the storeId from the cluster marker with the 
							 * marker id that was set when the info window was opened 
							 */
							if ( clusters[i].markers_[j].storeId == activeWindowMarkerId ) {

								/* 
								 * If there is a visible info window, but the markers_[j].map is null ( hidden ) 
								 * it means the info window belongs to a marker that is part of a marker cluster.
								 * 
								 * If that is the case then we hide the info window ( the individual marker isn't visible ).
								 *
								 * The default info window script handles this automatically, but the
								 * infobox library in combination with the marker clusters doesn't.
								 */
								if ( infoWindow.getVisible() && clusters[i].markers_[j].map === null ) {
									infoWindow.setVisible( false );
								} else if ( !infoWindow.getVisible() && clusters[i].markers_[j].map !== null ) {
									infoWindow.setVisible( true );
								}

								break;
							}
						}
					}
				}
			}
		});
	});
}

/**
 * Set the correct info window content for the marker.
 * 
 * @since	1.2.20
 * @param	{object} marker			   Marker data
 * @param	{string} infoWindowContent The infoWindow content
 * @param	{object} infoWindow		   The infoWindow object
 * @param	{object} currentMap		   The map object
 * @returns {void}
 */
function setInfoWindowContent( marker, infoWindowContent, infoWindow, currentMap ) {
	openInfoWindow.length = 0;
	
	infoWindow.setContent( infoWindowContent );
	infoWindow.open( currentMap, marker );
	
	openInfoWindow.push( infoWindow );

	/* 
	 * Store the marker id if both the marker clusters and the infobox are enabled.
	 * 
	 * With the normal info window script the info window is automatically closed 
	 * once a user zooms out, and the marker clusters are enabled, 
	 * but this doesn't happen with the infobox library. 
	 * 
	 * So we need to show/hide it manually when the user zooms out, 
	 * and for this to work we need to know which marker to target. 
	 */
	if ( typeof wpslSettings.infoWindowStyle !== "undefined" && wpslSettings.infoWindowStyle == "infobox" && wpslSettings.markerClusters == 1 ) {
		activeWindowMarkerId = marker.storeId;
		infoWindow.setVisible( true );
	}
}

/**
 * Handle clicks for the different info window actions like, 
 * direction, streetview and zoom here.
 * 
 * @since	1.2.20
 * @param	{object} marker		Holds the marker data
 * @param	{object} currentMap	The map object
 * @returns {void}
 */
function infoWindowClickActions( marker, currentMap ) {
	$( ".wpsl-info-actions a" ).on( "click", function( e ) {
		var maxZoom = Number( wpslSettings.autoZoomLevel );

		e.stopImmediatePropagation();
				
		if ( $( this ).hasClass( "wpsl-directions" ) ) {

			/* 
			 * Check if we need to show the direction on the map
			 * or send the users to maps.google.com 
			 */
			if ( wpslSettings.directionRedirect == 1 ) {
				return true;
			} else {
				renderDirections( $( this ) );
			}
		} else if ( $( this ).hasClass( "wpsl-streetview" ) ) {
			activateStreetView( marker, currentMap );
		} else if ( $( this ).hasClass( "wpsl-zoom-here" ) ) {
			currentMap.setCenter( marker.getPosition() );
			currentMap.setZoom( maxZoom );
		}
		
		return false;
	});
}

/**
 * Check if have reached the max auto zoom level.
 * 
 * If so we hide the 'Zoom here' text in the info window, 
 * otherwise we show it.
 * 
 * @since	2.0.0
 * @returns {void}
 */
function checkMaxZoomLevel() {
	var zoomLevel = map.getZoom();

	if ( zoomLevel >= wpslSettings.autoZoomLevel ) {
		$( ".wpsl-zoom-here" ).hide();
	} else {
		$( ".wpsl-zoom-here" ).show();
	}	
}
	
/**
 * Activate streetview for the clicked location.
 * 
 * @since	1.2.20
 * @param	{object} marker	    The current marker
 * @param	{object} currentMap The map object
 * @returns {void}
 */
function activateStreetView( marker, currentMap ) {
	var panorama = currentMap.getStreetView();
		panorama.setPosition( marker.getPosition() );
		panorama.setVisible( true );
				
	$( "#wpsl-map-controls" ).hide();
		
	StreetViewListener( panorama, currentMap );
}

/**
 * Listen for changes in the streetview visibility.
 * 
 * Sometimes the infowindow offset is incorrect after switching back from streetview.
 * We fix this by zooming in and out. If someone has a better fix, then let me know at
 * info at tijmensmit.com
 * 
 * @since	1.2.20
 * @param	{object} panorama   The streetview object
 * @param	{object} currentMap The map object
 * @returns {void}
 */
function StreetViewListener( panorama, currentMap ) {
	google.maps.event.addListener( panorama, "visible_changed", function() {
		if ( !panorama.getVisible() ) {
			var currentZoomLevel = currentMap.getZoom();
			
			$( "#wpsl-map-controls" ).show();
			
			currentMap.setZoom( currentZoomLevel-1 );
			currentMap.setZoom( currentZoomLevel );
		}
	});
}

/**
 * Check the streetview status.
 * 
 * Make sure that a streetview exists for 
 * the latlng for the open info window.
 * 
 * @since	1.2.20
 * @param	{object}   latLng The latlng coordinates
 * @param	{callback} callback
 * @returns {void}
 */
function checkStreetViewStatus( latLng, callback ) {
	var service = new google.maps.StreetViewService();

	service.getPanoramaByLocation( latLng, 50, function( result, status ) {
		streetViewAvailable = ( status == google.maps.StreetViewStatus.OK ) ? true : false;	
		callback();
	});
}

/**
 * Helper methods for the underscore templates.
 * 
 * @link	 http://underscorejs.org/#template
 * @requires underscore.js
 * @todo move it to another JS file to make it accessible for add-ons?
 * @since	 2.0.0
 */
var templateHelpers = {
	/**
	 * Make the phone number clickable if we are dealing with a mobile useragent.
	 * 
	 * @since	1.2.20
	 * @param	{string} phoneNumber The phone number
	 * @returns {string} phoneNumber Either just the plain number, or with a link wrapped around it with tel:
	 */
	formatPhoneNumber: function( phoneNumber ) {
		if ( ( wpslSettings.phoneUrl == 1 ) && ( checkMobileUserAgent() ) || wpslSettings.clickableDetails == 1 ) {
			phoneNumber = "<a href='tel:" + templateHelpers.formatClickablePhoneNumber( phoneNumber ) + "'>" + phoneNumber + "</a>";
		}

		return phoneNumber;
	},
	/**
	 * Replace spaces - . and () from phone numbers. 
	 * Also if the number starts with a + we check for a (0) and remove it.
	 * 
	 * @since	1.2.20
	 * @param	{string} phoneNumber The phone number
	 * @returns {string} phoneNumber The 'cleaned' number
	 */
	formatClickablePhoneNumber: function( phoneNumber ) {
		if ( ( phoneNumber.indexOf( "+" ) != -1 ) && ( phoneNumber.indexOf( "(0)" ) != -1 ) ) {
			phoneNumber = phoneNumber.replace( "(0)", "" );
		}

		return phoneNumber.replace( /(-| |\(|\)|\.|)/g, "" );	
	},
    /**
	 * Check if we need to make the email address clickable.
	 *
	 * @since 2.2.13
     * @param   {string} email The email address
	 * @returns {string} email Either the normal email address, or the clickable version.
     */
	formatEmail: function( email ) {
        if ( wpslSettings.clickableDetails == 1 ) {
            email = "<a href='mailto:" + email + "'>" + email + "</a>";
        }

		return email;
	},
	/**
	 * Create the html for the info window action.
	 * 
	 * @since	2.0.0
	 * @param	{string} id		The store id
	 * @returns {string} output The html for the info window actions
	 */
	createInfoWindowActions: function( id ) {
		var output, 
			streetView = "",
			zoomTo	   = "";

		if ( $( "#wpsl-gmap" ).length ) {
			if ( streetViewAvailable ) {
				streetView = "<a class='wpsl-streetview' href='#'>" + wpslLabels.streetView + "</a>";
			}

			if ( wpslSettings.markerZoomTo == 1 ) {
				zoomTo = "<a class='wpsl-zoom-here' href='#'>" + wpslLabels.zoomHere + "</a>";
			}

			output = "<div class='wpsl-info-actions'>" + templateHelpers.createDirectionUrl( id ) + streetView + zoomTo + "</div>";	
		}

		return output;
	},
	/**
	 * Create the url that takes the user to the maps.google.com page 
	 * and shows the correct driving directions.
	 * 
	 * @since	1.0.0
	 * @param	{string} id			  The store id
	 * @returns {string} directionUrl The full maps.google.com url with the encoded start + end address
	 */
	createDirectionUrl: function( id ) {
		var directionUrl, destinationAddress, zip,
			url = {};

		if ( wpslSettings.directionRedirect == 1 ) {

			// If we somehow failed to determine the start address, just set it to empty.
			if ( typeof startAddress === "undefined" ) {
				startAddress = "";
			}
			
			url.target = "target='_blank'";
			
			// If the id exists the user clicked on a marker we get the direction url from the search results.
			if ( typeof id !== "undefined" ) {
				url.src = $( "[data-store-id=" + id + "] .wpsl-directions" ).attr( "href" );
			} else {

				// Only add a , after the zip if the zip value exists.
				if ( this.zip ) {
					zip = this.zip + ", ";
				} else {
					zip = "";
				}

				destinationAddress = this.address + ", " + this.city + ", " + zip + this.country;

				url.src = "https://www.google.com/maps/dir/?api=1&origin=" + templateHelpers.rfc3986EncodeURIComponent( startAddress ) + "&destination=" + templateHelpers.rfc3986EncodeURIComponent( destinationAddress ) + "&travelmode=" + wpslSettings.directionsTravelMode.toLowerCase() + "";
			}
		} else {
			url = {
				src: "#",
				target: ""
			};
		}	

		directionUrl = "<a class='wpsl-directions' " + url.target + " href='" + url.src + "'>" + wpslLabels.directions + "</a>";

		return directionUrl;
	},
	/**
	 * Make the URI encoding compatible with RFC 3986.
	 * 
	 * !, ', (, ), and * will be escaped, otherwise they break the string.
	 * 
	 * @since	1.2.20
	 * @param	{string} str The string to encode
	 * @returns {string} The encoded string
	 */
	rfc3986EncodeURIComponent: function( str ) {  
		return encodeURIComponent( str ).replace( /[!'()*]/g, escape );  
	}
};

/**
 * Create the HTML template used in the info windows on the map.
 * 
 * @since	1.0.0
 * @param	{object} infoWindowData	The data that is shown in the info window (address, url, phone etc)
 * @returns {string} windowContent	The HTML content that is placed in the info window
 */
function createInfoWindowHtml( infoWindowData ) {
	var windowContent, template;

	if ( $( "#wpsl-base-gmap_0" ).length ) {
		template = $( "#wpsl-cpt-info-window-template" ).html();
	} else {
		template = $( "#wpsl-info-window-template" ).html();
	}

	windowContent = _.template( template )( infoWindowData ); //see http://underscorejs.org/#template

	return windowContent;
}

/**
 * Zoom the map so that all markers fit in the window.
 * 
 * @since	1.0.0
 * @returns {void}
 */
function fitBounds() {
    var i, markerLen, 
		maxZoom = Number( wpslSettings.autoZoomLevel ),
		bounds  = new google.maps.LatLngBounds();
		
    // Make sure we don't zoom to far.
    attachBoundsChangedListener( map, maxZoom );

    for ( i = 0, markerLen = markersArray.length; i < markerLen; i++ ) {
		bounds.extend ( markersArray[i].position );
    }

    map.fitBounds( bounds );
}

/**
 * Remove all existing markers from the map.
 * 
 * @since	1.0.0
 * @param	{boolean} keepStartMarker Whether or not to keep the start marker while removing all the other markers from the map
 * @returns {void}
 */
function deleteOverlays( keepStartMarker ) {
	var markerLen, i;
	
    directionsDisplay.setMap( null );
	
    // Remove all the markers from the map, and empty the array.
    if ( markersArray ) {
		for ( i = 0, markerLen = markersArray.length; i < markerLen; i++ ) {
			
			// Check if we need to keep the start marker, or remove everything.
			if ( keepStartMarker ) {
				if ( markersArray[i].draggable != true ) {
					markersArray[i].setMap( null );
				} else {
					startMarkerData = markersArray[i];
				}
			} else {
				markersArray[i].setMap( null );
			}
		}

		markersArray.length = 0;
    }
	
	// If marker clusters exist, remove them from the map.
	if ( markerClusterer ) {
		markerClusterer.clearMarkers();
	}
}

/**
 * Handle the geocode errors.
 * 
 * @since	1.0.0
 * @param   {string} status Contains the error code
 * @returns {void}
 */
function geocodeErrors( status ) {
    var msg;

    switch ( status ) {
		case "ZERO_RESULTS":
			msg = wpslLabels.noResults;
			break;	
		case "OVER_QUERY_LIMIT":
			msg = wpslLabels.queryLimit;
			break;	
		default:
			msg = wpslLabels.generalError;
			break;
    }

    alert( msg );	
}

/**
 * Handle the driving direction errors.
 * 
 * @since   1.2.20
 * @param   {string} status Contains the error code
 * @returns {void}
 */
function directionErrors( status ) {
    var msg;

    switch ( status ) {
		case "NOT_FOUND":
		case "ZERO_RESULTS":
			msg = wpslLabels.noDirectionsFound;
			break;	
		case "OVER_QUERY_LIMIT":
			msg = wpslLabels.queryLimit;
			break;
		default:
			msg = wpslLabels.generalError;
			break;
    }

    alert( msg );	
}

$( "#wpsl-stores" ).on( "click", ".wpsl-store-details", function() {	
	var i, len,
		$parentLi = $( this ).parents( "li" ),
		storeId   = $parentLi.data( "store-id" );

	// Check if we should show the 'more info' details.
	if ( wpslSettings.moreInfoLocation == "info window" ) {
		for ( i = 0, len = markersArray.length; i < len; i++ ) {
			if ( markersArray[i].storeId == storeId ) {
				google.maps.event.trigger( markersArray[i], "click" );
			}
		}
	} else {
		
		// Check if we should set the 'more info' item to active or not.
		if ( $parentLi.find( ".wpsl-more-info-listings" ).is( ":visible" ) ) {
			$( this ).removeClass( "wpsl-active-details" );
		} else {
			$( this ).addClass( "wpsl-active-details" );
		}		
		
		$parentLi.siblings().find( ".wpsl-store-details" ).removeClass( "wpsl-active-details" );
		$parentLi.siblings().find( ".wpsl-more-info-listings" ).hide();
		$parentLi.find( ".wpsl-more-info-listings" ).toggle();
	}

	/* 
	 * If we show the store listings under the map, we do want to jump to the 
	 * top of the map to focus on the opened infowindow 
	 */
	if ( wpslSettings.templateId != "default" || wpslSettings.moreInfoLocation == "store listings" ) {
		return false;
	}
});

/**
 * Create the styled dropdown filters.
 * 
 * Inspired by https://github.com/patrickkunka/easydropdown
 * 
 * @since	1.2.24
 * @returns {void}
 */
function createDropdowns() {
	var maxDropdownHeight = Number( wpslSettings.maxDropdownHeight );
		
	$( ".wpsl-dropdown" ).each( function( index ) {
		var	active, maxHeight, $this = $( this );
		
		$this.$dropdownWrap = $this.wrap( "<div class='wpsl-dropdown'></div>" ).parent();	
		$this.$selectedVal  = $this.val();							
		$this.$dropdownElem = $( "<div><ul/></div>" ).appendTo( $this.$dropdownWrap );
		$this.$dropdown     = $this.$dropdownElem.find( "ul" );
		$this.$options 	  	= $this.$dropdownWrap.find( "option" );
		
		// Hide the original <select> and remove the css class.
		$this.hide().removeClass( "wpsl-dropdown" );
		
		// Loop over the options from the <select> and move them to a <li> instead.
		$.each( $this.$options, function() {
			if ( $( this ).val() == $this.$selectedVal ) {
				active = 'class="wpsl-selected-dropdown"';
			} else {
				active = '';
			}

			$this.$dropdown.append( "<li data-value=" + $( this ).val() + " " + active + ">" + $( this ).text() + "</li>" );
		});	
		
		$this.$dropdownElem.before( "<span data-value=" + $this.find( ":selected" ).val() + " class='wpsl-selected-item'>" + $this.find( ":selected" ).text() + "</span>" );
		$this.$dropdownItem = $this.$dropdownElem.find( "li" );
		
		// Listen for clicks on the 'wpsl-dropdown' div.
		$this.$dropdownWrap.on( "click", function( e ) {

			// Check if we only need to close the current open dropdown.
			if ( $( this ).hasClass( "wpsl-active" ) ) {
				$( this ).removeClass( "wpsl-active" );

				return;
			}

			closeAllDropdowns();

			$( this ).toggleClass( "wpsl-active" );
			maxHeight = 0;

			// Either calculate the correct height for the <ul>, or set it to 0 to hide it.
			if ( $( this ).hasClass( "wpsl-active" ) ) {
				$this.$dropdownItem.each( function( index ) {
					maxHeight += $( this ).outerHeight();
				});

				$this.$dropdownElem.css( "height", maxHeight + 2 + "px" );
			} else {
				$this.$dropdownElem.css( "height", 0 );
			}

			// Check if we need to enable the scrollbar in the dropdown filter.
			if ( maxHeight > maxDropdownHeight ) {
				$( this ).addClass( "wpsl-scroll-required" );
				$this.$dropdownElem.css( "height", ( maxDropdownHeight ) + "px" );
			}

			e.stopPropagation();
		});
		
		// Listen for clicks on the individual dropdown items.
		$this.$dropdownItem.on( "click", function( e ) {
			
			// Set the correct value as the selected item.
			$this.$dropdownWrap.find( $( ".wpsl-selected-item" ) ).html( $( this ).text() ).attr( "data-value", $( this ).attr( "data-value" ) );	

			// Apply the class to the correct item to make it bold.
			$this.$dropdownItem.removeClass( "wpsl-selected-dropdown" );
			$( this ).addClass( "wpsl-selected-dropdown" );
			
			closeAllDropdowns();
			
			e.stopPropagation();
		});
	});	
	
	$( document ).click( function() {
		closeAllDropdowns();
	});
}

/**
 * Close all the dropdowns.
 * 
 * @since	1.2.24
 * @returns {void}
 */
function closeAllDropdowns() {
	$( ".wpsl-dropdown" ).removeClass( "wpsl-active" );
	$( ".wpsl-dropdown div" ).css( "height", 0 );	
}

/**
 * Check if the user submitted a search through a search widget.
 *
 * @since	2.1.0
 * @returns {void}
 */
function checkWidgetSubmit() {
	if ( $( ".wpsl-search" ).hasClass( "wpsl-widget" ) ) {
		$( "#wpsl-search-btn" ).trigger( "click" );
		$( ".wpsl-search" ).removeClass( "wpsl-widget" );
	}
}

/**
 * Check if we need to run the code to prevent Google Maps
 * from showing up grey when placed inside one or more tabs.
 *
 * @since 2.2.10
 * @return {void}
 */
function maybeApplyTabFix() {
	var mapNumber, len;

	if ( _.isArray( wpslSettings.mapTabAnchor ) ) {
		for ( mapNumber = 0, len = mapsArray.length; mapNumber < len; mapNumber++ ) {
			fixGreyTabMap( mapsArray[mapNumber], wpslSettings.mapTabAnchor[mapNumber], mapNumber );
		}
	} else if ( $( "a[href='#" + wpslSettings.mapTabAnchor + "']" ).length ) {
		fixGreyTabMap( map, wpslSettings.mapTabAnchor );
	}
}

/**
 * This code prevents the map from showing a large grey area if
 * the store locator is placed in a tab, and that tab is actived.
 *
 * The default map anchor is set to 'wpsl-map-tab', but you can
 * change this with the 'wpsl_map_tab_anchor' filter.
 *
 * Note: If the "Attempt to auto-locate the user" option is enabled,
 * and the user quickly switches to the store locator tab, before the
 * Geolocation timeout is reached, then the map is sometimes centered in the ocean.
 *
 * I haven't really figured out why this happens. The only option to fix this
 * is to simply disable the "Attempt to auto-locate the user" option if
 * you use the store locator in a tab.
 *
 * @since   2.2.10
 * @param   {object} currentMap	  The map object from the current map
 * @param   {string} mapTabAnchor The anchor used in the tab that holds the map
 * @param 	(int) 	 mapNumber    Map number
 * @link    http://stackoverflow.com/questions/9458215/google-maps-not-working-in-jquery-tabs
 * @returns {void}
 */
function fixGreyTabMap( currentMap, mapTabAnchor, mapNumber ) {
    var mapZoom, mapCenter, maxZoom, bounds, tabMap,
        returnBool = Number( wpslSettings.mapTabAnchorReturn ) ? true : false,
		$wpsl_tab  = $( "a[href='#" + mapTabAnchor + "']" );

    if ( typeof currentMap.maxZoom !== "undefined" ) {
        maxZoom = currentMap.maxZoom;
	} else {
        maxZoom = Number( wpslSettings.autoZoomLevel );
	}

	/*
	 * We need to do this to prevent the map from flashing if
	 * there's only a single marker on the first click on the tab.
	 */
	if ( typeof mapNumber !== "undefined" && mapNumber == 0 ) {
        $wpsl_tab.addClass( "wpsl-fitbounds" );
	}

	$wpsl_tab.on( "click", function() {
		setTimeout( function() {
            if ( typeof currentMap.map !== "undefined" ) {
                bounds = currentMap.bounds;
                tabMap = currentMap.map;
            } else {
            	tabMap = currentMap;
			}

            mapZoom   = tabMap.getZoom();
            mapCenter = tabMap.getCenter();

			google.maps.event.trigger( tabMap, "resize" );

			if ( !$wpsl_tab.hasClass( "wpsl-fitbounds" ) ) {

                //Make sure fitBounds doesn't zoom past the max zoom level.
                attachBoundsChangedListener( tabMap, maxZoom );

                tabMap.setZoom( mapZoom );
				tabMap.setCenter( mapCenter );

                if ( typeof bounds !== "undefined" ) {
                    tabMap.fitBounds( bounds );
                } else {
                	fitBounds();
				}

				$wpsl_tab.addClass( "wpsl-fitbounds" );
            }
        }, 50 );

        return returnBool;
    });
}

/**
 * Add the bounds_changed event listener to the map object
 * to make sure we don't zoom past the max zoom level.
 *
 * @since 2.2.10
 * @param object The map object to attach the event listener to
 * @returns {void}
 */
function attachBoundsChangedListener( map, maxZoom ) {
    google.maps.event.addListenerOnce( map, "bounds_changed", function() {
        google.maps.event.addListenerOnce( map, "idle", function() {
            if ( this.getZoom() > maxZoom ) {
                this.setZoom( maxZoom );
            }
        });
    });
}

/**
 * Handle keyboard submits when the autocomplete option is enabled.
 *
 * If we don't do this, then the search will break the second time
 * the user makes a search, selects the item with the keyboard
 * and submits it with the enter key.
 *
 * @since 2.2.20
 * @returns {void}
 */
function keyboardAutoCompleteSubmit() {
	$( "#wpsl-search-input" ).keypress( function( e ) {

		if ( e.which == 13 ) {
			resetSearchResults();
			codeAddress( infoWindow );

			return false;
		}
	});
}

/**
 * Reset all elements before a search is made.
 *
 * @since 2.2.20
 * @returns {void}
 */
function resetSearchResults() {
	var keepStartMarker = false;

	$( "#wpsl-result-list ul" ).empty();
	$( "#wpsl-stores" ).show();
	$( ".wpsl-direction-before, .wpsl-direction-after" ).remove();
	$( "#wpsl-direction-details" ).hide();

	resetMap = false;

	// Force the open InfoBox info window to close.
	closeInfoBoxWindow();

	deleteOverlays( keepStartMarker );
	deleteStartMarker();
}

});js/infobox.js000064400000057161151327220640007176 0ustar00/**
 * @name InfoBox
 * @version 1.1.13 [March 19, 2014]
 * @author Gary Little (inspired by proof-of-concept code from Pamela Fox of Google)
 * @copyright Copyright 2010 Gary Little [gary at luxcentral.com]
 * @fileoverview InfoBox extends the Google Maps JavaScript API V3 <tt>OverlayView</tt> class.
 *  <p>
 *  An InfoBox behaves like a <tt>google.maps.InfoWindow</tt>, but it supports several
 *  additional properties for advanced styling. An InfoBox can also be used as a map label.
 *  <p>
 *  An InfoBox also fires the same events as a <tt>google.maps.InfoWindow</tt>.
 */

/*!
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*jslint browser:true */
/*global google */

/**
 * @name InfoBoxOptions
 * @class This class represents the optional parameter passed to the {@link InfoBox} constructor.
 * @property {string|Node} content The content of the InfoBox (plain text or an HTML DOM node).
 * @property {boolean} [disableAutoPan=false] Disable auto-pan on <tt>open</tt>.
 * @property {number} maxWidth The maximum width (in pixels) of the InfoBox. Set to 0 if no maximum.
 * @property {Size} pixelOffset The offset (in pixels) from the top left corner of the InfoBox
 *  (or the bottom left corner if the <code>alignBottom</code> property is <code>true</code>)
 *  to the map pixel corresponding to <tt>position</tt>.
 * @property {LatLng} position The geographic location at which to display the InfoBox.
 * @property {number} zIndex The CSS z-index style value for the InfoBox.
 *  Note: This value overrides a zIndex setting specified in the <tt>boxStyle</tt> property.
 * @property {string} [boxClass="infoBox"] The name of the CSS class defining the styles for the InfoBox container.
 * @property {Object} [boxStyle] An object literal whose properties define specific CSS
 *  style values to be applied to the InfoBox. Style values defined here override those that may
 *  be defined in the <code>boxClass</code> style sheet. If this property is changed after the
 *  InfoBox has been created, all previously set styles (except those defined in the style sheet)
 *  are removed from the InfoBox before the new style values are applied.
 * @property {string} closeBoxMargin The CSS margin style value for the close box.
 *  The default is "2px" (a 2-pixel margin on all sides).
 * @property {string} closeBoxURL The URL of the image representing the close box.
 *  Note: The default is the URL for Google's standard close box.
 *  Set this property to "" if no close box is required.
 * @property {Size} infoBoxClearance Minimum offset (in pixels) from the InfoBox to the
 *  map edge after an auto-pan.
 * @property {boolean} [isHidden=false] Hide the InfoBox on <tt>open</tt>.
 *  [Deprecated in favor of the <tt>visible</tt> property.]
 * @property {boolean} [visible=true] Show the InfoBox on <tt>open</tt>.
 * @property {boolean} alignBottom Align the bottom left corner of the InfoBox to the <code>position</code>
 *  location (default is <tt>false</tt> which means that the top left corner of the InfoBox is aligned).
 * @property {string} pane The pane where the InfoBox is to appear (default is "floatPane").
 *  Set the pane to "mapPane" if the InfoBox is being used as a map label.
 *  Valid pane names are the property names for the <tt>google.maps.MapPanes</tt> object.
 * @property {boolean} enableEventPropagation Propagate mousedown, mousemove, mouseover, mouseout,
 *  mouseup, click, dblclick, touchstart, touchend, touchmove, and contextmenu events in the InfoBox
 *  (default is <tt>false</tt> to mimic the behavior of a <tt>google.maps.InfoWindow</tt>). Set
 *  this property to <tt>true</tt> if the InfoBox is being used as a map label.
 */

/**
 * Creates an InfoBox with the options specified in {@link InfoBoxOptions}.
 *  Call <tt>InfoBox.open</tt> to add the box to the map.
 * @constructor
 * @param {InfoBoxOptions} [opt_opts]
 */
function InfoBox(opt_opts) {

  opt_opts = opt_opts || {};

  google.maps.OverlayView.apply(this, arguments);

  // Standard options (in common with google.maps.InfoWindow):
  //
  this.content_ = opt_opts.content || "";
  this.disableAutoPan_ = opt_opts.disableAutoPan || false;
  this.maxWidth_ = opt_opts.maxWidth || 0;
  this.pixelOffset_ = opt_opts.pixelOffset || new google.maps.Size(0, 0);
  this.position_ = opt_opts.position || new google.maps.LatLng(0, 0);
  this.zIndex_ = opt_opts.zIndex || null;

  // Additional options (unique to InfoBox):
  //
  this.boxClass_ = opt_opts.boxClass || "infoBox";
  this.boxStyle_ = opt_opts.boxStyle || {};
  this.closeBoxMargin_ = opt_opts.closeBoxMargin || "2px";
  this.closeBoxURL_ = opt_opts.closeBoxURL || "http://www.google.com/intl/en_us/mapfiles/close.gif";
  if (opt_opts.closeBoxURL === "") {
    this.closeBoxURL_ = "";
  }
  this.infoBoxClearance_ = opt_opts.infoBoxClearance || new google.maps.Size(1, 1);

  if (typeof opt_opts.visible === "undefined") {
    if (typeof opt_opts.isHidden === "undefined") {
      opt_opts.visible = true;
    } else {
      opt_opts.visible = !opt_opts.isHidden;
    }
  }
  this.isHidden_ = !opt_opts.visible;

  this.alignBottom_ = opt_opts.alignBottom || false;
  this.pane_ = opt_opts.pane || "floatPane";
  this.enableEventPropagation_ = opt_opts.enableEventPropagation || false;

  this.div_ = null;
  this.closeListener_ = null;
  this.moveListener_ = null;
  this.contextListener_ = null;
  this.eventListeners_ = null;
  this.fixedWidthSet_ = null;
}

/* InfoBox extends OverlayView in the Google Maps API v3.
 */
InfoBox.prototype = new google.maps.OverlayView();

/**
 * Creates the DIV representing the InfoBox.
 * @private
 */
InfoBox.prototype.createInfoBoxDiv_ = function () {

  var i;
  var events;
  var bw;
  var me = this;

  // This handler prevents an event in the InfoBox from being passed on to the map.
  //
  var cancelHandler = function (e) {
    e.cancelBubble = true;
    if (e.stopPropagation) {
      e.stopPropagation();
    }
  };

  // This handler ignores the current event in the InfoBox and conditionally prevents
  // the event from being passed on to the map. It is used for the contextmenu event.
  //
  var ignoreHandler = function (e) {

    e.returnValue = false;

    if (e.preventDefault) {

      e.preventDefault();
    }

    if (!me.enableEventPropagation_) {

      cancelHandler(e);
    }
  };

  if (!this.div_) {

    this.div_ = document.createElement("div");

    this.setBoxStyle_();

    if (typeof this.content_.nodeType === "undefined") {
      this.div_.innerHTML = this.getCloseBoxImg_() + this.content_;
    } else {
      this.div_.innerHTML = this.getCloseBoxImg_();
      this.div_.appendChild(this.content_);
    }

    // Add the InfoBox DIV to the DOM
    this.getPanes()[this.pane_].appendChild(this.div_);

    this.addClickHandler_();

    if (this.div_.style.width) {

      this.fixedWidthSet_ = true;

    } else {

      if (this.maxWidth_ !== 0 && this.div_.offsetWidth > this.maxWidth_) {

        this.div_.style.width = this.maxWidth_;
        this.div_.style.overflow = "auto";
        this.fixedWidthSet_ = true;

      } else { // The following code is needed to overcome problems with MSIE

        bw = this.getBoxWidths_();

        this.div_.style.width = (this.div_.offsetWidth - bw.left - bw.right) + "px";
        this.fixedWidthSet_ = false;
      }
    }

    this.panBox_(this.disableAutoPan_);

    if (!this.enableEventPropagation_) {

      this.eventListeners_ = [];

      // Cancel event propagation.
      //
      // Note: mousemove not included (to resolve Issue 152)
      events = ["mousedown", "mouseover", "mouseout", "mouseup",
      "click", "dblclick", "touchstart", "touchend", "touchmove"];

      for (i = 0; i < events.length; i++) {

        this.eventListeners_.push(google.maps.event.addDomListener(this.div_, events[i], cancelHandler));
      }
      
      // Workaround for Google bug that causes the cursor to change to a pointer
      // when the mouse moves over a marker underneath InfoBox.
      this.eventListeners_.push(google.maps.event.addDomListener(this.div_, "mouseover", function (e) {
        this.style.cursor = "default";
      }));
    }

    this.contextListener_ = google.maps.event.addDomListener(this.div_, "contextmenu", ignoreHandler);

    /**
     * This event is fired when the DIV containing the InfoBox's content is attached to the DOM.
     * @name InfoBox#domready
     * @event
     */
    google.maps.event.trigger(this, "domready");
  }
};

/**
 * Returns the HTML <IMG> tag for the close box.
 * @private
 */
InfoBox.prototype.getCloseBoxImg_ = function () {

  var img = "";

  if (this.closeBoxURL_ !== "") {

    img  = "<img";
    img += " src='" + this.closeBoxURL_ + "'";
    img += " align=right"; // Do this because Opera chokes on style='float: right;'
    img += " style='";
    img += " position: relative;"; // Required by MSIE
    img += " cursor: pointer;";
    img += " margin: " + this.closeBoxMargin_ + ";";
    img += "'>";
  }

  return img;
};

/**
 * Adds the click handler to the InfoBox close box.
 * @private
 */
InfoBox.prototype.addClickHandler_ = function () {

  var closeBox;

  if (this.closeBoxURL_ !== "") {

    closeBox = this.div_.firstChild;
    this.closeListener_ = google.maps.event.addDomListener(closeBox, "click", this.getCloseClickHandler_());

  } else {

    this.closeListener_ = null;
  }
};

/**
 * Returns the function to call when the user clicks the close box of an InfoBox.
 * @private
 */
InfoBox.prototype.getCloseClickHandler_ = function () {

  var me = this;

  return function (e) {

    // 1.0.3 fix: Always prevent propagation of a close box click to the map:
    e.cancelBubble = true;

    if (e.stopPropagation) {

      e.stopPropagation();
    }

    /**
     * This event is fired when the InfoBox's close box is clicked.
     * @name InfoBox#closeclick
     * @event
     */
    google.maps.event.trigger(me, "closeclick");

    me.close();
  };
};

/**
 * Pans the map so that the InfoBox appears entirely within the map's visible area.
 * @private
 */
InfoBox.prototype.panBox_ = function (disablePan) {

  var map;
  var bounds;
  var xOffset = 0, yOffset = 0;

  if (!disablePan) {

    map = this.getMap();

    if (map instanceof google.maps.Map) { // Only pan if attached to map, not panorama

      if (!map.getBounds().contains(this.position_)) {
      // Marker not in visible area of map, so set center
      // of map to the marker position first.
        map.setCenter(this.position_);
      }

      bounds = map.getBounds();

      var mapDiv = map.getDiv();
      var mapWidth = mapDiv.offsetWidth;
      var mapHeight = mapDiv.offsetHeight;
      var iwOffsetX = this.pixelOffset_.width;
      var iwOffsetY = this.pixelOffset_.height;
      var iwWidth = this.div_.offsetWidth;
      var iwHeight = this.div_.offsetHeight;
      var padX = this.infoBoxClearance_.width;
      var padY = this.infoBoxClearance_.height;
      var pixPosition = this.getProjection().fromLatLngToContainerPixel(this.position_);

      if (pixPosition.x < (-iwOffsetX + padX)) {
        xOffset = pixPosition.x + iwOffsetX - padX;
      } else if ((pixPosition.x + iwWidth + iwOffsetX + padX) > mapWidth) {
        xOffset = pixPosition.x + iwWidth + iwOffsetX + padX - mapWidth;
      }
      if (this.alignBottom_) {
        if (pixPosition.y < (-iwOffsetY + padY + iwHeight)) {
          yOffset = pixPosition.y + iwOffsetY - padY - iwHeight;
        } else if ((pixPosition.y + iwOffsetY + padY) > mapHeight) {
          yOffset = pixPosition.y + iwOffsetY + padY - mapHeight;
        }
      } else {
        if (pixPosition.y < (-iwOffsetY + padY)) {
          yOffset = pixPosition.y + iwOffsetY - padY;
        } else if ((pixPosition.y + iwHeight + iwOffsetY + padY) > mapHeight) {
          yOffset = pixPosition.y + iwHeight + iwOffsetY + padY - mapHeight;
        }
      }

      if (!(xOffset === 0 && yOffset === 0)) {

        // Move the map to the shifted center.
        //
        var c = map.getCenter();
        map.panBy(xOffset, yOffset);
      }
    }
  }
};

/**
 * Sets the style of the InfoBox by setting the style sheet and applying
 * other specific styles requested.
 * @private
 */
InfoBox.prototype.setBoxStyle_ = function () {

  var i, boxStyle;

  if (this.div_) {

    // Apply style values from the style sheet defined in the boxClass parameter:
    this.div_.className = this.boxClass_;

    // Clear existing inline style values:
    this.div_.style.cssText = "";

    // Apply style values defined in the boxStyle parameter:
    boxStyle = this.boxStyle_;
    for (i in boxStyle) {

      if (boxStyle.hasOwnProperty(i)) {

        this.div_.style[i] = boxStyle[i];
      }
    }

    // Fix for iOS disappearing InfoBox problem.
    // See http://stackoverflow.com/questions/9229535/google-maps-markers-disappear-at-certain-zoom-level-only-on-iphone-ipad
    this.div_.style.WebkitTransform = "translateZ(0)";

    // Fix up opacity style for benefit of MSIE:
    //
    if (typeof this.div_.style.opacity !== "undefined" && this.div_.style.opacity !== "") {
      // See http://www.quirksmode.org/css/opacity.html
      this.div_.style.MsFilter = "\"progid:DXImageTransform.Microsoft.Alpha(Opacity=" + (this.div_.style.opacity * 100) + ")\"";
      this.div_.style.filter = "alpha(opacity=" + (this.div_.style.opacity * 100) + ")";
    }

    // Apply required styles:
    //
    this.div_.style.position = "absolute";
    this.div_.style.visibility = 'hidden';
    if (this.zIndex_ !== null) {

      this.div_.style.zIndex = this.zIndex_;
    }
  }
};

/**
 * Get the widths of the borders of the InfoBox.
 * @private
 * @return {Object} widths object (top, bottom left, right)
 */
InfoBox.prototype.getBoxWidths_ = function () {

  var computedStyle;
  var bw = {top: 0, bottom: 0, left: 0, right: 0};
  var box = this.div_;

  if (document.defaultView && document.defaultView.getComputedStyle) {

    computedStyle = box.ownerDocument.defaultView.getComputedStyle(box, "");

    if (computedStyle) {

      // The computed styles are always in pixel units (good!)
      bw.top = parseInt(computedStyle.borderTopWidth, 10) || 0;
      bw.bottom = parseInt(computedStyle.borderBottomWidth, 10) || 0;
      bw.left = parseInt(computedStyle.borderLeftWidth, 10) || 0;
      bw.right = parseInt(computedStyle.borderRightWidth, 10) || 0;
    }

  } else if (document.documentElement.currentStyle) { // MSIE

    if (box.currentStyle) {

      // The current styles may not be in pixel units, but assume they are (bad!)
      bw.top = parseInt(box.currentStyle.borderTopWidth, 10) || 0;
      bw.bottom = parseInt(box.currentStyle.borderBottomWidth, 10) || 0;
      bw.left = parseInt(box.currentStyle.borderLeftWidth, 10) || 0;
      bw.right = parseInt(box.currentStyle.borderRightWidth, 10) || 0;
    }
  }

  return bw;
};

/**
 * Invoked when <tt>close</tt> is called. Do not call it directly.
 */
InfoBox.prototype.onRemove = function () {

  if (this.div_) {

    this.div_.parentNode.removeChild(this.div_);
    this.div_ = null;
  }
};

/**
 * Draws the InfoBox based on the current map projection and zoom level.
 */
InfoBox.prototype.draw = function () {

  this.createInfoBoxDiv_();

  var pixPosition = this.getProjection().fromLatLngToDivPixel(this.position_);

  this.div_.style.left = (pixPosition.x + this.pixelOffset_.width) + "px";
  
  if (this.alignBottom_) {
    this.div_.style.bottom = -(pixPosition.y + this.pixelOffset_.height) + "px";
  } else {
    this.div_.style.top = (pixPosition.y + this.pixelOffset_.height) + "px";
  }

  if (this.isHidden_) {

    this.div_.style.visibility = "hidden";

  } else {

    this.div_.style.visibility = "visible";
  }
};

/**
 * Sets the options for the InfoBox. Note that changes to the <tt>maxWidth</tt>,
 *  <tt>closeBoxMargin</tt>, <tt>closeBoxURL</tt>, and <tt>enableEventPropagation</tt>
 *  properties have no affect until the current InfoBox is <tt>close</tt>d and a new one
 *  is <tt>open</tt>ed.
 * @param {InfoBoxOptions} opt_opts
 */
InfoBox.prototype.setOptions = function (opt_opts) {
  if (typeof opt_opts.boxClass !== "undefined") { // Must be first

    this.boxClass_ = opt_opts.boxClass;
    this.setBoxStyle_();
  }
  if (typeof opt_opts.boxStyle !== "undefined") { // Must be second

    this.boxStyle_ = opt_opts.boxStyle;
    this.setBoxStyle_();
  }
  if (typeof opt_opts.content !== "undefined") {

    this.setContent(opt_opts.content);
  }
  if (typeof opt_opts.disableAutoPan !== "undefined") {

    this.disableAutoPan_ = opt_opts.disableAutoPan;
  }
  if (typeof opt_opts.maxWidth !== "undefined") {

    this.maxWidth_ = opt_opts.maxWidth;
  }
  if (typeof opt_opts.pixelOffset !== "undefined") {

    this.pixelOffset_ = opt_opts.pixelOffset;
  }
  if (typeof opt_opts.alignBottom !== "undefined") {

    this.alignBottom_ = opt_opts.alignBottom;
  }
  if (typeof opt_opts.position !== "undefined") {

    this.setPosition(opt_opts.position);
  }
  if (typeof opt_opts.zIndex !== "undefined") {

    this.setZIndex(opt_opts.zIndex);
  }
  if (typeof opt_opts.closeBoxMargin !== "undefined") {

    this.closeBoxMargin_ = opt_opts.closeBoxMargin;
  }
  if (typeof opt_opts.closeBoxURL !== "undefined") {

    this.closeBoxURL_ = opt_opts.closeBoxURL;
  }
  if (typeof opt_opts.infoBoxClearance !== "undefined") {

    this.infoBoxClearance_ = opt_opts.infoBoxClearance;
  }
  if (typeof opt_opts.isHidden !== "undefined") {

    this.isHidden_ = opt_opts.isHidden;
  }
  if (typeof opt_opts.visible !== "undefined") {

    this.isHidden_ = !opt_opts.visible;
  }
  if (typeof opt_opts.enableEventPropagation !== "undefined") {

    this.enableEventPropagation_ = opt_opts.enableEventPropagation;
  }

  if (this.div_) {

    this.draw();
  }
};

/**
 * Sets the content of the InfoBox.
 *  The content can be plain text or an HTML DOM node.
 * @param {string|Node} content
 */
InfoBox.prototype.setContent = function (content) {
  this.content_ = content;

  if (this.div_) {

    if (this.closeListener_) {

      google.maps.event.removeListener(this.closeListener_);
      this.closeListener_ = null;
    }

    // Odd code required to make things work with MSIE.
    //
    if (!this.fixedWidthSet_) {

      this.div_.style.width = "";
    }

    if (typeof content.nodeType === "undefined") {
      this.div_.innerHTML = this.getCloseBoxImg_() + content;
    } else {
      this.div_.innerHTML = this.getCloseBoxImg_();
      this.div_.appendChild(content);
    }

    // Perverse code required to make things work with MSIE.
    // (Ensures the close box does, in fact, float to the right.)
    //
    if (!this.fixedWidthSet_) {
      this.div_.style.width = this.div_.offsetWidth + "px";
      if (typeof content.nodeType === "undefined") {
        this.div_.innerHTML = this.getCloseBoxImg_() + content;
      } else {
        this.div_.innerHTML = this.getCloseBoxImg_();
        this.div_.appendChild(content);
      }
    }

    this.addClickHandler_();
  }

  /**
   * This event is fired when the content of the InfoBox changes.
   * @name InfoBox#content_changed
   * @event
   */
  google.maps.event.trigger(this, "content_changed");
};

/**
 * Sets the geographic location of the InfoBox.
 * @param {LatLng} latlng
 */
InfoBox.prototype.setPosition = function (latlng) {

  this.position_ = latlng;

  if (this.div_) {

    this.draw();
  }

  /**
   * This event is fired when the position of the InfoBox changes.
   * @name InfoBox#position_changed
   * @event
   */
  google.maps.event.trigger(this, "position_changed");
};

/**
 * Sets the zIndex style for the InfoBox.
 * @param {number} index
 */
InfoBox.prototype.setZIndex = function (index) {

  this.zIndex_ = index;

  if (this.div_) {

    this.div_.style.zIndex = index;
  }

  /**
   * This event is fired when the zIndex of the InfoBox changes.
   * @name InfoBox#zindex_changed
   * @event
   */
  google.maps.event.trigger(this, "zindex_changed");
};

/**
 * Sets the visibility of the InfoBox.
 * @param {boolean} isVisible
 */
InfoBox.prototype.setVisible = function (isVisible) {

  this.isHidden_ = !isVisible;
  if (this.div_) {
    this.div_.style.visibility = (this.isHidden_ ? "hidden" : "visible");
  }
};

/**
 * Returns the content of the InfoBox.
 * @returns {string}
 */
InfoBox.prototype.getContent = function () {

  return this.content_;
};

/**
 * Returns the geographic location of the InfoBox.
 * @returns {LatLng}
 */
InfoBox.prototype.getPosition = function () {

  return this.position_;
};

/**
 * Returns the zIndex for the InfoBox.
 * @returns {number}
 */
InfoBox.prototype.getZIndex = function () {

  return this.zIndex_;
};

/**
 * Returns a flag indicating whether the InfoBox is visible.
 * @returns {boolean}
 */
InfoBox.prototype.getVisible = function () {

  var isVisible;

  if ((typeof this.getMap() === "undefined") || (this.getMap() === null)) {
    isVisible = false;
  } else {
    isVisible = !this.isHidden_;
  }
  return isVisible;
};

/**
 * Shows the InfoBox. [Deprecated; use <tt>setVisible</tt> instead.]
 */
InfoBox.prototype.show = function () {

  this.isHidden_ = false;
  if (this.div_) {
    this.div_.style.visibility = "visible";
  }
};

/**
 * Hides the InfoBox. [Deprecated; use <tt>setVisible</tt> instead.]
 */
InfoBox.prototype.hide = function () {

  this.isHidden_ = true;
  if (this.div_) {
    this.div_.style.visibility = "hidden";
  }
};

/**
 * Adds the InfoBox to the specified map or Street View panorama. If <tt>anchor</tt>
 *  (usually a <tt>google.maps.Marker</tt>) is specified, the position
 *  of the InfoBox is set to the position of the <tt>anchor</tt>. If the
 *  anchor is dragged to a new location, the InfoBox moves as well.
 * @param {Map|StreetViewPanorama} map
 * @param {MVCObject} [anchor]
 */
InfoBox.prototype.open = function (map, anchor) {

  var me = this;

  if (anchor) {

    this.position_ = anchor.getPosition();
    this.moveListener_ = google.maps.event.addListener(anchor, "position_changed", function () {
      me.setPosition(this.getPosition());
    });
  }

  this.setMap(map);

  if (this.div_) {

    this.panBox_();
  }
};

/**
 * Removes the InfoBox from the map.
 */
InfoBox.prototype.close = function () {

  var i;

  if (this.closeListener_) {

    google.maps.event.removeListener(this.closeListener_);
    this.closeListener_ = null;
  }

  if (this.eventListeners_) {
    
    for (i = 0; i < this.eventListeners_.length; i++) {

      google.maps.event.removeListener(this.eventListeners_[i]);
    }
    this.eventListeners_ = null;
  }

  if (this.moveListener_) {

    google.maps.event.removeListener(this.moveListener_);
    this.moveListener_ = null;
  }

  if (this.contextListener_) {

    google.maps.event.removeListener(this.contextListener_);
    this.contextListener_ = null;
  }

  this.setMap(null);
};
js/markerclusterer.js000064400000103252151327220640010735 0ustar00// ==ClosureCompiler==
// @compilation_level ADVANCED_OPTIMIZATIONS
// @externs_url http://closure-compiler.googlecode.com/svn/trunk/contrib/externs/maps/google_maps_api_v3_3.js
// ==/ClosureCompiler==

/**
 * @name MarkerClusterer for Google Maps v3
 * @version version 1.0.1
 * @author Luke Mahe
 * @fileoverview
 * The library creates and manages per-zoom-level clusters for large amounts of
 * markers.
 * <br/>
 * This is a v3 implementation of the
 * <a href="http://gmaps-utility-library-dev.googlecode.com/svn/tags/markerclusterer/"
 * >v2 MarkerClusterer</a>.
 */

/**
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


/**
 * A Marker Clusterer that clusters markers.
 *
 * @param {google.maps.Map} map The Google map to attach to.
 * @param {Array.<google.maps.Marker>=} opt_markers Optional markers to add to
 *   the cluster.
 * @param {Object=} opt_options support the following options:
 *     'gridSize': (number) The grid size of a cluster in pixels.
 *     'maxZoom': (number) The maximum zoom level that a marker can be part of a
 *                cluster.
 *     'zoomOnClick': (boolean) Whether the default behaviour of clicking on a
 *                    cluster is to zoom into it.
 *     'averageCenter': (boolean) Wether the center of each cluster should be
 *                      the average of all markers in the cluster.
 *     'minimumClusterSize': (number) The minimum number of markers to be in a
 *                           cluster before the markers are hidden and a count
 *                           is shown.
 *     'styles': (object) An object that has style properties:
 *       'url': (string) The image url.
 *       'height': (number) The image height.
 *       'width': (number) The image width.
 *       'anchor': (Array) The anchor position of the label text.
 *       'textColor': (string) The text color.
 *       'textSize': (number) The text size.
 *       'backgroundPosition': (string) The position of the backgound x, y.
 * @constructor
 * @extends google.maps.OverlayView
 */
function MarkerClusterer(map, opt_markers, opt_options) {
  // MarkerClusterer implements google.maps.OverlayView interface. We use the
  // extend function to extend MarkerClusterer with google.maps.OverlayView
  // because it might not always be available when the code is defined so we
  // look for it at the last possible moment. If it doesn't exist now then
  // there is no point going ahead :)
  this.extend(MarkerClusterer, google.maps.OverlayView);
  this.map_ = map;

  /**
   * @type {Array.<google.maps.Marker>}
   * @private
   */
  this.markers_ = [];

  /**
   *  @type {Array.<Cluster>}
   */
  this.clusters_ = [];

  this.sizes = [53, 56, 66, 78, 90];

  /**
   * @private
   */
  this.styles_ = [];

  /**
   * @type {boolean}
   * @private
   */
  this.ready_ = false;

  var options = opt_options || {};

  /**
   * @type {number}
   * @private
   */
  this.gridSize_ = options['gridSize'] || 60;

  /**
   * @private
   */
  this.minClusterSize_ = options['minimumClusterSize'] || 2;


  /**
   * @type {?number}
   * @private
   */
  this.maxZoom_ = options['maxZoom'] || null;

  this.styles_ = options['styles'] || [];

  /**
   * @type {string}
   * @private
   */
  this.imagePath_ = options['imagePath'] ||
      this.MARKER_CLUSTER_IMAGE_PATH_;

  /**
   * @type {string}
   * @private
   */
  this.imageExtension_ = options['imageExtension'] ||
      this.MARKER_CLUSTER_IMAGE_EXTENSION_;

  /**
   * @type {boolean}
   * @private
   */
  this.zoomOnClick_ = true;

  if (options['zoomOnClick'] != undefined) {
    this.zoomOnClick_ = options['zoomOnClick'];
  }

  /**
   * @type {boolean}
   * @private
   */
  this.averageCenter_ = false;

  if (options['averageCenter'] != undefined) {
    this.averageCenter_ = options['averageCenter'];
  }

  this.setupStyles_();

  this.setMap(map);

  /**
   * @type {number}
   * @private
   */
  this.prevZoom_ = this.map_.getZoom();

  // Add the map event listeners
  var that = this;
  google.maps.event.addListener(this.map_, 'zoom_changed', function() {
    // Determines map type and prevent illegal zoom levels
    var zoom = that.map_.getZoom();
    var minZoom = that.map_.minZoom || 0;
    var maxZoom = Math.min(that.map_.maxZoom || 100,
                         that.map_.mapTypes[that.map_.getMapTypeId()].maxZoom);
    zoom = Math.min(Math.max(zoom,minZoom),maxZoom);

    if (that.prevZoom_ != zoom) {
      that.prevZoom_ = zoom;
      that.resetViewport();
    }
  });

  google.maps.event.addListener(this.map_, 'idle', function() {
    that.redraw();
  });

  // Finally, add the markers
  if (opt_markers && (opt_markers.length || Object.keys(opt_markers).length)) {
    this.addMarkers(opt_markers, false);
  }
}

/**
 * The marker cluster image path.
 *
 * @type {string}
 * @private
 */
MarkerClusterer.prototype.MARKER_CLUSTER_IMAGE_PATH_ = wpslSettings.clusterImagePath;

/**
 * The marker cluster image path.
 *
 * @type {string}
 * @private
 */
MarkerClusterer.prototype.MARKER_CLUSTER_IMAGE_EXTENSION_ = 'png';

/**
 * Extends a objects prototype by anothers.
 *
 * @param {Object} obj1 The object to be extended.
 * @param {Object} obj2 The object to extend with.
 * @return {Object} The new extended object.
 * @ignore
 */
MarkerClusterer.prototype.extend = function(obj1, obj2) {
  return (function(object) {
    for (var property in object.prototype) {
      this.prototype[property] = object.prototype[property];
    }
    return this;
  }).apply(obj1, [obj2]);
};

/**
 * Implementaion of the interface method.
 * @ignore
 */
MarkerClusterer.prototype.onAdd = function() {
  this.setReady_(true);
};

/**
 * Implementaion of the interface method.
 * @ignore
 */
MarkerClusterer.prototype.draw = function() {};

/**
 * Sets up the styles object.
 *
 * @private
 */
MarkerClusterer.prototype.setupStyles_ = function() {
  if (this.styles_.length) {
    return;
  }

  for (var i = 0, size; size = this.sizes[i]; i++) {
    this.styles_.push({
      url: this.imagePath_ + (i + 1) + '.' + this.imageExtension_,
      height: size,
      width: size
    });
  }
};

/**
 *  Fit the map to the bounds of the markers in the clusterer.
 */
MarkerClusterer.prototype.fitMapToMarkers = function() {
  var markers = this.getMarkers();
  var bounds = new google.maps.LatLngBounds();
  for (var i = 0, marker; marker = markers[i]; i++) {
    bounds.extend(marker.getPosition());
  }

  this.map_.fitBounds(bounds);
};


/**
 *  Sets the styles.
 *
 *  @param {Object} styles The style to set.
 */
MarkerClusterer.prototype.setStyles = function(styles) {
  this.styles_ = styles;
};


/**
 *  Gets the styles.
 *
 *  @return {Object} The styles object.
 */
MarkerClusterer.prototype.getStyles = function() {
  return this.styles_;
};


/**
 * Whether zoom on click is set.
 *
 * @return {boolean} True if zoomOnClick_ is set.
 */
MarkerClusterer.prototype.isZoomOnClick = function() {
  return this.zoomOnClick_;
};

/**
 * Whether average center is set.
 *
 * @return {boolean} True if averageCenter_ is set.
 */
MarkerClusterer.prototype.isAverageCenter = function() {
  return this.averageCenter_;
};


/**
 *  Returns the array of markers in the clusterer.
 *
 *  @return {Array.<google.maps.Marker>} The markers.
 */
MarkerClusterer.prototype.getMarkers = function() {
  return this.markers_;
};


/**
 *  Returns the number of markers in the clusterer
 *
 *  @return {Number} The number of markers.
 */
MarkerClusterer.prototype.getTotalMarkers = function() {
  return this.markers_.length;
};


/**
 *  Sets the max zoom for the clusterer.
 *
 *  @param {number} maxZoom The max zoom level.
 */
MarkerClusterer.prototype.setMaxZoom = function(maxZoom) {
  this.maxZoom_ = maxZoom;
};


/**
 *  Gets the max zoom for the clusterer.
 *
 *  @return {number} The max zoom level.
 */
MarkerClusterer.prototype.getMaxZoom = function() {
  return this.maxZoom_;
};


/**
 *  The function for calculating the cluster icon image.
 *
 *  @param {Array.<google.maps.Marker>} markers The markers in the clusterer.
 *  @param {number} numStyles The number of styles available.
 *  @return {Object} A object properties: 'text' (string) and 'index' (number).
 *  @private
 */
MarkerClusterer.prototype.calculator_ = function(markers, numStyles) {
  var index = 0;
  var count = markers.length;
  var dv = count;
  while (dv !== 0) {
    dv = parseInt(dv / 10, 10);
    index++;
  }

  index = Math.min(index, numStyles);
  return {
    text: count,
    index: index
  };
};


/**
 * Set the calculator function.
 *
 * @param {function(Array, number)} calculator The function to set as the
 *     calculator. The function should return a object properties:
 *     'text' (string) and 'index' (number).
 *
 */
MarkerClusterer.prototype.setCalculator = function(calculator) {
  this.calculator_ = calculator;
};


/**
 * Get the calculator function.
 *
 * @return {function(Array, number)} the calculator function.
 */
MarkerClusterer.prototype.getCalculator = function() {
  return this.calculator_;
};


/**
 * Add an array of markers to the clusterer.
 *
 * @param {Array.<google.maps.Marker>} markers The markers to add.
 * @param {boolean=} opt_nodraw Whether to redraw the clusters.
 */
MarkerClusterer.prototype.addMarkers = function(markers, opt_nodraw) {
  if (markers.length) {
    for (var i = 0, marker; marker = markers[i]; i++) {
      this.pushMarkerTo_(marker);
    }
  } else if (Object.keys(markers).length) {
    for (var marker in markers) {
      this.pushMarkerTo_(markers[marker]);
    }
  }
  if (!opt_nodraw) {
    this.redraw();
  }
};


/**
 * Pushes a marker to the clusterer.
 *
 * @param {google.maps.Marker} marker The marker to add.
 * @private
 */
MarkerClusterer.prototype.pushMarkerTo_ = function(marker) {
  marker.isAdded = false;
  if (marker['draggable']) {
    // If the marker is draggable add a listener so we update the clusters on
    // the drag end.
    var that = this;
    google.maps.event.addListener(marker, 'dragend', function() {
      marker.isAdded = false;
      that.repaint();
    });
  }
  this.markers_.push(marker);
};


/**
 * Adds a marker to the clusterer and redraws if needed.
 *
 * @param {google.maps.Marker} marker The marker to add.
 * @param {boolean=} opt_nodraw Whether to redraw the clusters.
 */
MarkerClusterer.prototype.addMarker = function(marker, opt_nodraw) {
  this.pushMarkerTo_(marker);
  if (!opt_nodraw) {
    this.redraw();
  }
};


/**
 * Removes a marker and returns true if removed, false if not
 *
 * @param {google.maps.Marker} marker The marker to remove
 * @return {boolean} Whether the marker was removed or not
 * @private
 */
MarkerClusterer.prototype.removeMarker_ = function(marker) {
  var index = -1;
  if (this.markers_.indexOf) {
    index = this.markers_.indexOf(marker);
  } else {
    for (var i = 0, m; m = this.markers_[i]; i++) {
      if (m == marker) {
        index = i;
        break;
      }
    }
  }

  if (index == -1) {
    // Marker is not in our list of markers.
    return false;
  }

  marker.setMap(null);

  this.markers_.splice(index, 1);

  return true;
};


/**
 * Remove a marker from the cluster.
 *
 * @param {google.maps.Marker} marker The marker to remove.
 * @param {boolean=} opt_nodraw Optional boolean to force no redraw.
 * @return {boolean} True if the marker was removed.
 */
MarkerClusterer.prototype.removeMarker = function(marker, opt_nodraw) {
  var removed = this.removeMarker_(marker);

  if (!opt_nodraw && removed) {
    this.resetViewport();
    this.redraw();
    return true;
  } else {
   return false;
  }
};


/**
 * Removes an array of markers from the cluster.
 *
 * @param {Array.<google.maps.Marker>} markers The markers to remove.
 * @param {boolean=} opt_nodraw Optional boolean to force no redraw.
 */
MarkerClusterer.prototype.removeMarkers = function(markers, opt_nodraw) {
  var removed = false;

  for (var i = 0, marker; marker = markers[i]; i++) {
    var r = this.removeMarker_(marker);
    removed = removed || r;
  }

  if (!opt_nodraw && removed) {
    this.resetViewport();
    this.redraw();
    return true;
  }
};


/**
 * Sets the clusterer's ready state.
 *
 * @param {boolean} ready The state.
 * @private
 */
MarkerClusterer.prototype.setReady_ = function(ready) {
  if (!this.ready_) {
    this.ready_ = ready;
    this.createClusters_();
  }
};


/**
 * Returns the number of clusters in the clusterer.
 *
 * @return {number} The number of clusters.
 */
MarkerClusterer.prototype.getTotalClusters = function() {
  return this.clusters_.length;
};


/**
 * Returns the google map that the clusterer is associated with.
 *
 * @return {google.maps.Map} The map.
 */
MarkerClusterer.prototype.getMap = function() {
  return this.map_;
};


/**
 * Sets the google map that the clusterer is associated with.
 *
 * @param {google.maps.Map} map The map.
 */
MarkerClusterer.prototype.setMap = function(map) {
  this.map_ = map;
};


/**
 * Returns the size of the grid.
 *
 * @return {number} The grid size.
 */
MarkerClusterer.prototype.getGridSize = function() {
  return this.gridSize_;
};


/**
 * Sets the size of the grid.
 *
 * @param {number} size The grid size.
 */
MarkerClusterer.prototype.setGridSize = function(size) {
  this.gridSize_ = size;
};


/**
 * Returns the min cluster size.
 *
 * @return {number} The grid size.
 */
MarkerClusterer.prototype.getMinClusterSize = function() {
  return this.minClusterSize_;
};

/**
 * Sets the min cluster size.
 *
 * @param {number} size The grid size.
 */
MarkerClusterer.prototype.setMinClusterSize = function(size) {
  this.minClusterSize_ = size;
};


/**
 * Extends a bounds object by the grid size.
 *
 * @param {google.maps.LatLngBounds} bounds The bounds to extend.
 * @return {google.maps.LatLngBounds} The extended bounds.
 */
MarkerClusterer.prototype.getExtendedBounds = function(bounds) {
  var projection = this.getProjection();

  // Turn the bounds into latlng.
  var tr = new google.maps.LatLng(bounds.getNorthEast().lat(),
      bounds.getNorthEast().lng());
  var bl = new google.maps.LatLng(bounds.getSouthWest().lat(),
      bounds.getSouthWest().lng());

  // Convert the points to pixels and the extend out by the grid size.
  var trPix = projection.fromLatLngToDivPixel(tr);
  trPix.x += this.gridSize_;
  trPix.y -= this.gridSize_;

  var blPix = projection.fromLatLngToDivPixel(bl);
  blPix.x -= this.gridSize_;
  blPix.y += this.gridSize_;

  // Convert the pixel points back to LatLng
  var ne = projection.fromDivPixelToLatLng(trPix);
  var sw = projection.fromDivPixelToLatLng(blPix);

  // Extend the bounds to contain the new bounds.
  bounds.extend(ne);
  bounds.extend(sw);

  return bounds;
};


/**
 * Determins if a marker is contained in a bounds.
 *
 * @param {google.maps.Marker} marker The marker to check.
 * @param {google.maps.LatLngBounds} bounds The bounds to check against.
 * @return {boolean} True if the marker is in the bounds.
 * @private
 */
MarkerClusterer.prototype.isMarkerInBounds_ = function(marker, bounds) {
  return bounds.contains(marker.getPosition());
};


/**
 * Clears all clusters and markers from the clusterer.
 */
MarkerClusterer.prototype.clearMarkers = function() {
  this.resetViewport(true);

  // Set the markers a empty array.
  this.markers_ = [];
};


/**
 * Clears all existing clusters and recreates them.
 * @param {boolean} opt_hide To also hide the marker.
 */
MarkerClusterer.prototype.resetViewport = function(opt_hide) {
  // Remove all the clusters
  for (var i = 0, cluster; cluster = this.clusters_[i]; i++) {
    cluster.remove();
  }

  // Reset the markers to not be added and to be invisible.
  for (var i = 0, marker; marker = this.markers_[i]; i++) {
    marker.isAdded = false;
    if (opt_hide) {
      marker.setMap(null);
    }
  }

  this.clusters_ = [];
};

/**
 *
 */
MarkerClusterer.prototype.repaint = function() {
  var oldClusters = this.clusters_.slice();
  this.clusters_.length = 0;
  this.resetViewport();
  this.redraw();

  // Remove the old clusters.
  // Do it in a timeout so the other clusters have been drawn first.
  window.setTimeout(function() {
    for (var i = 0, cluster; cluster = oldClusters[i]; i++) {
      cluster.remove();
    }
  }, 0);
};


/**
 * Redraws the clusters.
 */
MarkerClusterer.prototype.redraw = function() {
  this.createClusters_();
};


/**
 * Calculates the distance between two latlng locations in km.
 * @see http://www.movable-type.co.uk/scripts/latlong.html
 *
 * @param {google.maps.LatLng} p1 The first lat lng point.
 * @param {google.maps.LatLng} p2 The second lat lng point.
 * @return {number} The distance between the two points in km.
 * @private
*/
MarkerClusterer.prototype.distanceBetweenPoints_ = function(p1, p2) {
  if (!p1 || !p2) {
    return 0;
  }

  var R = 6371; // Radius of the Earth in km
  var dLat = (p2.lat() - p1.lat()) * Math.PI / 180;
  var dLon = (p2.lng() - p1.lng()) * Math.PI / 180;
  var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
    Math.cos(p1.lat() * Math.PI / 180) * Math.cos(p2.lat() * Math.PI / 180) *
    Math.sin(dLon / 2) * Math.sin(dLon / 2);
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  var d = R * c;
  return d;
};


/**
 * Add a marker to a cluster, or creates a new cluster.
 *
 * @param {google.maps.Marker} marker The marker to add.
 * @private
 */
MarkerClusterer.prototype.addToClosestCluster_ = function(marker) {
  var distance = 40000; // Some large number
  var clusterToAddTo = null;
  var pos = marker.getPosition();
  for (var i = 0, cluster; cluster = this.clusters_[i]; i++) {
    var center = cluster.getCenter();
    if (center) {
      var d = this.distanceBetweenPoints_(center, marker.getPosition());
      if (d < distance) {
        distance = d;
        clusterToAddTo = cluster;
      }
    }
  }

  if (clusterToAddTo && clusterToAddTo.isMarkerInClusterBounds(marker)) {
    clusterToAddTo.addMarker(marker);
  } else {
    var cluster = new Cluster(this);
    cluster.addMarker(marker);
    this.clusters_.push(cluster);
  }
};


/**
 * Creates the clusters.
 *
 * @private
 */
MarkerClusterer.prototype.createClusters_ = function() {
  if (!this.ready_) {
    return;
  }

  // Get our current map view bounds.
  // Create a new bounds object so we don't affect the map.
  var mapBounds = new google.maps.LatLngBounds(this.map_.getBounds().getSouthWest(),
      this.map_.getBounds().getNorthEast());
  var bounds = this.getExtendedBounds(mapBounds);

  for (var i = 0, marker; marker = this.markers_[i]; i++) {
    if (!marker.isAdded && this.isMarkerInBounds_(marker, bounds)) {
      this.addToClosestCluster_(marker);
    }
  }
};


/**
 * A cluster that contains markers.
 *
 * @param {MarkerClusterer} markerClusterer The markerclusterer that this
 *     cluster is associated with.
 * @constructor
 * @ignore
 */
function Cluster(markerClusterer) {
  this.markerClusterer_ = markerClusterer;
  this.map_ = markerClusterer.getMap();
  this.gridSize_ = markerClusterer.getGridSize();
  this.minClusterSize_ = markerClusterer.getMinClusterSize();
  this.averageCenter_ = markerClusterer.isAverageCenter();
  this.center_ = null;
  this.markers_ = [];
  this.bounds_ = null;
  this.clusterIcon_ = new ClusterIcon(this, markerClusterer.getStyles(),
      markerClusterer.getGridSize());
}

/**
 * Determins if a marker is already added to the cluster.
 *
 * @param {google.maps.Marker} marker The marker to check.
 * @return {boolean} True if the marker is already added.
 */
Cluster.prototype.isMarkerAlreadyAdded = function(marker) {
  if (this.markers_.indexOf) {
    return this.markers_.indexOf(marker) != -1;
  } else {
    for (var i = 0, m; m = this.markers_[i]; i++) {
      if (m == marker) {
        return true;
      }
    }
  }
  return false;
};


/**
 * Add a marker the cluster.
 *
 * @param {google.maps.Marker} marker The marker to add.
 * @return {boolean} True if the marker was added.
 */
Cluster.prototype.addMarker = function(marker) {
  if (this.isMarkerAlreadyAdded(marker)) {
    return false;
  }

  if (!this.center_) {
    this.center_ = marker.getPosition();
    this.calculateBounds_();
  } else {
    if (this.averageCenter_) {
      var l = this.markers_.length + 1;
      var lat = (this.center_.lat() * (l-1) + marker.getPosition().lat()) / l;
      var lng = (this.center_.lng() * (l-1) + marker.getPosition().lng()) / l;
      this.center_ = new google.maps.LatLng(lat, lng);
      this.calculateBounds_();
    }
  }

  marker.isAdded = true;
  this.markers_.push(marker);

  var len = this.markers_.length;
  if (len < this.minClusterSize_ && marker.getMap() != this.map_) {
    // Min cluster size not reached so show the marker.
    marker.setMap(this.map_);
  }

  if (len == this.minClusterSize_) {
    // Hide the markers that were showing.
    for (var i = 0; i < len; i++) {
      this.markers_[i].setMap(null);
    }
  }

  if (len >= this.minClusterSize_) {
    marker.setMap(null);
  }

  this.updateIcon();
  return true;
};


/**
 * Returns the marker clusterer that the cluster is associated with.
 *
 * @return {MarkerClusterer} The associated marker clusterer.
 */
Cluster.prototype.getMarkerClusterer = function() {
  return this.markerClusterer_;
};


/**
 * Returns the bounds of the cluster.
 *
 * @return {google.maps.LatLngBounds} the cluster bounds.
 */
Cluster.prototype.getBounds = function() {
  var bounds = new google.maps.LatLngBounds(this.center_, this.center_);
  var markers = this.getMarkers();
  for (var i = 0, marker; marker = markers[i]; i++) {
    bounds.extend(marker.getPosition());
  }
  return bounds;
};


/**
 * Removes the cluster
 */
Cluster.prototype.remove = function() {
  this.clusterIcon_.remove();
  this.markers_.length = 0;
  delete this.markers_;
};


/**
 * Returns the center of the cluster.
 *
 * @return {number} The cluster center.
 */
Cluster.prototype.getSize = function() {
  return this.markers_.length;
};


/**
 * Returns the center of the cluster.
 *
 * @return {Array.<google.maps.Marker>} The cluster center.
 */
Cluster.prototype.getMarkers = function() {
  return this.markers_;
};


/**
 * Returns the center of the cluster.
 *
 * @return {google.maps.LatLng} The cluster center.
 */
Cluster.prototype.getCenter = function() {
  return this.center_;
};


/**
 * Calculated the extended bounds of the cluster with the grid.
 *
 * @private
 */
Cluster.prototype.calculateBounds_ = function() {
  var bounds = new google.maps.LatLngBounds(this.center_, this.center_);
  this.bounds_ = this.markerClusterer_.getExtendedBounds(bounds);
};


/**
 * Determines if a marker lies in the clusters bounds.
 *
 * @param {google.maps.Marker} marker The marker to check.
 * @return {boolean} True if the marker lies in the bounds.
 */
Cluster.prototype.isMarkerInClusterBounds = function(marker) {
  return this.bounds_.contains(marker.getPosition());
};


/**
 * Returns the map that the cluster is associated with.
 *
 * @return {google.maps.Map} The map.
 */
Cluster.prototype.getMap = function() {
  return this.map_;
};


/**
 * Updates the cluster icon
 */
Cluster.prototype.updateIcon = function() {
  var zoom = this.map_.getZoom();
  var mz = this.markerClusterer_.getMaxZoom();

  if (mz && zoom > mz) {
    // The zoom is greater than our max zoom so show all the markers in cluster.
    for (var i = 0, marker; marker = this.markers_[i]; i++) {
      marker.setMap(this.map_);
    }
    return;
  }

  if (this.markers_.length < this.minClusterSize_) {
    // Min cluster size not yet reached.
    this.clusterIcon_.hide();
    return;
  }

  var numStyles = this.markerClusterer_.getStyles().length;
  var sums = this.markerClusterer_.getCalculator()(this.markers_, numStyles);
  this.clusterIcon_.setCenter(this.center_);
  this.clusterIcon_.setSums(sums);
  this.clusterIcon_.show();
};


/**
 * A cluster icon
 *
 * @param {Cluster} cluster The cluster to be associated with.
 * @param {Object} styles An object that has style properties:
 *     'url': (string) The image url.
 *     'height': (number) The image height.
 *     'width': (number) The image width.
 *     'anchor': (Array) The anchor position of the label text.
 *     'textColor': (string) The text color.
 *     'textSize': (number) The text size.
 *     'backgroundPosition: (string) The background postition x, y.
 * @param {number=} opt_padding Optional padding to apply to the cluster icon.
 * @constructor
 * @extends google.maps.OverlayView
 * @ignore
 */
function ClusterIcon(cluster, styles, opt_padding) {
  cluster.getMarkerClusterer().extend(ClusterIcon, google.maps.OverlayView);

  this.styles_ = styles;
  this.padding_ = opt_padding || 0;
  this.cluster_ = cluster;
  this.center_ = null;
  this.map_ = cluster.getMap();
  this.div_ = null;
  this.sums_ = null;
  this.visible_ = false;

  this.setMap(this.map_);
}


/**
 * Triggers the clusterclick event and zoom's if the option is set.
 */
ClusterIcon.prototype.triggerClusterClick = function() {
  var markerClusterer = this.cluster_.getMarkerClusterer();

  // Trigger the clusterclick event.
  google.maps.event.trigger(markerClusterer, 'clusterclick', this.cluster_);

  if (markerClusterer.isZoomOnClick()) {
    // Zoom into the cluster.
    this.map_.fitBounds(this.cluster_.getBounds());
  }
};


/**
 * Adding the cluster icon to the dom.
 * @ignore
 */
ClusterIcon.prototype.onAdd = function() {
  this.div_ = document.createElement('DIV');
  if (this.visible_) {
    var pos = this.getPosFromLatLng_(this.center_);
    this.div_.style.cssText = this.createCss(pos);
    this.div_.innerHTML = this.sums_.text;
  }

  var panes = this.getPanes();
  panes.overlayMouseTarget.appendChild(this.div_);

  var that = this;
  google.maps.event.addDomListener(this.div_, 'click', function() {
    that.triggerClusterClick();
  });
};


/**
 * Returns the position to place the div dending on the latlng.
 *
 * @param {google.maps.LatLng} latlng The position in latlng.
 * @return {google.maps.Point} The position in pixels.
 * @private
 */
ClusterIcon.prototype.getPosFromLatLng_ = function(latlng) {
  var pos = this.getProjection().fromLatLngToDivPixel(latlng);
  pos.x -= parseInt(this.width_ / 2, 10);
  pos.y -= parseInt(this.height_ / 2, 10);
  return pos;
};


/**
 * Draw the icon.
 * @ignore
 */
ClusterIcon.prototype.draw = function() {
  if (this.visible_) {
    var pos = this.getPosFromLatLng_(this.center_);
    this.div_.style.top = pos.y + 'px';
    this.div_.style.left = pos.x + 'px';
  }
};


/**
 * Hide the icon.
 */
ClusterIcon.prototype.hide = function() {
  if (this.div_) {
    this.div_.style.display = 'none';
  }
  this.visible_ = false;
};


/**
 * Position and show the icon.
 */
ClusterIcon.prototype.show = function() {
  if (this.div_) {
    var pos = this.getPosFromLatLng_(this.center_);
    this.div_.style.cssText = this.createCss(pos);
    this.div_.style.display = '';
  }
  this.visible_ = true;
};


/**
 * Remove the icon from the map
 */
ClusterIcon.prototype.remove = function() {
  this.setMap(null);
};


/**
 * Implementation of the onRemove interface.
 * @ignore
 */
ClusterIcon.prototype.onRemove = function() {
  if (this.div_ && this.div_.parentNode) {
    this.hide();
    this.div_.parentNode.removeChild(this.div_);
    this.div_ = null;
  }
};


/**
 * Set the sums of the icon.
 *
 * @param {Object} sums The sums containing:
 *   'text': (string) The text to display in the icon.
 *   'index': (number) The style index of the icon.
 */
ClusterIcon.prototype.setSums = function(sums) {
  this.sums_ = sums;
  this.text_ = sums.text;
  this.index_ = sums.index;
  if (this.div_) {
    this.div_.innerHTML = sums.text;
  }

  this.useStyle();
};


/**
 * Sets the icon to the the styles.
 */
ClusterIcon.prototype.useStyle = function() {
  var index = Math.max(0, this.sums_.index - 1);
  index = Math.min(this.styles_.length - 1, index);
  var style = this.styles_[index];
  this.url_ = style['url'];
  this.height_ = style['height'];
  this.width_ = style['width'];
  this.textColor_ = style['textColor'];
  this.anchor_ = style['anchor'];
  this.textSize_ = style['textSize'];
  this.backgroundPosition_ = style['backgroundPosition'];
};


/**
 * Sets the center of the icon.
 *
 * @param {google.maps.LatLng} center The latlng to set as the center.
 */
ClusterIcon.prototype.setCenter = function(center) {
  this.center_ = center;
};


/**
 * Create the css text based on the position of the icon.
 *
 * @param {google.maps.Point} pos The position.
 * @return {string} The css style text.
 */
ClusterIcon.prototype.createCss = function(pos) {
  var style = [];
  style.push('background-image:url(' + this.url_ + ');');
  var backgroundPosition = this.backgroundPosition_ ? this.backgroundPosition_ : '0 0';
  style.push('background-position:' + backgroundPosition + ';');

  if (typeof this.anchor_ === 'object') {
    if (typeof this.anchor_[0] === 'number' && this.anchor_[0] > 0 &&
        this.anchor_[0] < this.height_) {
      style.push('height:' + (this.height_ - this.anchor_[0]) +
          'px; padding-top:' + this.anchor_[0] + 'px;');
    } else {
      style.push('height:' + this.height_ + 'px; line-height:' + this.height_ +
          'px;');
    }
    if (typeof this.anchor_[1] === 'number' && this.anchor_[1] > 0 &&
        this.anchor_[1] < this.width_) {
      style.push('width:' + (this.width_ - this.anchor_[1]) +
          'px; padding-left:' + this.anchor_[1] + 'px;');
    } else {
      style.push('width:' + this.width_ + 'px; text-align:center;');
    }
  } else {
    style.push('height:' + this.height_ + 'px; line-height:' +
        this.height_ + 'px; width:' + this.width_ + 'px; text-align:center;');
  }

  var txtColor = this.textColor_ ? this.textColor_ : 'black';
  var txtSize = this.textSize_ ? this.textSize_ : 11;

  style.push('cursor:pointer; top:' + pos.y + 'px; left:' +
      pos.x + 'px; color:' + txtColor + '; position:absolute; font-size:' +
      txtSize + 'px; font-family:Arial,sans-serif; font-weight:bold');
  return style.join('');
};


// Export Symbols for Closure
// If you are not going to compile with closure then you can remove the
// code below.
window['MarkerClusterer'] = MarkerClusterer;
MarkerClusterer.prototype['addMarker'] = MarkerClusterer.prototype.addMarker;
MarkerClusterer.prototype['addMarkers'] = MarkerClusterer.prototype.addMarkers;
MarkerClusterer.prototype['clearMarkers'] =
    MarkerClusterer.prototype.clearMarkers;
MarkerClusterer.prototype['fitMapToMarkers'] =
    MarkerClusterer.prototype.fitMapToMarkers;
MarkerClusterer.prototype['getCalculator'] =
    MarkerClusterer.prototype.getCalculator;
MarkerClusterer.prototype['getGridSize'] =
    MarkerClusterer.prototype.getGridSize;
MarkerClusterer.prototype['getExtendedBounds'] =
    MarkerClusterer.prototype.getExtendedBounds;
MarkerClusterer.prototype['getMap'] = MarkerClusterer.prototype.getMap;
MarkerClusterer.prototype['getMarkers'] = MarkerClusterer.prototype.getMarkers;
MarkerClusterer.prototype['getMaxZoom'] = MarkerClusterer.prototype.getMaxZoom;
MarkerClusterer.prototype['getStyles'] = MarkerClusterer.prototype.getStyles;
MarkerClusterer.prototype['getTotalClusters'] =
    MarkerClusterer.prototype.getTotalClusters;
MarkerClusterer.prototype['getTotalMarkers'] =
    MarkerClusterer.prototype.getTotalMarkers;
MarkerClusterer.prototype['redraw'] = MarkerClusterer.prototype.redraw;
MarkerClusterer.prototype['removeMarker'] =
    MarkerClusterer.prototype.removeMarker;
MarkerClusterer.prototype['removeMarkers'] =
    MarkerClusterer.prototype.removeMarkers;
MarkerClusterer.prototype['resetViewport'] =
    MarkerClusterer.prototype.resetViewport;
MarkerClusterer.prototype['repaint'] =
    MarkerClusterer.prototype.repaint;
MarkerClusterer.prototype['setCalculator'] =
    MarkerClusterer.prototype.setCalculator;
MarkerClusterer.prototype['setGridSize'] =
    MarkerClusterer.prototype.setGridSize;
MarkerClusterer.prototype['setMaxZoom'] =
    MarkerClusterer.prototype.setMaxZoom;
MarkerClusterer.prototype['onAdd'] = MarkerClusterer.prototype.onAdd;
MarkerClusterer.prototype['draw'] = MarkerClusterer.prototype.draw;

Cluster.prototype['getCenter'] = Cluster.prototype.getCenter;
Cluster.prototype['getSize'] = Cluster.prototype.getSize;
Cluster.prototype['getMarkers'] = Cluster.prototype.getMarkers;

ClusterIcon.prototype['onAdd'] = ClusterIcon.prototype.onAdd;
ClusterIcon.prototype['draw'] = ClusterIcon.prototype.draw;
ClusterIcon.prototype['onRemove'] = ClusterIcon.prototype.onRemove;

Object.keys = Object.keys || function(o) {  
    var result = [];  
    for(var name in o) {  
        if (o.hasOwnProperty(name))  
          result.push(name);  
    }  
    return result;  
};
img/ajax-loader.gif000064400000003471151327220640010205 0ustar00GIF89a����������FFFzzzXXX$$$���������666hhh!�NETSCAPE2.0!�Created with ajaxload.info!�	
,w  	!�DB�A��H���¬��a��D���@ ^�A�X��P�@�"U���Q#	��B�\;���1�o�:2$v@
$|,3

�_#
d�53�"s5e!!�	
,v  i@e9�DA�A�����/�`ph$�Ca%@ ���pH���x�F��uS��x#�
�.�݄�Yf�L_"
p
3B�W��]|L
\6�{|z�8�7[7!!�	
,x  �e9�DE"������2r,��qP���j��`�8��@8bH, *��0-�
�mFW��9�LP�E3+
(�B"
f�{�*BW_/�
@_$��~Kr�7Ar7!!�	
,v  �4e9��!H�"�*��Q�/@���-�4�ép4�R+��-��p�ȧ`�P(�6�᠝�U/� 	*,�)(+/]"lO�/�*Ak���K���]A~66�6!!�	
,l  ie9�"���*���-�80H���=N;���T�E�����q��e��UoK2_WZ�݌V��1jgWe@tuH//w`?��f~#���6��#!!�	
,~  �,e9��"���*
�;pR�%��#0��`� �'�c�(��J@@���/1�i4��`�V��B�V
u}�"caNi/]))�-Lel	mi}
me[+!!�	
,y  Ie9��"M�6�*¨"7E͖��@G((L&�pqj@Z����� ��%@�w�Z) �pl(
���ԭ�q�u*R&c	`))(s_J��>_\'Gm7�$+!!�	
,w  Ie9�*,� (�*�(�B5[1� �Z��Iah!G��exz��J0�e�6��@V|U��4��Dm��%$͛�p
	\Gx		
}@+|=+
1�-	Ea5l)+!!�	
,y  )�䨞'A�K����ڍ,�����E\(l���&;5 ��5D���0��3�a�0-���-�����ÃpH4V	%
i
p[R"|	��#
�	6iZwcw*!!�	
,y  )�䨞,K�*�����0�a�;׋аY8�b`4�n�¨Bb�b�x�,������������(	Ƚ� %
>

2*�i*	/:�+$v*!!�	
,u  )�䨞l[�$�
�Jq[��q3�`Q[�5��:���IX!0�rAD8Cv����HPfi��iQ���AP@pC
%D
PQ46�
iciNj0w
�)#!!�	
,y  )��.q��
,G�Jr(�J�8�C��*���B�,����&<
�����h�W~-��`�,	����,�>;

8RN<,�<1T]
�c��'
qk$
@)#!;img/markers/purple.png000064400000002205151327220640011002 0ustar00�PNG


IHDR#��ʖtEXtSoftwareAdobe ImageReadyq�e<'IDATxڤW]h[e~��$'隶�Y���s���A�"�?���ꥸ�("�w�Q*�cC�¡��r5a��Na�.uMӤ��Ѥ�i������9ɉy×��;�<�|�פo����s�Dqy�e'W��X^��\�����+W�m�b�"I�S��X����gG�á�w0�	���'�nC�q��ǰ��:!��߉�����l����V+��H�kG0=����$.��$�L1!��F�O��n���|N#��N�k����=�����Ӎ�P�ӏ����{��|��"��f��c=G�n��;�L�b=�$ێ��}�`
ZN(��GN=�^yF��C��`��%X�r��̓�jM}z<Aߠw ����=��C�����+��/}�:�/�6���(~:UQ�|"��L���W
y�hG්�"���{�ޅ��3����-�BL���,c�D�P�v60��XJ��0�1.�c�D��3;�$�^��u��ʉ&��� �A"d]R��V��-�ir�|]�b�&��eu�2��+B%W�%�XL�|��%ŒQ�d���{��ѩ��E��R��
��ڋ\��|
~�����0�&���jQԥs4��no �.6�?:�"���u�DN�1�P5O�B[���9כ�X)*�e��b��!o��HP�DA������.�ݡ�E��&�K�CS
U�H�
>Κ	|�eJ�S� #m�(��U��1�֐��QP�bf�:p�EZ�n�E_�" ;���wD����$]V��E���n�3�sK�J�S���.b������խhA)�N�i�ޑ�^C����6}~��/�r�;�M�?�z�;%��k·+�Z����V������}�)w�/�9TTN‰�����iE@���<�J*�f�_�c�1F/����!IUj|���8��r+��$�A�m�TtM�i��v��((�1.�SQ*:
c���g��hיq��QA'�|�C/�5��w˶7�����tS��S���?����K�g�IEND�B`�img/markers/green.png000064400000002203151327220640010571 0ustar00�PNG


IHDR#��ʖtEXtSoftwareAdobe ImageReadyq�e<%IDATxڬV]�U���?���nw7���5�Z*ڢ(�?`Q�A�‚�b}hZ���/J��>X��� �b�"mE٦�nu7�m&��;�d�3����N2�x����=�|g�9�ܫ:|�K
÷������B}�T�a��y�J�8�z|X)�u�%���2����(�E���{z�����&�N��oU�B��e�9��UW��EZV�8~{��qY���,�Ns����	mu��=�K���O�f�:G1Y����yx�$�=-ݓ��9>����Ud��&Ss{F'��ys�R/��@��z'����O��n�;�`ѻ��R���y�~���Ό�� ��͙m�g-:����}��!�܏�Y#��ur#r���~"���m��m�f,eKO0S�����N���Ǐ���� ��i���Qg"S#{���i4�,�H��E�8��LV��=F��KD�h�۳�������<O�3�f2���3z�NCSBZ��N�����C���s����)!�DN�a��ۊ?B�%�4%���Dh�uD��Ɔ��ZUhД6��:Ǐ����|�S��
5���5R���\�u��\E����<GS����o~O�\��;o܍�I�����2	@M�$�,T`��t��U@��͆�<�����9Ȗ������d#qk�������UW��y)�f_�@�C1���3�J�^��烴�d��l4[��V��J�M�a�,�a��D8U�� �Ϻ���<8����üF%����v���H��}^��<�'J�L���h��8FA��D�A���^v��
6�I|�WP$+�\���9Vm:������S��|�͊2Mp��W�n�+�R�Ծ��Al ��{�y�����|%.sE�*��kl0�YwVN�����Z$M�
�	��az����B�"U�ލD�e�Gj.�s�V�$g�YQJ�Ec�,R� c%
��M(����S0���?�X�0�W^�E���h5����n�t�*�f��MƷJ��`l�1��@gIEND�B`�img/markers/pink.png000064400000002204151327220640010433 0ustar00�PNG


IHDR#��ʖtEXtSoftwareAdobe ImageReadyq�e<&IDATxڬ�_hSW�O��?M�4�k��ZL� l��
�u�=��t|{|A��^&
��D��(��͈Rԡk*���ci��M���$7�7�M���'ɍ��sz�|��~�;�9Q�[�LQA�Yn��"`���HQ�ʷP�)��M&-v�8n)��=��7@���2���ņ5kL�KS�^��NXL�2�H���h:텮��"p���pX;�f��!���K$��'�������N�U	>!uH�P �`0zor�-�+%s��l�w8��z�-�%��]۶�n����`9�+p��]��w���uw[�mm��G
˭j��1��_��p|� @Tj�s�6?��n������n!�͛���"9�'��1�{H��%�\nŚV���,�$�|����6uv�E*o߽������N�
QD��E������af�DqD����0���j4ji֣�;w�fՊ�U����.bڸ��*����j=�f�VM�[��J��يshbz��f�Z��MB���k�V��f��A�&�֒� P�Ag"� di���c�O/DP�91�_�j�f	�q�0�2LE?1AX��:6�Z�7�AF�MJz��իd)�d����/�¥��3A_$���6�t��d��&���̝�DLr-�7=�����}����A��A�����r@i���E�<���� �En�8�l6�h.ʈb����4�Hi8���L�Q�wn..��ϥKGz�}�F��	Yh��]8
�.[��(gLO��^5�2q8@��I��B.����D�^����(��Iz��(���S�XJ�r8C��]P~�|LYaͅ[~W�����d)Ž\�_L:}��@ Z~g�]t���ʱ��$Š9;�q0�W�S
���ŋ0�U��0�!�>�.�b
�Dx�P>�pz:�`t͵j
�2��8�
V�*|�BX�kN�Z,�7�c|<��«���C�a���X-3��,����p���Zʖ�P��х�q|)����`��W5�)IEND�B`�img/markers/dark-blue@2x.png000064400000003575151327220640011726 0ustar00�PNG


IHDR0F�y[tEXtSoftwareAdobe ImageReadyq�e<IDATx��[{�Te?��ڝ��}����Z��Pff%�a��Y$J�?	��(�(IAP	��E֢ ��.	�R)-Z3�}���c米3�ߝ��^u^��oG�ν3�;���^s����6S�h9���c��U}�"9+�W1?�6f�.�|���q�T�t����{;+���,%�I��"�n�r�΂��O05��ń	A�W����W��^�Ҹš~^��ME&ui�J�|��;�J)��ǼNXa�JoUy��jw�Z�db��A?��c���׽�G����N@��&rV��h�2g�jL��(64�V��\t賡�KUm����RQ����M��N��71�d�>�&��g���������RP�A������ڃ�z�Z#�Ss ���Cs�b���e!�jg��L ��c��y�����z&��w�����&�l~9f��Ԧ�QM��o&���5�rEE��8�m.��<M���@bԒ�'�l�wcU��T.�4���י���'LG_��"d{�)���Z'l�,�W�����%����joJM�͡q���]�v������M�w74s�@G���< �k̟ٜUT��ab���<�mZ�(=�`k�k/�u��<�}~�C�?�oj�����֥��	��8���պ��W���-ki~�7���T�ӕ�ť�!�
>�&��#=�]���6<-=�������y	&���x5����1��dȮ��r�J�M�R��+AdI�¬�����2���h��a�!Ȁ,���hh��6�M	B�*��e�@=�f��#Ϋ"YY�-k3�S%�\�)��
��e�
]�Y%*���ftuW�M'�g)!(T��,t7D�	�p������F��2�:�q4=%� Ca��det�?�(	K	AU��l��%ۂ��B��y7~��$FU9W���ڠk���@,�u�d%��=���XȐ��ţq�3�i��
u(�l��4Jb�{��MZ�C'/H����B~ѹ;.�(.6"�Vz�
8��|��r�	`��>%�<(46�N�E�!N�Ȑ�h�7ܿ$cw��[J��ȍ?EG�'��ѯ�_֚I��e����#����]	�i�Ig��t��n@u�����pP�>��L���4�#�7���;t��#�^<d0<1)9A���h�d�M�&LJ�@ht�h��l@R	#@ӱh���{vgi� NA$
��z�3�aF�.�/�l�
�E�.����t�ZD�
?/�d�5���*G������y<�U���@�B���WĒ�'j~l6ve��!G�
�ي�`�s6��	3�KpAW��na�s Lɸ�
�w���|���Hn�RN)�Z�8��S��	�w�hp\t.�"�D��35@��R�
���C2ce|���G��N��q
��cxR��"�q�8�ˎ7�O��v:C�؄�$(8<�Q�-q��x�*4j�K�
�}�i�fd����)0S�T���w*6����)
�I�R2� ��-c̿X
"[���*�����L�/�b.��a�:��-<1z������ׄ
���V���?4�Pd/��Tr:��ndg�C����z���Qqo��V�D# 2��4�:Ƅ����*�3����=%8y`6a��k{���M���>~�}���|�A����z�ʼ8��B/O�2�W�ߊTI��/�NG����*o�ߔ�g,�?4]ol|~�����;
�m!�4^(�0�h܏�IEND�B`�img/markers/green@2x.png000064400000004155151327220640011153 0ustar00�PNG


IHDR0F�y[tEXtSoftwareAdobe ImageReadyq�e<IDATx��[ilE�؎_Ml'Ν6��T�j
Tq��(q��?�����V!�
T��J�*P%�VHP5UU�TE�%Mz�rǎ�k};�yo=KWibg�u�W}ή���}�o޼y���R')���Հ`����Dz6�E0,�(��2�{�TR��~��z�E]�VU%�"U Y�H0��d���� �S�_������bck�k�z�N����(��fҙL8����x���B�PH=
�����wjIR�0p��Ǔj�Bnn7���*�����Kϥ�~W �v�8?�_������ۀ7�F[Sݱ��h0���=���xW��>����~�+_;y�C���/��IkWK]ϖ���F%��(����l��z���pw��O���[��O�W+��67��VIm�|�Ѩ��}"�H��1%|�"�"��B���a�������X?/Fd �&��0�qn��	��k��V��{��&�WEV@�zZM�m�E]� ����2�k�6v6��e
IkW�	]
�"��jU��gKW�J/Ț
fm�VIW�����O�
�끄�T��wo�l��["��:�F��T��uj�ȕ�Y(���um�b;�Ӛ��ͤ�����:�Ig��]d�k!�Λ�}�"ޢ���6��Sp��-xS�eT�:��U1�ld{�#���H�����-��t?H,�rq�,�0r�d���[�Z�:����݀������ް��x�JGvn�Mv��~�������H4fꯡŤ��c�
s`+���jYG��x�`l�:XR
�LίK�T�et�m�tA�y�m�1^Lu�F$�A_CO7"��yf��\�E�/UP�b���R|$���N͔�`�Yh²
�@]L�N�Q��>$�Χ�j%�R	�.��mH�֬��q^���Q��a=��C!��())�U�(;�:�rYE$nK" �	���Ѣ�f�L�"�R	�.�nu&$����\�E	�6R	�.�5-pG|�x4�T!��L*a��$R�ЂiY#���JL�Jԁ�X����e�O���(����Ru��ל�W��?B�$V�XaJ|z�D��c[�Z�߾א=��e>e��cJ\	l�mY�AO(��L�ܥ�����MXcQ�J'Ɉ}��>�U鉡@b�>����d`�ߖU��6_,�I�-`XH���܁(��Ū���_#��߲n)�}`#=�]�'�/O����B��͆b:@�.���Q�ؽ\&��p��Ǵ+�e[��MS������߱p,��h���(������[�)�@��O8b#��&��!���b|�����;���|�ԕ��2���O���|P�gS���H<Ya���{�ڸ�1͌�}�<��@���
�J΅B���ޅ��fc�����G�S!"A�[n��k��/D�i��i�r�����)�(O�C�P�Wp�yHp�`_t��ψ�P,A�1���i��nx��8�/qߥ��<�JΥg��V��NܓR\�8&�AH��VQ7�!�S*���
&��\P7
�i��@هJ��P�;�Im<�kuS�-������s#5�~*�ĵOz��,mY	��q��H!�+MݴzD��P�]����	=�H���N�eust�<�ھN�{s�LO�E�bf���C����^7+;BwE��䜵�d�6>�=�s���CV��?��G��dSe�Ĭ��=\���p��H����+e2����K�a�<�n0}��Yr�0j��F	��Xb~9Q)�r�`!��:��u��y��{r�E��qp�|+\ˌ]�p��#�vx�	PX�HƓi�)w�˝�&���,�9,Eߒ��_(�ȕ��@X�`} U����g��ܵI���w&5>d�����TJ�W�������#�!�I㞄����r���.�#��[Gl�B.�o���'ug2���H��.�3�6��z�I^��*����o������彻��.F9	����V�O�D��2�DIEND�B`�img/markers/red@2x.png000064400000003562151327220640010626 0ustar00�PNG


IHDR0F�y[tEXtSoftwareAdobe ImageReadyq�e<IDATx��[}h�U�r��;�͚��e�Y��qK
$,��P�
��A�"!h
!%�A Ѡm6�ij���3��rny�y?��{�sx_o�������g���{�����y�y�yޯ�%�d-����5�z�5���2Mv�Y��ω���v�v�� �#��C���_�|��O��CəO$(I��?�$TJ;�I�#�Nof}��좲2Z������I�0�@F�qe0�'+��D���z��C1S�`��n�/�䲊
z���j��:�6���B��z,F}��J$��O�7Y�~��G����ή���Fv��p�`��(f��Ŗ��։�t`�
�.��h?��2Pĉ�~/���LO�T2�I����L�
�J�8������3�����z�C�&����^�J���F6��-�����U<�B��"�:֯0���|�
�=��	���LY!�J���#�,;��
��CH�47]������;/�i���U��4?�`~4q�jo��O���
y��1���:b�JJ��mT�$]02�Zk�(Ky}=ծ_O5��4g�j�h4*:0@ӗ/�dO�����Pa�-�v-�3[�d���T��(.y��m�J�l�ꦦ�}]�j��u�7�To/�?Ncǎq)�"���8�	*�޾b����ha(DB���`���%K���W�4��r
eTy��)�
ڒb��g��������V5ʅ����l�F��͐
y�+�>���},Xpީ�l��
@3<f�&�y	�M��*�[*�|]�p�J�J]�j�o��W
�H(.&�y]�j���W~��S*y��ϊ�|��P(�bJ���+�p:�$(t�������0fI�A@m�KTmE,7�*��U��L��ڲ�z~�խDB��JfN6`KE����e�Wlލs%rI��ҩ��jym�
��j�g �Xޢ$劲PA[��VY���Ŗs8�p��Y��/l%q! �mU�7�G���q_�<{�6�5,���{���w)��I��*���򆆜�im��C����r���1񧬽�����s�f<].���911!sV�؞М`}�I�����":7=-��jꩄqh���*M�=���T@�~
�.�Y�a����'3l�6�*-9�X�t����X��x�3���*a�L^}8�� ,�dG\t�`.\I��l Ƴ)$������ߓ�}:ì��.��,d�L {����r�~6���2u���g@��n*��:�}��� ,g��Gb6�3�:k��יF?9ݷ��}�Ȭ@_�͵��û�ݛ�q\�\��B+Nۺk�u>@����-\k��%���T�O�+�B�=����E��l�K�����aѧ6��a��O�տئ8�(�"�d�j��&�Z�mf�NT|���{5R	�l�U<����o
;7d�~��aa��pC�ܘ���܀�=SS�WlT�g�������䆟q�d��S��
��䍎]򤠐b��+��-�	'��$�a�P)��vON�c~O1�ly
4P�J�:�;�����p$�#*�0�l���s��W$��X�<����+��㶽E @ ��#;��b�ZgҤη�f���u�W�}ij%$>[�zWW�����di`?S
�;3���� @|�G&;����v�x�{��i�٧�㶰�O$��Z�T]<�;O�H����J��U��3֝�ݤ�<.�M�y��ϴ�Pk0���n��Ե���s��X�;IEND�B`�img/markers/dark-blue.png000064400000002053151327220640011342 0ustar00�PNG


IHDR#��ʖtEXtSoftwareAdobe ImageReadyq�e<�IDATxڬVkHSq?���n�M|dHi)���>�ҷ cT$DR�AE1�O�A��)���*j�S��w��v;g������:p�w�=���w��2�5�BѠV�gQyZp��	?R'qz�u@dt�)R�J��oS�O�ZN%r��9Aj+��/�͙���A���3�y�{]�8!$��Ox�A%��)���4E��۶�O���9����zs�ŜW��*���
��O�w{��9l�{R1�F*,�c�sC���!=����iy��<b����
�5�,b���������'�P�;+��A����:7tp�|\�=
5e��`�[���9���P8�`X&��[���m5��4�伭�޼eEy�g�`6ꡲ$�*N���5 b8��T1:���i��A�e���g���:�\].�Y(5P�aXI#�E�2�\�e���3�}��ң�����q�LjʥmT�H�f�_^ÒF�d��mDQ�O�K$�&f�����l��� �q��$�F&ga������?�K���VJ�?�P�!#'�h��>��\0u�Av�\�`zqzߎ���"첱_��
��=��W���(x3�
��D�'`�-�����|	�މr�]��!���h�Yg"�Tx�=b��0]HU�}H����r0�����sl��9�	�#z���]><Z*�����mZ�I]8)���oEwo��*:ir��H0%�sF6וhl�1��<[��`�����\���#���c���G�J�:]�#+�{s�_�+�8tyw6��'�����ݿ:��؎�{5�EyO��Qf��&6I����*-n��=G~����m�󉚡T����y��R�KM��:�}��Nl!:����X%���;[ҹUa�c�V�m����ʚ�h��_��–��&ԗJ?�+����Ju�yIEND�B`�img/markers/purple@2x.png000064400000004154151327220640011361 0ustar00�PNG


IHDR0F�y[tEXtSoftwareAdobe ImageReadyq�e<IDATx��[klTE���j�AK�(P(��"X�BP~H�Wb|�1��W�1F��h0B$$�5$c4*?4L}E!(����m���v߯�w��m���]f�nٓ|���Ι��9s��`h�T�"�5#�L�	���ލ�tҳ�Т��i~!�A���Q()Co��NXMXx�+M��f`�A2�ҩ�_	&�9��#��_��m�-�u��V��ʫ��T.3�Ʃ**i%�Kb�7�z䉘�T�W�~��t'��p3,���`��l(��(����^2�T���p�+�b��!�!�{zx��(
v�ͼ�vUU���A&b�k2⭜�z�'��i� �B���S5���U.)_�]�u�Y��C]�h*���Q�S��h$ �9�v�*�5��o6�ju��K���WpǦ����h���Ú��Z��Y��ʍ��y>BoX�k�uR1M�s��Q���� ��g��hv6�)��d�y�M2����q3��?�ݰy�\�ڹr��5�2W�b��P�x\A��ok*o�,��+�\�Ϋr�}im��i��l�����H�X�L���T��&�OE�`0�9�'+1q���z�x~�`n=��Eʕo#s]lن�X���~e#s5�f�?;�FN����ݬ����ύ��m�k(~.�f��:��N�;�6UX���	h���~����Gne�+1gM3�(㻦[[���K�$Il�c@<t6�p*�*!D�D�*��@�V�29�+[��mz�^v�K�Xe}n�M����\na��L��E�F��0?¸�T�BbF�]t�7<y��£�:�ktt.S�
$xPY.�U��B�d�<k�m̫�Z�!ꑪL�����Q&:a[��P�w������%(��u�m�,-�t@��8Mv/.�,cLb�\�^"�K�� �q�VA����KDu!���j�q�$	y�H�u
�؅�8�����.s-P�&�K��(Ax����BvC�3��%9�L�(Al����Ӳ�r�L�p*"��#0�KDu����V�6��r0.�Q���ނ;�%"I��C�S�I6����(AH|��ւ	@�hx�!pN�H�Hg�(:v�ֺ��;���!�r��/�D8���ų���䰊(DH����	w�u�W����	�|2w��b�M��:��$:p��8�e�*g�=l�Ȟ�ُD@���H�7�D0�?"t��9�hC:|S����WzK	�~��Ѿ�Ԧ�A��Z�R�²��Kq�
�:�=n>�]���0Ć�i.�b 6���b`u,��e�싔Z��'�
��M��L���3�����Y������0�C����J�i���&<��A‡�D�)�3ѳ�B�7��՘y,H�lj$>
+�D����K77���p��Tt�[ʣ?�ۘ�Ȁ]ɹ�k��[8<�t�����g#yK�H�d :ӝDZk���E�3�rg��3��3ڢ6����F?ƙ��ш�|����6�����)�܂�b�9����q�-mۅ�d>�H�ʩH��*�@[�E�)���?~
���V�mh�ԋ@���i&����Y�m�F�
���Hb4�w��]=�'�=�-�7�'|�ƹ��6qO��=��H]Q��/���)t3%���Lܢ��(~.䖽a=vZgc#A�p���\Bz���n�&S,,���V��l�Y�	0�+�	��
	�NG����O�}��
x���^՟O��P�LtP���ͷ����I�W��1SBb�P����ۉ鮜]��Nh���dZQj-��:����߇���t!�X��!Ć�q���ITc:�
m�`[]�Un#S���[J�����}T���$��8Kŕ�,�RW�;�Dq����գm]p١&��J�=i�W�jT74�8+}#���{�ڜ�2̋?���N�K���\j�D��|���*�B]���0�怞m�f⋄2��������ExI��$��c�_C�ܥ�B
5Ǻ���{z�P�C��7�xy�}���+�]�b���#�,����Njx]D�IEND�B`�img/markers/dark-green@2x.png000064400000004132151327220640012065 0ustar00�PNG


IHDR0F�y[tEXtSoftwareAdobe ImageReadyq�e<�IDATx��[}lE���k{m����- �����1!Fb@�%!�h	QH4#!�WC4��Ƥ��(��"��BK���}���}���l]��fo��/��v�v��o�͛7o�:�=&R!��"�:@к�Fz�)�0�sq�y��y�\R�2�6z`)�{��Y��Gt���1A�f��<z���L���'�*ko�X��f���d�8}���L6�G��$�x8�������e�i���MiN{��r��9}}[M����0�
F5��Ig�Q?���D8�ӯG�jI`+�E�0Y
���F{��F�6���Q�����Q_"�0��w9fv���쪫wv�9u�v
�c���k ���܎^\TC`��j�Mm=�-`�2
��$�o<F�Bgq6߳zK�~�ƣ6�6���;�ڹ*���8��.�tl��
-��pͧ��^����VI�)$6��ug�[���o�b����fˌy�v-�*uf[JH��N�d�p!��7Lz}��z}~>�b���c0��H+��Oʿq��}���nh2�R%�&��Jo�f�#�2`h:5Nk-�21ٌf�4�]�m�������ީ����6��•d�����y��g�\�u��~�9����w�����p�ܱɒ�p�&�#�O�B,c�������8z�:�z�Z����^�@N�t�|}�K�����~�+�E��m�G� ��-v�ɪ�^O6��B6��FZ��E��gV.y������y&�^�{�H��Qy,�G;k�?����U��e���V�ܼ�A������}2y45�W�@��Zg��d!X�W�/K�h��
�@],�k9�G=xo�)�AoSl������E�v���C��1��L�Uj%���e'h�0�?�y��U��	ب{�X�ȓ�ªKK^Hr��&�?h���6�&�pVd�1<�JXue@�(�U:5�eI���Vª+#f��҇�J�SL2̴V]��� ��!ɢ�J��ԁ�X�*P8��$�xN�(����ru��׊$�E$0 %�b���E��8���Xu��\�	W0�����l��d�i�̢Cb��Y���I�-����7�����zc��ћ���1%���L<�q�i(�&@����~��A��Kng8�� �pY^�٤�]y�����.��%%����C4���dD�Z|�G�����5
�8]�����Ϧ�Y	i�!0
�,�J	܎��m�LY��'���xp�ql\�Fr;:y[�so!�6�щ6��O`7�O#�ɐ���ji|2&�Q���qS)�ĩ)!�@���T�9_���7�Ģ�o�*�w�X�)�!���������"��.Z����X(���[8N{�W��_��^�#A������k��/F�b��0}O��uA��w�M���"�F2䉅���X�Ir��{
f(J	ݥA1�.x�F�X���r	�`�K���w��n�H�}�#)��lJ#��
�Uԍu(�Ԋ�5yrz*E@ҝs�h��@فJ�A��x�a��:��i�w�Z�c��3��n|iQ�-����/Xʲ�
�26<�f��
y��P�P(qn�k�҂�n�N��X˫!���>�.<��t��k�/�Ƀ$wܬ�]��SU�[�=?��4�s
�_�����;�)���{*�zC^��Sۈr���#����s��&�Ʈ��
�Im#�:rV��,N�2]Yp��kI;�.�������p�|A�!bB,^�W�4��_��]n�e���kP��~��PĚIg3��8��e/�u�f2�RB:=~s�	'?��΃�e�iQ�&���;b%XF��ZU��Q<"��4��rP�SJ%Ӣ̋��gG��%q>�drn�%�=gql���6�qx�W�:+q2q;`&�i��,��G��xU��8�BcO�!�
���w8$�Xw�o��gt���[7omúgɒU*r��&f{@Ų�0�`���AIEND�B`�img/markers/blue@2x.png000064400000003527151327220640011004 0ustar00�PNG


IHDR0F�y[tEXtSoftwareAdobe ImageReadyq�e<�IDATx��[{h�U?},kҮY���nK�9ܬ�Cن L�(�@e ���BA�˜(� ��` c��@'n�fqbYQ�ڦK�&m�G�6m=�����.��/7M~�_�}����s�=_VT���:XJX,�,��LwRjH�~��,����Ͱ\c��򳸎��>!����,+#**�E���L�h�+�֋B$�X.��[/0�u��Uc+**�U^N�.��&W���D���477G��fR/�-�;,߳|$fjM(�Xq<|JJJhKUUWW���5����
�)Z��Xβ|b���,��6�ד����0��~���V]�=����a�KmM
ճ�����CV9��v�0�z�����z��
��ڥ����*�߸q#�ܱ�sb���M�����*++�ID��t	��0�Em�5B���GZ[���V���T$��b�?omi���BcC���ɏ��Kg$��pq8lin6�P�c��͸t'�+���x�q�|������De�W6�/�8�[y�nذ�
p�f���,-����#�����^q�O����±��J'=���:Z�iW����\�߽�st������_?�Gl/�P(����b�Io"Up:���%V��O�RgG3�k���}O}�%��7ӟ#A��?B�nݥe�~��� !\�G���6���Ao����5=��m[��k�P82��_�� ��k�e���5�:ƫ@�Սs�zž.\�ªF��y�6v�WI@�nD��<
��
�Gw���t@�[���\����&ق�t@�Ħf5�2��:�s�4v����H��v�*C��MAW�bk=T�š�I���.%Gs�&���HF�bQt�J:@z`
��Pݐu&�
��ۘ���x�� 0��XL�@���tu)��������e��*��e�.(5�����n�et��Ye����Z!p�����9�����j^$�-�@ �*��|:@�BJl�ڠ���/1Q����nH.^��*��d,�H���'�t��.ջ�}��-h��q��b�V�妬�b3������)��>R�}��3��IKQξ�7^���T+b���aKr� ۦ�OhuU�*�A�]y��u5��:�533Sp�æ��Gؿ����7$4�;PmLE�s�!�d�D"c<6.���=��WR���q��#�ֻ�0oj�X��F��Cg�d�Y�"�'���"t��Q��Z�4��`.����tH0�"�n�m�3��g"0#galll]wg�>�K5���Y��F�����>i��ɴ�5���{౛q*�ߛ�IJ�p��U�s�p�@�IΖ�t%ujs�U�zjME�5�-77eq�,Ί>�ކR�7zLcjjJ��ۢ/2M@f�4v���q�כ��/u���
q�t%�RnN	x?��<)�Y�IuҚd�g�n{;�2�ƴ+�bm���+?�2�dgW��g��uqν�rڎ�l�j�/+v�=���ٻۮ�@��W$idtT˕�,�(1��|�����NTB� j�?��\�QiU�p�+�i�����n�W���#}x��"]Ɗ{p���f�	�}؝���t�B�b\�6�&�6�n��,$;�`�S6�wMuj��(V�{2WRkJX���̜�g�
�� q��C���$dxdD���L��>K�<��x���A���+^���V�I�~���q��D�������М8v���G=F/|x>'ߢ�%�M�R����/��3IEND�B`�img/markers/dark-orange@2x.png000064400000004110151327220640012234 0ustar00�PNG


IHDR0F�y[tEXtSoftwareAdobe ImageReadyq�e<�IDATx��[klU�3��G[��B�Ih#�HT ���/15��&Fh�ƨ$��	�!I�5!D 1$զ��նZ�(�G��n[����<v<g�N;��ww�ݓ|�;��{�w��s�=�p͏�I�d5@�
�*@�z�E�4MX��{"��E�v�Kʖ�����M�Yi���N�qU��nm�0�ppb�4�<lV��aw/��J����9a����'GMB�(j|XV$ �
n!^��'e9\�7���\�v��w;J}o��d�/r�<�5�Id]�I(������
b�8�����Pv��]��i��l$qp�P�r� �\�I��:�Z�n@ ��=��4x]e�^g��q����е��[3$��_�b0�%��'��;S?>˘u�c�|�Mpl/�/y��,��fY�ywV����{���!Vu��q�徥�Bd�Mks�w1<q��Db:�����.�oc�wQ�W=���X� �95�	�ͯO�z��S��F�W꽮
�t~h">��@�ǻy�Vސ
~wU�]p�(�;��RJܕ��m�HMxc���^>�������:�~RdRj�&Szk�8�?`�T�:	W����a�",�'\Uz��[D�y�h���b+$FC9���箸�#z:Zvb�Zh�9�58)��&b߼�+�]�����g����Di��(�bt�i4k�ھ��˧�
[�c��Q¬���8�z����"��:"�n&z�.�|��(����X���N��u�Y��_��>ؗ0��j�౥�&�n�F�L<<��y�lrQ�L�`�HU�YA=O�>`fs�nX��|����	]��
l��f��O�/�6�lXfc�X,���
j( ����
l�UZ��2�	T��n`���`�5yd�D��q/����=PUkֱl��q�y��cы0����H�"� �X%�ci:���3!�T(��z�i�m�ֱɤF�cH`[-�T!���2�c���B�H�[���`�JL��V��X$�hmv�>I�R�d��cV�����u@Q
�H�ol�+���2��!%�O�Yy�J�Y���Ay�@@�[�a���}詔8����	��H{`QX�/OEe�-�:؎��D��sD�3L89�+jf�y��~"�9���*=Qi<���_z���G,Y&1�ԵL��lOB��(Q{~*��gPV�����,<�'nHrx�ǹ ������
!��w
�|"S��W�rX'�)WD9d�u*d�R5eDV�bS>:�n���s6Saߐ��b�n��ԩ=[e�+��m��wT-Q,ʃ.:h��JD6"5%�K�)��:Mf.e#�r��h�1�����?��t����.N2/���D�3L��6�{a���F��)l��Ɗu��@���HA�T�
�׮3��L���-���suDĠ)O�r!@(�nX���D/��\8'I�ޗ�����h|����kƉs��Ηn�	��p�8�E7�)+��9R(T@��c��9�"�o��H<X(86u�霖@y��
I	[����J��\�j(_�WJ�vj�ƽG�%S������Qy���R���-(�-E�Z\��+��|�Ǔ�ո��sk�\���/G�����<��7��/0u�����bZR�'��%�i��
М�|O/~�	~;�dS�K1�8��U�|��K��Cb�Ŕ4]��A�Ͽ8�hنf��Fg۩'���jx\=���A��J�1��W
���N���|'ϛ���e�
���@��U3s���зw�	PX�h�����:!׉��f+�9`�ܖ���(�ɕ�h5����2���Ᏹ}�����BA�ໃEG��8	N�)7N�/��}�{
�s��9���w�c�����:8�N�ɗ�Z=o���¸�b�/�A�a�X��=��3\��MSc���ܶ�{i]A~�QH���U3�`_n���ۃIEND�B`�img/markers/orange@2x.png000064400000004077151327220640011331 0ustar00�PNG


IHDR0F�y[tEXtSoftwareAdobe ImageReadyq�e<�IDATx��[khU�3�~$�dk�&ٴ��6��V�RlQ)���������E[PZD)�J)�C)ժP�"H1R
�(m�G���6m���&�}�����x��dL7������6wv��{�;�{��	wb��TH:6� n�VOb�h�.@���|O\\�/�K�^�ү���a�kwq��9NQTu:��**��[[(t���X,;�6�}�����z���q�BeEUbBN��e1��ґ�$����
�Y�!z�J��p�w������hpׄ\u^'�0�z9Y��R�~T�O�r"}{pp��;��Ml�\6Gg�������8•e�p�Z�Zޙ���X<�F���
�(�@;`�n.��@G�;f�YM���+�-`V��C�p:��Y��蝯_d�U��Q��͹yumۚfϲJ(o�e~��鎺PK���&�O�'X	��v؄m�
�
�E4����i����|$
�4�ջ�C��J��|�k�gH|MMzAh�A��h���\G-WV7z��
�h">_���]vn��y���e]����cw�]~w1��e}�w���*4�
!_�|�R�����4�9kH�	DB����/�l�p���I���{�…�$\�z��>���:v�����i��GM�a<88�I�*y.��:��0U�<��P��w��5µu?�ic�ҵ��C�r�G����2͂f�p���2I�|pD'��]�̺{Ķ�m�oz�4�@���W��AB�1�� ��b��>�)1���Ǻ�,��1��%��.�{m��/aR���ۂ��y4�1������|3Y�z�f}��f��6_v�D���X�~6��B4L1��Z�)���c1�T'm�E!�� TZ%�cy3�6$Ј-��c���`�	���}#<h�l�i�@�uDz�3�K�B>J�*���,���E'�3Ӷ��U�:V7�:жBIV�I!����Xٜ*�f	�c+�Q�*d��YF�q�TV�h�	\�V,��0M�Y%$fe+c�X,�%ڼ��$�&si��!%Ƭ�\�1X�kC�	��V\�e�R�49��ʹC敇������75{�!T���2�h)��GK���$��.X�����[Gc�$���F�|^�s/Q���=�̵y��Б6O���c�b<�$�E�U���	��Q�Y�#�V�g��oF��)�5�
�2�Aw������~ Q�eJ~�E�I̭Jh?0܋d�J�R�#�Q׹���Ɍ,M�$�ڔ��)�n�<O}�`a�l�i&Vm�gN�g�U����$D9S-��EY�kVq+�Ԕ��8U-n�	�3�@9���L2���U���(
���1�;!NV���G�+t|��-�/,����]8�_�t�ZW��/���_z��ǜ��_�v�U�YG��b��8W߈6�i��2����2ӋE��9I���}ž[J-�(��&Y<f3N��8w�Й{�pk"]�sЪC�H�%����
V2��؆�s)}J%pS�ܮ�:��c�`q��i�]8(>�Ǻ��ʏMg86U|W��x�y�×��T�P��q��"�L�J�g�˨<D
�L�18nE	��Ӄ�'���0�OZ���8���7C`��!p�ÆJ1�`_|��^~C�U����3鬒�9n>��G�R�s��A3c�e�/��nX�6��a�|{��{����p��/
�&XLIQU�w 9a��W����[�A3�1����.������s,1��$݋�q|Ⰴ��ۏ�pI	���Я�0�R��5fvi09N/B߾%'@I`%�G���H�t> rA�4�9`�ܖ��[/ȕ�h�4lX�X5�e`E��ϰ}uXkJiI�.�y��}�ݡ�#@I�N@HU/���g��㒬�ٓ�V�Y�'?�O�s��	���4��#�'�VW�Sl߁]R
�ƺ>��<�U�hv�y���C���?vn�ȳ�$���V�j�Mg���E1IEND�B`�img/markers/blue.png000064400000002035151327220640010423 0ustar00�PNG


IHDR#��ʖtEXtSoftwareAdobe ImageReadyq�e<�IDATxڬV�KSa��6��M
����ЄD�.?�� �.�	�0A�$z	�(��I^�W�7�}�`^�%-u��r_���Þ��ٚ�َ����s�����}��y�[�@���ۏ�7�y��燊NR�z
}��B�HUVV��+�J���U��؊PH�}@���L&����V����!�@(AV��4�fF�s��j���h�����������νS����/44R"�li��������`��������9f�����\�
n#-�.66�)x�QkG{>�@��
�P����S��3h�i�]��9��UCo��[,��hNH���~X�p������9�z=�b�N���wy�ae����]��tS�BF]\1�@��z�'Ӱ�B��I�!zp&N�u�,�����I��tp��
n4�%3��f6i4� �E�VI�m9���滣�	�V�b!�KY[c-[��	SC�|&�a�-e��b>?<υ'GB��V1[�Y
����H$�IK\,����4.	���{LW��8\X&��P8���^�	��ÿ��Lg`��W7q���*-�[*4��Ea�Q-�mC�����>|w�
ғ�3��9PU�sj:;Y��c1���]�⮦�h�hJ�RekQ+x?�ۙ|�Lէ>��l��O #��N�������ޟ�g���){4�h�>��b�V H^1K&���E7V�m���\�S���H�?�R}�D$]@�k�ڗ%>*��]H�`���:��y/`�a��]�<�I\��Ӷ��X��bB(J5
�?{��g�M�c0���*�|��{����6�sD�Ph^��Yjf����x�SE��7[�#�&���;�;;�]t���xKMV�L�9��v��D�
f�DN-���U(�k�)���;�aҕ�_�IEND�B`�img/markers/pink@2x.png000064400000004124151327220640011010 0ustar00�PNG


IHDR0F�y[tEXtSoftwareAdobe ImageReadyq�e<�IDATx��[klU���>����t�Z�
��J����DC���cb
�H�%F"F
��@4&(1$DEJ�,���{���|�;vR�v���vO�mgv�{�;�s��i�ΖVV y��%�I�
BB�N�Uҳ��Z��{�%t.���*�sЯ!�kM&CYY��Gzjj��&诉.=�!K��x�l'<KxL9X{eeE��\Qk6�Z�v���t:�Fc�H$�	�'��P�Hm�K�����R�f�-�81��k���Y�m�*�^��F�V���[,&���,�J�Ƃ�ȿO���[��G	��$�6�
X
�ʦ��ƪ*�#��ѓj���|�d��H ���$�&�2N�SUՙ��>#�(�����G���**`�ejz�
��|qM�u��bp��1z:m���#��UF�~�ҥ������>[�����I$��XLO_m#�I��~M����4+�˖-��jdE��Zz��dw��\�-�*�8�q˚��Z|el��Fۊ�&��ܤ�%��N�h\��b/�����vL
����|$o��k��z�t67�טLz�wg"�
>nn�3�����0�����#6�E�M�t���J�Ѡ0�w�
d��AAʖ���٘�����/g�%�L�� }�p8X��v��zzX���I?-h[����
�C�[&�R��l Tk��bۼ��l��w]6��I�ݰ�E�����Y�=}���)�n`��->_�N����r�Ja��XX��/���[�TD�762׏�Y*�\������Rbf�Z͢3/2x��
�2AGG���%$�u��. Q��e�J�!ꑈ�����Ց�]���|:�Kh�f����҉(���V8y#�%"�
�a,�e�)��cr��e���L3cm�z�E	�?��Z"��AyM��I�h��Q")5DT�";���y֗%/��6ixщ��XXDz����L��r�	�%%�TZD	r�DTWbr2��  ���B2$fj��.k����8�E�q%�*���=x�]"�Db���'�;�Q��Ye���g�@����D�2�����u�D΃G[)��8��	\�Ne>!m�)q.$�mE��P(�&��)����b3|)�cB	��e�>/�Z�L_W7�ͻ�#'���rul��Ű��&\�Ӈ_Q�
��NS��.gz�S�Y��RA��0��@@�\�����S���/ZT�S40ߙ3
!�~(=m?0��쪄�J݂A�hr��(�:�X]�}�#�h�
�G��_dӿ��Y�:/1u��K����1��T���0<B%01/��S����;�JD&QnJ`�/p�
3�e"9�W|X4�+���}}.n�Qx�k���g�^ �"AEl!��|������|��:��@>�=e�<~v�o��#��?����aO1�3��r+�X.gރ�ڀ�(��w�ت��to6��#���nxr�8ї��|	`1w�''S�p��#>]u�I�dSb7)���`n�o�d���i�-��rp�v�tsgq����.)E
�bC~P������|W��4��|�g������p���<��{���~�_���S�fJ�����-(ޥ�S���"�;��O��=��s!�d�o�������L�XX�:��H]�A��]ѹh"1y%�d����.Ԟ#�E�&���7\�@.�R�>�S���u����+�쯁��)ѽS��]
�߻�hyfO"�.x�������B��R��te�<dn
�ٛo�y���yG��dJ�2V��E�8��Aj{e�	p�dtM$��L��e
~�x|��6��[\v˅�]�mÊ���Z��F�f��c�k�ʚŋ$<?�G��N�$�97�G��p�J�=��g�爚}���w	-�ht5Ei�N���]h^�N�;Ө��f3����ձ1�ƺ���^�)+��lzǎ�����}������QH���U3�`�ٌ���{IEND�B`�img/markers/dark-orange.png000064400000002147151327220640011672 0ustar00�PNG


IHDR#��ʖtEXtSoftwareAdobe ImageReadyq�e<	IDATxڬ�khU���<vg�nI��Z��Ԗ� b�|PA*>Z�I�S��-��� ��%B���"�AQ
A�B�5	���I��҇�j�4�;f�=��&����끻sg��w��sϹ�U�("Zf�M�Ϋ�Z�IB�&�ѶD�w�R���ێi{�4��hY@���@\+�OnP��zEN�Ę�W�˰ʗu�\��I��%@G�ރ���RjO�,E��&������G��c��C��k;פ��g��8�ydU�u�����ݗ����^�)P���#���d|���$�V�=���w�my�l�k�˯�0؏Q:�_���)��!@D	��H�=!>�I�$m�I���3*�̎�}��Slj�aNw�"������L2�\��`��K�P��7)v�F�	�4��n&)�`U���q�\��<�(�%��A��+�wɍ�B�:R����a���c3�V�1)����w��oI'@���6�3`�����LP�udA`�)�1�� %��V��:��qBd�\�q�@�scͭcs�tJ�c�q��޴l=H�C������4Y���!/��I|10}��o��{�*|�󢍕_��̑a���@�U�b��;=�t;�nY�=dp���&*�-;���tЬ_��̌�^v�u�Yu��#�u�nYM4n�F��7�U.V��.�^��e��Ns��y��QD���Y��V3�.hf�t�����(v���������A��8��˫υ��C3�^;x�Ds]{�R[����ɢ㈿�[���.�tY����~��9��^3�JT�|j��a�PC�
���ɢ��˕��8�q\Y�qp���T�[�Se=�h;������|8S1F��M.\:6��n8�(5K�����|���5cmI�]�^�/�Z
A"<8U1r+�U�|n�5#��"�����*����T�5���`�
o�\�nऻ��y?���߇�\��R�Pϖ7s�T}KA1G�|Zϖ��UH�|S@�*���[���IEND�B`�img/markers/orange.png000064400000002142151327220640010746 0ustar00�PNG


IHDR#��ʖtEXtSoftwareAdobe ImageReadyq�e<IDATxڬV_�E�v�����
�UP�8��`| �>�3<i�&��1QCH�=��9#1 ��� INmbB$x1�煜(wG�]��뵽�v����}[*�u���|�tf;�~3������G���=j�âQ��ڊ���X��� �Ƹ쳜K�����b�*�4�d�%��r�K����`,���1`wX���lIW�
��T�a��"]�Bp�?��N���d/���Ty������H�������&xt��X�+8Y4$_)��M����{���Dw<px[w�Y�[�6
��Iy͋�Б�
,'؇�ޑ��چ~�օɘ�C$9d'8��'��N��+ye}x-�H"��M1Y�L�E�`�-�@�}��^n��gn���5Vk	J������*�ă���=���W[? �q��a�`7�����4t}W �{I�>�'|k�;����$�����y���b!)��V"H�~��H���/�wW
�q�P����� 9��-7���'	���*��hC[����pJ�D�Qu�p$�cepf`D9��uS�j�~/�k�9�
ťYW|>3j�8�%�&�_����0q��S���aŞo��� ��#�Ò�ﯴ�L���1/<Dl�2@����Bnh���Kț�Oՙ��w1�7�s�[Mdx�؝�x�l��H��=���U�0��i.�!����+v;NM�k�N	28{��׍K�~��D�NVA��7W)b�[���UL����ݮ̳��E��v�5�����ەi�a�llF͵K�le�~n���.�,���%=>���k~�)#���ntZ��㊵�8=Yq��z�j��e�"@��.:�����/�絫�Vqs�'��u�n>+�y�8�-�9IE��U�>��W���B0�!�wL�B�bI3���!HQ��]*z��}��4�[
�B`�
?Pfk(���6�	�˷���i<�}w�Տ�2�|�ȖO����l�:F/,���W����}�IEND�B`�img/markers/dark-green.png000064400000002176151327220640011521 0ustar00�PNG


IHDR#��ʖtEXtSoftwareAdobe ImageReadyq�e< IDATxڤW]hSY���&�I���D[u��E� hY|qY���i��ۊ��"H}�AEAtU,�®,("H�Eqw}X�����l�m�57����q&6�6�6�8�'�̙o�̜���֥�H.��(�&�:�&G�e86�X���T��fY��8��cA���ǀ��}�:�����M^�F5���x>�s-�?�W�b-P�P��[<|-�#��#qQ�hC��8����]�!�@�z� �II���Sp���YƲ?�Ѽc~O[�n�EU�-n����)�zglD����k_���A�%B���oG��B=mA��Ѡ�'	.:�9� .7�������P��k���}� ����;p��p��M0M�bǻ9_����J����h�
|Ê�}��i�n�^�����}���jP�<D&G�0�J���0�Da���'�7������![��_���Zŋ����郩*��BZ�Qg�"����2����v�XLd�jd��t9Iv�~ԂU�XL��j�S��{g�0!���:����s
'���h���#B��iMa1Q(�d���O�{2ה�J2Q�������f3M��AA입�Ő-e�"�����{�naH*bcIIW�C�4
k5^��iϗ�r"# ƣŹ��;9
7\�K7~��O���t��ň�����)1��QEL��2]�}�8j�d4���P����X8�$f���2-S�ʤpz� �'��D�(�L~�Tt���d&��)H��DZ��/����)PAyZ�8��,j��(�W����L�~hFʘ}?�z�c�`-�p��� :����9�&�0o��`h����V$=�=�E_%b�M�uԲ��V���qZ�cW��Sq�Ρ�W� :����0o�peuKQw̎g.��,S�i�F$�}�}�S�)���d����H'�d��s	p�$��)��Tԋ�Ƌ�����Zt4Þ����eRqEӼ���܏k�j��5��0�հ�*�'��L)[Vm���)���)�c����^�
���ҟIEND�B`�img/markers/red.png000064400000002012151327220640010241 0ustar00�PNG


IHDR#��ʖtEXtSoftwareAdobe ImageReadyq�e<�IDATxڬV]HQ>��?��%�F�P�F!	Q$��oAII)��(����
�*���%kZT���꺳?��wWW���\g�;�|�~�����l2iF��y�4oo'\dM��F+��B$�
�$�b	��$ƫz��j"��Ǩ9'w�8t�n'��h,[�L��(��DhGQ����1��OK���m���>��G���o#�����:��FFFR��
�Q�
�<���^Z��v��S:?����F�Ng
��y�hyv�-��]�m6@<�5<uP��8xvD����	��(���\�YRB��.&&�?8H;##�J҉5�Gy�瓤2����;z�a��:r��RZa!Y���rQzQe���"�^\$r=nQU�5I�3E��A7z�<���,N�9��My���*/7T�������aZ8j#s��S�ѳ�g��u$�9Of���aQ6X�	MfF����f����O�d�Ͷ��c��|,��!�87G��!ݹߚ|���2*��팎����"++�B9��NO�z{;��L�ي��VDU��xdW��Σkk��SM��?<L�}};|�͈����������6e���0k��0?��kQ�Ol;�e>%�M��'  ���/�P�^D�2��t�IoYr*���4z:�.��w1��QW���(#��b�W�%Q�"��)Q<5�c�چ�ߨ/j[�F�Vuj��m�P��D���l��=�]H&�dr�ӽY�����̘H�,Aa�@�oO�:6 �#>�;7f�(�^M��g�M��v�bj&0��G�>p���m�ա�3�e���M����>��x����@��-���D�A�"|~�5	��B�-���z?Nj�`�ގ��i�U���*���0ޘ]�O�W��gcIEND�B`�img/store-locator-icon.png000064400000000371151327220640011554 0ustar00�PNG


IHDR�atEXtSoftwareAdobe ImageReadyq�e<�IDATxڤ��
!E��;Q�o�Rl�ɝĉ�"KF����{w'���>�a��""�Z+�F0aƺ�"�J��2�D+���;������� �����zb����%�sAql5��lq�η/�*&[���O��H)u����w���|���TIEND�B`�languages/wpsl-nl_NL.mo000064400000146322151327220640011046 0ustar00��{�U�' 5�!5��5�T6@�6@7Z7l7�7�7�7�7�7��7�s89
$929I9P9X9o9	w9�9�9�9�9�9
�9p�9=:�P:H;\;k;�;�;�;
�;�;�;�;	�;�;�;�;�;	<<@#<Fd<
�<�<�<�<
�<�<�<��<k=�=�=�=>
>>>>'>>>G>
[>i>p>�>�>�>�>	�>�>�>�>�>�>�>.	?
8?C?Y?a?j?z?�?
�?�?�?�?�?�?
@@@@-@C@T@#Y@N}@�@�@�@�@
AA A(A4AEA
RA]AeAmAvA{A�A�AM�A�ABBB)B0B5BHBPB `B�B
�B�B
�B�B
�B�B�B�B�BCC"C
*C5CICOC[CaCvC�C�C�C�C�C�
D�D�DEE4EFENETE\EeElE/�EG�E �E
F(F.F2F7F@FMFUF�]FGG%G
,G:GKGgGnGtG}G�G�G
�G3�G�G�G�G�GH	
HH$H+H	1H;H
CHNH	SH]HfH
mH{H�H�H�H�H'�H(�HII0I6I	?IIIUI	[IeImItIQ|I9�IbJGkKK�Kh�KhLBqM��N�rO�P<�Pg�P^BQ\�Ql�QkR�R�R	�R
�R�R�R�R�R�R�RSSSSS#S,S3S:S
BSMSSS\ScSjS
qS|S�S�S�S�S�S�S�S�S�S�S�S�S
�S	�S
TT+T$4T	YT
cTnT{T�T
�TU�T*�T2U4RU�U	�U	�U	�U�U�U�U�U
�U	�U�U!�UVVV
)V
4V	?VIV]V%pV�V�V�V
�V�V5�V�VWW
W
W	*W4WY<W
�W�W�W�W�W�W�W
�W	�W�WX	"X,X2X:X?XOXhX|X:�X�X�X�X�XYY	!Y+Y=YYY7^Y�Y
�Y�Yd�Y5ZJZcZlZ	rZ|Z�Z�Z�Z�Z	�Z�Z�Z�Z�Z.�Z�+[�[�\�\�\�\
�\�\�\]"]
4]B]N]T]4f]3�]�]:�]^^ ^&^.^6^?^F^N^U^b^x^ �^�^
�^	�^�^�^�^�^�^
__._'A_
i_w_�_�_5�_<�_(`8`Q`f`y`�`�`
�`�`�`�`
�`.�`+a;a
Taba}a �a!�a�a�a8b	DbNb[bbbkb	tb~b�bX�b'�bc($cMcYceckc	sc}c�c�c�c�c�c�c�c
�c�c
dd*d?d	Vd`dud�d�d"�d�d+�d
ee0e?eKeQe	Xebeieqe}e�e�e�e�e
�e�e�e�e�e�e�e�e�eOf2Vf6�f/�fH�fy9g]�gMh4_ho�hDi&Ii�pij)+j�Uj"-k�Pk��k2blK�l4�l�mM�n}ob�oL�on4p6�p��p�_qh�q�Vr�sO�s�s�s
tttt#t7tHtPtXt_tgttt�t�t�t	�t�t�t
�t�t�t�t*u,u
<uGuOu	\ufu
nuyu
�u�u�u#�u�u
�u	�uv"v^1v2�v�v
�v�vL�vC;wEww�w�=x4
y1?yOqya�yu#z
�z�z�z�z�z��zl{	�{�{�{�{�{�{�{X�{�~��~�yN3�������Ҁ������#��Ӂ�����Ă
Ђނ���
���� �)�B�rO�ƒ/׃F�N�-_�������
����Åȅх݅�	�?��
5�
@�KK�E��݆����
��������)�5�=�D�L�R�Z�a�i������	�� ��͈��	�����#�,�5�<�4P�����	��	����ʉ�����3�D�I�
[�f�l�r�������,��f�
J�U�
^�
l�z�����������
̋׋܋	������_-���	��	��	��������	Ҍ܌�
	��&�9�J�S�
`�n�w�����
����
��΍������"6�Y�s�)����ώ����2�E�M�S�	[�e�l�6��G�������#�	(�2�?�G��L�0�	I�S�Y�f�*w�����������ɒߒ/��$�	*�4�K�	Q�[�k�w�	~���
����	������
��ȓѓؓߓ	��&�)*�T�o�����	��������	��”ɔcєU5�u��T�bV�p��T*�o��������@�SB�u��s�q����$�
*�5�A�S�k�p�u�}���	������������	��ʟ
ҟݟ������	����'�/�4�<�B�J�R�Y�q�	��
������9���7�%�	1�;�H�
N�
Y�Fd� ��6̡=�A�	H�R�[�d�i�o�
u�������%��ʢҢڢ
���	���&0�W�g�o�
v�	��6��£ɣ	ѣ
ۣ�	���b�
g�r�������	������
Ǥդ
�	���	���&,�"S�v�?��ϥ����	%�/�
5�C�\�La� ��Ϧަs�a�x�����	������ç̧�	���

���/��N�F��Y��#�)�	2�<�R�g�x���������9Ǫ3�5�>=�
|�����
��	��������ƫͫ٫����
�	*�4�=�L�`�e�~�����%��߬� ��	�M)�Mw�ŭح��
���#�,�;�[�{�
��.��-®&�
�%� B�c�%����ů>ү	��(�	1�	;�E�N�_�bg�,ʰ��.�
2�
=�H�O�	V�`�
s���
��	������ɱڱ
�
����2�I�V�q�������ٲ.��'�9�L�X�^�
e�p�w�~���������Ƴ
ͳس޳���	���
�h�8|�D��#��H��g�e�MZ�A��{�Jf�&���ط��*¸��"������\'�Q��1ֻ��I��/�fǾQ.����:��Y������9��H�H!�	j�
t�������������������������	�	�
�%�B�V�g�����/����
������	����
�
�
�+�<�&[�����������b��*=�h�}���R��9��[��x��	�9��4�^K�o��|�
�������������x�	������������
��v�!�3
�a7�A56��(&S(\�l��`Y���������M���W
/������_��M�G���&���V"q*�^!�y9 K�0wE�����9F�?�=���iuV��/#E�	:�u��$�&���:��m�?��h�x����8�t�f�-W��d@h7I��q�s
QN
�sY�f�[�H�R�#;���GCL��"����*�D��n�.H	���9�g�����L,j7XH�}e����i�s�'1�4C��4�>�o��[�O�CF{�-4FE�������eKw<��B:.rB_�g`/�)�c��J�@���R���[.��U2$�D�
3����2�o�N=U�^j��%��!N���x'�m���_o�T
\�ab�#�I�S���h�Z�PT+�����m5W�,�kGe���lr��xjv�R�0��Jl;P�)8>+�%SD3J�B�\�k|��f(vp�@z�Q��]i)dKL���{�t�-;�~��<X�Qy0q����p=X TO����A�]5?��Z�$�`�'nw���u	�b��c�A�zP~2>�rOV}1�U�y,I�b^Z�6<��g �*������n�8%ap1"M+�cz��Y{k|��6t]�d��%sError message: %s %s Check if your issue is covered in the %stroubleshooting%s section, if not, then please open a %ssupport ticket%s.%sError message: %s. %s Make sure the IP address mentioned in the error matches with the IP set as the %sreferrer%s for the server API key in the %sGoogle API Console%s.%sRequired field.%s %s If auto-locating the user is disabled or fails, the center of the provided city or country will be used as the initial starting point for the user.%sWarning!%s %sWPML%s, or a plugin using the WPML API is active.(city) (state) (zip code)(city) (zip code)(city), (state) (zip code)(city), (zip code)(zip code) (city)(zip code) (city) (state)12 Hours24 HoursA %sbrowser key%s allows you to monitor the usage of the Google Maps %sJavaScript API%s. %s %sRequired%s for %sapplications%s created after June 22, 2016.A %sserver key%s allows you to monitor the usage of the Google Maps %sGeocoding API%s. %s %sRequired%s for %sapplications%s created after June 22, 2016.API usage limit reachedAdd New StoreAdd New Store CategoryAdd-OnAdd-OnsAdditional InformationAddressAddress 2Address formatAfghanistanAlbaniaAlgeriaAll Store CategoriesAll StoresAll the store locations are now converted to custom post types. %s You can view them on the %sAll Stores%s page.Already Installed.Although the location data is cached after the first load, a lower number will result in the map being more responsive. %s If this field is left empty or set to 0, then all locations are loaded.Always show the contact details below the address in the search results?American SamoaAn unknown error occurred.AndorraAngolaAnguillaAntarcticaAntigua and BarbudaAnyArabicArgentinaArmeniaArubaAscension IslandAttempt to auto-locate the userAustraliaAustriaAuto adjust the zoom level to make sure all markers are visible?Automatically restrict the returned results to one or more categories?AzerbaijanBackBahamasBahrainBangladeshBarbadosBasqueBecause you updated WP Store Locator from version 1.x, the %s current store locations need to be %sconverted%s to custom post types.Before adding the [wpsl] shortcode to a page, please don't forget to define a start point on the %ssettings%s page. %sDismiss%sBelarusBelgiumBelizeBengaliBeninBermudaBhutanBoliviaBosnia and HerzegovinaBotswanaBounces up and downBouvet IslandBrazilBritish Indian Ocean TerritoryBritish Virgin IslandsBrowser keyBruneiBulgariaBulgarianBurkina FasoBurundiCambodiaCameroonCanadaCanary IslandsCannot determine the address at this location.Cape VerdeCaribbean NetherlandsCatalanCategoryCategory filterCategory filter typeCategory first itemCategory slugCayman IslandsCentral African RepublicCeuta and MelillaChadCheckbox columnsCheckboxesChileChinaChinese (Simplified)Chinese (Traditional)Christmas IslandCityClear store locator transient cacheClicking this link will make the map zoom in to the %s max auto zoom level %s.Clipperton IslandClosedCluster sizeCocos (Keeling) IslandsColombiaComing soon!ComorosCongo (DRC)Congo (Republic)Cook IslandsCosta RicaCountryCroatiaCroatianCubaCuraçaoCustom field deleted.Custom field updated.Custom map styles only work if the map type is set to "Roadmap" or "Terrain".CyprusCzechCzech RepublicCôte d'IvoireDanishDaysDeactivate LicenseDefaultDefault countryDemocratic Republic of the CongoDenmarkDirectionsDismiss this notice.Distance unitDjiboutiDocumentationDoes not respondDominicaDominican RepublicDropdownDropdowns (recommended)DutchEcuadorEdit StoreEdit Store CategoryEgyptEl SalvadorEmailEnable autocomplete?Enable category filters?Enable compatibility mode?Enable marker clusters?Enable permalink?Enable scroll wheel zooming?Enable store locator debug?Enabling this option can sometimes result in a small delay in the opening of the info window. %s This happens because an API request is made to Google Maps to check if street view is available for the current location.EnglishEnglish (Australian)English (Great Britain)Enter store title hereEquatorial GuineaEritreaErrorEstoniaEthiopiaExportExport Location DataFailed to load the add-on list from the server.Failed to publish the store. Please fill in the required store details.Falkland Islands(Islas Malvinas)Faroe IslandsFarsiFaxFijiFilipinoFilter type:FinlandFinnishFor this option to work correctly you need to set a map region and restrict the results to the selected region. %s You can do this in the %sGoogle Maps API section%s.Force zipcode only searchFranceFrenchFrench GuianaFrench PolynesiaFrench Southern TerritoriesFridayGabonGalicianGambiaGeneralGeneral OptionsGeneral errorGeocode was not successful for the following reasonGeorgiaGermanGermanyGet directionsGhanaGibraltarGoogle Maps APIGreeceGreekGreenlandGrenadaGuadeloupeGuamGuatemalaGuernseyGuineaGuinea-BissauGujaratiGuyanaHaitiHeard and McDonald IslandsHebrewHide the country in the search results?Hide the distance in the search results?Hide the opening hours?Hide the scrollbar?HindiHondurasHong KongHour formatHoursHungarianHungaryHybridIcelandIf %spermalinks%s are enabled, the store name will always link to the store page.If a user hovers over the search results the store markerIf marker clusters are enabled this option will not work as expected as long as the markers are clustered. %s The bouncing of the marker won't be visible at all unless a user zooms in far enough for the marker cluster to change back in to individual markers. %s The info window will open as expected, but it won't be clear to which marker it belongs to. If no map language is selected the browser's prefered language is used.If nothing it set, then the start point from the %ssettings%s page is used.If street view is available for the current location, then show a "Street view" link in the info window?If the %sbrowser console%s shows the error below, then enabling this option should fix it. %s %sYou have included the Google Maps API multiple times on this page. This may cause unexpected errors.%s %s This error can in some situations break the store locator map.If the %sgeocoding%s API finds more relevant results outside of the set map region ( some location names exist in multiple regions ), the user will likely see a "No results found" message. %s To rule this out you can restrict the results to the set map region. %s You can modify the used restrictions with %sthis%s filter.If the default style is disabled the %sInfoBox%s library will be used instead. %s This enables you to easily change the look and feel of the info window through the .wpsl-infobox css class.If the store locator is not placed at the top of the page, enabling this feature can result in the page scrolling down. %s %sThis option is disabled on mobile devices.%sIf this zoom level is reached or exceeded, then all markers are moved out of the marker cluster and shown as individual markers.If you like this plugin please leave us a %s5 star%s rating.If you like to write the style code yourself, then you can find the documentation from Google %shere%s.If you use the [wpsl_address] shortcode outside a store page you need to set the ID attribute.If you use the [wpsl_hours] shortcode outside a store page you need to set the ID attribute.If you use the [wpsl_map] shortcode outside a store page, then you need to set the ID or category attribute.In the info window on the mapIn the store listingsIndiaIndonesiaIndonesianInitial zoom levelInsert Store LocatorIranIraqIrelandIsle of ManIsraelItalianItalyJamaicaJapanJapaneseJerseyJordanKannadaKazakhstanKenyaKiribatiKoreanKosovoKuwaitKyrgyzstanLabelsLaosLatitudeLatviaLatvianLebanonLeftLesothoLiberiaLibyaLicense Expiry DateLicense KeyLicensesLiechtensteinLithuaniaLithuanianLoad locations on page loadLocationLocation information is unavailable.LongitudeLuxembourgM j, Y @ G:iMacauMacedonia (FYROM)MadagascarMake sure you call the %sget_template_details%s function with the correct parameters.Make the contact details always clickable?Make the phone number clickable on mobile devices?Make the store name clickable if a store URL exists?MalawiMalayalamMalaysia Maldives MaliMaltaMapMap languageMap regionMap styleMap typeMap type for the location previewMarathiMarkersMarshall IslandsMartiniqueMauritaniaMauritiusMax auto zoom levelMax search resultsMax width for the info window contentMax zoom levelMayotteMexicoMicronesiaMoldovaMon %sTue %sWed %sThu %sFri %sSat Closed %sSun ClosedMonacoMondayMongoliaMontenegroMontserratMore infoMoroccoMost modern browsers %srequire%s a HTTPS connection before the Geolocation feature works.MozambiqueMyanmar (Burma)NamibiaNauruNepalNetherlandsNetherlands AntillesNew CaledoniaNew StoreNew Store Category NameNew ZealandNicaraguaNigerNigeriaNiueNo Stores foundNo Stores found in trashNo directions foundNo results foundNo route could be found between the origin and destinationNo template found for %sNoneNorfolk IslandNorth KoreaNorthern Mariana IslandsNorwayNorwegianNorwegian NynorskNumber of locations to showOmanOn page load move the mouse cursor to the search field?Open links in a new window?Opening HoursOpening PeriodsOpening hours created in version 1.x %sare not%s automatically converted to the new dropdown format.Opening hours formatOpening hours input typePakistanPalauPalestinePanamaPapua New GuineaParaguayParent Store CategoryParent Store Category:PermalinkPeruPhilippinesPhonePitcairn IslandsPlease fill in all the required store details.Please provide the name of a city or country that can be used as a starting point under "Map Settings". %s This will only be used if auto-locating the user fails, or the option itself is disabled.Please try again later!Please use the "String Translations" section in the used multilingual plugin to change the labels. Changing them here will have no effect as long as the multilingual plugin remains active.PolandPolishPortugalPortuguesePortuguese (Brazil)Portuguese (Portugal)Preview LocationPreview Map StylePreview storePuerto RicoQatarQuery limit errorRecommended for maps with a large amount of markers.Remove the front base from the permalink structure?ResetRestrict the geocoding results to the selected map region?ResultsReunionRightRoadmapRomaniaRomanianRussiaRussianRwandaSaint HelenaSaint Kitts and NevisSaint LuciaSaint Vincent and the GrenadinesSamoaSan MarinoSatelliteSaturdaySaudi ArabiaSave ChangesSearchSearch Store CategoriesSearch StoresSearch and radius label widthSearch field widthSearch provided by %sWP Store Locator%sSearch radiusSearch radius optionsSearching (preloader text)Searching...Security check failed, reload the page and try again.Security check failed. Please reload the page and try again.Select categorySelect the used templateSelect your languageSelect your regionSenegalSerbiaSerbianServer keySet a selected category?Set selected checkboxesSettingsSeychellesShow a "More info" link in the store listings?Show a "Zoom here" link in the info window?Show a reset map button?Show credits?Show the map type control?Show the max results dropdown?Show the search radius dropdown?Show the store list below the mapShow the street view controls?Sierra LeoneSign up for the latest plugin updates and announcements.SingaporeSint MaartenSlovakSlovakiaSloveniaSlovenianSolomon IslandsSomaliaSomething went wrong connecting to the Google Geocode API: %s %s Please try again later.Something went wrong, please try again!South AfricaSouth Georgia and South Sandwich IslandsSouth KoreaSouth SudanSpainSpanishSri LankaStart ConvertingStart locationStart location markerStart pointStateStoreStore CategoriesStore CategoryStore DetailsStore EditorStore LocatorStore Locator ManagerStore Locator heightStore Locator templateStore MapStore draft updated.Store location markerStore locations to convert:Store published.Store restored to revision from %sStore saved.Store scheduled for: <strong>%1$s</strong>.Store slugStore submitted.Store updated.Street viewSudanSundaySwazilandSwedenSwedishSwitzerlandSyriaSão Tomé & PríncipeSão Tomé and PríncipeTagalogTaiwanTajikistanTamilTanzaniaTelTeluguTerrainTextareaThaiThailandThe %s license failed to deactivate, please try again later or contact support!The %s license key does not belong to this add-on.The %s license key does not have any activations left.The %s license key is expired. Please renew it.The Google Geocode API reported the following problem: error %s %s %s %sThe Google Geocode API reported the following problem: error %s %s %s Please contact %ssupport%s if the problem persists.The Google Geocode API reported the following problem: error %s %s %s Please try again later.The Google Geocoding API failed to return valid data, please try again later.The Google Geocoding API returned REQUEST_DENIED. %sThe Google Geocoding API returned no results for the supplied address. Please change the address and try again.The application does not have permission to use the Geolocation API.The code for the map style is invalid.The default country and opening hours are only used when a new store is created. So changing the default values will have no effect on existing store locations.The default opening hoursThe default value is set between the [ ].The front base is set on the %spermalink settings%s page in the "Custom structure" field. %s If a front base is set ( for example /blog/ ), then enabling this option will remove it from the store locator permalinks.The geolocation request timed out.The grid size of a cluster in pixels. %s A larger number will result in a lower amount of clusters and also make the algorithm run faster.The map preview is based on the provided address, city and country details. %s It will ignore any custom latitude or longitude values.The map preview requires all the location details.The max results field cannot be empty, the default value has been restored.The permalink slugs %smust be unique%s on your site.The script converting the locations timed out. %s You can click the "Start Converting" button again to restart the script. %s If there are thousands of store locations left to convert and you keep seeing this message, then you can try to contact your host and ask if they can increase the maximum execution time. %s The plugin tried to disable the maximum execution time, but if you are reading this then that failed.The search radius field cannot be empty, the default value has been restored.The selected template is used with the [wpsl] shortcode. %s You can add a custom template with the %swpsl_templates%s filter.There is a new version of %1$s available. %2$sView version %3$s details%4$s or %5$supdate now%6$s.There is a new version of %1$s available. %2$sView version %3$s details%4$s.There was a problem activating the license key for the %s, please try again or contact support. Error code: %sThere's a problem with the provided %sserver key%s. %sThis disables the WPSL transient cache. %sThe transient cache is only used if the %sLoad locations on page load%s option is enabled.This places a "More Info" link below the address and will show the phone, fax, email, opening hours and description once the link is clicked.This runs after a search is made, and makes sure all the returned locations are visible in the viewport.This value sets the zoom level for the "Zoom here" link in the info window. %s It is also used to limit the zooming when the viewport of the map is changed to make all the markers fit on the screen.This will bias the %sgeocoding%s results towards the selected region. %s If no region is selected the bias is set to the United States.This will place a "Search provided by WP Store Locator" backlink below the map.ThursdayTimor-LesteTogoTokelauTongaToolsTrinidad and TobagoTristan da CunhaTuesdayTunisiaTurkeyTurkishTurkmenistanTurks and Caicos IslandsTuvaluUgandaUkraineUkrainianUnited Arab EmiratesUnited KingdomUnited StatesUpdate Store CategoryUrlUruguayUse the default style for the info window?User ExperienceUzbekistanVanuatuVatican CityVenezuelaVietnamVietnameseView StoresView storeWP Store LocatorWP Store Locator Add-OnsWP Store Locator Transients ClearedWPSL transientsWallis FutunaWednesdayWelcome to WP Store LocatorWestern SaharaWhen a user clicks on "Directions", open a new window, and show the route on google.com/maps ?Where do you want to show the "More info" details?Will open the info windowWorld viewYemenYou can add custom address formats with the %swpsl_address_formats%s filter.You can drag the marker to adjust the exact location of the marker.You can fix this by making sure the CSV file uses %sUTF-8 encoding%s.You can raise the %susage limit%s by obtaining an API %skey%s, and fill in the "API key" field at the top of this page.You can use existing map styles from %sSnazzy Maps%s or %sMap Stylr%s and paste it in the textarea below, or you can generate a custom map style through the %sMap Style Editor%s or %sStyled Maps Wizard%s.You do not have permission to install plugin updatesYou do not have permission to perform this actionYou have reached the daily allowed geocoding limit, you can read more %shere%s.You need to create %sAPI keys%s for Google Maps before you can use the store locator! %sDismiss%sYou need to provide the details for either the address, city, state or country before the API can return coordinates.Your locationZambiaZimbabweZipZip CodeZipcode only search does unfortunately not work well in combination with the autocomplete option. %s It's recommended to not have both options active at the same time.Zoom control positionZoom hereinfo windowkmmistore-categorystoresÅland IslandsProject-Id-Version: WP Store Locator 2.2.22
Report-Msgid-Bugs-To: 
POT-Creation-Date: 2019-03-21 11:27+0700
PO-Revision-Date: 2019-03-21 11:28+0700
Last-Translator: 
Language-Team: 
Language: nl_NL
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Plural-Forms: nplurals=2; plural=n != 1;
X-Generator: Poedit 1.8.11
X-Poedit-SourceCharset: UTF-8
X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2
X-Poedit-Basepath: ..
X-Textdomain-Support: yes
X-Poedit-SearchPath-0: .
%sFoutmelding: %s %s Controleer of dit probleem beschreven is in het %stroubleshooting%s gedeelte op de website, mocht dit niet het geval zijn, open dan een %ssupport ticket%s.%sFoutmelding: %s. %s Controleer of het IP adres dat vermeld is in de foutmelding ook is opgegeven als de %sreferrer%s voor de server API key in de %sGoogle API Console%s.%sVerplicht veld.%s %s Als het automatische achterhalen van de gebruikers locatie is uitgeschakeld of mislukt, dan wordt het middelpunt van de opgegeven locatie als begin punt gebruikt.%sWaarschuwing!%s %sWPML%s, of een plugin die de WPML API  gebruikt is actief.(stad) (provincie) (postcode)(stad) (postcode)(stad), (provincie), (postcode)(stad), (postcode)(postcode) (stad)(postcode) (stad) (provincie)12 uur24 uurEen %sbrowser sleutel%s maakt het mogelijk om het gebruik te bekijken van de Google Maps %sJavaScript API%s. %s %sVerplicht%s voor %sapplicaties%s aangemaakt na 22 juni, 2016.Een %sserver sleutel%s maakt het mogelijk om het gebruik van de Google Maps %sGeocode API%s te bekijken. %s %sVerplicht%s voor %sapplicaties%s aangemaakt na 22 juni, 2016.API gebruikslimiet bereiktVoeg winkel toeVoeg winkel categorie toeUitbreidingUitbreidingenExtra informatieAdresAdres 2Adres formaatAfghanistanAlbaniëAlgerijeAlle winkel categorieënAlle winkelsAlle winkel locaties zijn nu omgezet naar custom post types. %s Je kunt ze bekijken op de %sAlle Winkels%s pagina.Is al geinstalleerd.Ondanks dat de winkel data in het cache worden opgeslagen, is het aan te raden om het aantal winkels wat tegelijk geladen wordt niet te groot te laten worden. Dit zorgt er voor dat de kaart vloeiender blijft reageren. %s Als het veld leeg blijft of er wordt 0 ingevuld, dan worden alle locaties geladen.Toon altijd de contact gegevens onder het adres in de zoek resultaten?Amerikaans Samoa Er heeft zich een onbekende fout voorgedaan.AndorraAngolaAnguillaAntarcticaAntigua en BarbudaAlleArabischArgentiniëArmeniaArubaAscensionProbeer de locatie van de gebruiker automatische te achterhalenAustraliëOostenrijkZoom de kaart automatische in om te zorgen dat alle markers zichtbaar zijn?Beperk de zoekresultaten automatische tot één of meer categorieën?AzerbeidzjanTerugBahamasBahreinBangladeshBarbadosBaskDoordat je WP Store Locator update van versie 1.x, de %s huidige winkel locaties moeten worden %somgezet%s naar custom post types.Vergeet niet voordat je de [wpsl] shortcode op een pagina plaatst, om een start locatie op te geven op de %sinstellingen%s pagina. %sSluit%sWit-RuslandBelgiëBelizeBengaliBeninBermudaBhutanBoliviaBosnia en HerzegovinaBotswanaBeweegt op en neerBouvetBraziliëBrits Indische OceaanterritoriumBritse MaagdeneilandenBrowser sleutelBruneiBulgarijeBulgaarsBurkina FasoBurundiCambodjaKameroenCanadaCanarische EilandenEr kan geen adres gevonden worden voor deze locatie.KaapverdiëCaribisch NederlandCatalaansCategorieCategorie filterType categorie filterEerste categorie itemCategorie slugKaaimaneilandenCentraal-Afrikaanse RepubliekCeuta en MelillaChadCheckbox kolommenCheckboxesChiliChinaChinees (Vereenvoudigd)Chinees (Traditioneel)ChristmaseilandStadVerwijder het store locator transient cache.Als er op deze link geklikt word dan zoomt de kaart in totdat de %s max auto zoom level %s bereikt is.ClippertonGeslotenCluster groteCocoseilandenColombiaBinnenkort beschikbaar!ComorenCongo (DRC)Republiek CongoCookeilandenCosta RicaLandKroatiëKroatischCubaCuraçaoCustom veld verwijderd.Custom veld bijgewerkt.Custom map stijlen werken alleen maar als de kaart soort op "Wegenkaart" of "Terrein" is gezet.CyprusTjechischTsjechiëIvoorkustDeensDagenDeactiveer licensieStandaardStandaard landDemocratische Republiek CongoDenemarkenRoutebeschrijvingSluit deze notice.Afstands eenheidDjiboutiDocumentatieReageert nietDominicaDominicaanse RepubliekDropdownDropdown (aangeraden)NederlandsEcuadorWijzig winkelWijzig winkel categorieEgypteEl SalvadorE-mailActiveer autocomplete?Activeer de categorie filters?Activeer de compatibiliteitsmodus?Activeer marker clusters?Activeer permalink?Activeer het inzoomen met je scrollwheel?Activeer store locator debug?Het activeren van deze optie kan er soms toe leiden dat er een kleine vertraging optreed bij het openen van de info window. %s Dit gebeurt omdat er een verzoek naar  de Google Maps API word gemaakt om te controleren ofdat street view wel beschikbaar is voor de huidige locatie.EngelsEngels (Australisch)Engels (Verenigd Koninkrijk)Voer winkel naam inEquatoriaal-GuineaEritreaErrorEstlandEthiopiëExportExport locatie dataDe add-on lijst kon niet geladen worden van de server.Het publiceren van de winkel is mislukt. Vul alle verplichte velden in.FalklandeilandenFaeröerFarsiFaxFijiFilipijnsFilter type:FinlandFinsDeze optie werkt alleen maar correct als er een map region geselecteerd is en de 'Limiteer de geocode resultaten tot de geselecteerde map regio?' optie ook geactiveerd is. %s Dit kan je doen in het %sGoogle Maps API%s gedeelte.Zoek alleen op postcodesFrankrijkFransFrans GuyanaFrans-PolynesiëFranse Zuidelijke en Antarctische GebiedenVrijdagGabonGallischGambiaAlgemeenAlgemene instellingenFoutmeldingGeocode was niet succesvol om de volgende redenGeorgiëDuitsDuitslandToon routebeschrijvingGhanaGibraltarGoogle Maps APIGriekenlandGrieksGroenlandGrenadaGuadeloupeGuamGuatemalaGuernseyGuineeGuinee-BissauGujuratiGuyanaHaïtiHeard en McDonaldeilandenHebreeuwsVerberg het land in de zoekresultaten?Verberg de afstand in de zoek resultaten?Verberg de openingstijden?Verberg de scrollbar?HindiHondurasHong KongUur formaatUrenHongaarsHongarijeHybridIJslandAls de %spermalinks%s zijn ingeschakeld dan zal de winkel naam altijd linken naar de winkel pagina.Als een gebruiker over de zoekresultaten beweegt met zijn muis de bijbehorende markerAls de marker cluster optie actief is en de markers op de kaart als cluster te zien zijn, dan werkt deze optie niet als verwacht. %s Het op en neer gaan van de markers is niet zichtbaar totdat een gebruiker ver genoeg inzoomt, en de marker cluster wordt omgezet naar losse markers. %s De info window wordt wel geopend, maar het is niet duidelijk bij welke marker het hoort.Als er geen kaart taal is geselecteerd, dan word de standaard browser taal gebruikt.Als er niks is opgegeven, dan zal de start locatie van de %sinstellingen%s pagina gebruikt worden.Als voor de huidge locatie street view beschikbaar is, toon dan een "Street view" link om vanuit de info window?Als de %sbrowser console%s de onderstaande foutmelding laat zien, dan kan je dat oplossen door deze optie te activeren. %s %sYou have included the Google Maps API multiple times on this page. This may cause unexpected errors.%s %s  Deze foutmelding kan er in sommige situations voor zorgen dat de store locator kaart niet goed functioneerd.Als de %sgeocode%s API meer relevante resultaten vindt buiten de ingestelde map regio ( sommige locatie namen bestaan in meerdere regio's ), dan zal de gebruiker waarschijnlijk een "Geen resultaten gevonden" boodschap zien. %s Om dit uit te sluiten kan  je een restrictie plaatsen om dit te voorkomen. %s Je kan de gebruikte restricties aanpassen met %sdeze%s filter.Als de standaard stijl is uitgeschakeld dan wordt het %sInfoBox%s script gebruikt. %s Dit script maakt het mogelijk om makkelijk het ontwerp te wijzigen met behulp van de .wpsl-infobox css class.Als de store locator niet bovenaan de pagina geplaatst wordt, dan kan deze instelling ervoor zorgen dat de pagina naar benenden schuift tijden het laden. %s %sDeze optie staat uit op mobiele apparaten.%sAls dit zoom niveau bereikt is of gepasseerd, dan worden alle markers uit de marker cluster gehaald en als losse markers getoond.Als je tevreden bent met deze plugin geef het dan %s5 sterren%s.Als je zelf de stijl code wil schrijven dan kun je de documentatie %shier%s vinden.Als je de [wpsl_address] shortcode op een pagina gebruikt die geen winkel pagina is dan is de ID attribute verplicht.Als je de [wpsl_hours] shortcode op een pagina gebruikt die geen winkel pagina is dan is de ID attribute verplicht.Als de [wpsl_map] shortcode buiten een winkel page is geplaatst, dan moet je de ID of category attribute opgeven.In de info window op de kaartIn de locatie lijstIndiaIndonesiëIndonesischStart zoom niveauPlaats de Store LocatorIranIrakIerlandMan (eiland)IsraëlItaliaansItaliëJamaicaJapanJapansJerseyJordaniëKannadaKazachstanKeniaKiribatiKoreaansKosovoKoeweitKirgiziëLabelsLaosBreedtegraadLetlandLetsLibanonLinksLesothoLiberiaLibiëVerloop datum licensie Licensie sleutelLicentiesLiechtensteinLitouwenLitouwsToon alle locaties op de kaart zodra de pagina geladen isLocatieInformatie over de huidige locatie is niet beschikbaar.LengtegraadLuxemburgM j, Y @ G:iMacauMacedoniëMadagascarRoep de %sget_template_details%s functie aan met de juiste parameters.Maak de contact gevens klikbaar?Maak het telefoonnummer klikbaar op mobiele apparaten?Als een winkel url bestaat, maak de winkel naam dan klikbaar?MalawiMalayalamMaleisieMaldivenMaliMaltaKaartKaart taalKaart regioKaart stijlKaart soortKaart type voor het lokatie voorbeeldMarathiMarkersMarshalleilandenMartiniqueMauritaniëMauritiusMax zoom niveauMax zoek resultatenMax breedte voor de info window inhoudMax zoom niveauMayotteMexicoMicronesiaMoldaviëma %sdi %swoe %sdo %svrij %szat gesloten %szo geslotenMonacoMaandagMongoliëMontenegroMontserrat Meer infoMarokkoDe meeste browsers %shebben%s een HTTPS verbindingen nodig om de geolocatie optie te laten werken.MozambiqueMyanmar (Birma)NamibiëNauruNepalNederlandNederlandse AntillenNieuw-CaledoniëNieuwe winkelNaam winkel categorieNieuw ZeelandNicaraguaNigerNigeriaNiueGeen winkels gevondenGeen winkels gevonden in de prullenbakGeen routebeschrijving beschikbaarGeen resultaten gevondenEr kon geen route gevonden worden tussen het begin- en eindpuntGeen template gevonden voor %sGeenNorfolk (eiland)Noord-KoreaNoordelijke MarianenNoorwegenNoorsNoors NynorskAantal getoonde locatiesOmanAls de pagina wordt geladen, verplaats de muiscursor dan naar het invulveld?Open links in een nieuw venster?OpeningstijdenOpeningstijdenDe openingstijden die zijn aangemaakt in versie 1.x %sworden niet%s automatische omgezet naar het dropdown formaat.Openingstijden formaatOpeningstijden formaatPakistanPalauPalestinePanamaPapoea-Nieuw-GuineaParaguayHoofd winkel categorieHoofd winkel categorie:PermalinkPeruFilipijnenTelefoonPitcairneilandenVul alle verplichte velden in.Geef de naam van een stad of land op als start locatie onder de  "Kaart Instellingen". %s Deze locatie wordt alleen maar gebruikt als het automatische achterhalen van de gebruikers locatie mislukt, of het automatische achterhalen is uitgeschakeld.Probeer het later Gebruik het "String Translations" gedeelte in de vertaal plugin om de labels te wijzigen. Wijzigingen die in dit gedeelte worden aangebracht hebben geen effect zolang de vertaal plugin actief is.PolenPoolsPortugalPortugeesPortugees (Brazilië)Portugees (Portugal)Bekijk voorbeeldMap stijl voorbeeldWinkel voorbeeldPuerto RicoQatarQuery limit foutmeldingAan te raden voor kaarten met grote hoeveelheden markers.Verwijder de front base uit de permalink structuur.HerstelLimiteer de geocode resultaten tot de geselecteerde map regio?ResultatenRéunionRechtsWegenkaartRoemeniëRoemeensRuslandRussischRwandaSint-HelenaSaint Kitts en NevisSaint LuciaSaint Vincent en de GrenadinesSamoaSan MarinoSatellietZaterdagSaoedi-ArabiëWijzigingen opslaanZoekZoek winkel categorieënZoek winkelsZoek en radius label breedteZoekveld breedteOndersteund door %sWP Store Locator%sZoek radiusZoek radius optiesAan het zoeken (preloader tekst)Zoeken...Beveiligings controle mislukt, herlaad de pagina en probeer het nog een keer.Beveiligings controle mislukt, herlaad de pagina en probeer het nog een keer.Kies een categorieSelecteer de gebruikte templateKies uw taalKies uw regioSenegalServiëServischServer sleutelKies de geselecteerde categorieKies de geslecteerde checkboxesInstellingenSeychellenToon een "Meer info" link in de locatie lijst?Toon een  "zoom hier" link in de info window?Toon een knop om de kaart te resetten?Toon credits?Toon de kaart type controls?Toon de max resultaten dropdown?Toon de zoek radius dropdown?Toon the locatie lijst onder de kaartToon de street view controls?Sierra LeoneMeld je aan voor de nieuwsbrief en ontvang het laatste nieuws.SingaporeSint MaartenSlowaaksSlowakijeSloveniëSloveensSalomonseilandenSomalieEr kon geen verbinding gemaakt worden met de Google Geocode API: %s %s Probeer het later nogmaals.Er ging iets fout, probeer het nog een keer!Zuid AfrikaZuid-Georgia en de Zuidelijke SandwicheilandenZuid KoreaZuid SudanSpanjeSpaansSri LankaBegin met omzettenStart locatieStart locatie markerStart locatieProvinciewinkelWinkel categorieënWinkel categorieWinkel detailsWinkel editorStore LocatorStore Locator BeheerderStore Locator hoogteStore locator templateWinkel kaartWinkel concept bijgewerkt.Winkel locatie markerLocaties die omgezet worden:Winkel gepubliceerd.Winkel hersteld naar revisie %sWinkel opgeslagen.Winkel ingepland voor: <strong>%1$s</strong>. Winkel slugWinkel ingediend.Winkel bijgewerkt.Street viewSudanZondagSwaziland ZwedenZweedsZwitserlandSyriëSão Tomé & PríncipeSao Tomé en PrincipeTagalogTaiwanTajikistanTamilTanzaniaTel.TeluguTerreinTekstvlakThaiThailandHet activeren van %s licensie is mislukt. Probeer het later nog een keer of neem contact op met support!De %s licensie sleutel hoort bij een andere uitbreiding.De %s licensie sleutel heeft het maximaal aantal activaties bereikt.De %s licensie sleutel is verlopen.De Google Geocode API geeft het volgende probleem aan: error %s %s %s %sDe Google Geocode API geeft het volgende probleem aan: error %s %s %s Neem contact met %ssupport%s op als het probleem zich blijft herhalen.De Google Geocode API geeft het volgende probleem aan: error %s %s %s Probeer het later nog een keer.De Google Geocoding API geeft ongeldige data terug, probeer het nog een keer.Er is een probleem met Google Geocoding API  - REQUEST_DENIED. %sDe Google Geocoding API gaf geen resultaten terug voor deze locatie. Wijzig de locatie details en probeer het nog een keer.Deze applicatie heeft geen toestemming om de Geolocation API te gebruiken.De code voor de map stijl is ongeldig.De standaard waardes voor het land en de openingstijden worden alleen gebruikt als een nieuwe locatie wordt aangemaakt. Het wijzigen van deze waardes heeft dus geen enkele invloed op de bestaande locaties.De standaard openingstijden* De standaard waarde staat tussen de  [].De front base kan je instellen op de %sPermalink instellingen%s pagina in het "Aangepaste structuur" veld. %s Als een front base is gebruikt ( bijvoorbeeld /blog/ ) dan zal met deze optie het uit de store locator permalinks verwijderd worden.Het geolocation verzoek timed out.Het grid formaat van een cluster in pixels. %s Een hoger nummer zorgt er voor dat er minder clusters zichtbaar zijn en het algoritme dus ook sneller klaar is.Het voorbeeld is gebaseerd op het adres, de stad en het opgegeven land. %s De opgegeven lengte en breedtegraad worden niet gebruikt.Alle locatie details moeten zijn ingevuld voordat de locatie op de kaart getoond kan worden.Het max. zoek resulaten veld kan niet leeg zijn, de standaard waarde is hersteld.De permalink slug %smoet uniek%s zijn op je site.Het script dat de winkel locaties omzet timed out. %s Je kunt op de "Begin met omzetten" knop klikken om het script opnieuw te starten. %s Als er duizenden winkel locaties zijn die nog omgezet moeten worden en je blijft deze boodschap zien dan kun je proberen om contact op te nemen met je host en vragen ofdat ze de maximum execution time kunnen verhogen. %s De plugin heeft al geprobeerd om de maximum execution time uit te zetten, maar als je dit leest dan is dat  mislukt.Het zoek radius veld kan niet leeg zijn, de standaard waarde is hersteld.De geselecteerde template wordt gebruikt bij de [wpsl] shortcode. %s Je kunt een custom template gebruiken met behulp van de %swpsl_templates%s filter.Er is een nieuwe versie beschikbaar van %1$s. %2$sBekijk versie %3$s details%4$s of %5$supdate nu%6$s.Er is een nieuwe versie beschikbaar van %1$s. %2$sBekijk versie %3$s details%4$s.Er is een probleem met het activeren van de licensie sleutel voor de %s. Probeer het later nog een keer of neem contact op met support. Foutmeldings code: %sEr is een probleem met de opgegeven %sserver sleutel%s. %sDit schakelt het WPSL transient cache uit. %sHet transient cache wordt alleen gebruikt als de %sToon alle locaties op de kaart zodra de pagina geladen is%s optie is geactiveerd.Dit plaatst een "Meer Info" link onder het adres. Als een gebruiker hierop klikt dan wordt het telefoon / fax nummer, email, openings tijden en omschrijving getoond.Dit wordt uitgevoerd nadat een zoekopdracht is gemaakt, en zorgt ervoor dat alle geretourneerde locaties zichtbaar zijn in de viewport.Deze waarde word gebruikt om het zoom niveau te bepalen voor de "Zoom hier" link in de info window. %s Het wordt ook gebruikt om het zoom niveau te limiteren als de viewport van de kaart verandert,  wanneer geprobeerd wordt om alle markers op het scherm te laten passen.Dit zorgt er voor dat de %sgeocode%s resultaten uit de geselecteerde regio voorkeur krijgen over resultaten uit andere regio's . %s Als er geen regio is geselecteerd dan gaat de voorkeur uit naar de Verenigde Staten.Dit plaatst een "Ondersteund door WP Store Locator" link onder de kaart.DonderdagOost-TimorTogoTokelauTongaToolsTrinidad en TobagoTristan da CunhaDinsdagTunesiëTurkijeTurksTurkmenistanTurks- en Caicos eilandenTuvaluUgandaOekraïneOekraïensVerenigde Arabische EmiratenVerenigd KoninkrijkVerenigde StatenWinkel categorie bijwerkenUrlUruguayGebruik de standaard style voor de info window?Gebruikers ervaringUzbekistanVanuatuVaticaanstadVenezuelaVietnamVietnameesBekijk winkelBekijk winkelWP Store LocatorWP Store Locator UitbreidingenWP Store Locator transients verwijderdWPSL transientsWallis en FutunaWoensdagWelkom bij WP Store LocatorWestelijke SaharaZodra een gebruiker op "Route" klikt, open een nieuwe venster en toon de route op google.com/maps?Waar wil je de  "Meer info" details tonen?Opent de info windowWereldkaartYemenJe kunt een nieuwe adres formaat toevoegen met de %swpsl_address_formats%s filter.Je kunt de locatie aanpassen door de marker te verslepen.Je kan dit oplossen door er voor te zorgen dat het CSV bestand %sUTF-8 encoding%s gebruikt.Je kan de %sgebruiks limiet%s verhogen door een API %ssleutel%s aan te vragen en die in het  "API sleutel" veld bovenaan de pagina in te vullen.Je kunt bestaande map stijlen van %sSnazzy Maps%s of %sMap Stylr%s kopieren en in het onderstaande tekstvlak plaatsen. Of je kunt de map stijl genereren via de %sMap Style Editor%s of de %sStyled Maps Wizard%s.Je hebt geen toestemming om plugin updates te installerenJe hebt geen toestemming om deze actie uit te voerenJe hebt de dagelijkse toegestane geocoding limiet bereikt, je kan er %shier%s meer over lezen.Je moet %sAPI sleutels%s aanmaken voor Google Maps voordat je gebruik kan maken van de store locator! %sSluit%sJe moet minimaal de gegevens voor het adres, stad, provincie of land opgeven voordat de API de coördinaten kan terugsturen.Uw locatieZambiaZimbabwePostcodePostcodeDe optie om alleen op een postcode te zoeken werkt helaas niet goed in combinatie met de autocomplete optie. %s Het is daarom beter om niet beide opties tegelijk actief te hebben.Zoom bediening positieZoom hierinfo windowkmmiwinkel-categoriewinkelsÅland Eilandlanguages/wpsl-pt_PT.mo000064400000116202151327220640011064 0ustar00��t�� �+��+l,�,�,�,�,�,�,�,q-v-~-
�-�-�-�-	�-�-�-�-...p(.��.\/k/�/�/�/�/�/�/	�/�/�/�/	�/�/
0000
'020;0�B0j�021�1�1�1�1�1�1�1�1�122"2)2H2O2	X2b2o2w2�2�2.�2
�2�2�2�2
�2�23!3&3,323G3]3n3#s3N�3�3�3
�3444
4*424:4C4H4^4Mt4�4�4�4�4�4�4�4 
5+5
35
>5L5
U5c5t5}5�5�5�5�5�5�5�5�5�56616�M6(707E7]7t7�7�7�7G�7�7�7�7�7�7888
8+82888A8H8
Y83g8�8�8�8�8�8�8�8	�8�8
�8�8	�89
99&9,9(39\9t9�9�9	�9�9�9	�9�9�9�9Q�99&:b`:G�;h<�t<�2=��=<]>g�>^?\a?Z�?@7@M@	S@
]@h@{@�@�@�@�@�@�@�@�@�@�@
�@�@�@�@
�@�@�@�@A
AAA$A)A1A9A
?A	MA
WAbA~A$�A	�A
�A�A�A	�A
�A2�A4BQB	XB	bBlBqBuB
�B	�B�B!�B�B�B�B
�B
�B	�BCC%*CPC_C
fCqC5yC�C�C�C
�C
�C	�C�C
�C�CD	DDD!D6D=DUD	aDkDqDyD~D�D�D�D:�D�DE	E)E;EWE7\E�E
�E�Ed�E3FHFaFjFsFzF�F�F�F	�F�F�F�F�F.�F�"G�G�G�G
�G	HH3HDH
VHdHjH4|H�H�H�H�H�H�H�H�H�H�H�H	II +ILI
RI	]IgIpI}I�I	�I�I�I�I'�I
JJ0JKJ5XJ�J�J�J�J�J�J
�J.�J+K<K
UKcKK�K�K �K!�KL2L8?L	xL�L�L	�L�L�L�L'�L�L�L�LM		MM$M3MIMUM[MaMrM
�M�M
�M�M�M�M	�M�MN!N=N"NNqN+~N
�N�N�N�N�N�N�N	�N�NOOO O9OAO
HOSOYObOfOmOuO~O�OM�Oo�ODJP&�P��PWQ)qQ"�Q��Q�IR2�RKS4OS��SM&U}tU��UwV��W�GXO�XY$Y0Y5Y=YCYIY]YeYmYtY|Y�Y�Y�Y	�Y�Y�Y
�Y�Y�Y�Y*�Y(Z
8Z	CZMZ
UZ`Z
hZ#sZ�Z
�Z	�Z�Z^�Z2:[m[
�[�[L�[C�[w)\��\On]
�]�]�]�]�]�]�]	^^(^+^.^=^~D^��`"�a�a#�a�ab"!bDbMb�Vb�b�bc c8cOcVc_cqc}c�c�c�c��cGdJeYewee�e�e�e�e	�e�e�e(�e	�e�e
ffff
%f0f9f�@f��f�bghhhhh%h-h4h<hSh\h|h�h�h�h	�h�h�h�h�h�h=�h
(i3i	;iEiYijiyi�i�i�i�i�i�i�i2�i^jxj�j
�j�j�j�j
�j�j�j�j�j�jkt k�k�k�k�k�k�k
�k �k�kll&l/l
>lLlUlhl�l�l	�l�l�l�l�l!�l�lm'mDmPnXnmn�n�n�n�n�nO�no$o(o-o6o>oFoMo
Tobonoto}o�o
�o;�o�o�o�oppp%p	+p5p
=pHp	MpWp
^plpup{p1�p �p�p�p�p	q
qq	!q+q3q;qyCqM�q�rR�s�t��t��u�HvQ�vqLwl�wj+xh�x"�x"y7y	=y
GyRyiynysy{y�y�y�y�y�y�y�y
�y�y�y�y
�y	�y�y�y�y�yzzzz'z/z
5z	Cz
Mz2Xz
�z;�z	�z
�z�z�z	�z
{>{FQ{�{	�{	�{�{�{�{�{�{�{(�{$|
,|7|
H|
S|	^|"h|�|;�|�|�|
}}8}Q}
X}f}
o}
z}�}�}
�}�}�}�}�}�}�}�}�}~	~$~*~2~7~I~c~~4�~�~�~	�~�~'L,y��u�9�%V�|�����������Ȁ������;��Y�B�I�P�
Y�d�x�����˂��?��>�
E�P�X�`�r�z������������� ȃ�
�	�����	.�8�D�'b���,��Ԅ�"�
%�K0�|���������…
υ7څ5�)H�r� ��&��+͆$��'�'F�"n���A��	���	�����+$�P�]�i�o�	w�����#��Ј�����$�3�H�`�x�����!��&܉�#�7�*F�q�}�����������	��ɊЊ؊����
��#�,�0�7�?�N�S�e\�{‹E>�-�����q�&��%���؍���G!�Ti�5����RБ�#����1W�����y�W�o�|�������������ȖЖזߖ����	��!�
0�>�[�_�5g���
��	×͗
՗��-��
/�=�J�hh�5ј$�,�<�_B�G�������[n�ʛܛ����
�(�C�P�g�j�m�|���
�����8�\%6��^�

�^2�%F�u��|��0.��>c�}��X=��!_���q�g���=�0Q���F8����s[�a�7�b��4��\�������z/����Al}��w�T���3��-�xfK7���T�����"@�������	�L���?<C�����,UWB�i|�H`.�M	��db��G�)�N�>��k�(eII�&e9��Y��5?AKZ!S~:#�m���J�E�5���R'��Pq1�C*J�{�+���r2�hy����n�����	�
�f����3�X�����G��[S�c�����k��Dhv;QE���_�~�s jt�yV��w:�n��i��j�x��z��Vm6��u���p��{�N'�Oo��@��L1"�� ���-��#DB��R,�Y���O�P;�������&H$��orU���+���]��4�p$����l(��M<t)�������g��]��
�W�*d/�Z�9v����a���������`�%sRequired field.%s %s If auto-locating the user is disabled or fails, the center of the provided city or country will be used as the initial starting point for the user.(city) (state) (zip code)(city) (zip code)(city), (state) (zip code)(city), (zip code)(zip code) (city)(zip code) (city) (state)12 Hours24 HoursA valid %sAPI key%s allows you to monitor the API usage and is required if you need to purchase additional quota.API keyAPI usage limit reachedAdd New %sAdd New Store CategoryAdditional InformationAddressAddress 2Address formatAfghanistanAlbaniaAlgeriaAll %sAll Store CategoriesAll the store locations are now converted to custom post types. %s You can view them on the %sAll Stores%s page.Although the location data is cached after the first load, a lower number will result in the map being more responsive. %s If this field is left empty or set to 0, then all locations are loaded.American SamoaAn unknown error occurred.AndorraAngolaAnguillaAntigua and BarbudaAnyArabicArgentinaArmeniaArubaAttempt to auto-locate the userAustraliaAustriaAzerbaijanBackBahamasBahrainBangladeshBarbadosBasqueBecause you updated WP Store Locator from version 1.x, the %s current store locations need to be %sconverted%s to custom post types.Before adding the [wpsl] shortcode to a page, please don't forget to define a %sstart point%s. %sDismiss%sBefore adding the [wpsl] shortcode to a page, please don't forget to define a start point on the %ssettings%s page. %sDismiss%sBelarusBelgiumBelizeBengaliBeninBermudaBhutanBoliviaBosnia and HerzegovinaBotswanaBounces up and downBrazilBritish Indian Ocean TerritoryBruneiBulgariaBulgarianBurkina FasoBurundiCambodiaCameroonCanadaCannot determine the address at this location.Cape VerdeCatalanCategoryCategory filterCategory slugCayman IslandsCentral African RepublicChadChileChinaChinese (Simplified)Chinese (Traditional)Christmas IslandCityClear store locator transient cacheClicking this link will make the map zoom in to the %s max auto zoom level %s.ClosedCluster sizeCocos IslandsColombiaComorosCongoCosta RicaCountryCroatiaCroatianCubaCustom field deleted.Custom field updated.Custom map styles only work if the map type is set to "Roadmap" or "Terrain".CzechCzech RepublicCôte d'IvoireDanishDaysDefaultDefault countryDemocratic Republic of the CongoDenmarkDirectionsDistance unitDjiboutiDocumentationDoes not respondDominicaDominican RepublicDropdowns (recommended)DutchEcuadorEdit %sEdit Store CategoryEgyptEl SalvadorEmailEnable marker clusters?Enable permalink?Enable scroll wheel zooming?Enable store locator debug?Enabling this option can sometimes result in a small delay in the opening of the info window. %s This happens because an API request is made to Google Maps to check if street view is available for the current location.EnglishEnglish (Australian)English (Great Britain)Enter store title hereEquatorial GuineaEritreaEstoniaEthiopiaFailed to publish the store. Please fill in the required store details.FarsiFaxFijiFilipinoFinlandFinnishFranceFrenchFrench GuianaFridayGabonGalicianGambiaGeneral SettingsGeneral errorGeocode was not successful for the following reasonGermanGermanyGet directionsGhanaGoogle Maps APIGreeceGreekGreenlandGrenadaGuadeloupeGuamGuatemalaGuineaGuinea-BissauGujaratiHaitiHebrewHide the distance in the search results?Hide the opening hours?Hide the scrollbar?HindiHondurasHong KongHour formatHoursHungarianHungaryHybridIcelandIf %spermalinks%s are enabled, the store name will always link to the store page.If a user hovers over the search results the store markerIf marker clusters are enabled this option will not work as expected as long as the markers are clustered. %s The bouncing of the marker won't be visible at all unless a user zooms in far enough for the marker cluster to change back in to individual markers. %s The info window will open as expected, but it won't be clear to which marker it belongs to. If no map language is selected the browser's prefered language is used.If street view is available for the current location, then show a "Street view" link in the info window?If the default style is disabled the %sInfoBox%s library will be used instead. %s This enables you to easily change the look and feel of the info window through the .wpsl-infobox css class.If the store locator is not placed at the top of the page, enabling this feature can result in the page scrolling down. %s %sThis option is disabled on mobile devices.%sIf this zoom level is reached or exceeded, then all markers are moved out of the marker cluster and shown as individual markers.If you like this plugin please leave us a %s5 star%s rating.If you like to write the style code yourself, then you can find the documentation from Google %shere%s.If you use the [wpsl_address] shortcode outside a store page you need to set the ID attribute.If you use the [wpsl_hours] shortcode outside a store page you need to set the ID attribute.If you use the [wpsl_map] shortcode outside a store page you need to set the ID attribute.In the info window on the mapIn the store listingsIndiaIndonesiaIndonesianInitial zoom levelIranIraqIrelandIsraelItalianItalyJamaicaJapanJapaneseJordanKannadaKazakhstanKenyaKoreanKuwaitKyrgyzstanLabelsLaosLargeLatitudeLatviaLatvianLebanonLeftLesothoLiberiaLibyaLiechtensteinLithuaniaLithuanianLoad locations on page loadLocationLocation information is unavailable.LongitudeLuxembourgM j, Y @ G:iMacauMacedoniaMadagascarMake the phone number clickable on mobile devices?Make the store name clickable if a store URL exists?MalawiMalayalamMalaysia MaliMapMap languageMap regionMap styleMap typeMap type for the location previewMarathiMarkersMarshall IslandsMartiniqueMauritaniaMauritiusMax auto zoom levelMax search resultsMax width for the info window contentMax zoom levelMexicoMicronesiaMoldovaMon %sTue %sWed %sThu %sFri %sSat Closed %sSun ClosedMonacoMondayMongoliaMontenegroMontserratMore infoMoroccoMozambiqueMyanmarNamibiaNauruNepalNetherlandsNetherlands AntillesNew %sNew Store Category NameNew ZealandNicaraguaNigerNigeriaNiueNo %s foundNo %s found in trashNo directions foundNo results foundNo route could be found between the origin and destinationNorthern Mariana IslandsNorwayNorwegianNorwegian NynorskNumber of locations to showOmanOn page load move the mouse cursor to the search field?Open links in a new window?Opening HoursOpening PeriodsOpening hours created in version 1.x %sare not%s automatically converted to the new dropdown format.Opening hours formatOpening hours input typeOptionalPakistanPanamaPapua New GuineaParaguayParent Store CategoryParent Store Category:PermalinkPeruPhilippinesPhonePitcairn IslandsPlease fill in all the required store details.Please provide the name of a city or country that can be used as a starting point under "Map Settings". %s This will only be used if auto-locating the user fails, or the option itself is disabled.PolandPolishPortugalPortuguesePortuguese (Brazil)Portuguese (Portugal)Preview LocationPreview Map StylePreview storeQatarQuery limit errorRecommended for maps with a large amount of markers.ResetResultsReunionRightRoadmapRomaniaRomanianRussiaRussianRwandaSaint HelenaSaint Kitts and NevisSaint LuciaSaint Vincent and the GrenadinesSamoaSan MarinoSatelliteSaturdaySaudi ArabiaSave ChangesSearchSearch %sSearch Store CategoriesSearch and radius label widthSearch field widthSearch provided by %sWP Store Locator%sSearch radiusSearch radius optionsSearching (preloader text)Searching...Security check failed, reload the page and try again.Select your languageSelect your regionSenegalSerbiaSerbianSettingsSeychellesShow a "More info" link in the store listings?Show a "Zoom here" link in the info window?Show a reset map button?Show credits?Show the category dropdown?Show the map type control?Show the max results dropdown?Show the pan controls?Show the search radius dropdown?Show the store list below the mapShow the street view controls?Sierra LeoneSign up for the latest plugin updates and announcements.SingaporeSlovakSlovakiaSlovenianSmallSolomon IslandsSomaliaSomething went wrong, please try again!South AfricaSouth KoreaSpainSpanishSri LankaStart ConvertingStart locationStart location markerStart pointStateStoreStore CategoriesStore CategoryStore DetailsStore EditorStore LocatorStore Locator ManagerStore Locator heightStore Locator templateStore MapStore draft updated.Store location markerStore locations to convert:Store published.Store restored to revision from %sStore saved.Store scheduled for: <strong>%1$s</strong>.Store slugStore submitted.Store updated.StoresStreet viewSudanSundaySwazilandSwedenSwedishSwitzerlandSyriaSão Tomé and PríncipeTagalogTaiwanTajikistanTamilTanzaniaTelTeluguTerrainTextareaThaiThailandThe Google Geocoding API failed to return valid data, please try again later.The Google Geocoding API returned no results for the supplied address. Please change the address and try again.The application does not have permission to use the Geolocation API.The code for the map style is invalid.The default country and opening hours are only used when a new store is created. So changing the default values will have no effect on existing store locations.The default opening hoursThe default value is set between the [ ].The geolocation request timed out.The grid size of a cluster in pixels. %s A larger number will result in a lower amount of clusters and also make the algorithm run faster.The map preview is based on the provided address, city and country details. %s It will ignore any custom latitude or longitude values.The map preview requires all the location details.The max results field cannot be empty, the default value has been restored.The permalink slugs %smust be unique%s on your site.The script converting the locations timed out. %s You can click the "Start Converting" button again to restart the script. %s If there are thousands of store locations left to convert and you keep seeing this message, then you can try to contact your host and ask if they can increase the maximum execution time. %s The plugin tried to disable the maximum execution time, but if you are reading this then that failed.The search radius field cannot be empty, the default value has been restored.The selected template is used with the [wpsl] shortcode. %s You can add a custom template with the %swpsl_templates%s filter.This disables the WPSL transient cache. %sThe transient cache is only used if the %sLoad locations on page load%s option is enabled.This places a "More Info" link below the address and will show the phone, fax, email, opening hours and description once the link is clicked. %s If you for example want the contact details to always be visible, then please follow the instructions on %sthis%s page.This value sets the zoom level for the "Zoom here" link in the info window. %s It is also used to limit the zooming when the viewport of the map is changed to make all the markers fit on the screen.This will bias the geocoding results towards the selected region. %s If no region is selected the bias is set to the United States.This will place a "Search provided by WP Store Locator" backlink below the map.ThursdayTimor-LesteTogoTokelauTongaToolsTrinidad and TobagoTuesdayTunisiaTurkeyTurkishTurkmenistanTuvaluUgandaUkraineUkrainianUnited Arab EmiratesUnited KingdomUnited StatesUpdate Store CategoryUrlUruguayUse the default style for the info window?User ExperienceUzbekistanVenezuelaVietnamVietnameseView %sView storeWP Store Locator Transients ClearedWPSL transientsWallis FutunaWednesdayWelcome to WP Store LocatorWhen a user clicks on "Directions", open a new window, and show the route on google.com/maps ?Where do you want to show the "More info" details?Will open the info windowWorld viewYemenYou can add custom address formats with the %swpsl_address_formats%s filter.You can drag the marker to adjust the exact location of the marker.You can raise the %susage limit%s by obtaining an API %skey%s, and fill in the "API key" field at the top of this page.You can use existing map styles from %sSnazzy Maps%s or %sMap Stylr%s and paste it in the textarea below, or you can generate a custom map style through the %sMap Style Editor%s or %sStyled Maps Wizard%s.You have reached the daily allowed geocoding limit, you can read more %shere%s.Your locationZambiaZimbabweZipZip CodeZoom control positionZoom control styleZoom hereinfo windowkmmistore-categorystoresProject-Id-Version: WP Store Locator v2.0
Report-Msgid-Bugs-To: 
POT-Creation-Date: 2015-09-01 13:49+0100
PO-Revision-Date: 2015-09-05 13:48-0000
Last-Translator: Rúben Martins <geral@rubenmartins.pt>
Language-Team: 
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Plural-Forms: nplurals=2; plural=(n != 1);
X-Generator: Poedit 1.6.4
X-Poedit-SourceCharset: UTF-8
X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2
X-Poedit-Basepath: ../
X-Textdomain-Support: yes
Language: pt_PT
X-Poedit-SearchPath-0: .
%sCampos obrigatórios.%s %s Se a auto-localização do utilizador estiver desativada ou falhar, o centro da cidade ou país fornecido será utilizado como ponto de partida inicial para o utilizador.(cidade) (estado) (código postal)(cidade) (código postal)(cidade), (estado) (código postal)(cidade), (código postal)(código postal) (cidade)(código postal) (cidade) (estado)12 Horas24 HorasA %schave de API%s válida permite que você monitorize o uso da API e é necessário se você precisar de comprar quota adicional.Chave de APILimite de uso de API atingidoAdicionar Nova %sAdicionar Nova Categoria de LojaInformação AdicionalMoradaMorada 2Formato de moradaAfghanistanAlbaniaAlgeriaTodos %sTodas as Categorias de LojasTodos as localizações de lojas agora são convertidos em tipos de conteúdos personalizados. %s Você pode vê-las na página %sTodas as Lojas%s.Embora os dados de localização são colocadas em cache depois do primeiro carregamento, um número inferior irá resultar no mapa ser mais ajustável. %s Se este campo for deixado em branco ou definido como 0, em seguida, todos os locais serão carregados.American SamoaOcorreu um erro desconhecido.AndorraAngolaAnguillaAntigua and BarbudaAlgumArabicArgentinaArmeniaArubaTentativa de auto-localizar o utilizadorAustraliaAustriaAzerbaijanVoltarBahamasBahrainBangladeshBarbadosBasquePorque você atualizou o WP Store Locator da versão 1.x, %sa atual localização de loja precisa de ser %sconvertida%s para tipos de conteúdo personalizado.Antes de adicionar o shortcode [WPSL] para uma página, por favor, não se esqueça de definir %sum ponto de inicio%s. %sRemover%sAntes de adicionar o shortcode [WPSL] para uma página, por favor, não se esqueça de definir um ponto de partida na página de %sdefinições%s. %sAnular%sBelarusBelgiumBelizeBengaliBeninBermudaBhutanBoliviaBosnia and HerzegovinaBotswanaBalança para cima e para baixoBrazilBritish Indian Ocean TerritoryBruneiBulgariaBulgarianBurkina FasoBurundiCambodiaCameroonCanadaNão é possível determinar o endereço nesta localização.Cape VerdeCatalanCategoriaFiltro de categoriaURL de categoriaCayman IslandsCentral African RepublicChadChileChinaChinese (Simplified)Chinese (Traditional)Christmas IslandCidadeLimpar localização de lojas de cache temporárioAo clicar nessa ligação vai fazer o mapa ampliar ao%s nível máximo de zoom automático %s.FechadoTamanho de agrupamentoCocos IslandsColombiaComorosCongoCosta RicaPaísCroatiaCroatianCubaCampo personalizado apagado.Campo personalizado atualizado.Estilos de mapa personalizados só funcionam se o tipo de mapa estiver definido para "Mapa de Estrada" ou "Terreno".CzechCzech RepublicCôte d'IvoireDanishDiasPadrãoPaís padrãoDemocratic Republic of the CongoDenmarkDirecçõesUnidade de distânciaDjiboutiDocumentaçãoNão respondeDominicaDominican RepublicDropdowns (recomendado)DutchEcuadorEditar %sEditar Categoria de LojaEgyptEl SalvadorE-mailAtivar agrupamento de marcadores?Activar links permanentes?Activar roda de scroll do zoom?Activar store locator debug?A ativação desta opção, por vezes, pode resultar em um pequeno atraso na abertura da janela de informações. %s Isso acontece porque uma solicitação de API é feita para o Google Maps para verificar se vista da rua está disponível para a localização atual.EnglishEnglish (Australian)English (Great Britain)Insira o título da loja aquiEquatorial GuineaEritreaEstoniaEthiopiaFalha ao publicar a loja. Por favor, preencha os detalhes necessários da loja.FarsiFaxFijiFilipinoFinlandFinnishFranceFrenchFrench GuianaSexta-FeiraGabonGalicianGambiaDefinições GeraisErro geralGeocodificação não foi bem sucedida pelo seguinte motivoGermanGermanyObter direcçõesGhanaAPI dos Mapas do GoogleGreeceGreekGreenlandGrenadaGuadeloupeGuamGuatemalaGuineaGuinea-BissauGujaratiHaitiHebrewEsconder a distância nos resultados da pesquisa?Esconder o horário de abertura?Esconder a barra de scroll?HindiHondurasHong KongFormato de horasHorasHungarianHungaryHibridoIcelandSe as %sligações permanentes% s estiverem activadas, o nome da loja será sempre uma ligação para as página da loja.Se um utilizador passar sobre os resultados da pesquisa os marcadores de lojaSe o agrupamento de marcadores estiverem habilitados, esta opção não irá funcionar como esperado, enquanto os marcadores estão agrupados. %s O salto do marcador não será visível a todos, a menos que um utilizador se aproxime suficientemente longe para o agrupamento de marcadores mudar novamente para marcadores individuais. %s A janela de informações será apresentada como previsto, mas não vai ser claro sobre qual marcador pertence.Se nenhum idioma de mapa é selecionado, o idioma preferido do navegador é usado.Se a vista da rua estiver disponível para a localização atual, em seguida, mostrar um link "Vista da Rua" na janela de informação?Se o estilo padrão é desativado a livraria da %sCaixa de informação%s será usado em seu lugar. %s Isso permite que você facilmente mude a aparência da janela de informações através da classe css .wpsl-infobox.Se o localizador de lojas não é colocado na parte superior da página, activando esta funcionalidade pode resultar que a página desça. %s %sEsta opção é desativada em dispositivos móveis.%sSe este nível de zoom for atingido ou ultrapassado, em seguida, todos os marcadores são movidos para fora do agrupamento de marcadores e mostrados como marcadores individuais.Se gosta deste plugin, por favor deixe-nos uma classificação de %s5 estrelas%s.Se você gosta de escrever os código de estilo, então você pode encontrar a documentação do Google %saqui%s.Se utilizar o shortcode [wpsl_address] fora de uma página de loja você necessita de definir o atributo ID.Se utilizar o shortcode [wpsl_hours] fora de uma página de loja você necessita de definir o atributo ID.Se utilizar o shortcode [wpsl_map] fora de uma página de loja você necessita de definir o atributo ID.Na janela de informações do mapaNa listagem de lojasIndiaIndonesiaIndonesianNível de zoom inicialIranIraqIrelandIsraelItalianItalyJamaicaJapanJapaneseJordanKannadaKazakhstanKenyaKoreanKuwaitKyrgyzstanEtiquetasLaosGrandeLatitudeLatviaLatvianLebanonEsquerdaLesothoLiberiaLibyaLiechtensteinLithuaniaLithuanianCarregar localizações no carregamento da páginaLocalizaçãoAs informações de localização não estão disponíveis.LongitudeLuxembourgj M, Y @ G:iMacauMacedoniaMadagascarFazer o número de telefone clicável em dispositivos móveis?Permitir que o nome da loja seja clicável se um link da loja existir?MalawiMalayalamMalaysia MaliMapaLinguagem de mapaRegião de mapaEstilo do mapaTipo de mapaTipo de mapa para a visualização localMarathiMarcadoresMarshall IslandsMartiniqueMauritaniaMauritiusNível de zoom máximo automáticoMáximos resultados da pesquisaMáxima largura para o conteúdo da janela de informaçõesNível de zoom máximoMexicoMicronesiaMoldovaSeg %sTer %sQua %sQui %sSex %sSáb Fechado %sDom FechadoMonacoSegunda-FeiraMongoliaMontenegroMontserratMais informaçãoMoroccoMozambiqueMyanmarNamibiaNauruNepalNetherlandsNetherlands AntillesNova %sNovo Nome de Categoria de LojaNew ZealandNicaraguaNigerNigeriaNiueSem %s encontradaSem %s encontrada no lixoSem direcções encontradasSem resultados encontradosNenhuma rota foi encontrada entre a origem e destinoNorthern Mariana IslandsNorwayNorwegianNorwegian NynorskNúmero de locais a mostrarOmanNo carregamento da página mover o cursor do mouse para o campo de pesquisa?Abrir links numa nova janela?Horas de AberturaHorário de FuncionamentoHorário de abertura criado na versão 1.x %snão são%s automaticamente convertidos para o novo formato de dropdown.Formato de horas de aberturaTipo de campo de horário de aberturaOpcionalPakistanPanamaPapua New GuineaParaguayPai da Categoria de LojaPai da Categoria de Loja:Link permanentePeruPhilippinesTelefonePitcairn IslandsPor favor, preencha todos os detalhes necessários da loja.Por favor, forneça o nome de uma cidade ou país que pode ser usado como um ponto de partida em "Definições do mapa". %s Isso só será usado se a auto-localização do utilizador falhar, ou a própria opção estiver desativada.PolandPolishPortugalPortuguesePortuguese (Brazil)Portuguese (Portugal)Pré-visualizar localizaçãoPré-visualizar estilo do mapaPré-visualizar lojaQatarErro limite da consultaRecomendado para mapas com uma grande quantidade de marcadores.LimparResultadosReunionDireitaMapa das estradasRomaniaRomanianRussiaRussianRwandaSaint HelenaSaint Kitts and NevisSaint LuciaSaint Vincent and the GrenadinesSamoaSan MarinoSatéliteSábadoSaudi ArabiaGuardar alteraçõesPesquisarProcurar %sPesquisar Categorias de LojasLargura  de marcador de pesquisa e raioLargura do campo de pesquisaPesquisa fornecido pelo %sWP Store Locator%sRaio de pesquisaOpções de raio de pesquisaPesquisando (texto pré-carregado)ProcurandoVerificação de segurança falhou, recarregue a página e tente novamente.Selecione o seu idiomaSelecione a sua regiãoSenegalSerbiaSerbianDefiniçõesSeychellesMostrar o link "Mais informação" nas listas de lojas?Mostrar o link "Zoom aqui" na janela de informação?Mostrar um botão de reposição de mapa?Mostrar créditos?Mostrar a categoria em dropdown?Mostrar o controlador do tipo de mapa?Mostrar os máximos resultados em dropdown?Mostrar os controlos de panorâmica?Mostrar o raio de pesquisa em dropdown?Mostrar a lista de lojas abaixo do mapaMostrar controlos de vista de rua?Sierra LeoneRegiste-se para as últimas atualizações de plugin e anúncios.SingaporeSlovakSlovakiaSlovenianPequenoSolomon IslandsSomaliaAlgo deu errado, por favor tente novamente!South AfricaSouth KoreaSpainSpanishSri LankaIniciar a ConversãoLocalização inicialMarcador de inicio de localizaçãoPonto de partidaEstadoLojaCategorias de LojasCategoria de LojaDetalhes da LojaEditor de LojaLocalizador de lojasGestor do Store LocatorAltura do Store LocatorModelo de Store LocatorMapa da LojaRascunho de loja atualizado.Marcador de localização da lojaLocalização de lojas para converter:Loja publicada.Loja restaurada para revisão de% sLoja Guardada.Loja agendada para: <strong>%1$s</strong>.URL de lojaLoja submetida.Loja atualizada.LojasVista da ruaSudanDomingoSwazilandSwedenSwedishSwitzerlandSyriaSão Tomé and PríncipeTagalogTaiwanTajikistanTamilTanzaniaTelTeluguTerrenoÁrea de TextoThaiThailandO Google Geocoding API não conseguiu retornar dados válidos, por favor, tente novamente mais tarde.O Google Geocoding API nao retornou resultados para o endereço fornecido. Por favor, altere o endereço e tente novamente.O aplicativo não tem permissão para usar a API de Geolocalização.O código para o estilo de mapa é inválido.O país padrão e as horas de abertura são somente aplicadas quando uma nova loja é criada. Por isso alterar os valores padrão não irá ter efeito nas localizações de lojas existentes.Horas de abertura padrãoO valor padrão é definido entre [ ].O pedido de geolocalização expirou.O tamanho da grelha de um agrupamento em pixels. %s Um número maior resultará em uma menor quantidade de agrupamentos e também fazer o algoritmo funcionar mais rápido.A pré-visualização do mapa é baseado no endereço, cidade e país fornecidos. %s Irá ignorar quaisquer valores de latitude ou longitude personalizados.A pré-visualização de mapa exige todos os detalhes da localização.O campo de máximo resultados não pode estar vazio, o valor padrão foi restaurado.Os urls permanentes %sdevem ser unicos%s no seu site.O script de conversão de locais expirou. %s Você pode clicar no botão "Começar a converter" novamente para reiniciar o script. %s Se existem milhares de localizações de lojas por converter e você continua vendo esta mensagem, então você pode tentar entrar em contato com seu alojamento e perguntar se eles podem aumentar o tempo máximo de execução. O plugin%s tentou desativar o tempo máximo de execução, mas se você está lendo isso, então é porque falhou.O campo de raio de pesquisa não pode estar vazio, o valor padrão foi restaurado.O modelo selecionado é utilizado com o [WPSL] shortcode. %s Você pode adicionar um modelo personalizado com o filtro %swpsl_templates%s.Isto desativa o cache temporário do WPSL. %sO de cache temporário só é usado se a opção %sCarregar localizações no carregamento da página%s estiver habilitado.Isto coloca um link de "Mais Informação" abaixo do endereço e vai mostrar o telefone, fax, e-mail, horário de funcionamento e descrição uma vez que o link seja clicado. %s Se você quiser, por exemplo, quiser que os dados de contacto estejam sempre visíveis, siga as instruções %snesta%s página.Esse valor define o nível de zoom para a ligação "zoom aqui" na janela de informações. %s Também é usado para limitar o zoom quando a janela de visualização do mapa é alterada para fazer todos os marcadores se ajustarem ao ecran.Este será os resultados de geocodificação para a região selecionada. %s Se nenhuma região for selecionada, o padrão é definido para os Estados Unidos.Isto irá colocar a "Pesquisa fornecida pela WP Store Locator" backlink abaixo do mapa.Quinta-FeiraTimor-LesteTogoTokelauTongaFerramentasTrinidad and TobagoTerça-FeiraTunisiaTurkeyTurkishTurkmenistanTuvaluUgandaUkraineUkrainianUnited Arab EmiratesUnited KingdomUnited StatesActualizar Categoria de LojaUrlUruguayUsar o estilo padrão para a janela de informações?Experiência de utilizadorUzbekistanVenezuelaVietnamVietnameseVer %sVer lojaCache temporário de WP Store Locator apagadoWPSL temporárioWallis FutunaQuarta-FeiraBem-vindo ao WP Store LocatorQuando um utilizador clica em "Como chegar", abrir uma nova janela, e mostrar a rota em google.com/maps?Onde quer mostrar os detalhes de "Mais informação"?Irá abrir a janela de informaçõesVisão de mundoYemenVocê pode adicionar formatos personalizados de endereço com o filtro%swpsl_address_formats%s.Você pode arrastar o marcador para ajustar ao local exato do marcador.Você pode aumentar os limite de %sutilização% s através da obtenção de uma %schave%s API, e preencher o campo "chave API " na parte superior da página.Você pode usar estilos de mapa existente %sSnazzy Mapas%s ou%sMAP Stylr%s e cole-o na área de texto abaixo, ou você pode gerar um estilo de mapa personalizado através do %sMAP Editor de estilos%s ou %sAssistente de mapas% s.Você atingiu o limite diário de geocodificação permitido, você pode ler mais %saqui%s.Sua localizaçãoZambiaZimbabweCódigo postalCódigo PostalPosição do controlo de ZoomEstilo de controlo de ZoomAmpliar aquiinformação de janelakmmistore-categorylojaslanguages/wpsl-es_ES.po000064400000231750151327220640011045 0ustar00msgid ""
msgstr ""
"Project-Id-Version: WP Store Locator v2.2.10\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-12-01 13:23+0700\n"
"PO-Revision-Date: 2017-12-01 09:40-0600\n"
"Last-Translator: Jaime Smeke <hola@untaljai.me>\n"
"Language-Team: Jaime Smeke <hola@untaljai.me>\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.0.4\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;"
"_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2\n"
"X-Poedit-Basepath: ..\n"
"X-Textdomain-Support: yes\n"
"X-Poedit-SearchPath-0: .\n"

#: admin/EDD_SL_Plugin_Updater.php:201
#, php-format
msgid ""
"There is a new version of %1$s available. %2$sView version %3$s details%4$s."
msgstr ""
"Una nueva versión de %1$s está disponible. %2$sVer los detalles de la %3$s "
"versión%4$s."

#: admin/EDD_SL_Plugin_Updater.php:209
#, php-format
msgid ""
"There is a new version of %1$s available. %2$sView version %3$s details%4$s "
"or %5$supdate now%6$s."
msgstr ""
"Una nueva versión de %1$s está disponible. %2$sVer detalles de la %3$s "
"versión%4$s o %5$sactualizar ahora%6$s."

#: admin/EDD_SL_Plugin_Updater.php:399
msgid "You do not have permission to install plugin updates"
msgstr "No tienes los permisos necesarios para actualizar el plugin"

#: admin/EDD_SL_Plugin_Updater.php:399 admin/class-shortcode-generator.php:61
msgid "Error"
msgstr "Error"

#: admin/class-admin.php:117
#, php-format
msgid ""
"You need to create %sAPI keys%s for Google Maps before you can use the store "
"locator! %sDismiss%s"
msgstr ""
"¡Debes crear una %sLlave API%s de Google Maps antes de poder usar el "
"Localizador de tiendas! %sDescartar%s"

#: admin/class-admin.php:119
#, php-format
msgid ""
"Before adding the [wpsl] shortcode to a page, please don't forget to define "
"a start point on the %ssettings%s page. %sDismiss%s"
msgstr ""
"Por favor no olvides definir un punto de inicio en la página de %sajustes%s "
"antes de añadir el shortcode de [wpsl] a una página. %sCerrar%s"

#: admin/class-admin.php:156
msgid "Security check failed. Please reload the page and try again."
msgstr ""
"Chequeo de seguridad fallido, por favor recarga la página e intenta "
"nuevamente."

#: admin/class-admin.php:175 admin/class-admin.php:176
#: admin/class-admin.php:468 admin/templates/map-settings.php:11
msgid "Settings"
msgstr "Ajustes"

#: admin/class-admin.php:182 admin/class-admin.php:183
#: admin/class-admin.php:488
msgid "Add-Ons"
msgstr "Extensiones"

#: admin/class-admin.php:294
msgid "Cannot determine the address at this location."
msgstr "Imposible determinar la dirección en esta ubicación."

#: admin/class-admin.php:295
msgid "Geocode was not successful for the following reason"
msgstr "La geolocalización falló por la siguiente razón"

#: admin/class-admin.php:296 admin/upgrade.php:452
msgid "Security check failed, reload the page and try again."
msgstr ""
"Chequeo de seguridad fallido, por favor recarga la página e intenta de nuevo."

#: admin/class-admin.php:297
msgid "Please fill in all the required store details."
msgstr "Por favor llena todos los detalles de tienda necesarios."

#: admin/class-admin.php:298
msgid "The map preview requires all the location details."
msgstr "El mapa de previsualización requiere todos los detalles de ubicación."

#: admin/class-admin.php:299 admin/class-metaboxes.php:525
#: frontend/class-frontend.php:561
msgid "Closed"
msgstr "Cerrado"

#: admin/class-admin.php:300
msgid "The code for the map style is invalid."
msgstr "El código para el estilo del mapa es inválido."

#: admin/class-admin.php:301
#, php-format
msgid ""
"There's a problem with the provided %sbrowser key%s. %s You can read more "
"about how to determine the exact issue, and how to solve it %shere%s."
msgstr ""
"Hubo un problema con la %sllave de navegador%s proporcionada. %s Puedes leer "
"más acerca de cómo determinar el error exacto, y cómo solucionarlo, %saquí%s."

#: admin/class-admin.php:302
msgid "Dismiss this notice."
msgstr "Descartar este aviso."

#: admin/class-admin.php:423
msgid "Welcome to WP Store Locator"
msgstr "Bienvenido a WP Store Locator"

#: admin/class-admin.php:424
msgid "Sign up for the latest plugin updates and announcements."
msgstr "Regístrate para recibir los anuncios y actualizaciones más recientes."

#: admin/class-admin.php:487
msgid "Documentation"
msgstr "Documentación"

#: admin/class-admin.php:510
#, php-format
msgid "If you like this plugin please leave us a %s5 star%s rating."
msgstr ""
"Si te gusta este plugin, por favor déjanos una calificación de %s5 estrellas"
"%s."

#: admin/class-geocode.php:80
msgid ""
"The Google Geocoding API returned no results for the supplied address. "
"Please change the address and try again."
msgstr ""
"El API de Geolocalización de Google no devolvió ningún resultado para la "
"dirección provista. Por favor cambia la dirección e intenta de nuevo."

#: admin/class-geocode.php:83
#, php-format
msgid ""
"You have reached the daily allowed geocoding limit, you can read more %shere"
"%s."
msgstr ""
"Llegaste el límite diario permitido de geolocalización, puedes leer más "
"%saquí%s."

#: admin/class-geocode.php:86
#, php-format
msgid "The Google Geocoding API returned REQUEST_DENIED. %s"
msgstr "El API de Geolocalización de Google devolvió REQUEST_DENIED. %s"

#: admin/class-geocode.php:89
msgid ""
"The Google Geocoding API failed to return valid data, please try again later."
msgstr ""
"El API de Geolocalización de Google no devolvió datos válidos, por favor "
"intenta de nuevo más tarde."

#: admin/class-geocode.php:117
#, php-format
msgid ""
"%sError message: %s. %s Make sure the IP address mentioned in the error "
"matches with the IP set as the %sreferrer%s for the server API key in the "
"%sGoogle API Console%s."
msgstr ""
"%sMensaje de error: %s %s Asegúrate de que la dirección IP mencionada en el "
"error sea la misma que la dirección IP establecida como %sreferrer%s para la "
"Llave API del servidor en la %sConsola de API de Google%s."

#: admin/class-geocode.php:119
#, php-format
msgid ""
"%sError message: %s %s Check if your issue is covered in the "
"%stroubleshooting%s section, if not, then please open a %ssupport ticket%s."
msgstr ""
"%sMensaje de error: %s %s Revisa si tu problema está cubierto en la sección "
"de %ssolución de errores%s, si no, por favor abre un %sticket de soporte%s."

#: admin/class-geocode.php:141
#, php-format
msgid ""
"Something went wrong connecting to the Google Geocode API: %s %s Please try "
"again later."
msgstr ""
"Algo falló al conectarse al API de Geolocalización de Google: %s %s Por "
"favor intenta de nuevo más tarde."

#: admin/class-geocode.php:143
#, php-format
msgid ""
"The Google Geocode API reported the following problem: error %s %s %s Please "
"try again later."
msgstr ""
"El API de Geolocalización de Google reportó el siguiente problemama: error "
"%s %s %s Por favor inténtalo nuevamente más tarde."

#: admin/class-geocode.php:148
#, php-format
msgid "You can fix this by making sure the CSV file uses %sUTF-8 encoding%s."
msgstr ""
"Puedes solucionar esto asegurándote de que tu archivo CSV esté usando el "
"%scodificado UTF-8%s."

#: admin/class-geocode.php:150
msgid ""
"You need to provide the details for either the address, city, state or "
"country before the API can return coordinates."
msgstr ""
"Necesitas introducir al menos una dirección, ciudad, estado o país para que "
"el API pueda devolver coordenadas."

#: admin/class-geocode.php:153
#, php-format
msgid ""
"The Google Geocode API reported the following problem: error %s %s %s %s"
msgstr ""
"El API de Geolocalización de Google reportó el siguiente problema: error %s "
"%s %s %s"

#: admin/class-geocode.php:155
#, php-format
msgid ""
"The Google Geocode API reported the following problem: error %s %s %s Please "
"contact %ssupport%s if the problem persists."
msgstr ""
"El API de Geolocalización de Google reportó el siguiente error: %s %s %s Por "
"favor contacta a %ssoporte%s si el problema continúa."

#: admin/class-license-manager.php:183
#, php-format
msgid ""
"The %s license failed to deactivate, please try again later or contact "
"support!"
msgstr ""
"La licencia de %s no pudo ser desactivada, ¡por favor intenta de nuevo más "
"tarde o contacta a soporte!"

#: admin/class-license-manager.php:209 admin/templates/add-ons.php:56
msgid "Please try again later!"
msgstr "¡Por favor intenta de nuevo más tarde!"

#: admin/class-license-manager.php:257
#, php-format
msgid "The %s license key does not belong to this add-on."
msgstr "La clave de licencia %s no corresponde a esta extensión."

#: admin/class-license-manager.php:260
#, php-format
msgid "The %s license key does not have any activations left."
msgstr "La clave de licencia %s ya no tiene activaciones disponibles."

#: admin/class-license-manager.php:263
#, php-format
msgid "The %s license key is expired. Please renew it."
msgstr "La clave de licencia %s ha expirado. Por favor renuévala."

#: admin/class-license-manager.php:266
#, php-format
msgid ""
"There was a problem activating the license key for the %s, please try again "
"or contact support. Error code: %s"
msgstr ""
"Hubo un problema al activar la clave de licencia para %s, por favor intenta "
"de nuevo o contacta a soporte. Código de error: %s"

#: admin/class-metaboxes.php:33
msgid "Store Details"
msgstr "Detalles de tienda"

#: admin/class-metaboxes.php:34
msgid "Store Map"
msgstr "Mapa de tiendas"

#: admin/class-metaboxes.php:48
msgid "Location"
msgstr "Ubicación"

#: admin/class-metaboxes.php:50 inc/class-post-types.php:159
msgid "Address"
msgstr "Dirección"

#: admin/class-metaboxes.php:54
msgid "Address 2"
msgstr "Dirección 2"

#: admin/class-metaboxes.php:57 inc/class-post-types.php:160
msgid "City"
msgstr "Ciudad"

#: admin/class-metaboxes.php:61 inc/class-post-types.php:161
msgid "State"
msgstr "Estado"

#: admin/class-metaboxes.php:64
msgid "Zip Code"
msgstr "Código postal"

#: admin/class-metaboxes.php:67
msgid "Country"
msgstr "País"

#: admin/class-metaboxes.php:74
msgid "Latitude"
msgstr "Latitud"

#: admin/class-metaboxes.php:77
msgid "Longitude"
msgstr "Longitud"

#: admin/class-metaboxes.php:80 admin/class-metaboxes.php:129
#: admin/class-metaboxes.php:144
msgid "Opening Hours"
msgstr "Horarios de operación"

#: admin/class-metaboxes.php:82 admin/templates/map-settings.php:539
#: admin/templates/map-settings.php:540 frontend/underscore-functions.php:160
#: inc/wpsl-functions.php:150
msgid "Hours"
msgstr "Horas"

#: admin/class-metaboxes.php:86
msgid "Additional Information"
msgstr "Información adicional"

#: admin/class-metaboxes.php:88
msgid "Tel"
msgstr "Tel"

#: admin/class-metaboxes.php:91 admin/templates/map-settings.php:527
#: admin/templates/map-settings.php:528 frontend/class-frontend.php:825
#: frontend/underscore-functions.php:32 frontend/underscore-functions.php:68
#: frontend/underscore-functions.php:150 inc/wpsl-functions.php:147
msgid "Fax"
msgstr "Fax"

#: admin/class-metaboxes.php:94 admin/templates/map-settings.php:531
#: admin/templates/map-settings.php:532 admin/upgrade.php:198
#: frontend/class-frontend.php:829 frontend/underscore-functions.php:35
#: frontend/underscore-functions.php:71 frontend/underscore-functions.php:153
#: inc/wpsl-functions.php:148
msgid "Email"
msgstr "Email"

#: admin/class-metaboxes.php:97 admin/templates/map-settings.php:535
#: admin/templates/map-settings.php:536 admin/upgrade.php:202
#: frontend/class-frontend.php:834 inc/wpsl-functions.php:149
msgid "Url"
msgstr "Url"

#: admin/class-metaboxes.php:447
msgid "Hour format"
msgstr "Formato de hora"

#: admin/class-metaboxes.php:454
msgid "Days"
msgstr "Días"

#: admin/class-metaboxes.php:455
msgid "Opening Periods"
msgstr "Períodos de operación"

#: admin/class-metaboxes.php:705
msgid "Failed to publish the store. Please fill in the required store details."
msgstr ""
"Falló la publicación de la tienda. Por favor ingresa toda la información "
"requerida."

#: admin/class-metaboxes.php:841
msgid "Preview Location"
msgstr "Previsualizar ubicación"

#: admin/class-metaboxes.php:842
#, php-format
msgid ""
"The map preview is based on the provided address, city and country details. "
"%s It will ignore any custom latitude or longitude values."
msgstr ""
"El mapa de previsualización se basa en la dirección ingresada, ciudad y "
"país. %s Va a ignorar cualquier valor de latitud o longitud personalizado."

#: admin/class-metaboxes.php:843
msgid "You can drag the marker to adjust the exact location of the marker."
msgstr "Puedes arrastrar el marcador para ajustar la dirección exacta de éste."

#: admin/class-metaboxes.php:863 admin/class-metaboxes.php:866
msgid "Store updated."
msgstr "Tienda actualizada."

#: admin/class-metaboxes.php:864
msgid "Custom field updated."
msgstr "Campo personalizado actualizado."

#: admin/class-metaboxes.php:865
msgid "Custom field deleted."
msgstr "Campo personalizado eliminado."

#: admin/class-metaboxes.php:867
#, php-format
msgid "Store restored to revision from %s"
msgstr "Tienda restaurada a la revisión de %s"

#: admin/class-metaboxes.php:868
msgid "Store published."
msgstr "Tienda publicada."

#: admin/class-metaboxes.php:869
msgid "Store saved."
msgstr "Tienda guardada."

#: admin/class-metaboxes.php:870
msgid "Store submitted."
msgstr "Tienda publicada."

#: admin/class-metaboxes.php:872
#, php-format
msgid "Store scheduled for: <strong>%1$s</strong>."
msgstr "Tienda programada para: <strong>%1$s</strong>."

#: admin/class-metaboxes.php:873
msgid "M j, Y @ G:i"
msgstr "M j, Y @ G:i"

#: admin/class-metaboxes.php:875
msgid "Store draft updated."
msgstr "Borrador de tienda actualizado."

#: admin/class-metaboxes.php:881
msgid "View store"
msgstr "Ver tienda"

#: admin/class-metaboxes.php:887
msgid "Preview store"
msgstr "Previsualizar tienda"

#: admin/class-settings.php:40
msgid "WP Store Locator Transients Cleared"
msgstr "Transients de WP Store Locator eliminados"

#: admin/class-settings.php:367
#, php-format
msgid "There's a problem with the provided %sserver key%s. %s"
msgstr "Hay un problema con la %sllave de servidor%s proporcionada. %s"

#: admin/class-settings.php:481
msgid ""
"The max results field cannot be empty, the default value has been restored."
msgstr ""
"El campo de resultados máximos no puede estar vacío, el valor predeterminado "
"ha sido restablecido."

#: admin/class-settings.php:484
msgid ""
"The search radius field cannot be empty, the default value has been restored."
msgstr ""
"El campo de radio de búsqueda no puede estar vacío, el valor predeterminado "
"ha sido restablecido."

#: admin/class-settings.php:487
#, php-format
msgid ""
"Please provide the name of a city or country that can be used as a starting "
"point under \"Map Settings\". %s This will only be used if auto-locating the "
"user fails, or the option itself is disabled."
msgstr ""
"Por favor ingresa el nombre de una ciudad o país que pueda ser usado como "
"punto de inicio en “Ajustes del mapa”. %s Éste solo se usará si la "
"autolocalización del usuario falla, o si dicha opción está desactivada."

#: admin/class-settings.php:508
msgid "Select your language"
msgstr "Elige tu lenguaje"

#: admin/class-settings.php:509
msgid "English"
msgstr "Inglés"

#: admin/class-settings.php:510
msgid "Arabic"
msgstr "Árabe"

#: admin/class-settings.php:511
msgid "Basque"
msgstr "Vasco"

#: admin/class-settings.php:512
msgid "Bulgarian"
msgstr "Búlgaro"

#: admin/class-settings.php:513
msgid "Bengali"
msgstr "Bengalí"

#: admin/class-settings.php:514
msgid "Catalan"
msgstr "Catalán"

#: admin/class-settings.php:515
msgid "Czech"
msgstr "Checo"

#: admin/class-settings.php:516
msgid "Danish"
msgstr "Danés"

#: admin/class-settings.php:517
msgid "German"
msgstr "Alemán"

#: admin/class-settings.php:518
msgid "Greek"
msgstr "Griego"

#: admin/class-settings.php:519
msgid "English (Australian)"
msgstr "Inglés (Australiano)"

#: admin/class-settings.php:520
msgid "English (Great Britain)"
msgstr "Inglés (Gran Bretaña)"

#: admin/class-settings.php:521
msgid "Spanish"
msgstr "Español"

#: admin/class-settings.php:522
msgid "Farsi"
msgstr "Farsí"

#: admin/class-settings.php:523
msgid "Finnish"
msgstr "Finlandés"

#: admin/class-settings.php:524
msgid "Filipino"
msgstr "Filipino"

#: admin/class-settings.php:525
msgid "French"
msgstr "Francés"

#: admin/class-settings.php:526
msgid "Galician"
msgstr "Gallego"

#: admin/class-settings.php:527
msgid "Gujarati"
msgstr "Gujarati"

#: admin/class-settings.php:528
msgid "Hindi"
msgstr "Hindi"

#: admin/class-settings.php:529
msgid "Croatian"
msgstr "Croata"

#: admin/class-settings.php:530
msgid "Hungarian"
msgstr "Húngaro"

#: admin/class-settings.php:531
msgid "Indonesian"
msgstr "Indonesio"

#: admin/class-settings.php:532
msgid "Italian"
msgstr "Italiano"

#: admin/class-settings.php:533
msgid "Hebrew"
msgstr "Hebreo"

#: admin/class-settings.php:534
msgid "Japanese"
msgstr "Japonés"

#: admin/class-settings.php:535
msgid "Kannada"
msgstr "Kannada"

#: admin/class-settings.php:536
msgid "Korean"
msgstr "Coreano"

#: admin/class-settings.php:537
msgid "Lithuanian"
msgstr "Lituano"

#: admin/class-settings.php:538
msgid "Latvian"
msgstr "Letón"

#: admin/class-settings.php:539
msgid "Malayalam"
msgstr "Malayam"

#: admin/class-settings.php:540
msgid "Marathi"
msgstr "Marathi"

#: admin/class-settings.php:541
msgid "Dutch"
msgstr "Holandés"

#: admin/class-settings.php:542
msgid "Norwegian"
msgstr "Noruego"

#: admin/class-settings.php:543
msgid "Norwegian Nynorsk"
msgstr "Nynorsk Noruego"

#: admin/class-settings.php:544
msgid "Polish"
msgstr "Polaco"

#: admin/class-settings.php:545
msgid "Portuguese"
msgstr "Portugués"

#: admin/class-settings.php:546
msgid "Portuguese (Brazil)"
msgstr "Portugués (Brasil)"

#: admin/class-settings.php:547
msgid "Portuguese (Portugal)"
msgstr "Portugués (Portugal)"

#: admin/class-settings.php:548
msgid "Romanian"
msgstr "Rumano"

#: admin/class-settings.php:549
msgid "Russian"
msgstr "Ruso"

#: admin/class-settings.php:550
msgid "Slovak"
msgstr "Eslovaco"

#: admin/class-settings.php:551
msgid "Slovenian"
msgstr "Esloveno"

#: admin/class-settings.php:552
msgid "Serbian"
msgstr "Serbio"

#: admin/class-settings.php:553
msgid "Swedish"
msgstr "Sueco"

#: admin/class-settings.php:554
msgid "Tagalog"
msgstr "Tagalog"

#: admin/class-settings.php:555
msgid "Tamil"
msgstr "Tamil"

#: admin/class-settings.php:556
msgid "Telugu"
msgstr "Telugu"

#: admin/class-settings.php:557
msgid "Thai"
msgstr "Tailandés"

#: admin/class-settings.php:558
msgid "Turkish"
msgstr "Turco"

#: admin/class-settings.php:559
msgid "Ukrainian"
msgstr "Ucraniano"

#: admin/class-settings.php:560
msgid "Vietnamese"
msgstr "Vietnamita"

#: admin/class-settings.php:561
msgid "Chinese (Simplified)"
msgstr "Chino (Simplificado)"

#: admin/class-settings.php:562
msgid "Chinese (Traditional)"
msgstr "Chino (Tradicional)"

#: admin/class-settings.php:567
msgid "Select your region"
msgstr "Elige tu región"

#: admin/class-settings.php:568
msgid "Afghanistan"
msgstr "Afganistán"

#: admin/class-settings.php:569
msgid "Albania"
msgstr "Albania"

#: admin/class-settings.php:570
msgid "Algeria"
msgstr "Argelia"

#: admin/class-settings.php:571
msgid "American Samoa"
msgstr "Samoa Americana"

#: admin/class-settings.php:572
msgid "Andorra"
msgstr "Andorra"

#: admin/class-settings.php:573
msgid "Angola"
msgstr "Angola"

#: admin/class-settings.php:574
msgid "Anguilla"
msgstr "Anguila"

#: admin/class-settings.php:575
msgid "Antarctica"
msgstr "Antártida"

#: admin/class-settings.php:576
msgid "Antigua and Barbuda"
msgstr "Antigua y Barbuda"

#: admin/class-settings.php:577
msgid "Argentina"
msgstr "Argentina"

#: admin/class-settings.php:578
msgid "Armenia"
msgstr "Armenia"

#: admin/class-settings.php:579
msgid "Aruba"
msgstr "Aruba"

#: admin/class-settings.php:580
msgid "Ascension Island"
msgstr "Isla Ascensión"

#: admin/class-settings.php:581
msgid "Australia"
msgstr "Australia"

#: admin/class-settings.php:582
msgid "Austria"
msgstr "Austria"

#: admin/class-settings.php:583
msgid "Azerbaijan"
msgstr "Azerbaiyán"

#: admin/class-settings.php:584
msgid "Bahamas"
msgstr "Bahamas"

#: admin/class-settings.php:585
msgid "Bahrain"
msgstr "Bahrain"

#: admin/class-settings.php:586
msgid "Bangladesh"
msgstr "Bangladesh"

#: admin/class-settings.php:587
msgid "Barbados"
msgstr "Barbados"

#: admin/class-settings.php:588
msgid "Belarus"
msgstr "Bielorrusia"

#: admin/class-settings.php:589
msgid "Belgium"
msgstr "Bélgica"

#: admin/class-settings.php:590
msgid "Belize"
msgstr "Belice"

#: admin/class-settings.php:591
msgid "Benin"
msgstr "Benin"

#: admin/class-settings.php:592
msgid "Bermuda"
msgstr "Bermuda"

#: admin/class-settings.php:593
msgid "Bhutan"
msgstr "Bután"

#: admin/class-settings.php:594
msgid "Bolivia"
msgstr "Bolivia"

#: admin/class-settings.php:595
msgid "Bosnia and Herzegovina"
msgstr "Bosnia y Herzegovina"

#: admin/class-settings.php:596
msgid "Botswana"
msgstr "Botswana"

#: admin/class-settings.php:597
msgid "Bouvet Island"
msgstr "Isla Bouvet"

#: admin/class-settings.php:598
msgid "Brazil"
msgstr "Brasil"

#: admin/class-settings.php:599
msgid "British Indian Ocean Territory"
msgstr "Territorio del Océano Índico Británico"

#: admin/class-settings.php:600
msgid "British Virgin Islands"
msgstr "Islas Vírgenes Británicas"

#: admin/class-settings.php:601
msgid "Brunei"
msgstr "Brunei"

#: admin/class-settings.php:602
msgid "Bulgaria"
msgstr "Bulgaria"

#: admin/class-settings.php:603
msgid "Burkina Faso"
msgstr "Burkina Faso"

#: admin/class-settings.php:604
msgid "Burundi"
msgstr "Burundi"

#: admin/class-settings.php:605
msgid "Cambodia"
msgstr "Camboya"

#: admin/class-settings.php:606
msgid "Cameroon"
msgstr "Camerún"

#: admin/class-settings.php:607
msgid "Canada"
msgstr "Canadá"

#: admin/class-settings.php:608
msgid "Canary Islands"
msgstr "Islas Canarias"

#: admin/class-settings.php:609
msgid "Cape Verde"
msgstr "Cabo Verde"

#: admin/class-settings.php:610
msgid "Caribbean Netherlands"
msgstr "Caribe Holandés"

#: admin/class-settings.php:611
msgid "Cayman Islands"
msgstr "Islas Caimán"

#: admin/class-settings.php:612
msgid "Central African Republic"
msgstr "República Central Africana"

#: admin/class-settings.php:613
msgid "Ceuta and Melilla"
msgstr "Ceuta y Melilla"

#: admin/class-settings.php:614
msgid "Chad"
msgstr "Chad"

#: admin/class-settings.php:615
msgid "Chile"
msgstr "Chile"

#: admin/class-settings.php:616
msgid "China"
msgstr "China"

#: admin/class-settings.php:617
msgid "Christmas Island"
msgstr "Isla Navidad"

#: admin/class-settings.php:618
msgid "Clipperton Island"
msgstr "Isla Clipperton"

#: admin/class-settings.php:619
msgid "Cocos (Keeling) Islands"
msgstr "Islas Cocos (Keeling)"

#: admin/class-settings.php:620
msgid "Colombia"
msgstr "Colombia"

#: admin/class-settings.php:621
msgid "Comoros"
msgstr "Comoros"

#: admin/class-settings.php:622
msgid "Congo (DRC)"
msgstr "Congo (RDC)"

#: admin/class-settings.php:623
msgid "Congo (Republic)"
msgstr "Congo (República)"

#: admin/class-settings.php:624
msgid "Cook Islands"
msgstr "Islas Cook"

#: admin/class-settings.php:625
msgid "Costa Rica"
msgstr "Costa Rica"

#: admin/class-settings.php:626
msgid "Croatia"
msgstr "Croacia"

#: admin/class-settings.php:627
msgid "Cuba"
msgstr "Cuba"

#: admin/class-settings.php:628
msgid "Curaçao"
msgstr "Curaçao"

#: admin/class-settings.php:629
msgid "Cyprus"
msgstr "Chipre"

#: admin/class-settings.php:630
msgid "Czech Republic"
msgstr "República Checa"

#: admin/class-settings.php:631
msgid "Côte d'Ivoire"
msgstr "Costa de Marfil"

#: admin/class-settings.php:632
msgid "Denmark"
msgstr "Dinamarca"

#: admin/class-settings.php:633
msgid "Djibouti"
msgstr "Djibouti"

#: admin/class-settings.php:634
msgid "Democratic Republic of the Congo"
msgstr "República Democrática del Congo"

#: admin/class-settings.php:635
msgid "Dominica"
msgstr "Dominica"

#: admin/class-settings.php:636
msgid "Dominican Republic"
msgstr "República Dominicana"

#: admin/class-settings.php:637
msgid "Ecuador"
msgstr "Ecuador"

#: admin/class-settings.php:638
msgid "Egypt"
msgstr "Egipto"

#: admin/class-settings.php:639
msgid "El Salvador"
msgstr "El Salvador"

#: admin/class-settings.php:640
msgid "Equatorial Guinea"
msgstr "Guinea Ecuatorial"

#: admin/class-settings.php:641
msgid "Eritrea"
msgstr "Eritrea"

#: admin/class-settings.php:642
msgid "Estonia"
msgstr "Estonia"

#: admin/class-settings.php:643
msgid "Ethiopia"
msgstr "Etiopía"

#: admin/class-settings.php:644
msgid "Falkland Islands(Islas Malvinas)"
msgstr "Islas Malvinas"

#: admin/class-settings.php:645
msgid "Faroe Islands"
msgstr "Islas Feroe"

#: admin/class-settings.php:646
msgid "Fiji"
msgstr "Fiji"

#: admin/class-settings.php:647
msgid "Finland"
msgstr "Finlandia"

#: admin/class-settings.php:648
msgid "France"
msgstr "Francia"

#: admin/class-settings.php:649
msgid "French Guiana"
msgstr "Guyana Francesa"

#: admin/class-settings.php:650
msgid "French Polynesia"
msgstr "Polinesia Francesa"

#: admin/class-settings.php:651
msgid "French Southern Territories"
msgstr "Territorios Franceses del Sur"

#: admin/class-settings.php:652
msgid "Gabon"
msgstr "Gabón"

#: admin/class-settings.php:653
msgid "Gambia"
msgstr "Gambia"

#: admin/class-settings.php:654
msgid "Georgia"
msgstr "Georgia"

#: admin/class-settings.php:655
msgid "Germany"
msgstr "Alemania"

#: admin/class-settings.php:656
msgid "Ghana"
msgstr "Ghana"

#: admin/class-settings.php:657
msgid "Gibraltar"
msgstr "Gibraltar"

#: admin/class-settings.php:658
msgid "Greece"
msgstr "Grecia"

#: admin/class-settings.php:659
msgid "Greenland"
msgstr "Groenlandia"

#: admin/class-settings.php:660
msgid "Grenada"
msgstr "Granada"

#: admin/class-settings.php:661 admin/class-settings.php:663
msgid "Guam"
msgstr "Guam"

#: admin/class-settings.php:662
msgid "Guadeloupe"
msgstr "Guadalupe"

#: admin/class-settings.php:664
msgid "Guatemala"
msgstr "Guatemala"

#: admin/class-settings.php:665
msgid "Guernsey"
msgstr "Guernsey"

#: admin/class-settings.php:666
msgid "Guinea"
msgstr "Guinea"

#: admin/class-settings.php:667
msgid "Guinea-Bissau"
msgstr "Guinea-Bissau"

#: admin/class-settings.php:668
msgid "Guyana"
msgstr "Guyana"

#: admin/class-settings.php:669
msgid "Haiti"
msgstr "Haití"

#: admin/class-settings.php:670
msgid "Heard and McDonald Islands"
msgstr "Islas Heard y McDonald"

#: admin/class-settings.php:671
msgid "Honduras"
msgstr "Honduras"

#: admin/class-settings.php:672
msgid "Hong Kong"
msgstr "Hong Kong"

#: admin/class-settings.php:673
msgid "Hungary"
msgstr "Hungría"

#: admin/class-settings.php:674
msgid "Iceland"
msgstr "Islandia"

#: admin/class-settings.php:675
msgid "India"
msgstr "India"

#: admin/class-settings.php:676
msgid "Indonesia"
msgstr "Indonesia"

#: admin/class-settings.php:677
msgid "Iran"
msgstr "Irán"

#: admin/class-settings.php:678
msgid "Iraq"
msgstr "Irak"

#: admin/class-settings.php:679
msgid "Ireland"
msgstr "Irlanda"

#: admin/class-settings.php:680
msgid "Isle of Man"
msgstr "Isla de Man"

#: admin/class-settings.php:681
msgid "Israel"
msgstr "Israel"

#: admin/class-settings.php:682
msgid "Italy"
msgstr "Italia"

#: admin/class-settings.php:683
msgid "Jamaica"
msgstr "Jamaica"

#: admin/class-settings.php:684
msgid "Japan"
msgstr "Japón"

#: admin/class-settings.php:685
msgid "Jersey"
msgstr "Jersey"

#: admin/class-settings.php:686
msgid "Jordan"
msgstr "Jordania"

#: admin/class-settings.php:687
msgid "Kazakhstan"
msgstr "Kazajistán"

#: admin/class-settings.php:688
msgid "Kenya"
msgstr "Kenia"

#: admin/class-settings.php:689
msgid "Kiribati"
msgstr "Kiribati"

#: admin/class-settings.php:690
msgid "Kosovo"
msgstr "Kosovo"

#: admin/class-settings.php:691
msgid "Kuwait"
msgstr "Kuwait"

#: admin/class-settings.php:692
msgid "Kyrgyzstan"
msgstr "Kyrgyzstan"

#: admin/class-settings.php:693
msgid "Laos"
msgstr "Laos"

#: admin/class-settings.php:694
msgid "Latvia"
msgstr "Letonia"

#: admin/class-settings.php:695
msgid "Lebanon"
msgstr "Líbano"

#: admin/class-settings.php:696
msgid "Lesotho"
msgstr "Lesoto"

#: admin/class-settings.php:697
msgid "Liberia"
msgstr "Liberia"

#: admin/class-settings.php:698
msgid "Libya"
msgstr "Libia"

#: admin/class-settings.php:699
msgid "Liechtenstein"
msgstr "Liechtenstein"

#: admin/class-settings.php:700
msgid "Lithuania"
msgstr "Lituania"

#: admin/class-settings.php:701
msgid "Luxembourg"
msgstr "Luxemburgo"

#: admin/class-settings.php:702
msgid "Macau"
msgstr "Macau"

#: admin/class-settings.php:703
msgid "Macedonia (FYROM)"
msgstr "Macedonia (FYROM)"

#: admin/class-settings.php:704
msgid "Madagascar"
msgstr "Madagascar"

#: admin/class-settings.php:705
msgid "Malawi"
msgstr "Malawi"

#: admin/class-settings.php:706
msgid "Malaysia "
msgstr "Malasia "

#: admin/class-settings.php:707
msgid "Maldives "
msgstr "Maldivas "

#: admin/class-settings.php:708
msgid "Mali"
msgstr "Mali"

#: admin/class-settings.php:709
msgid "Malta"
msgstr "Malta"

#: admin/class-settings.php:710
msgid "Marshall Islands"
msgstr "Islas Marshall"

#: admin/class-settings.php:711
msgid "Martinique"
msgstr "Martinica"

#: admin/class-settings.php:712
msgid "Mauritania"
msgstr "Mauritania"

#: admin/class-settings.php:713
msgid "Mauritius"
msgstr "Mauritius"

#: admin/class-settings.php:714
msgid "Mayotte"
msgstr "Mayotte"

#: admin/class-settings.php:715
msgid "Mexico"
msgstr "México"

#: admin/class-settings.php:716
msgid "Micronesia"
msgstr "Micronesia"

#: admin/class-settings.php:717
msgid "Moldova"
msgstr "Moldova"

#: admin/class-settings.php:718
msgid "Monaco"
msgstr "Mónaco"

#: admin/class-settings.php:719
msgid "Mongolia"
msgstr "Mongolia"

#: admin/class-settings.php:720
msgid "Montenegro"
msgstr "Montenegro"

#: admin/class-settings.php:721
msgid "Montserrat"
msgstr "Montserrat"

#: admin/class-settings.php:722
msgid "Morocco"
msgstr "Marruecos"

#: admin/class-settings.php:723
msgid "Mozambique"
msgstr "Mozambique"

#: admin/class-settings.php:724
msgid "Myanmar (Burma)"
msgstr "Myanmar (Burma)"

#: admin/class-settings.php:725
msgid "Namibia"
msgstr "Namibia"

#: admin/class-settings.php:726
msgid "Nauru"
msgstr "Nauru"

#: admin/class-settings.php:727
msgid "Nepal"
msgstr "Nepal"

#: admin/class-settings.php:728
msgid "Netherlands"
msgstr "Holanda"

#: admin/class-settings.php:729
msgid "Netherlands Antilles"
msgstr "Antillas Holandesas"

#: admin/class-settings.php:730
msgid "New Caledonia"
msgstr "Nueva Caledonia"

#: admin/class-settings.php:731
msgid "New Zealand"
msgstr "Nueva Zelanda"

#: admin/class-settings.php:732
msgid "Nicaragua"
msgstr "Nicaragua"

#: admin/class-settings.php:733
msgid "Niger"
msgstr "Níger"

#: admin/class-settings.php:734
msgid "Nigeria"
msgstr "Nigeria"

#: admin/class-settings.php:735
msgid "Niue"
msgstr "Niue"

#: admin/class-settings.php:736
msgid "Norfolk Island"
msgstr "Isla de Norfolk"

#: admin/class-settings.php:737
msgid "North Korea"
msgstr "Corea del Norte"

#: admin/class-settings.php:738
msgid "Northern Mariana Islands"
msgstr "Islas Marianas del Norte"

#: admin/class-settings.php:739
msgid "Norway"
msgstr "Noruega"

#: admin/class-settings.php:740
msgid "Oman"
msgstr "Omán"

#: admin/class-settings.php:741
msgid "Pakistan"
msgstr "Pakistán"

#: admin/class-settings.php:742
msgid "Palau"
msgstr "Palau"

#: admin/class-settings.php:743
msgid "Palestine"
msgstr "Palestina"

#: admin/class-settings.php:744
msgid "Panama"
msgstr "Panamá"

#: admin/class-settings.php:745
msgid "Papua New Guinea"
msgstr "Papua Nueva Guinea"

#: admin/class-settings.php:746
msgid "Paraguay"
msgstr "Paraguay"

#: admin/class-settings.php:747
msgid "Peru"
msgstr "Perú"

#: admin/class-settings.php:748
msgid "Philippines"
msgstr "Filipinas"

#: admin/class-settings.php:749
msgid "Pitcairn Islands"
msgstr "Islas Pitcairn"

#: admin/class-settings.php:750
msgid "Poland"
msgstr "Polonia"

#: admin/class-settings.php:751
msgid "Portugal"
msgstr "Portugal"

#: admin/class-settings.php:752
msgid "Puerto Rico"
msgstr "Puerto Rico"

#: admin/class-settings.php:753
msgid "Qatar"
msgstr "Qatar"

#: admin/class-settings.php:754
msgid "Reunion"
msgstr "Reunión"

#: admin/class-settings.php:755
msgid "Romania"
msgstr "Rumania"

#: admin/class-settings.php:756
msgid "Russia"
msgstr "Rusia"

#: admin/class-settings.php:757
msgid "Rwanda"
msgstr "Rwanda"

#: admin/class-settings.php:758
msgid "Saint Helena"
msgstr "Santa Helena"

#: admin/class-settings.php:759
msgid "Saint Kitts and Nevis"
msgstr "San Kitts y Nevis"

#: admin/class-settings.php:760
msgid "Saint Vincent and the Grenadines"
msgstr "San Vicente y las Granadinas"

#: admin/class-settings.php:761
msgid "Saint Lucia"
msgstr "Santa Lucía"

#: admin/class-settings.php:762
msgid "Samoa"
msgstr "Samoa"

#: admin/class-settings.php:763
msgid "San Marino"
msgstr "San Marino"

#: admin/class-settings.php:764
msgid "São Tomé and Príncipe"
msgstr "São Tomé y Príncipe"

#: admin/class-settings.php:765
msgid "Saudi Arabia"
msgstr "Arabia Saudita"

#: admin/class-settings.php:766
msgid "Senegal"
msgstr "Senegal"

#: admin/class-settings.php:767
msgid "Serbia"
msgstr "Serbia"

#: admin/class-settings.php:768
msgid "Seychelles"
msgstr "Seychelles"

#: admin/class-settings.php:769
msgid "Sierra Leone"
msgstr "Sierra Leona"

#: admin/class-settings.php:770
msgid "Singapore"
msgstr "Singapur"

#: admin/class-settings.php:771
msgid "Sint Maarten"
msgstr "Sint Maarten"

#: admin/class-settings.php:772
msgid "Slovakia"
msgstr "Eslovaquia"

#: admin/class-settings.php:773
msgid "Slovenia"
msgstr "Eslovenia"

#: admin/class-settings.php:774
msgid "Solomon Islands"
msgstr "Islas Salomón"

#: admin/class-settings.php:775
msgid "Somalia"
msgstr "Somalia"

#: admin/class-settings.php:776
msgid "South Africa"
msgstr "Sudáfrica"

#: admin/class-settings.php:777
msgid "South Georgia and South Sandwich Islands"
msgstr "Islas Georgia y Sándwich del Sur"

#: admin/class-settings.php:778
msgid "South Korea"
msgstr "Corea del Sur"

#: admin/class-settings.php:779
msgid "South Sudan"
msgstr "Sudán del Sur"

#: admin/class-settings.php:780
msgid "Spain"
msgstr "España"

#: admin/class-settings.php:781
msgid "Sri Lanka"
msgstr "Sri Lanka"

#: admin/class-settings.php:782
msgid "Sudan"
msgstr "Sudán"

#: admin/class-settings.php:783
msgid "Swaziland"
msgstr "Swazilandia"

#: admin/class-settings.php:784
msgid "Sweden"
msgstr "Suecia"

#: admin/class-settings.php:785
msgid "Switzerland"
msgstr "Suiza"

#: admin/class-settings.php:786
msgid "Syria"
msgstr "Siria"

#: admin/class-settings.php:787
msgid "São Tomé & Príncipe"
msgstr "São Tomé y Príncipe"

#: admin/class-settings.php:788
msgid "Taiwan"
msgstr "Taiwán"

#: admin/class-settings.php:789
msgid "Tajikistan"
msgstr "Taijikistán"

#: admin/class-settings.php:790
msgid "Tanzania"
msgstr "Tanzania"

#: admin/class-settings.php:791
msgid "Thailand"
msgstr "Tailandia"

#: admin/class-settings.php:792
msgid "Timor-Leste"
msgstr "Timor-Leste"

#: admin/class-settings.php:793 admin/class-settings.php:795
msgid "Tokelau"
msgstr "Tokelau"

#: admin/class-settings.php:794
msgid "Togo"
msgstr "Togo"

#: admin/class-settings.php:796
msgid "Tonga"
msgstr "Tonga"

#: admin/class-settings.php:797
msgid "Trinidad and Tobago"
msgstr "Trinidad y Tobago"

#: admin/class-settings.php:798
msgid "Tristan da Cunha"
msgstr "Tristan da Cunha"

#: admin/class-settings.php:799
msgid "Tunisia"
msgstr "Túnez"

#: admin/class-settings.php:800
msgid "Turkey"
msgstr "Turquía"

#: admin/class-settings.php:801
msgid "Turkmenistan"
msgstr "Turkmenistán"

#: admin/class-settings.php:802
msgid "Turks and Caicos Islands"
msgstr "Islas Turcas y Caicos"

#: admin/class-settings.php:803
msgid "Tuvalu"
msgstr "Tuvalú"

#: admin/class-settings.php:804
msgid "Uganda"
msgstr "Uganda"

#: admin/class-settings.php:805
msgid "Ukraine"
msgstr "Ucrania"

#: admin/class-settings.php:806
msgid "United Arab Emirates"
msgstr "Emiratos Árabes Unidos"

#: admin/class-settings.php:807
msgid "United Kingdom"
msgstr "Reino Unido"

#: admin/class-settings.php:808
msgid "United States"
msgstr "Estados Unidos de América"

#: admin/class-settings.php:809
msgid "Uruguay"
msgstr "Uruguay"

#: admin/class-settings.php:810
msgid "Uzbekistan"
msgstr "Uzbekistán"

#: admin/class-settings.php:811
msgid "Vanuatu"
msgstr "Vanuatu"

#: admin/class-settings.php:812
msgid "Vatican City"
msgstr "Ciudad del Vaticano"

#: admin/class-settings.php:813
msgid "Venezuela"
msgstr "Venezuela"

#: admin/class-settings.php:814
msgid "Vietnam"
msgstr "Vietnam"

#: admin/class-settings.php:815
msgid "Wallis Futuna"
msgstr "Wallis Futuna"

#: admin/class-settings.php:816
msgid "Western Sahara"
msgstr "Sahara Occidental"

#: admin/class-settings.php:817
msgid "Yemen"
msgstr "Yemen"

#: admin/class-settings.php:818
msgid "Zambia"
msgstr "Zambia"

#: admin/class-settings.php:819
msgid "Zimbabwe"
msgstr "Zimbabwe"

#: admin/class-settings.php:820
msgid "Åland Islands"
msgstr "Islas Åland"

#: admin/class-settings.php:863
msgid "World view"
msgstr "Vista mundial"

#: admin/class-settings.php:866 admin/class-settings.php:980
#: inc/wpsl-functions.php:216
msgid "Default"
msgstr "Predeterminado"

#: admin/class-settings.php:869 inc/wpsl-functions.php:289
msgid "Roadmap"
msgstr "Mapa de caminos"

#: admin/class-settings.php:1010
msgid "Start location marker"
msgstr "Marcador del punto de partida"

#: admin/class-settings.php:1012
msgid "Store location marker"
msgstr "Marcador de ubicación de tienda"

#: admin/class-settings.php:1092
msgid "Textarea"
msgstr "Área de texto"

#: admin/class-settings.php:1093
msgid "Dropdowns (recommended)"
msgstr "Menús desplegables (recomendado)"

#: admin/class-settings.php:1101
msgid "Bounces up and down"
msgstr "Rebota de arriba a abajo"

#: admin/class-settings.php:1102
msgid "Will open the info window"
msgstr "Abrirá la ventana de información"

#: admin/class-settings.php:1103
msgid "Does not respond"
msgstr "No responde"

#: admin/class-settings.php:1111
msgid "In the store listings"
msgstr "En los listados de tiendas"

#: admin/class-settings.php:1112
msgid "In the info window on the map"
msgstr "En la ventana de información dentro del mapa"

#: admin/class-settings.php:1144 admin/class-shortcode-generator.php:115
msgid "Dropdown"
msgstr "Menú desplegable"

#: admin/class-settings.php:1145 admin/class-shortcode-generator.php:116
msgid "Checkboxes"
msgstr "Caja de selección múltiple"

#: admin/class-settings.php:1177
msgid "12 Hours"
msgstr "12 horas"

#: admin/class-settings.php:1178
msgid "24 Hours"
msgstr "24 horas"

#: admin/class-shortcode-generator.php:42
msgid "WP Store Locator"
msgstr "WP Store Locutor"

#: admin/class-shortcode-generator.php:42
#: admin/class-shortcode-generator.php:212
msgid "Insert Store Locator"
msgstr "Insertar Localizador de tiendas"

#: admin/class-shortcode-generator.php:61
msgid "You do not have permission to perform this action"
msgstr "No tienes permiso para realizar esta acción"

#: admin/class-shortcode-generator.php:90
msgid "General Options"
msgstr "Opciones generales"

#: admin/class-shortcode-generator.php:91 admin/templates/map-settings.php:367
msgid "Markers"
msgstr "Marcadores"

#: admin/class-shortcode-generator.php:97
msgid "Select the used template"
msgstr "Selecciona la plantilla usada"

#: admin/class-shortcode-generator.php:101 admin/templates/map-settings.php:198
msgid "Start point"
msgstr "Punto de inicio"

#: admin/class-shortcode-generator.php:101
#, php-format
msgid ""
"If nothing it set, then the start point from the %ssettings%s page is used."
msgstr ""
"Si se queda en blanco, se usará el punto de inicio definido en la página de "
"%sajustes%s."

#: admin/class-shortcode-generator.php:106 admin/templates/map-settings.php:184
msgid "Attempt to auto-locate the user"
msgstr "Intentar autolocalizar al usuario"

#: admin/class-shortcode-generator.php:106 admin/templates/map-settings.php:184
#, php-format
msgid ""
"Most modern browsers %srequire%s a HTTPS connection before the Geolocation "
"feature works."
msgstr ""
"La mayoría de los navegadores modernos %srequieren%s una conexión HTTPS para "
"permitir la funcionalidad de Geolocalización."

#: admin/class-shortcode-generator.php:111
msgid "Category filter type"
msgstr "Tipo de filtro de categoría"

#: admin/class-shortcode-generator.php:114
msgid "None"
msgstr "Ninguno"

#: admin/class-shortcode-generator.php:126
msgid "Automatically restrict the returned results to one or more categories?"
msgstr "¿Limitar automáticamente los resultados a una o más categorías?"

#: admin/class-shortcode-generator.php:142
msgid "Set a selected category?"
msgstr "¿Establecer una categoría seleccionada?"

#: admin/class-shortcode-generator.php:147
msgid "Select category"
msgstr "Elegir categoría"

#: admin/class-shortcode-generator.php:163
msgid "Checkbox columns"
msgstr "Columnas de selección"

#: admin/class-shortcode-generator.php:182
msgid "Set selected checkboxes"
msgstr "Establecer cajas de selección seleccionadas"

#: admin/class-shortcode-generator.php:198 admin/templates/map-settings.php:236
msgid "Map type"
msgstr "Tipo de mapa"

#: admin/roles.php:20
msgid "Store Locator Manager"
msgstr "Gestor de Store Locator"

#: admin/templates/add-ons.php:21
msgid "WP Store Locator Add-Ons"
msgstr "Extensiones de WP Store Locutor"

#: admin/templates/add-ons.php:41
msgid "Already Installed."
msgstr "Ya instalado."

#: admin/templates/add-ons.php:43
msgid "Coming soon!"
msgstr "¡Próximamente!"

#: admin/templates/add-ons.php:55
msgid "Failed to load the add-on list from the server."
msgstr "No se pudo cargar la lista de extensiones desde el servidor."

#: admin/templates/map-settings.php:44
msgid "Add-On"
msgstr "Extensión"

#: admin/templates/map-settings.php:45
msgid "License Key"
msgstr "Clave de licencia"

#: admin/templates/map-settings.php:46
msgid "License Expiry Date"
msgstr "Fecha de expiración de licencia"

#: admin/templates/map-settings.php:60
msgid "Deactivate License"
msgstr "Desactivar licencia"

#: admin/templates/map-settings.php:80 admin/templates/map-settings.php:119
#: admin/templates/map-settings.php:171 admin/templates/map-settings.php:254
#: admin/templates/map-settings.php:357 admin/templates/map-settings.php:385
#: admin/templates/map-settings.php:435 admin/templates/map-settings.php:463
#: admin/templates/map-settings.php:575 admin/templates/map-settings.php:600
msgid "Save Changes"
msgstr "Guardar cambios"

#: admin/templates/map-settings.php:92
msgid "Google Maps API"
msgstr "API de Google Maps"

#: admin/templates/map-settings.php:95
msgid "Server key"
msgstr "Clave de servidor"

#: admin/templates/map-settings.php:95
#, php-format
msgid ""
"A %sserver key%s allows you to monitor the usage of the Google Maps "
"%sGeocoding API%s. %s %sRequired%s for %sapplications%s created after June "
"22, 2016."
msgstr ""
"Una %sclave de servidor%s te permite monitorear el uso del %sAPI de "
"Geolocalización%s de Google Maps. %s %sRequerido%s para %saplicaciones%s "
"creadas después del 22 de junio de 2016."

#: admin/templates/map-settings.php:99
msgid "Browser key"
msgstr "Clave de navegador"

#: admin/templates/map-settings.php:99
#, php-format
msgid ""
"A %sbrowser key%s allows you to monitor the usage of the Google Maps "
"%sJavaScript API%s. %s %sRequired%s for %sapplications%s created after June "
"22, 2016."
msgstr ""
"Una %sclave de navegador%s te permite monitorear el uso del %sAPI de "
"Geolocalización%s de Google Maps. %s %sRequerido%s para %saplicaciones%s "
"creadas después del 22 de junio de 2016."

#: admin/templates/map-settings.php:103
msgid "Map language"
msgstr "Idioma del mapa"

#: admin/templates/map-settings.php:103
msgid "If no map language is selected the browser's prefered language is used."
msgstr ""
"Si no hay un idioma seleccionado, se usará el idioma preferido del navegador."

#: admin/templates/map-settings.php:109
msgid "Map region"
msgstr "Región del mapa"

#: admin/templates/map-settings.php:109
#, php-format
msgid ""
"This will bias the %sgeocoding%s results towards the selected region. %s If "
"no region is selected the bias is set to the United States."
msgstr ""
"Esto inclinará los resultados de la %sgeocodificación%s hacia la región "
"seleccionada. %s Si no hay una región seleccionada, la inclinación será "
"hacia los Estados Unidos."

#: admin/templates/map-settings.php:115
msgid "Restrict the geocoding results to the selected map region?"
msgstr ""
"¿Restringir los resultados de geocodificación a la región del mapa "
"seleccionada?"

#: admin/templates/map-settings.php:115
#, php-format
msgid ""
"If the %sgeocoding%s API finds more relevant results outside of the set map "
"region ( some location names exist in multiple regions ), the user will "
"likely see a \"No results found\" message. %s To rule this out you can "
"restrict the results to the set map region. %s You can modify the used "
"restrictions with %sthis%s filter."
msgstr ""
"Si el API de %sgeocodificación%s encuentra resultados más relevantes fuera "
"de la región establecida (algunos nombres de ubicaciones existen en "
"múltiples regiones), el usuario probablemente verá un mensaje de “No se "
"encontraron resultados”. %s Para descartar esto puedes restringir los "
"resultados a la región del mapa establecida. %s Puedes modificar las "
"restricciones usadas con %seste%s filtro."

#: admin/templates/map-settings.php:129 admin/templates/map-settings.php:499
#: admin/templates/map-settings.php:500 frontend/templates/default.php:44
#: frontend/templates/store-listings-below.php:44 inc/wpsl-functions.php:133
msgid "Search"
msgstr "Buscar"

#: admin/templates/map-settings.php:132
msgid "Enable autocomplete?"
msgstr "¿Permitir autocompletar?"

#: admin/templates/map-settings.php:136
msgid "Show the max results dropdown?"
msgstr "¿Mostrar el menú desplegable de máximo de resultados?"

#: admin/templates/map-settings.php:140
msgid "Show the search radius dropdown?"
msgstr "¿Mostrar el menú desplegable de radio de búsqueda?"

#: admin/templates/map-settings.php:144
msgid "Enable category filters?"
msgstr "¿Activar los filtros por categoría?"

#: admin/templates/map-settings.php:149
msgid "Filter type:"
msgstr "Tipo de filtro:"

#: admin/templates/map-settings.php:154
msgid "Distance unit"
msgstr "Unidad de distancia"

#: admin/templates/map-settings.php:157
msgid "km"
msgstr "km"

#: admin/templates/map-settings.php:159
msgid "mi"
msgstr "mi"

#: admin/templates/map-settings.php:163
msgid "Max search results"
msgstr "Máximo de resultados de búsqueda"

#: admin/templates/map-settings.php:163 admin/templates/map-settings.php:167
msgid "The default value is set between the [ ]."
msgstr "El valor predeterminado está puesto entre [ ]."

#: admin/templates/map-settings.php:167
msgid "Search radius options"
msgstr "Opciones de radio de búsqueda"

#: admin/templates/map-settings.php:181
msgid "Map"
msgstr "Mapa"

#: admin/templates/map-settings.php:188
msgid "Load locations on page load"
msgstr "Cargar ubicaciones al terminar de cargar la página"

#: admin/templates/map-settings.php:193
msgid "Number of locations to show"
msgstr "Número de ubicaciones a mostrar"

#: admin/templates/map-settings.php:193
#, php-format
msgid ""
"Although the location data is cached after the first load, a lower number "
"will result in the map being more responsive. %s If this field is left empty "
"or set to 0, then all locations are loaded."
msgstr ""
"Aunque los datos de ubicación se guardan en caché tras la primer carga, un "
"número más bajo resultará en un mapa más responsivo. %s Si este campo se "
"queda vacío o está en 0 se cargarán todas las ubicaciones."

#: admin/templates/map-settings.php:198
#, php-format
msgid ""
"%sRequired field.%s %s If auto-locating the user is disabled or fails, the "
"center of the provided city or country will be used as the initial starting "
"point for the user."
msgstr ""
"%sCampo requerido.%s %s Si la autolocalización del usuario falla, el centro "
"de la ciudad o país establecido se usará como punto de inicio para el "
"usuario."

#: admin/templates/map-settings.php:203
msgid "Auto adjust the zoom level to make sure all markers are visible?"
msgstr ""
"¿Ajustar automáticamente el nivel de zoom para asegurarse que todos los "
"marcadores estén visibles?"

#: admin/templates/map-settings.php:203
msgid ""
"This runs after a search is made, and makes sure all the returned locations "
"are visible in the viewport."
msgstr ""
"Esto corre tras efectuar una búsqueda, y se asegura de que todos los "
"resultados sean visibles en la pantalla."

#: admin/templates/map-settings.php:207
msgid "Initial zoom level"
msgstr "Nivel de zoom inicial"

#: admin/templates/map-settings.php:211
msgid "Max auto zoom level"
msgstr "Nivel de zoom máximo"

#: admin/templates/map-settings.php:211
#, php-format
msgid ""
"This value sets the zoom level for the \"Zoom here\" link in the info "
"window. %s It is also used to limit the zooming when the viewport of the map "
"is changed to make all the markers fit on the screen."
msgstr ""
"Este valor define el nivel de zoom para la opción de “Hacer zoom aquí” en la "
"ventana de información. %s También se usa para limitar el zoom cuando la "
"ventana del mapa cambia para que quepan todos los marcadores en la pantalla."

#: admin/templates/map-settings.php:215
msgid "Show the street view controls?"
msgstr "¿Mostrar los controles de vista de calle?"

#: admin/templates/map-settings.php:219
msgid "Show the map type control?"
msgstr "¿Mostrar los controles de tipo de mapa?"

#: admin/templates/map-settings.php:223
msgid "Enable scroll wheel zooming?"
msgstr "¿Activar zoom con la rueda del ratón?"

#: admin/templates/map-settings.php:227
msgid "Zoom control position"
msgstr "Posición de los controles de zoom"

#: admin/templates/map-settings.php:230
msgid "Left"
msgstr "Izquierda"

#: admin/templates/map-settings.php:232
msgid "Right"
msgstr "Derecha"

#: admin/templates/map-settings.php:240
msgid "Map style"
msgstr "Estilo de mapa"

#: admin/templates/map-settings.php:240
msgid ""
"Custom map styles only work if the map type is set to \"Roadmap\" or "
"\"Terrain\"."
msgstr ""
"Los estilos de mapa personalizados solo funcionan en los tipos de mapa "
"\"Mapa de caminos\" o \"Terreno\"."

#: admin/templates/map-settings.php:243
#, php-format
msgid ""
"You can use existing map styles from %sSnazzy Maps%s or %sMap Stylr%s and "
"paste it in the textarea below, or you can generate a custom map style "
"through the %sMap Style Editor%s or %sStyled Maps Wizard%s."
msgstr ""
"Puedes usar estilos de %sSnazzy Mapps%s o %sMap Stylr%s existentes  y "
"pegarlos en el área de texto a continuación, o puedes generar un estilo de "
"mapa personalizado a través del %sEditor de estilos de mapa%s o el "
"%sAsistente de mapas estilizados%s."

#: admin/templates/map-settings.php:244
#, php-format
msgid ""
"If you like to write the style code yourself, then you can find the "
"documentation from Google %shere%s."
msgstr ""
"Si prefieres escribir el código de estilo por tu cuenta, puedes encontrar la "
"documentación de Google %saquí%s."

#: admin/templates/map-settings.php:246
msgid "Preview Map Style"
msgstr "Previsualizar estilo del mapa"

#: admin/templates/map-settings.php:250
msgid "Show credits?"
msgstr "¿Mostrar créditos?"

#: admin/templates/map-settings.php:250
msgid ""
"This will place a \"Search provided by WP Store Locator\" backlink below the "
"map."
msgstr ""
"Esto mostrará un backlink con el texto “Búsqueda proporcionada por WP Store "
"Locutor” debajo del mapa."

#: admin/templates/map-settings.php:264
msgid "User Experience"
msgstr "Experiencia de usuario"

#: admin/templates/map-settings.php:267
msgid "Store Locator height"
msgstr "Altura del Localizador de tiendas"

#: admin/templates/map-settings.php:271
msgid "Max width for the info window content"
msgstr "Ancho máximo del contenido en la ventana de información"

#: admin/templates/map-settings.php:275
msgid "Search field width"
msgstr "Ancho de campo de búsqueda"

#: admin/templates/map-settings.php:279
msgid "Search and radius label width"
msgstr "Ancho de las etiquetas de búsqueda y radio"

#: admin/templates/map-settings.php:283
msgid "Store Locator template"
msgstr "Plantilla del Localizador de tiendas"

#: admin/templates/map-settings.php:283
#, php-format
msgid ""
"The selected template is used with the [wpsl] shortcode. %s You can add a "
"custom template with the %swpsl_templates%s filter."
msgstr ""
"La plantilla seleccionada se usa con el shortcode [wpsl]. %s Puedes añadir "
"una plantilla personalizada con el filtro %swpsl_templates%s."

#: admin/templates/map-settings.php:287
msgid "Hide the scrollbar?"
msgstr "¿Esconder la barra de deslizamiento?"

#: admin/templates/map-settings.php:291
msgid "Open links in a new window?"
msgstr "¿Abrir enlaces en una nueva ventana?"

#: admin/templates/map-settings.php:295
msgid "Show a reset map button?"
msgstr "¿Mostrar un botón de Restablecer mapa?"

#: admin/templates/map-settings.php:299
msgid ""
"When a user clicks on \"Directions\", open a new window, and show the route "
"on google.com/maps ?"
msgstr ""
"Cuando el usuario hace click en “Direcciones”, ¿abrir una nueva ventana y "
"mostrar la ruta en google.com/maps?"

#: admin/templates/map-settings.php:303
msgid "Show a \"More info\" link in the store listings?"
msgstr "¿Mostrar un enlace de “Más información” en los listados de tiendas?"

#: admin/templates/map-settings.php:303
msgid ""
"This places a \"More Info\" link below the address and will show the phone, "
"fax, email, opening hours and description once the link is clicked."
msgstr ""
"Esto añade un enlace de “Más información” abajo de la dirección y muestra el "
"teléfono, fax, email, horas de operación y descripción al hacer click en él."

#: admin/templates/map-settings.php:308
msgid "Where do you want to show the \"More info\" details?"
msgstr "¿Dónde quieres mostrar los detalles de “Más información”?"

#: admin/templates/map-settings.php:313
msgid ""
"Always show the contact details below the address in the search results?"
msgstr ""
"¿Siempre mostrar los datos de contacto abajo de la dirección en los "
"resultados de búsqueda?"

#: admin/templates/map-settings.php:317
msgid "Make the store name clickable if a store URL exists?"
msgstr "¿Hacer el nombre de la tienda clickeable si existe un Url de tienda?"

#: admin/templates/map-settings.php:317
#, php-format
msgid ""
"If %spermalinks%s are enabled, the store name will always link to the store "
"page."
msgstr ""
"Si están activados los %senlaces permanentes%s, el nombre de la tienda "
"siempre enlazará a la página de la tienda."

#: admin/templates/map-settings.php:321
msgid "Make the phone number clickable on mobile devices?"
msgstr "¿Hacer el número de teléfono clickeable en dispositivos móviles?"

#: admin/templates/map-settings.php:325
msgid ""
"If street view is available for the current location, then show a \"Street "
"view\" link in the info window?"
msgstr ""
"Si la vista de calle no está disponible en la ubicación actual, ¿mostrar un "
"enlace a “Vista de calle” en la ventana de información?"

#: admin/templates/map-settings.php:325
#, php-format
msgid ""
"Enabling this option can sometimes result in a small delay in the opening of "
"the info window. %s This happens because an API request is made to Google "
"Maps to check if street view is available for the current location."
msgstr ""
"Activar esta opción en ocasiones puede resultar en una pequeña demora al "
"abrir la ventana de información. %s Esto pasa porque la petición de API se "
"hace a Google Maps para checar si la vista de calle está disponible en la "
"ubicación actual."

#: admin/templates/map-settings.php:329
msgid "Show a \"Zoom here\" link in the info window?"
msgstr "¿Mostrar un enlace a “Hacer zoom aquí” en la ventana de información?"

#: admin/templates/map-settings.php:329
#, php-format
msgid ""
"Clicking this link will make the map zoom in to the %s max auto zoom level "
"%s."
msgstr ""
"Hacer click aquí hará que el mapa haga zoom al %s nivel máximo de zoom%s."

#: admin/templates/map-settings.php:333
msgid "On page load move the mouse cursor to the search field?"
msgstr "Al cargar la página, ¿mover el cursor a la barra de búsqueda?"

#: admin/templates/map-settings.php:333
#, php-format
msgid ""
"If the store locator is not placed at the top of the page, enabling this "
"feature can result in the page scrolling down. %s %sThis option is disabled "
"on mobile devices.%s"
msgstr ""
"Si el Localizador de tiendas no está colocado al inicio de la página, "
"activar esta función puede hacer que la página se deslice hacia abajo. %s "
"%sEsta opción está desactivada en dispositivos móviles.%s"

#: admin/templates/map-settings.php:337
msgid "Use the default style for the info window?"
msgstr "¿Usar el estilo predeterminado para la ventana de información?"

#: admin/templates/map-settings.php:337
#, php-format
msgid ""
"If the default style is disabled the %sInfoBox%s library will be used "
"instead. %s This enables you to easily change the look and feel of the info "
"window through the .wpsl-infobox css class."
msgstr ""
"Si el estilo predeterminado está desactivado se usará la librería %sInfoBox"
"%s. %s Esto te permite cambiar el estilo de la ventana de información "
"fácilmente a través de la clase de css .wpsl-infobox."

#: admin/templates/map-settings.php:341
msgid "Hide the country in the search results?"
msgstr "¿Esconder el país en los resultados de búsqueda?"

#: admin/templates/map-settings.php:345
msgid "Hide the distance in the search results?"
msgstr "¿Esconder la distancia en los resultados de búsqueda?"

#: admin/templates/map-settings.php:349
msgid "If a user hovers over the search results the store marker"
msgstr ""
"Si el usuario coloca el cursor encima de los resultados de búsqueda, el "
"marcador de la tienda"

#: admin/templates/map-settings.php:349
#, php-format
msgid ""
"If marker clusters are enabled this option will not work as expected as long "
"as the markers are clustered. %s The bouncing of the marker won't be visible "
"at all unless a user zooms in far enough for the marker cluster to change "
"back in to individual markers. %s The info window will open as expected, but "
"it won't be clear to which marker it belongs to. "
msgstr ""
"Si los grupos de marcadores están activados, esta opción no funcionará "
"adecuadamente mientras los marcadores estén agrupados. %s El rebote del "
"marcador no será visible a menos que el usuario haga suficiente zoom para "
"que se disuelva el grupo y aparezcan los marcadores individuales. %s La "
"ventana de información se abrirá correctamente, pero no será claro a qué "
"marcador pertenece esta ventana. "

#: admin/templates/map-settings.php:353
msgid "Address format"
msgstr "Formato de dirección"

#: admin/templates/map-settings.php:353
#, php-format
msgid ""
"You can add custom address formats with the %swpsl_address_formats%s filter."
msgstr ""
"Puedes añadir formatos de dirección personalizados con el filtro "
"%swpsl_address_formats%s."

#: admin/templates/map-settings.php:371
msgid "Enable marker clusters?"
msgstr "¿Activar marcadores agrupados?"

#: admin/templates/map-settings.php:371
msgid "Recommended for maps with a large amount of markers."
msgstr "Recomendado para mapas con un gran número de marcadores."

#: admin/templates/map-settings.php:376
msgid "Max zoom level"
msgstr "Nivel máximo de zoom"

#: admin/templates/map-settings.php:376
msgid ""
"If this zoom level is reached or exceeded, then all markers are moved out of "
"the marker cluster and shown as individual markers."
msgstr ""
"Si el nivel de zoom es alcanzado o excedido, todos los marcadores se salen "
"del grupo y son mostrados como marcadores individuales."

#: admin/templates/map-settings.php:380
msgid "Cluster size"
msgstr "Tamaño del grupo"

#: admin/templates/map-settings.php:380
#, php-format
msgid ""
"The grid size of a cluster in pixels. %s A larger number will result in a "
"lower amount of clusters and also make the algorithm run faster."
msgstr ""
"El tamaño de cuadrícula de un grupo en pixeles. %s Un número mayor resultará "
"en una menor cantidad de grupos, haciendo al algoritmo correr más rápido."

#: admin/templates/map-settings.php:395
msgid "Store Editor"
msgstr "Editor de tienda"

#: admin/templates/map-settings.php:398
msgid "Default country"
msgstr "País predeterminado"

#: admin/templates/map-settings.php:402
msgid "Map type for the location preview"
msgstr "Tipo de mapa para la previsualización de ubicación"

#: admin/templates/map-settings.php:406
msgid "Hide the opening hours?"
msgstr "¿Esconder las horas de operación?"

#: admin/templates/map-settings.php:412
msgid "Opening hours input type"
msgstr "Tipo de ingreso de horas de operación"

#: admin/templates/map-settings.php:416
#, php-format
msgid ""
"Opening hours created in version 1.x %sare not%s automatically converted to "
"the new dropdown format."
msgstr ""
"Las horas de operación creadas en la versión 1.x %sno son%s convertidas "
"automáticamente al nuevo formato de menú desplegable."

#: admin/templates/map-settings.php:419 admin/templates/map-settings.php:428
msgid "The default opening hours"
msgstr "Las horas de operación predeterminadas"

#: admin/templates/map-settings.php:425
msgid "Opening hours format"
msgstr "Formato de horas de operación"

#: admin/templates/map-settings.php:432
msgid ""
"The default country and opening hours are only used when a new store is "
"created. So changing the default values will have no effect on existing "
"store locations."
msgstr ""
"El país y las horas predeterminados se usan únicamente al crear una tienda "
"nueva, así que cambiar los valores predeterminados no tiene efecto en las "
"ubicaciones existentes."

#: admin/templates/map-settings.php:445
msgid "Permalink"
msgstr "Enlace permanente"

#: admin/templates/map-settings.php:448
msgid "Enable permalink?"
msgstr "¿Activar enlace permanente?"

#: admin/templates/map-settings.php:453
msgid "Store slug"
msgstr "Slug de tienda"

#: admin/templates/map-settings.php:457
msgid "Category slug"
msgstr "Slug de categoría"

#: admin/templates/map-settings.php:460
#, php-format
msgid "The permalink slugs %smust be unique%s on your site."
msgstr "Los slugs de los enlaces permanentes %sdeben ser únicos%s en tu sitio."

#: admin/templates/map-settings.php:473
msgid "Labels"
msgstr "Etiquetas"

#: admin/templates/map-settings.php:482
#, php-format
msgid "%sWarning!%s %sWPML%s, or a plugin using the WPML API is active."
msgstr ""
"%s¡Advertencia!%s %sWPML%s, o un plugin usando el API de WPML está activo."

#: admin/templates/map-settings.php:483
msgid ""
"Please use the \"String Translations\" section in the used multilingual "
"plugin to change the labels. Changing them here will have no effect as long "
"as the multilingual plugin remains active."
msgstr ""
"Por favor usa la sección de “Traducción de textos” en el plugin "
"multilenguaje para cambiar las etiquetas. Cambiarlas aquí no servirá "
"mientras esté activo el plugin multilenguaje."

#: admin/templates/map-settings.php:487 admin/templates/map-settings.php:488
#: frontend/templates/default.php:12
#: frontend/templates/store-listings-below.php:12 inc/wpsl-functions.php:132
msgid "Your location"
msgstr "Tu ubicación"

#: admin/templates/map-settings.php:491 admin/templates/map-settings.php:492
#: frontend/templates/default.php:21
#: frontend/templates/store-listings-below.php:21 inc/wpsl-functions.php:135
msgid "Search radius"
msgstr "Radio de búsqueda"

#: admin/templates/map-settings.php:495 admin/templates/map-settings.php:496
#: frontend/class-frontend.php:1801 inc/wpsl-functions.php:136
msgid "No results found"
msgstr "No se encontraron resultados"

#: admin/templates/map-settings.php:503
msgid "Searching (preloader text)"
msgstr "Buscando (texto de preloader)"

#: admin/templates/map-settings.php:504 frontend/class-frontend.php:1800
#: inc/wpsl-functions.php:134
msgid "Searching..."
msgstr "Buscando…"

#: admin/templates/map-settings.php:507 admin/templates/map-settings.php:508
#: frontend/templates/default.php:30
#: frontend/templates/store-listings-below.php:30 inc/wpsl-functions.php:137
msgid "Results"
msgstr "Resultados"

#: admin/templates/map-settings.php:511 admin/upgrade.php:206
#: inc/wpsl-functions.php:151
msgid "Category filter"
msgstr "Filtro por categoría"

#: admin/templates/map-settings.php:512 frontend/class-frontend.php:1374
msgid "Category"
msgstr "Categoría"

#: admin/templates/map-settings.php:515
msgid "Category first item"
msgstr "Primer artículo de categoría"

#: admin/templates/map-settings.php:516 admin/upgrade.php:367
#: frontend/class-frontend.php:1377 inc/wpsl-functions.php:152
msgid "Any"
msgstr "Cualquiera"

#: admin/templates/map-settings.php:519 admin/templates/map-settings.php:520
#: admin/upgrade.php:59 frontend/class-frontend.php:1802
#: frontend/underscore-functions.php:138 frontend/underscore-functions.php:168
#: inc/wpsl-functions.php:138
msgid "More info"
msgstr "Más información"

#: admin/templates/map-settings.php:523 admin/templates/map-settings.php:524
#: frontend/class-frontend.php:821 frontend/underscore-functions.php:29
#: frontend/underscore-functions.php:65 frontend/underscore-functions.php:147
#: inc/wpsl-functions.php:146
msgid "Phone"
msgstr "Teléfono"

#: admin/templates/map-settings.php:543 admin/templates/map-settings.php:544
#: frontend/class-frontend.php:1807 inc/wpsl-functions.php:131
msgid "Start location"
msgstr "Punto de partida"

#: admin/templates/map-settings.php:547
msgid "Get directions"
msgstr "Obtener direcciones"

#: admin/templates/map-settings.php:548 frontend/class-frontend.php:1805
#: inc/wpsl-functions.php:139
msgid "Directions"
msgstr "Direcciones"

#: admin/templates/map-settings.php:551
msgid "No directions found"
msgstr "No se encontraron direcciones"

#: admin/templates/map-settings.php:552 admin/upgrade.php:151
#: frontend/class-frontend.php:1806 inc/wpsl-functions.php:140
msgid "No route could be found between the origin and destination"
msgstr "No se encontró una ruta entre el origen y el destino"

#: admin/templates/map-settings.php:555 admin/templates/map-settings.php:556
#: admin/upgrade.php:77 frontend/class-frontend.php:1808
#: inc/wpsl-functions.php:141
msgid "Back"
msgstr "Regresar"

#: admin/templates/map-settings.php:559 admin/templates/map-settings.php:560
#: admin/upgrade.php:143 frontend/class-frontend.php:1809
#: inc/wpsl-functions.php:142
msgid "Street view"
msgstr "Vista de calle"

#: admin/templates/map-settings.php:563 admin/templates/map-settings.php:564
#: admin/upgrade.php:147 frontend/class-frontend.php:1810
#: inc/wpsl-functions.php:143
msgid "Zoom here"
msgstr "Hacer zoom aquí"

#: admin/templates/map-settings.php:567
msgid "General error"
msgstr "Error general"

#: admin/templates/map-settings.php:568 frontend/class-frontend.php:1803
#: inc/wpsl-functions.php:144
msgid "Something went wrong, please try again!"
msgstr "Algo salió mal, ¡por favor inténtalo nuevamente!"

#: admin/templates/map-settings.php:571
msgid "Query limit error"
msgstr "Error de límite de peticiones"

#: admin/templates/map-settings.php:571
#, php-format
msgid ""
"You can raise the %susage limit%s by obtaining an API %skey%s, and fill in "
"the \"API key\" field at the top of this page."
msgstr ""
"Puedes subir el %slímite de uso%s obteniendo una %sclave%s de API e "
"introduciéndola en el campo de “Clave de API” en la parte superior de esta "
"página."

#: admin/templates/map-settings.php:572 frontend/class-frontend.php:1804
#: inc/wpsl-functions.php:145
msgid "API usage limit reached"
msgstr "Límite de uso de API alcanzado"

#: admin/templates/map-settings.php:585
msgid "Tools"
msgstr "Herramientas"

#: admin/templates/map-settings.php:588
msgid "Enable store locator debug?"
msgstr "¿Activar debugging de Localizador de tiendas?"

#: admin/templates/map-settings.php:588
#, php-format
msgid ""
"This disables the WPSL transient cache. %sThe transient cache is only used "
"if the %sLoad locations on page load%s option is enabled."
msgstr ""
"Esto desactiva el caché de transients de WPSL. %sEl caché de transients solo "
"se usa cuando está activada la opción de %sCargar ubicaciones al terminar de "
"cargar la página%s."

#: admin/templates/map-settings.php:592
msgid "Enable compatibility mode?"
msgstr "¿Activar modo de compatibilidad?"

#: admin/templates/map-settings.php:592
#, php-format
msgid ""
"If the %sbrowser console%s shows the error below, then enabling this option "
"should fix it. %s %sYou have included the Google Maps API multiple times on "
"this page. This may cause unexpected errors.%s %s This error can in some "
"situations break the store locator map."
msgstr ""
"Si la %sconsola de navegador%s muestra el error a continuación, soluciónalo "
"activando esta opción. %s %sHas incluido el API de Google Maps más de una "
"vez en esta página. Esto puede causar errores inesperados.%s %s Este error "
"puede, en ocasiones, romper el Mapa de Tiendas."

#: admin/templates/map-settings.php:596
msgid "WPSL transients"
msgstr "Transients de WPSL"

#: admin/templates/map-settings.php:597
msgid "Clear store locator transient cache"
msgstr "Borrar el caché de transients del Localizador de tiendas"

#: admin/upgrade.php:73
msgid "info window"
msgstr "ventana de info"

#: admin/upgrade.php:81
msgid "Reset"
msgstr "Restablecer"

#: admin/upgrade.php:174 inc/wpsl-functions.php:125
msgid "stores"
msgstr "tiendas"

#: admin/upgrade.php:178 inc/wpsl-functions.php:126
msgid "store-category"
msgstr "categoria-tienda"

#: admin/upgrade.php:430
#, php-format
msgid ""
"Because you updated WP Store Locator from version 1.x, the %s current store "
"locations need to be %sconverted%s to custom post types."
msgstr ""
"Al actualizar WP Store Locutor de la versión 1.x, las %s ubicaciones de "
"tiendas actuales deben ser %sconvertidas%s a tipos de entrada personalizados."

#: admin/upgrade.php:451
#, php-format
msgid ""
"The script converting the locations timed out. %s You can click the \"Start "
"Converting\" button again to restart the script. %s If there are thousands "
"of store locations left to convert and you keep seeing this message, then "
"you can try to contact your host and ask if they can increase the maximum "
"execution time. %s The plugin tried to disable the maximum execution time, "
"but if you are reading this then that failed."
msgstr ""
"El script convirtiendo las ubicaciones agotó el tiempo de espera. %s Puedes "
"hacer click en “Iniciar conversión” nuevamente para reiniciarlo. %s Si hay "
"miles de ubicaciones por convertir y sigues viendo este mensaje, contacta a "
"tu proveedor de hosting y pídele que por favor incremente el tiempo de "
"ejecución máximo. %s El plugin trató de desactivar el tiempo máximo de "
"ejecución, pero, si estás leyendo esto, falló."

#: admin/upgrade.php:472
msgid "Store locations to convert:"
msgstr "Ubicaciones de tienda a convertir:"

#: admin/upgrade.php:474
msgid "Start Converting"
msgstr "Iniciar conversión"

#: admin/upgrade.php:596
#, php-format
msgid ""
"All the store locations are now converted to custom post types. %s You can "
"view them on the %sAll Stores%s page."
msgstr ""
"Todas las ubicaciones de tiendas han sido convertidas a tipos de entrada "
"personalizados. %s Puedes verlos en la página de %sTodas las tiendas%s."

#: frontend/class-frontend.php:758
msgid ""
"If you use the [wpsl_address] shortcode outside a store page you need to set "
"the ID attribute."
msgstr ""
"Si usas el shortcode de [wpsl_address] fuera de una página de tienda "
"necesitarás establecer el atributo ID."

#: frontend/class-frontend.php:872
msgid ""
"If you use the [wpsl_hours] shortcode outside a store page you need to set "
"the ID attribute."
msgstr ""
"Si usas el shortcode de [wpsl_hours] fuera de una página de tienda "
"necesitarás establecer el atributo ID."

#: frontend/class-frontend.php:920
msgid ""
"If you use the [wpsl_map] shortcode outside a store page, then you need to "
"set the ID or category attribute."
msgstr ""
"Si usas el shortcode de [wpsl_map] fuera de una página de tienda necesitarás "
"establecer el atributo ID o Categoría."

#: frontend/class-frontend.php:1575
msgid "The application does not have permission to use the Geolocation API."
msgstr "Esta aplicación no tiene permiso para usar el API de Geolocalización."

#: frontend/class-frontend.php:1576
msgid "Location information is unavailable."
msgstr "Información de ubicación no disponible."

#: frontend/class-frontend.php:1577
msgid "The geolocation request timed out."
msgstr "La petición de geolocalización agotó el tiempo de espera."

#: frontend/class-frontend.php:1578
msgid "An unknown error occurred."
msgstr "Ocurrió un error desconocido."

#: frontend/templates/default.php:62
#: frontend/templates/store-listings-below.php:68
#, php-format
msgid "Search provided by %sWP Store Locator%s"
msgstr "Búsqueda proporcionada por %sWP Store Locutor%s"

#: inc/class-post-types.php:52
msgid "Store Locator"
msgstr "Localizador de tiendas"

#: inc/class-post-types.php:53
msgid "All Stores"
msgstr "Todas las tiendas"

#: inc/class-post-types.php:54
msgid "Store"
msgstr "Tienda"

#: inc/class-post-types.php:55 inc/class-post-types.php:58
msgid "New Store"
msgstr "Añadir tienda"

#: inc/class-post-types.php:56
msgid "Add New Store"
msgstr "Añadir Tienda"

#: inc/class-post-types.php:57
msgid "Edit Store"
msgstr "Editar Tienda"

#: inc/class-post-types.php:59
msgid "View Stores"
msgstr "Ver Tiendas"

#: inc/class-post-types.php:60
msgid "Search Stores"
msgstr "Buscar Tiendas"

#: inc/class-post-types.php:61
msgid "No Stores found"
msgstr "No se encontraron resultados"

#: inc/class-post-types.php:62
msgid "No Stores found in trash"
msgstr "No se encontraron %s en la Papelera"

#: inc/class-post-types.php:104 inc/class-post-types.php:114
msgid "Store Categories"
msgstr "Categorías de tiendas"

#: inc/class-post-types.php:105
msgid "Store Category"
msgstr "Categoría de tienda"

#: inc/class-post-types.php:106
msgid "Search Store Categories"
msgstr "Buscar categorías de tiendas"

#: inc/class-post-types.php:107
msgid "All Store Categories"
msgstr "Todas las categorías"

#: inc/class-post-types.php:108
msgid "Parent Store Category"
msgstr "Categoría superior"

#: inc/class-post-types.php:109
msgid "Parent Store Category:"
msgstr "Categoría superior:"

#: inc/class-post-types.php:110
msgid "Edit Store Category"
msgstr "Editar categoría de tienda"

#: inc/class-post-types.php:111
msgid "Update Store Category"
msgstr "Actualizar categoría de tienda"

#: inc/class-post-types.php:112
msgid "Add New Store Category"
msgstr "Añadir categoría de tienda"

#: inc/class-post-types.php:113
msgid "New Store Category Name"
msgstr "Nombre de la nueva categoría de tienda"

#: inc/class-post-types.php:144
msgid "Enter store title here"
msgstr "Introduce el nombre de la tienda aquí"

#: inc/class-post-types.php:162
msgid "Zip"
msgstr "Código postal"

#: inc/wpsl-functions.php:221
msgid "Show the store list below the map"
msgstr "Mostrar la lista de tiendas debajo del mapa"

#: inc/wpsl-functions.php:238
msgid "Monday"
msgstr "Lunes"

#: inc/wpsl-functions.php:239
msgid "Tuesday"
msgstr "Martes"

#: inc/wpsl-functions.php:240
msgid "Wednesday"
msgstr "Miércoles"

#: inc/wpsl-functions.php:241
msgid "Thursday"
msgstr "Jueves"

#: inc/wpsl-functions.php:242
msgid "Friday"
msgstr "Viernes"

#: inc/wpsl-functions.php:243
msgid "Saturday"
msgstr "Sábado"

#: inc/wpsl-functions.php:244
msgid "Sunday"
msgstr "Domingo"

#: inc/wpsl-functions.php:274
#, php-format
msgid "Mon %sTue %sWed %sThu %sFri %sSat Closed %sSun Closed"
msgstr "Lun %sMar %sMiér %sJue %sVie %sSáb Cerrado %sDom Cerrado"

#: inc/wpsl-functions.php:290
msgid "Satellite"
msgstr "Satélite"

#: inc/wpsl-functions.php:291
msgid "Hybrid"
msgstr "Híbrido"

#: inc/wpsl-functions.php:292
msgid "Terrain"
msgstr "Terreno"

#: inc/wpsl-functions.php:307
msgid "(city) (state) (zip code)"
msgstr "(ciudad) (estado) (código postal)"

#: inc/wpsl-functions.php:308
msgid "(city), (state) (zip code)"
msgstr "(ciudad), (estado) (código postal)"

#: inc/wpsl-functions.php:309
msgid "(city) (zip code)"
msgstr "(ciudad) (código postal)"

#: inc/wpsl-functions.php:310
msgid "(city), (zip code)"
msgstr "(ciudad), (código postal)"

#: inc/wpsl-functions.php:311
msgid "(zip code) (city) (state)"
msgstr "(código postal) (ciudad) (estado)"

#: inc/wpsl-functions.php:312
msgid "(zip code) (city)"
msgstr "(código postal) (ciudad)"

#~ msgid ""
#~ "%sError message: %s %s Make sure the IP address mentioned in the error "
#~ "matches with the IP set as the %sreferrer%s for the server API key in the "
#~ "%sGoogle API Console%s."
#~ msgstr ""
#~ "%sMensaje de error: %s %s Asegúrate de que la dirección IP mencionada en "
#~ "el error sea la misma que la dirección IP establecida como %sreferrer%s "
#~ "para la Llave API del servidor en la %sConsola de API de Google%s."

#~ msgid "%sError message: %s"
#~ msgstr "%sMensaje de error: %s"

#~ msgid ""
#~ "As of %sJune 22, 2016%s Google Maps no longer allows request for new "
#~ "projects that doesn't include an %sAPI key%s. %sDismiss%s"
#~ msgstr ""
#~ "A partir del %s22 de junio de 2016%s Google Maps ya no permite nuevos "
#~ "proyectos que no incluyan una %sclave de API%s. %sDescartar%s"

#~ msgid "Congo (DRC"
#~ msgstr "Congo (RDC"

#~ msgid ""
#~ "Safari and Chrome %srequire%s a HTTPS connection before the Geolocation "
#~ "feature works."
#~ msgstr ""
#~ "Safari y Chrome %srequieren%s una conexión con cifrado HTTPS para "
#~ "permitir la Geolocalización."

#~ msgid "Optional"
#~ msgstr "Opcional"

#~ msgid "All %s"
#~ msgstr "Todas las %s"

#~ msgid "New %s"
#~ msgstr "Nueva %s"

#~ msgid "Add New %s"
#~ msgstr "Añadir %s"

#~ msgid "Edit %s"
#~ msgstr "Editar %s"

#~ msgid "View %s"
#~ msgstr "Ver %s"

#~ msgid "No %s found"
#~ msgstr "No se encontraron %s"
languages/wpsl-nl_NL.po000064400000275166151327220640011062 0ustar00msgid ""
msgstr ""
"Project-Id-Version: WP Store Locator 2.2.22\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-03-21 11:27+0700\n"
"PO-Revision-Date: 2019-03-21 11:28+0700\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: nl_NL\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Poedit 1.8.11\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;"
"_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2\n"
"X-Poedit-Basepath: ..\n"
"X-Textdomain-Support: yes\n"
"X-Poedit-SearchPath-0: .\n"

#: admin/EDD_SL_Plugin_Updater.php:201
#, php-format
msgid ""
"There is a new version of %1$s available. %2$sView version %3$s details%4$s."
msgstr ""
"Er is een nieuwe versie beschikbaar van %1$s. %2$sBekijk versie %3$s details"
"%4$s."

#: admin/EDD_SL_Plugin_Updater.php:209
#, php-format
msgid ""
"There is a new version of %1$s available. %2$sView version %3$s details%4$s "
"or %5$supdate now%6$s."
msgstr ""
"Er is een nieuwe versie beschikbaar van %1$s. %2$sBekijk versie %3$s details"
"%4$s of %5$supdate nu%6$s."

#: admin/EDD_SL_Plugin_Updater.php:399
msgid "You do not have permission to install plugin updates"
msgstr "Je hebt geen toestemming om plugin updates te installeren"

#: admin/EDD_SL_Plugin_Updater.php:399 admin/class-shortcode-generator.php:61
msgid "Error"
msgstr "Error"

#: admin/class-admin.php:121
#, php-format
msgid ""
"You need to create %sAPI keys%s for Google Maps before you can use the store "
"locator! %sDismiss%s"
msgstr ""
"Je moet %sAPI sleutels%s aanmaken voor Google Maps voordat je gebruik kan "
"maken van de store locator! %sSluit%s"

#: admin/class-admin.php:123
#, php-format
msgid ""
"Before adding the [wpsl] shortcode to a page, please don't forget to define "
"a start point on the %ssettings%s page. %sDismiss%s"
msgstr ""
"Vergeet niet voordat je de [wpsl] shortcode op een pagina plaatst, om een "
"start locatie op te geven op de %sinstellingen%s pagina. %sSluit%s"

#: admin/class-admin.php:160
msgid "Security check failed. Please reload the page and try again."
msgstr ""
"Beveiligings controle mislukt, herlaad de pagina en probeer het nog een keer."

#: admin/class-admin.php:179 admin/class-admin.php:180
#: admin/class-admin.php:511 admin/templates/map-settings.php:8
msgid "Settings"
msgstr "Instellingen"

#: admin/class-admin.php:186 admin/class-admin.php:187
#: admin/class-admin.php:531
msgid "Add-Ons"
msgstr "Uitbreidingen"

#: admin/class-admin.php:300
msgid "Cannot determine the address at this location."
msgstr "Er kan geen adres gevonden worden voor deze locatie."

#: admin/class-admin.php:301
msgid "Geocode was not successful for the following reason"
msgstr "Geocode was niet succesvol om de volgende reden"

#: admin/class-admin.php:302 admin/upgrade.php:471
msgid "Security check failed, reload the page and try again."
msgstr ""
"Beveiligings controle mislukt, herlaad de pagina en probeer het nog een keer."

#: admin/class-admin.php:303
msgid "Please fill in all the required store details."
msgstr "Vul alle verplichte velden in."

#: admin/class-admin.php:304
msgid "The map preview requires all the location details."
msgstr ""
"Alle locatie details moeten zijn ingevuld voordat de locatie op de kaart "
"getoond kan worden."

#: admin/class-admin.php:305 admin/class-metaboxes.php:534
#: frontend/class-frontend.php:582
msgid "Closed"
msgstr "Gesloten"

#: admin/class-admin.php:306
msgid "The code for the map style is invalid."
msgstr "De code voor de map stijl is ongeldig."

#: admin/class-admin.php:307
msgid "Dismiss this notice."
msgstr "Sluit deze notice."

#: admin/class-admin.php:308
#, php-format
msgid ""
"There's a problem with the provided %sbrowser key%s. %s You will have to "
"open the %sbrowser console%s ( %sctrl%s %sshift%s %sk%s in Firefox, or %sctrl"
"%s %sshift%s %sj%s in Chrome ) to see the error details returned by the "
"Google Maps API. %s The error itself includes a link explaining the problem "
"in more detail. %s Common API errors are also covered in the "
"%stroubleshooting section%s."
msgstr ""

#: admin/class-admin.php:309
msgid "No problems found with the browser key."
msgstr ""

#: admin/class-admin.php:310 admin/templates/map-settings.php:104
msgid "Server key"
msgstr "Server sleutel"

#: admin/class-admin.php:311
#, php-format
msgid "No %sserver key%s found!"
msgstr ""

#: admin/class-admin.php:312 admin/templates/map-settings.php:100
msgid "Browser key"
msgstr "Browser sleutel"

#: admin/class-admin.php:313
#, php-format
msgid "No %sbrowser key%s found!"
msgstr ""

#: admin/class-admin.php:314
msgid "and will only work for zip codes."
msgstr ""

#: admin/class-admin.php:315
#, php-format
msgid ""
"because no %smap region%s is selected the geocode API will search for "
"matching results around the world. This may result in unexpected results."
msgstr ""

#: admin/class-admin.php:316
#, php-format
msgid ""
"Google Maps didn't load correctly. Make sure you have an active %sbilling%s "
"%saccount%s for Google Maps. %s If the \"For development purposes only\" "
"text keeps showing after creating a billing account, then you will have to "
"contact %sGoogle Billing Support%s."
msgstr ""

#: admin/class-admin.php:317
#, php-format
msgid ""
"Google Maps failed to load correctly. This is likely due to a problem with "
"the provided %sbrowser key%s. %s You will have to open the %sbrowser console"
"%s ( %sctrl%s %sshift%s %sk%s in Firefox, or %sctrl%s %sshift%s %sj%s in "
"Chrome ) to see the error details returned by the Google Maps API. %s The "
"error itself includes a link explaining the problem in more detail. %s "
"Common API errors are also covered in the %stroubleshooting section%s."
msgstr ""

#: admin/class-admin.php:318
msgid "Close"
msgstr ""

#: admin/class-admin.php:332
#, php-format
msgid "with the current settings the results are %s to"
msgstr ""

#: admin/class-admin.php:466
msgid "Welcome to WP Store Locator"
msgstr "Welkom bij WP Store Locator"

#: admin/class-admin.php:467
msgid "Sign up for the latest plugin updates and announcements."
msgstr "Meld je aan voor de nieuwsbrief en ontvang het laatste nieuws."

#: admin/class-admin.php:530
msgid "Documentation"
msgstr "Documentatie"

#: admin/class-admin.php:553
#, php-format
msgid "If you like this plugin please leave us a %s5 star%s rating."
msgstr "Als je tevreden bent met deze plugin geef het dan %s5 sterren%s."

#: admin/class-geocode.php:80
msgid ""
"The Google Geocoding API returned no results for the supplied address. "
"Please change the address and try again."
msgstr ""
"De Google Geocoding API gaf geen resultaten terug voor deze locatie. Wijzig "
"de locatie details en probeer het nog een keer."

#: admin/class-geocode.php:83
#, php-format
msgid ""
"You have reached the daily allowed geocoding limit, you can read more %shere"
"%s."
msgstr ""
"Je hebt de dagelijkse toegestane geocoding limiet bereikt, je kan er %shier"
"%s meer over lezen."

#: admin/class-geocode.php:86
#, php-format
msgid "The Google Geocoding API returned REQUEST_DENIED. %s"
msgstr "Er is een probleem met Google Geocoding API  - REQUEST_DENIED. %s"

#: admin/class-geocode.php:89
msgid ""
"The Google Geocoding API failed to return valid data, please try again later."
msgstr ""
"De Google Geocoding API geeft ongeldige data terug, probeer het nog een keer."

#: admin/class-geocode.php:117
#, php-format
msgid ""
"%sError message: %s. %s Make sure the IP address mentioned in the error "
"matches with the IP set as the %sreferrer%s for the server API key in the "
"%sGoogle API Console%s."
msgstr ""
"%sFoutmelding: %s. %s Controleer of het IP adres dat vermeld is in de "
"foutmelding ook is opgegeven als de %sreferrer%s voor de server API key in "
"de %sGoogle API Console%s."

#: admin/class-geocode.php:119
#, php-format
msgid ""
"%sError message: %s %s Check if your issue is covered in the "
"%stroubleshooting%s section, if not, then please open a %ssupport ticket%s."
msgstr ""
"%sFoutmelding: %s %s Controleer of dit probleem beschreven is in het "
"%stroubleshooting%s gedeelte op de website, mocht dit niet het geval zijn, "
"open dan een %ssupport ticket%s."

#: admin/class-geocode.php:141
#, php-format
msgid ""
"Something went wrong connecting to the Google Geocode API: %s %s Please try "
"again later."
msgstr ""
"Er kon geen verbinding gemaakt worden met de Google Geocode API: %s %s "
"Probeer het later nogmaals."

#: admin/class-geocode.php:143
#, php-format
msgid ""
"The Google Geocode API reported the following problem: error %s %s %s Please "
"try again later."
msgstr ""
"De Google Geocode API geeft het volgende probleem aan: error %s %s %s "
"Probeer het later nog een keer."

#: admin/class-geocode.php:148
#, php-format
msgid "You can fix this by making sure the CSV file uses %sUTF-8 encoding%s."
msgstr ""
"Je kan dit oplossen door er voor te zorgen dat het CSV bestand %sUTF-8 "
"encoding%s gebruikt."

#: admin/class-geocode.php:150
msgid ""
"You need to provide the details for either the address, city, state or "
"country before the API can return coordinates."
msgstr ""
"Je moet minimaal de gegevens voor het adres, stad, provincie of land opgeven "
"voordat de API de coördinaten kan terugsturen."

#: admin/class-geocode.php:153
#, php-format
msgid ""
"The Google Geocode API reported the following problem: error %s %s %s %s"
msgstr ""
"De Google Geocode API geeft het volgende probleem aan: error %s %s %s %s"

#: admin/class-geocode.php:155
#, php-format
msgid ""
"The Google Geocode API reported the following problem: error %s %s %s Please "
"contact %ssupport%s if the problem persists."
msgstr ""
"De Google Geocode API geeft het volgende probleem aan: error %s %s %s Neem "
"contact met %ssupport%s op als het probleem zich blijft herhalen."

#: admin/class-license-manager.php:183
#, php-format
msgid ""
"The %s license failed to deactivate, please try again later or contact "
"support!"
msgstr ""
"Het activeren van %s licensie is mislukt. Probeer het later nog een keer of "
"neem contact op met support!"

#: admin/class-license-manager.php:209 admin/templates/add-ons.php:56
msgid "Please try again later!"
msgstr "Probeer het later "

#: admin/class-license-manager.php:257
#, php-format
msgid "The %s license key does not belong to this add-on."
msgstr "De %s licensie sleutel hoort bij een andere uitbreiding."

#: admin/class-license-manager.php:260
#, php-format
msgid "The %s license key does not have any activations left."
msgstr "De %s licensie sleutel heeft het maximaal aantal activaties bereikt."

#: admin/class-license-manager.php:263
#, php-format
msgid "The %s license key is expired. Please renew it."
msgstr "De %s licensie sleutel is verlopen."

#: admin/class-license-manager.php:266
#, php-format
msgid ""
"There was a problem activating the license key for the %s, please try again "
"or contact support. Error code: %s"
msgstr ""
"Er is een probleem met het activeren van de licensie sleutel voor de %s. "
"Probeer het later nog een keer of neem contact op met support. Foutmeldings "
"code: %s"

#: admin/class-metaboxes.php:36
msgid "Store Details"
msgstr "Winkel details"

#: admin/class-metaboxes.php:37
msgid "Store Map"
msgstr "Winkel kaart"

#: admin/class-metaboxes.php:42
msgid "Export"
msgstr "Export"

#: admin/class-metaboxes.php:57
msgid "Location"
msgstr "Locatie"

#: admin/class-metaboxes.php:59 inc/class-post-types.php:186
msgid "Address"
msgstr "Adres"

#: admin/class-metaboxes.php:63
msgid "Address 2"
msgstr "Adres 2"

#: admin/class-metaboxes.php:66 inc/class-post-types.php:187
msgid "City"
msgstr "Stad"

#: admin/class-metaboxes.php:70 inc/class-post-types.php:188
msgid "State"
msgstr "Provincie"

#: admin/class-metaboxes.php:73
msgid "Zip Code"
msgstr "Postcode"

#: admin/class-metaboxes.php:76
msgid "Country"
msgstr "Land"

#: admin/class-metaboxes.php:83
msgid "Latitude"
msgstr "Breedtegraad"

#: admin/class-metaboxes.php:86
msgid "Longitude"
msgstr "Lengtegraad"

#: admin/class-metaboxes.php:89 admin/class-metaboxes.php:138
#: admin/class-metaboxes.php:153
msgid "Opening Hours"
msgstr "Openingstijden"

#: admin/class-metaboxes.php:91 admin/templates/map-settings.php:574
#: admin/templates/map-settings.php:575 frontend/underscore-functions.php:160
#: inc/wpsl-functions.php:159
msgid "Hours"
msgstr "Uren"

#: admin/class-metaboxes.php:95
msgid "Additional Information"
msgstr "Extra informatie"

#: admin/class-metaboxes.php:97
msgid "Tel"
msgstr "Tel."

#: admin/class-metaboxes.php:100 admin/templates/map-settings.php:562
#: admin/templates/map-settings.php:563 frontend/class-frontend.php:846
#: frontend/underscore-functions.php:32 frontend/underscore-functions.php:68
#: frontend/underscore-functions.php:150 inc/wpsl-functions.php:156
msgid "Fax"
msgstr "Fax"

#: admin/class-metaboxes.php:103 admin/templates/map-settings.php:566
#: admin/templates/map-settings.php:567 admin/upgrade.php:198
#: frontend/class-frontend.php:850 frontend/underscore-functions.php:35
#: frontend/underscore-functions.php:71 frontend/underscore-functions.php:153
#: inc/wpsl-functions.php:157
msgid "Email"
msgstr "E-mail"

#: admin/class-metaboxes.php:106 admin/templates/map-settings.php:570
#: admin/templates/map-settings.php:571 admin/upgrade.php:202
#: frontend/class-frontend.php:855 inc/wpsl-functions.php:158
msgid "Url"
msgstr "Url"

#: admin/class-metaboxes.php:456
msgid "Hour format"
msgstr "Uur formaat"

#: admin/class-metaboxes.php:463
msgid "Days"
msgstr "Dagen"

#: admin/class-metaboxes.php:464
msgid "Opening Periods"
msgstr "Openingstijden"

#: admin/class-metaboxes.php:714
msgid "Failed to publish the store. Please fill in the required store details."
msgstr ""
"Het publiceren van de winkel is mislukt. Vul alle verplichte velden in."

#: admin/class-metaboxes.php:850
msgid "Preview Location"
msgstr "Bekijk voorbeeld"

#: admin/class-metaboxes.php:851
#, php-format
msgid ""
"The map preview is based on the provided address, city and country details. "
"%s It will ignore any custom latitude or longitude values."
msgstr ""
"Het voorbeeld is gebaseerd op het adres, de stad en het opgegeven land. %s "
"De opgegeven lengte en breedtegraad worden niet gebruikt."

#: admin/class-metaboxes.php:852
msgid "You can drag the marker to adjust the exact location of the marker."
msgstr "Je kunt de locatie aanpassen door de marker te verslepen."

#: admin/class-metaboxes.php:871
msgid "Export Location Data"
msgstr "Export locatie data"

#: admin/class-metaboxes.php:891 admin/class-metaboxes.php:894
msgid "Store updated."
msgstr "Winkel bijgewerkt."

#: admin/class-metaboxes.php:892
msgid "Custom field updated."
msgstr "Custom veld bijgewerkt."

#: admin/class-metaboxes.php:893
msgid "Custom field deleted."
msgstr "Custom veld verwijderd."

#: admin/class-metaboxes.php:895
#, php-format
msgid "Store restored to revision from %s"
msgstr "Winkel hersteld naar revisie %s"

#: admin/class-metaboxes.php:896
msgid "Store published."
msgstr "Winkel gepubliceerd."

#: admin/class-metaboxes.php:897
msgid "Store saved."
msgstr "Winkel opgeslagen."

#: admin/class-metaboxes.php:898
msgid "Store submitted."
msgstr "Winkel ingediend."

#: admin/class-metaboxes.php:900
#, php-format
msgid "Store scheduled for: <strong>%1$s</strong>."
msgstr "Winkel ingepland voor: <strong>%1$s</strong>. "

#: admin/class-metaboxes.php:901
msgid "M j, Y @ G:i"
msgstr "M j, Y @ G:i"

#: admin/class-metaboxes.php:903
msgid "Store draft updated."
msgstr "Winkel concept bijgewerkt."

#: admin/class-metaboxes.php:909
msgid "View store"
msgstr "Bekijk winkel"

#: admin/class-metaboxes.php:915
msgid "Preview store"
msgstr "Winkel voorbeeld"

#: admin/class-settings.php:40
msgid "WP Store Locator Transients Cleared"
msgstr "WP Store Locator transients verwijderd"

#: admin/class-settings.php:373
#, php-format
msgid "There's a problem with the provided %sserver key%s. %s"
msgstr "Er is een probleem met de opgegeven %sserver sleutel%s. %s"

#: admin/class-settings.php:396
msgid "No problems found with the server key."
msgstr ""

#: admin/class-settings.php:505
msgid ""
"The max results field cannot be empty, the default value has been restored."
msgstr ""
"Het max. zoek resulaten veld kan niet leeg zijn, de standaard waarde is "
"hersteld."

#: admin/class-settings.php:508
msgid ""
"The search radius field cannot be empty, the default value has been restored."
msgstr ""
"Het zoek radius veld kan niet leeg zijn, de standaard waarde is hersteld."

#: admin/class-settings.php:511
#, php-format
msgid ""
"Please provide the name of a city or country that can be used as a starting "
"point under \"Map Settings\". %s This will only be used if auto-locating the "
"user fails, or the option itself is disabled."
msgstr ""
"Geef de naam van een stad of land op als start locatie onder de  \"Kaart "
"Instellingen\". %s Deze locatie wordt alleen maar gebruikt als het "
"automatische achterhalen van de gebruikers locatie mislukt, of het "
"automatische achterhalen is uitgeschakeld."

#: admin/class-settings.php:532
msgid "Select your language"
msgstr "Kies uw taal"

#: admin/class-settings.php:533
msgid "English"
msgstr "Engels"

#: admin/class-settings.php:534
msgid "Arabic"
msgstr "Arabisch"

#: admin/class-settings.php:535
msgid "Basque"
msgstr "Bask"

#: admin/class-settings.php:536
msgid "Bulgarian"
msgstr "Bulgaars"

#: admin/class-settings.php:537
msgid "Bengali"
msgstr "Bengali"

#: admin/class-settings.php:538
msgid "Catalan"
msgstr "Catalaans"

#: admin/class-settings.php:539
msgid "Czech"
msgstr "Tjechisch"

#: admin/class-settings.php:540
msgid "Danish"
msgstr "Deens"

#: admin/class-settings.php:541
msgid "German"
msgstr "Duits"

#: admin/class-settings.php:542
msgid "Greek"
msgstr "Grieks"

#: admin/class-settings.php:543
msgid "English (Australian)"
msgstr "Engels (Australisch)"

#: admin/class-settings.php:544
msgid "English (Great Britain)"
msgstr "Engels (Verenigd Koninkrijk)"

#: admin/class-settings.php:545
msgid "Spanish"
msgstr "Spaans"

#: admin/class-settings.php:546
msgid "Farsi"
msgstr "Farsi"

#: admin/class-settings.php:547
msgid "Finnish"
msgstr "Fins"

#: admin/class-settings.php:548
msgid "Filipino"
msgstr "Filipijns"

#: admin/class-settings.php:549
msgid "French"
msgstr "Frans"

#: admin/class-settings.php:550
msgid "Galician"
msgstr "Gallisch"

#: admin/class-settings.php:551
msgid "Gujarati"
msgstr "Gujurati"

#: admin/class-settings.php:552
msgid "Hindi"
msgstr "Hindi"

#: admin/class-settings.php:553
msgid "Croatian"
msgstr "Kroatisch"

#: admin/class-settings.php:554
msgid "Hungarian"
msgstr "Hongaars"

#: admin/class-settings.php:555
msgid "Indonesian"
msgstr "Indonesisch"

#: admin/class-settings.php:556
msgid "Italian"
msgstr "Italiaans"

#: admin/class-settings.php:557
msgid "Hebrew"
msgstr "Hebreeuws"

#: admin/class-settings.php:558
msgid "Japanese"
msgstr "Japans"

#: admin/class-settings.php:559
msgid "Kannada"
msgstr "Kannada"

#: admin/class-settings.php:560
msgid "Korean"
msgstr "Koreaans"

#: admin/class-settings.php:561
msgid "Lithuanian"
msgstr "Litouws"

#: admin/class-settings.php:562
msgid "Latvian"
msgstr "Lets"

#: admin/class-settings.php:563
msgid "Malayalam"
msgstr "Malayalam"

#: admin/class-settings.php:564
msgid "Marathi"
msgstr "Marathi"

#: admin/class-settings.php:565
msgid "Dutch"
msgstr "Nederlands"

#: admin/class-settings.php:566
msgid "Norwegian"
msgstr "Noors"

#: admin/class-settings.php:567
msgid "Norwegian Nynorsk"
msgstr "Noors Nynorsk"

#: admin/class-settings.php:568
msgid "Polish"
msgstr "Pools"

#: admin/class-settings.php:569
msgid "Portuguese"
msgstr "Portugees"

#: admin/class-settings.php:570
msgid "Portuguese (Brazil)"
msgstr "Portugees (Brazilië)"

#: admin/class-settings.php:571
msgid "Portuguese (Portugal)"
msgstr "Portugees (Portugal)"

#: admin/class-settings.php:572
msgid "Romanian"
msgstr "Roemeens"

#: admin/class-settings.php:573
msgid "Russian"
msgstr "Russisch"

#: admin/class-settings.php:574
msgid "Slovak"
msgstr "Slowaaks"

#: admin/class-settings.php:575
msgid "Slovenian"
msgstr "Sloveens"

#: admin/class-settings.php:576
msgid "Serbian"
msgstr "Servisch"

#: admin/class-settings.php:577
msgid "Swedish"
msgstr "Zweeds"

#: admin/class-settings.php:578
msgid "Tagalog"
msgstr "Tagalog"

#: admin/class-settings.php:579
msgid "Tamil"
msgstr "Tamil"

#: admin/class-settings.php:580
msgid "Telugu"
msgstr "Telugu"

#: admin/class-settings.php:581
msgid "Thai"
msgstr "Thai"

#: admin/class-settings.php:582
msgid "Turkish"
msgstr "Turks"

#: admin/class-settings.php:583
msgid "Ukrainian"
msgstr "Oekraïens"

#: admin/class-settings.php:584
msgid "Vietnamese"
msgstr "Vietnamees"

#: admin/class-settings.php:585
msgid "Chinese (Simplified)"
msgstr "Chinees (Vereenvoudigd)"

#: admin/class-settings.php:586
msgid "Chinese (Traditional)"
msgstr "Chinees (Traditioneel)"

#: admin/class-settings.php:591
msgid "Select your region"
msgstr "Kies uw regio"

#: admin/class-settings.php:592
msgid "Afghanistan"
msgstr "Afghanistan"

#: admin/class-settings.php:593
msgid "Albania"
msgstr "Albanië"

#: admin/class-settings.php:594
msgid "Algeria"
msgstr "Algerije"

#: admin/class-settings.php:595
msgid "American Samoa"
msgstr "Amerikaans Samoa"

#: admin/class-settings.php:596
msgid "Andorra"
msgstr "Andorra"

#: admin/class-settings.php:597
msgid "Angola"
msgstr "Angola"

#: admin/class-settings.php:598
msgid "Anguilla"
msgstr "Anguilla"

#: admin/class-settings.php:599
msgid "Antarctica"
msgstr "Antarctica"

#: admin/class-settings.php:600
msgid "Antigua and Barbuda"
msgstr "Antigua en Barbuda"

#: admin/class-settings.php:601
msgid "Argentina"
msgstr "Argentinië"

#: admin/class-settings.php:602
msgid "Armenia"
msgstr "Armenia"

#: admin/class-settings.php:603
msgid "Aruba"
msgstr "Aruba"

#: admin/class-settings.php:604
msgid "Ascension Island"
msgstr "Ascension"

#: admin/class-settings.php:605
msgid "Australia"
msgstr "Australië"

#: admin/class-settings.php:606
msgid "Austria"
msgstr "Oostenrijk"

#: admin/class-settings.php:607
msgid "Azerbaijan"
msgstr "Azerbeidzjan"

#: admin/class-settings.php:608
msgid "Bahamas"
msgstr "Bahamas"

#: admin/class-settings.php:609
msgid "Bahrain"
msgstr "Bahrein"

#: admin/class-settings.php:610
msgid "Bangladesh"
msgstr "Bangladesh"

#: admin/class-settings.php:611
msgid "Barbados"
msgstr "Barbados"

#: admin/class-settings.php:612
msgid "Belarus"
msgstr "Wit-Rusland"

#: admin/class-settings.php:613
msgid "Belgium"
msgstr "België"

#: admin/class-settings.php:614
msgid "Belize"
msgstr "Belize"

#: admin/class-settings.php:615
msgid "Benin"
msgstr "Benin"

#: admin/class-settings.php:616
msgid "Bermuda"
msgstr "Bermuda"

#: admin/class-settings.php:617
msgid "Bhutan"
msgstr "Bhutan"

#: admin/class-settings.php:618
msgid "Bolivia"
msgstr "Bolivia"

#: admin/class-settings.php:619
msgid "Bosnia and Herzegovina"
msgstr "Bosnia en Herzegovina"

#: admin/class-settings.php:620
msgid "Botswana"
msgstr "Botswana"

#: admin/class-settings.php:621
msgid "Bouvet Island"
msgstr "Bouvet"

#: admin/class-settings.php:622
msgid "Brazil"
msgstr "Brazilië"

#: admin/class-settings.php:623
msgid "British Indian Ocean Territory"
msgstr "Brits Indische Oceaanterritorium"

#: admin/class-settings.php:624
msgid "British Virgin Islands"
msgstr "Britse Maagdeneilanden"

#: admin/class-settings.php:625
msgid "Brunei"
msgstr "Brunei"

#: admin/class-settings.php:626
msgid "Bulgaria"
msgstr "Bulgarije"

#: admin/class-settings.php:627
msgid "Burkina Faso"
msgstr "Burkina Faso"

#: admin/class-settings.php:628
msgid "Burundi"
msgstr "Burundi"

#: admin/class-settings.php:629
msgid "Cambodia"
msgstr "Cambodja"

#: admin/class-settings.php:630
msgid "Cameroon"
msgstr "Kameroen"

#: admin/class-settings.php:631
msgid "Canada"
msgstr "Canada"

#: admin/class-settings.php:632
msgid "Canary Islands"
msgstr "Canarische Eilanden"

#: admin/class-settings.php:633
msgid "Cape Verde"
msgstr "Kaapverdië"

#: admin/class-settings.php:634
msgid "Caribbean Netherlands"
msgstr "Caribisch Nederland"

#: admin/class-settings.php:635
msgid "Cayman Islands"
msgstr "Kaaimaneilanden"

#: admin/class-settings.php:636
msgid "Central African Republic"
msgstr "Centraal-Afrikaanse Republiek"

#: admin/class-settings.php:637
msgid "Ceuta and Melilla"
msgstr "Ceuta en Melilla"

#: admin/class-settings.php:638
msgid "Chad"
msgstr "Chad"

#: admin/class-settings.php:639
msgid "Chile"
msgstr "Chili"

#: admin/class-settings.php:640
msgid "China"
msgstr "China"

#: admin/class-settings.php:641
msgid "Christmas Island"
msgstr "Christmaseiland"

#: admin/class-settings.php:642
msgid "Clipperton Island"
msgstr "Clipperton"

#: admin/class-settings.php:643
msgid "Cocos (Keeling) Islands"
msgstr "Cocoseilanden"

#: admin/class-settings.php:644
msgid "Colombia"
msgstr "Colombia"

#: admin/class-settings.php:645
msgid "Comoros"
msgstr "Comoren"

#: admin/class-settings.php:646
msgid "Congo (DRC)"
msgstr "Congo (DRC)"

#: admin/class-settings.php:647
msgid "Congo (Republic)"
msgstr "Republiek Congo"

#: admin/class-settings.php:648
msgid "Cook Islands"
msgstr "Cookeilanden"

#: admin/class-settings.php:649
msgid "Costa Rica"
msgstr "Costa Rica"

#: admin/class-settings.php:650
msgid "Croatia"
msgstr "Kroatië"

#: admin/class-settings.php:651
msgid "Cuba"
msgstr "Cuba"

#: admin/class-settings.php:652
msgid "Curaçao"
msgstr "Curaçao"

#: admin/class-settings.php:653
msgid "Cyprus"
msgstr "Cyprus"

#: admin/class-settings.php:654
msgid "Czech Republic"
msgstr "Tsjechië"

#: admin/class-settings.php:655
msgid "Côte d'Ivoire"
msgstr "Ivoorkust"

#: admin/class-settings.php:656
msgid "Denmark"
msgstr "Denemarken"

#: admin/class-settings.php:657
msgid "Djibouti"
msgstr "Djibouti"

#: admin/class-settings.php:658
msgid "Democratic Republic of the Congo"
msgstr "Democratische Republiek Congo"

#: admin/class-settings.php:659
msgid "Dominica"
msgstr "Dominica"

#: admin/class-settings.php:660
msgid "Dominican Republic"
msgstr "Dominicaanse Republiek"

#: admin/class-settings.php:661
msgid "Ecuador"
msgstr "Ecuador"

#: admin/class-settings.php:662
msgid "Egypt"
msgstr "Egypte"

#: admin/class-settings.php:663
msgid "El Salvador"
msgstr "El Salvador"

#: admin/class-settings.php:664
msgid "Equatorial Guinea"
msgstr "Equatoriaal-Guinea"

#: admin/class-settings.php:665
msgid "Eritrea"
msgstr "Eritrea"

#: admin/class-settings.php:666
msgid "Estonia"
msgstr "Estland"

#: admin/class-settings.php:667
msgid "Ethiopia"
msgstr "Ethiopië"

#: admin/class-settings.php:668
msgid "Falkland Islands(Islas Malvinas)"
msgstr "Falklandeilanden"

#: admin/class-settings.php:669
msgid "Faroe Islands"
msgstr "Faeröer"

#: admin/class-settings.php:670
msgid "Fiji"
msgstr "Fiji"

#: admin/class-settings.php:671
msgid "Finland"
msgstr "Finland"

#: admin/class-settings.php:672
msgid "France"
msgstr "Frankrijk"

#: admin/class-settings.php:673
msgid "French Guiana"
msgstr "Frans Guyana"

#: admin/class-settings.php:674
msgid "French Polynesia"
msgstr "Frans-Polynesië"

#: admin/class-settings.php:675
msgid "French Southern Territories"
msgstr "Franse Zuidelijke en Antarctische Gebieden"

#: admin/class-settings.php:676
msgid "Gabon"
msgstr "Gabon"

#: admin/class-settings.php:677
msgid "Gambia"
msgstr "Gambia"

#: admin/class-settings.php:678
msgid "Georgia"
msgstr "Georgië"

#: admin/class-settings.php:679
msgid "Germany"
msgstr "Duitsland"

#: admin/class-settings.php:680
msgid "Ghana"
msgstr "Ghana"

#: admin/class-settings.php:681
msgid "Gibraltar"
msgstr "Gibraltar"

#: admin/class-settings.php:682
msgid "Greece"
msgstr "Griekenland"

#: admin/class-settings.php:683
msgid "Greenland"
msgstr "Groenland"

#: admin/class-settings.php:684
msgid "Grenada"
msgstr "Grenada"

#: admin/class-settings.php:685 admin/class-settings.php:687
msgid "Guam"
msgstr "Guam"

#: admin/class-settings.php:686
msgid "Guadeloupe"
msgstr "Guadeloupe"

#: admin/class-settings.php:688
msgid "Guatemala"
msgstr "Guatemala"

#: admin/class-settings.php:689
msgid "Guernsey"
msgstr "Guernsey"

#: admin/class-settings.php:690
msgid "Guinea"
msgstr "Guinee"

#: admin/class-settings.php:691
msgid "Guinea-Bissau"
msgstr "Guinee-Bissau"

#: admin/class-settings.php:692
msgid "Guyana"
msgstr "Guyana"

#: admin/class-settings.php:693
msgid "Haiti"
msgstr "Haïti"

#: admin/class-settings.php:694
msgid "Heard and McDonald Islands"
msgstr "Heard en McDonaldeilanden"

#: admin/class-settings.php:695
msgid "Honduras"
msgstr "Honduras"

#: admin/class-settings.php:696
msgid "Hong Kong"
msgstr "Hong Kong"

#: admin/class-settings.php:697
msgid "Hungary"
msgstr "Hongarije"

#: admin/class-settings.php:698
msgid "Iceland"
msgstr "IJsland"

#: admin/class-settings.php:699
msgid "India"
msgstr "India"

#: admin/class-settings.php:700
msgid "Indonesia"
msgstr "Indonesië"

#: admin/class-settings.php:701
msgid "Iran"
msgstr "Iran"

#: admin/class-settings.php:702
msgid "Iraq"
msgstr "Irak"

#: admin/class-settings.php:703
msgid "Ireland"
msgstr "Ierland"

#: admin/class-settings.php:704
msgid "Isle of Man"
msgstr "Man (eiland)"

#: admin/class-settings.php:705
msgid "Israel"
msgstr "Israël"

#: admin/class-settings.php:706
msgid "Italy"
msgstr "Italië"

#: admin/class-settings.php:707
msgid "Jamaica"
msgstr "Jamaica"

#: admin/class-settings.php:708
msgid "Japan"
msgstr "Japan"

#: admin/class-settings.php:709
msgid "Jersey"
msgstr "Jersey"

#: admin/class-settings.php:710
msgid "Jordan"
msgstr "Jordanië"

#: admin/class-settings.php:711
msgid "Kazakhstan"
msgstr "Kazachstan"

#: admin/class-settings.php:712
msgid "Kenya"
msgstr "Kenia"

#: admin/class-settings.php:713
msgid "Kiribati"
msgstr "Kiribati"

#: admin/class-settings.php:714
msgid "Kosovo"
msgstr "Kosovo"

#: admin/class-settings.php:715
msgid "Kuwait"
msgstr "Koeweit"

#: admin/class-settings.php:716
msgid "Kyrgyzstan"
msgstr "Kirgizië"

#: admin/class-settings.php:717
msgid "Laos"
msgstr "Laos"

#: admin/class-settings.php:718
msgid "Latvia"
msgstr "Letland"

#: admin/class-settings.php:719
msgid "Lebanon"
msgstr "Libanon"

#: admin/class-settings.php:720
msgid "Lesotho"
msgstr "Lesotho"

#: admin/class-settings.php:721
msgid "Liberia"
msgstr "Liberia"

#: admin/class-settings.php:722
msgid "Libya"
msgstr "Libië"

#: admin/class-settings.php:723
msgid "Liechtenstein"
msgstr "Liechtenstein"

#: admin/class-settings.php:724
msgid "Lithuania"
msgstr "Litouwen"

#: admin/class-settings.php:725
msgid "Luxembourg"
msgstr "Luxemburg"

#: admin/class-settings.php:726
msgid "Macau"
msgstr "Macau"

#: admin/class-settings.php:727
msgid "Macedonia (FYROM)"
msgstr "Macedonië"

#: admin/class-settings.php:728
msgid "Madagascar"
msgstr "Madagascar"

#: admin/class-settings.php:729
msgid "Malawi"
msgstr "Malawi"

#: admin/class-settings.php:730
msgid "Malaysia "
msgstr "Maleisie"

#: admin/class-settings.php:731
msgid "Maldives "
msgstr "Maldiven"

#: admin/class-settings.php:732
msgid "Mali"
msgstr "Mali"

#: admin/class-settings.php:733
msgid "Malta"
msgstr "Malta"

#: admin/class-settings.php:734
msgid "Marshall Islands"
msgstr "Marshalleilanden"

#: admin/class-settings.php:735
msgid "Martinique"
msgstr "Martinique"

#: admin/class-settings.php:736
msgid "Mauritania"
msgstr "Mauritanië"

#: admin/class-settings.php:737
msgid "Mauritius"
msgstr "Mauritius"

#: admin/class-settings.php:738
msgid "Mayotte"
msgstr "Mayotte"

#: admin/class-settings.php:739
msgid "Mexico"
msgstr "Mexico"

#: admin/class-settings.php:740
msgid "Micronesia"
msgstr "Micronesia"

#: admin/class-settings.php:741
msgid "Moldova"
msgstr "Moldavië"

#: admin/class-settings.php:742
msgid "Monaco"
msgstr "Monaco"

#: admin/class-settings.php:743
msgid "Mongolia"
msgstr "Mongolië"

#: admin/class-settings.php:744
msgid "Montenegro"
msgstr "Montenegro"

#: admin/class-settings.php:745
msgid "Montserrat"
msgstr "Montserrat "

#: admin/class-settings.php:746
msgid "Morocco"
msgstr "Marokko"

#: admin/class-settings.php:747
msgid "Mozambique"
msgstr "Mozambique"

#: admin/class-settings.php:748
msgid "Myanmar (Burma)"
msgstr "Myanmar (Birma)"

#: admin/class-settings.php:749
msgid "Namibia"
msgstr "Namibië"

#: admin/class-settings.php:750
msgid "Nauru"
msgstr "Nauru"

#: admin/class-settings.php:751
msgid "Nepal"
msgstr "Nepal"

#: admin/class-settings.php:752
msgid "Netherlands"
msgstr "Nederland"

#: admin/class-settings.php:753
msgid "Netherlands Antilles"
msgstr "Nederlandse Antillen"

#: admin/class-settings.php:754
msgid "New Caledonia"
msgstr "Nieuw-Caledonië"

#: admin/class-settings.php:755
msgid "New Zealand"
msgstr "Nieuw Zeeland"

#: admin/class-settings.php:756
msgid "Nicaragua"
msgstr "Nicaragua"

#: admin/class-settings.php:757
msgid "Niger"
msgstr "Niger"

#: admin/class-settings.php:758
msgid "Nigeria"
msgstr "Nigeria"

#: admin/class-settings.php:759
msgid "Niue"
msgstr "Niue"

#: admin/class-settings.php:760
msgid "Norfolk Island"
msgstr "Norfolk (eiland)"

#: admin/class-settings.php:761
msgid "North Korea"
msgstr "Noord-Korea"

#: admin/class-settings.php:762
msgid "Northern Mariana Islands"
msgstr "Noordelijke Marianen"

#: admin/class-settings.php:763
msgid "Norway"
msgstr "Noorwegen"

#: admin/class-settings.php:764
msgid "Oman"
msgstr "Oman"

#: admin/class-settings.php:765
msgid "Pakistan"
msgstr "Pakistan"

#: admin/class-settings.php:766
msgid "Palau"
msgstr "Palau"

#: admin/class-settings.php:767
msgid "Palestine"
msgstr "Palestine"

#: admin/class-settings.php:768
msgid "Panama"
msgstr "Panama"

#: admin/class-settings.php:769
msgid "Papua New Guinea"
msgstr "Papoea-Nieuw-Guinea"

#: admin/class-settings.php:770
msgid "Paraguay"
msgstr "Paraguay"

#: admin/class-settings.php:771
msgid "Peru"
msgstr "Peru"

#: admin/class-settings.php:772
msgid "Philippines"
msgstr "Filipijnen"

#: admin/class-settings.php:773
msgid "Pitcairn Islands"
msgstr "Pitcairneilanden"

#: admin/class-settings.php:774
msgid "Poland"
msgstr "Polen"

#: admin/class-settings.php:775
msgid "Portugal"
msgstr "Portugal"

#: admin/class-settings.php:776
msgid "Puerto Rico"
msgstr "Puerto Rico"

#: admin/class-settings.php:777
msgid "Qatar"
msgstr "Qatar"

#: admin/class-settings.php:778
msgid "Reunion"
msgstr "Réunion"

#: admin/class-settings.php:779
msgid "Romania"
msgstr "Roemenië"

#: admin/class-settings.php:780
msgid "Russia"
msgstr "Rusland"

#: admin/class-settings.php:781
msgid "Rwanda"
msgstr "Rwanda"

#: admin/class-settings.php:782
msgid "Saint Helena"
msgstr "Sint-Helena"

#: admin/class-settings.php:783
msgid "Saint Kitts and Nevis"
msgstr "Saint Kitts en Nevis"

#: admin/class-settings.php:784
msgid "Saint Vincent and the Grenadines"
msgstr "Saint Vincent en de Grenadines"

#: admin/class-settings.php:785
msgid "Saint Lucia"
msgstr "Saint Lucia"

#: admin/class-settings.php:786
msgid "Samoa"
msgstr "Samoa"

#: admin/class-settings.php:787
msgid "San Marino"
msgstr "San Marino"

#: admin/class-settings.php:788
msgid "São Tomé and Príncipe"
msgstr "Sao Tomé en Principe"

#: admin/class-settings.php:789
msgid "Saudi Arabia"
msgstr "Saoedi-Arabië"

#: admin/class-settings.php:790
msgid "Senegal"
msgstr "Senegal"

#: admin/class-settings.php:791
msgid "Serbia"
msgstr "Servië"

#: admin/class-settings.php:792
msgid "Seychelles"
msgstr "Seychellen"

#: admin/class-settings.php:793
msgid "Sierra Leone"
msgstr "Sierra Leone"

#: admin/class-settings.php:794
msgid "Singapore"
msgstr "Singapore"

#: admin/class-settings.php:795
msgid "Sint Maarten"
msgstr "Sint Maarten"

#: admin/class-settings.php:796
msgid "Slovakia"
msgstr "Slowakije"

#: admin/class-settings.php:797
msgid "Slovenia"
msgstr "Slovenië"

#: admin/class-settings.php:798
msgid "Solomon Islands"
msgstr "Salomonseilanden"

#: admin/class-settings.php:799
msgid "Somalia"
msgstr "Somalie"

#: admin/class-settings.php:800
msgid "South Africa"
msgstr "Zuid Afrika"

#: admin/class-settings.php:801
msgid "South Georgia and South Sandwich Islands"
msgstr "Zuid-Georgia en de Zuidelijke Sandwicheilanden"

#: admin/class-settings.php:802
msgid "South Korea"
msgstr "Zuid Korea"

#: admin/class-settings.php:803
msgid "South Sudan"
msgstr "Zuid Sudan"

#: admin/class-settings.php:804
msgid "Spain"
msgstr "Spanje"

#: admin/class-settings.php:805
msgid "Sri Lanka"
msgstr "Sri Lanka"

#: admin/class-settings.php:806
msgid "Sudan"
msgstr "Sudan"

#: admin/class-settings.php:807
msgid "Swaziland"
msgstr "Swaziland "

#: admin/class-settings.php:808
msgid "Sweden"
msgstr "Zweden"

#: admin/class-settings.php:809
msgid "Switzerland"
msgstr "Zwitserland"

#: admin/class-settings.php:810
msgid "Syria"
msgstr "Syrië"

#: admin/class-settings.php:811
msgid "São Tomé & Príncipe"
msgstr "São Tomé & Príncipe"

#: admin/class-settings.php:812
msgid "Taiwan"
msgstr "Taiwan"

#: admin/class-settings.php:813
msgid "Tajikistan"
msgstr "Tajikistan"

#: admin/class-settings.php:814
msgid "Tanzania"
msgstr "Tanzania"

#: admin/class-settings.php:815
msgid "Thailand"
msgstr "Thailand"

#: admin/class-settings.php:816
msgid "Timor-Leste"
msgstr "Oost-Timor"

#: admin/class-settings.php:817 admin/class-settings.php:819
msgid "Tokelau"
msgstr "Tokelau"

#: admin/class-settings.php:818
msgid "Togo"
msgstr "Togo"

#: admin/class-settings.php:820
msgid "Tonga"
msgstr "Tonga"

#: admin/class-settings.php:821
msgid "Trinidad and Tobago"
msgstr "Trinidad en Tobago"

#: admin/class-settings.php:822
msgid "Tristan da Cunha"
msgstr "Tristan da Cunha"

#: admin/class-settings.php:823
msgid "Tunisia"
msgstr "Tunesië"

#: admin/class-settings.php:824
msgid "Turkey"
msgstr "Turkije"

#: admin/class-settings.php:825
msgid "Turkmenistan"
msgstr "Turkmenistan"

#: admin/class-settings.php:826
msgid "Turks and Caicos Islands"
msgstr "Turks- en Caicos eilanden"

#: admin/class-settings.php:827
msgid "Tuvalu"
msgstr "Tuvalu"

#: admin/class-settings.php:828
msgid "Uganda"
msgstr "Uganda"

#: admin/class-settings.php:829
msgid "Ukraine"
msgstr "Oekraïne"

#: admin/class-settings.php:830
msgid "United Arab Emirates"
msgstr "Verenigde Arabische Emiraten"

#: admin/class-settings.php:831
msgid "United Kingdom"
msgstr "Verenigd Koninkrijk"

#: admin/class-settings.php:832
msgid "United States"
msgstr "Verenigde Staten"

#: admin/class-settings.php:833
msgid "Uruguay"
msgstr "Uruguay"

#: admin/class-settings.php:834
msgid "Uzbekistan"
msgstr "Uzbekistan"

#: admin/class-settings.php:835
msgid "Vanuatu"
msgstr "Vanuatu"

#: admin/class-settings.php:836
msgid "Vatican City"
msgstr "Vaticaanstad"

#: admin/class-settings.php:837
msgid "Venezuela"
msgstr "Venezuela"

#: admin/class-settings.php:838
msgid "Vietnam"
msgstr "Vietnam"

#: admin/class-settings.php:839
msgid "Wallis Futuna"
msgstr "Wallis en Futuna"

#: admin/class-settings.php:840
msgid "Western Sahara"
msgstr "Westelijke Sahara"

#: admin/class-settings.php:841
msgid "Yemen"
msgstr "Yemen"

#: admin/class-settings.php:842
msgid "Zambia"
msgstr "Zambia"

#: admin/class-settings.php:843
msgid "Zimbabwe"
msgstr "Zimbabwe"

#: admin/class-settings.php:844
msgid "Åland Islands"
msgstr "Åland Eiland"

#: admin/class-settings.php:887
msgid "World view"
msgstr "Wereldkaart"

#: admin/class-settings.php:890 admin/class-settings.php:1004
#: inc/wpsl-functions.php:225
msgid "Default"
msgstr "Standaard"

#: admin/class-settings.php:893 inc/wpsl-functions.php:298
msgid "Roadmap"
msgstr "Wegenkaart"

#: admin/class-settings.php:1034
msgid "Start location marker"
msgstr "Start locatie marker"

#: admin/class-settings.php:1036
msgid "Store location marker"
msgstr "Winkel locatie marker"

#: admin/class-settings.php:1116
msgid "Textarea"
msgstr "Tekstvlak"

#: admin/class-settings.php:1117
msgid "Dropdowns (recommended)"
msgstr "Dropdown (aangeraden)"

#: admin/class-settings.php:1125
msgid "Bounces up and down"
msgstr "Beweegt op en neer"

#: admin/class-settings.php:1126
msgid "Will open the info window"
msgstr "Opent de info window"

#: admin/class-settings.php:1127
msgid "Does not respond"
msgstr "Reageert niet"

#: admin/class-settings.php:1135
msgid "In the store listings"
msgstr "In de locatie lijst"

#: admin/class-settings.php:1136
msgid "In the info window on the map"
msgstr "In de info window op de kaart"

#: admin/class-settings.php:1168 admin/class-shortcode-generator.php:263
msgid "Dropdown"
msgstr "Dropdown"

#: admin/class-settings.php:1169 admin/class-shortcode-generator.php:264
msgid "Checkboxes"
msgstr "Checkboxes"

#: admin/class-settings.php:1201
msgid "12 Hours"
msgstr "12 uur"

#: admin/class-settings.php:1202
msgid "24 Hours"
msgstr "24 uur"

#: admin/class-shortcode-generator.php:42
msgid "WP Store Locator"
msgstr "WP Store Locator"

#: admin/class-shortcode-generator.php:42
#: admin/class-shortcode-generator.php:355
msgid "Insert Store Locator"
msgstr "Plaats de Store Locator"

#: admin/class-shortcode-generator.php:61
msgid "You do not have permission to perform this action"
msgstr "Je hebt geen toestemming om deze actie uit te voeren"

#: admin/class-shortcode-generator.php:233
msgid "General Options"
msgstr "Algemene instellingen"

#: admin/class-shortcode-generator.php:234 admin/templates/map-settings.php:398
msgid "Markers"
msgstr "Markers"

#: admin/class-shortcode-generator.php:240
msgid "Select the used template"
msgstr "Selecteer de gebruikte template"

#: admin/class-shortcode-generator.php:244 admin/templates/map-settings.php:225
msgid "Start point"
msgstr "Start locatie"

#: admin/class-shortcode-generator.php:244
#, php-format
msgid ""
"If nothing it set, then the start point from the %ssettings%s page is used."
msgstr ""
"Als er niks is opgegeven, dan zal de start locatie van de %sinstellingen%s "
"pagina gebruikt worden."

#: admin/class-shortcode-generator.php:249 admin/templates/map-settings.php:211
msgid "Attempt to auto-locate the user"
msgstr "Probeer de locatie van de gebruiker automatische te achterhalen"

#: admin/class-shortcode-generator.php:249 admin/templates/map-settings.php:211
#, php-format
msgid ""
"Most modern browsers %srequire%s a HTTPS connection before the Geolocation "
"feature works."
msgstr ""
"De meeste browsers %shebben%s een HTTPS verbindingen nodig om de geolocatie "
"optie te laten werken."

#: admin/class-shortcode-generator.php:259
msgid "Category filter type"
msgstr "Type categorie filter"

#: admin/class-shortcode-generator.php:262
msgid "None"
msgstr "Geen"

#: admin/class-shortcode-generator.php:269
msgid "Automatically restrict the returned results to one or more categories?"
msgstr "Beperk de zoekresultaten automatische tot één of meer categorieën?"

#: admin/class-shortcode-generator.php:285
msgid "Set a selected category?"
msgstr "Kies de geselecteerde categorie"

#: admin/class-shortcode-generator.php:290
msgid "Select category"
msgstr "Kies een categorie"

#: admin/class-shortcode-generator.php:306
msgid "Checkbox columns"
msgstr "Checkbox kolommen"

#: admin/class-shortcode-generator.php:325
msgid "Set selected checkboxes"
msgstr "Kies de geslecteerde checkboxes"

#: admin/class-shortcode-generator.php:341 admin/templates/map-settings.php:263
msgid "Map type"
msgstr "Kaart soort"

#: admin/roles.php:20
msgid "Store Locator Manager"
msgstr "Store Locator Beheerder"

#: admin/templates/add-ons.php:21
msgid "WP Store Locator Add-Ons"
msgstr "WP Store Locator Uitbreidingen"

#: admin/templates/add-ons.php:41
msgid "Already Installed."
msgstr "Is al geinstalleerd."

#: admin/templates/add-ons.php:43
msgid "Coming soon!"
msgstr "Binnenkort beschikbaar!"

#: admin/templates/add-ons.php:55
msgid "Failed to load the add-on list from the server."
msgstr "De add-on lijst kon niet geladen worden van de server."

#: admin/templates/map-settings.php:13
msgid "General"
msgstr "Algemeen"

#: admin/templates/map-settings.php:18
msgid "Licenses"
msgstr "Licenties"

#: admin/templates/map-settings.php:49
msgid "Add-On"
msgstr "Uitbreiding"

#: admin/templates/map-settings.php:50
msgid "License Key"
msgstr "Licensie sleutel"

#: admin/templates/map-settings.php:51
msgid "License Expiry Date"
msgstr "Verloop datum licensie "

#: admin/templates/map-settings.php:65
msgid "Deactivate License"
msgstr "Deactiveer licensie"

#: admin/templates/map-settings.php:85 admin/templates/map-settings.php:128
#: admin/templates/map-settings.php:198 admin/templates/map-settings.php:281
#: admin/templates/map-settings.php:388 admin/templates/map-settings.php:416
#: admin/templates/map-settings.php:466 admin/templates/map-settings.php:498
#: admin/templates/map-settings.php:610 admin/templates/map-settings.php:663
msgid "Save Changes"
msgstr "Wijzigingen opslaan"

#: admin/templates/map-settings.php:97
msgid "Google Maps API"
msgstr "Google Maps API"

#: admin/templates/map-settings.php:100
#, php-format
msgid ""
"A %sbrowser key%s allows you to monitor the usage of the Google Maps "
"%sJavaScript API%s. %s %sRequired%s for %sapplications%s created after June "
"22, 2016."
msgstr ""
"Een %sbrowser sleutel%s maakt het mogelijk om het gebruik te bekijken van de "
"Google Maps %sJavaScript API%s. %s %sVerplicht%s voor %sapplicaties%s "
"aangemaakt na 22 juni, 2016."

#: admin/templates/map-settings.php:104
#, php-format
msgid ""
"A %sserver key%s allows you to monitor the usage of the Google Maps "
"%sGeocoding API%s. %s %sRequired%s for %sapplications%s created after June "
"22, 2016."
msgstr ""
"Een %sserver sleutel%s maakt het mogelijk om het gebruik van de Google Maps "
"%sGeocode API%s te bekijken. %s %sVerplicht%s voor %sapplicaties%s "
"aangemaakt na 22 juni, 2016."

#: admin/templates/map-settings.php:108
msgid "Validate API keys"
msgstr ""

#: admin/templates/map-settings.php:109
msgid "Show response "
msgstr ""

#: admin/templates/map-settings.php:112
msgid "Map language"
msgstr "Kaart taal"

#: admin/templates/map-settings.php:112
msgid "If no map language is selected the browser's prefered language is used."
msgstr ""
"Als er geen kaart taal is geselecteerd, dan word de standaard browser taal "
"gebruikt."

#: admin/templates/map-settings.php:118
msgid "Map region"
msgstr "Kaart regio"

#: admin/templates/map-settings.php:118
#, php-format
msgid ""
"This will bias the %sgeocoding%s results towards the selected region. %s If "
"no region is selected the bias is set to the United States."
msgstr ""
"Dit zorgt er voor dat de %sgeocode%s resultaten uit de geselecteerde regio "
"voorkeur krijgen over resultaten uit andere regio's . %s Als er geen regio "
"is geselecteerd dan gaat de voorkeur uit naar de Verenigde Staten."

#: admin/templates/map-settings.php:124
msgid "Restrict the geocoding results to the selected map region?"
msgstr "Limiteer de geocode resultaten tot de geselecteerde map regio?"

#: admin/templates/map-settings.php:124
#, php-format
msgid ""
"If the %sgeocoding%s API finds more relevant results outside of the set map "
"region ( some location names exist in multiple regions ), the user will "
"likely see a \"No results found\" message. %s To rule this out you can "
"restrict the results to the set map region. %s You can modify the used "
"restrictions with %sthis%s filter."
msgstr ""
"Als de %sgeocode%s API meer relevante resultaten vindt buiten de ingestelde "
"map regio ( sommige locatie namen bestaan in meerdere regio's ), dan zal de "
"gebruiker waarschijnlijk een \"Geen resultaten gevonden\" boodschap zien. %s "
"Om dit uit te sluiten kan  je een restrictie plaatsen om dit te voorkomen. "
"%s Je kan de gebruikte restricties aanpassen met %sdeze%s filter."

#: admin/templates/map-settings.php:138 admin/templates/map-settings.php:534
#: admin/templates/map-settings.php:535 admin/templates/map-settings.php:686
#: frontend/templates/default.php:44
#: frontend/templates/store-listings-below.php:44 inc/wpsl-functions.php:142
msgid "Search"
msgstr "Zoek"

#: admin/templates/map-settings.php:141
msgid "Enable autocomplete?"
msgstr "Activeer autocomplete?"

#: admin/templates/map-settings.php:146
msgid "Force zipcode only search"
msgstr "Zoek alleen op postcodes"

#: admin/templates/map-settings.php:150
#, php-format
msgid ""
"For this option to work correctly you need to set a map region and restrict "
"the results to the selected region. %s You can do this in the %sGoogle Maps "
"API section%s."
msgstr ""
"Deze optie werkt alleen maar correct als er een map region geselecteerd is "
"en de 'Limiteer de geocode resultaten tot de geselecteerde map regio?' optie "
"ook geactiveerd is. %s Dit kan je doen in het %sGoogle Maps API%s gedeelte."

#: admin/templates/map-settings.php:158
#, php-format
msgid ""
"Zipcode only search does unfortunately not work well in combination with the "
"autocomplete option. %s It's recommended to not have both options active at "
"the same time."
msgstr ""
"De optie om alleen op een postcode te zoeken werkt helaas niet goed in "
"combinatie met de autocomplete optie. %s Het is daarom beter om niet beide "
"opties tegelijk actief te hebben."

#: admin/templates/map-settings.php:163
msgid "Show the max results dropdown?"
msgstr "Toon de max resultaten dropdown?"

#: admin/templates/map-settings.php:167
msgid "Show the search radius dropdown?"
msgstr "Toon de zoek radius dropdown?"

#: admin/templates/map-settings.php:171
msgid "Enable category filters?"
msgstr "Activeer de categorie filters?"

#: admin/templates/map-settings.php:176
msgid "Filter type:"
msgstr "Filter type:"

#: admin/templates/map-settings.php:181
msgid "Distance unit"
msgstr "Afstands eenheid"

#: admin/templates/map-settings.php:184
msgid "km"
msgstr "km"

#: admin/templates/map-settings.php:186
msgid "mi"
msgstr "mi"

#: admin/templates/map-settings.php:190
msgid "Max search results"
msgstr "Max zoek resultaten"

#: admin/templates/map-settings.php:190 admin/templates/map-settings.php:194
msgid "The default value is set between the [ ]."
msgstr "* De standaard waarde staat tussen de  []."

#: admin/templates/map-settings.php:194
msgid "Search radius options"
msgstr "Zoek radius opties"

#: admin/templates/map-settings.php:208
msgid "Map"
msgstr "Kaart"

#: admin/templates/map-settings.php:215
msgid "Load locations on page load"
msgstr "Toon alle locaties op de kaart zodra de pagina geladen is"

#: admin/templates/map-settings.php:220
msgid "Number of locations to show"
msgstr "Aantal getoonde locaties"

#: admin/templates/map-settings.php:220
#, php-format
msgid ""
"Although the location data is cached after the first load, a lower number "
"will result in the map being more responsive. %s If this field is left empty "
"or set to 0, then all locations are loaded."
msgstr ""
"Ondanks dat de winkel data in het cache worden opgeslagen, is het aan te "
"raden om het aantal winkels wat tegelijk geladen wordt niet te groot te "
"laten worden. Dit zorgt er voor dat de kaart vloeiender blijft reageren. %s "
"Als het veld leeg blijft of er wordt 0 ingevuld, dan worden alle locaties "
"geladen."

#: admin/templates/map-settings.php:225
#, php-format
msgid ""
"%sRequired field.%s %s If auto-locating the user is disabled or fails, the "
"center of the provided city or country will be used as the initial starting "
"point for the user."
msgstr ""
"%sVerplicht veld.%s %s Als het automatische achterhalen van de gebruikers "
"locatie is uitgeschakeld of mislukt, dan wordt het middelpunt van de "
"opgegeven locatie als begin punt gebruikt."

#: admin/templates/map-settings.php:230
msgid "Auto adjust the zoom level to make sure all markers are visible?"
msgstr ""
"Zoom de kaart automatische in om te zorgen dat alle markers zichtbaar zijn?"

#: admin/templates/map-settings.php:230
msgid ""
"This runs after a search is made, and makes sure all the returned locations "
"are visible in the viewport."
msgstr ""
"Dit wordt uitgevoerd nadat een zoekopdracht is gemaakt, en zorgt ervoor dat "
"alle geretourneerde locaties zichtbaar zijn in de viewport."

#: admin/templates/map-settings.php:234
msgid "Initial zoom level"
msgstr "Start zoom niveau"

#: admin/templates/map-settings.php:238
msgid "Max auto zoom level"
msgstr "Max zoom niveau"

#: admin/templates/map-settings.php:238
#, php-format
msgid ""
"This value sets the zoom level for the \"Zoom here\" link in the info "
"window. %s It is also used to limit the zooming when the viewport of the map "
"is changed to make all the markers fit on the screen."
msgstr ""
"Deze waarde word gebruikt om het zoom niveau te bepalen voor de \"Zoom hier"
"\" link in de info window. %s Het wordt ook gebruikt om het zoom niveau te "
"limiteren als de viewport van de kaart verandert,  wanneer geprobeerd wordt "
"om alle markers op het scherm te laten passen."

#: admin/templates/map-settings.php:242
msgid "Show the street view controls?"
msgstr "Toon de street view controls?"

#: admin/templates/map-settings.php:246
msgid "Show the map type control?"
msgstr "Toon de kaart type controls?"

#: admin/templates/map-settings.php:250
msgid "Enable scroll wheel zooming?"
msgstr "Activeer het inzoomen met je scrollwheel?"

#: admin/templates/map-settings.php:254
msgid "Zoom control position"
msgstr "Zoom bediening positie"

#: admin/templates/map-settings.php:257
msgid "Left"
msgstr "Links"

#: admin/templates/map-settings.php:259
msgid "Right"
msgstr "Rechts"

#: admin/templates/map-settings.php:267
msgid "Map style"
msgstr "Kaart stijl"

#: admin/templates/map-settings.php:267
msgid ""
"Custom map styles only work if the map type is set to \"Roadmap\" or "
"\"Terrain\"."
msgstr ""
"Custom map stijlen werken alleen maar als de kaart soort op \"Wegenkaart\" "
"of \"Terrein\" is gezet."

#: admin/templates/map-settings.php:270
#, php-format
msgid ""
"You can use existing map styles from %sSnazzy Maps%s or %sMap Stylr%s and "
"paste it in the textarea below, or you can generate a custom map style "
"through the %sMap Style Editor%s or %sStyled Maps Wizard%s."
msgstr ""
"Je kunt bestaande map stijlen van %sSnazzy Maps%s of %sMap Stylr%s kopieren "
"en in het onderstaande tekstvlak plaatsen. Of je kunt de map stijl genereren "
"via de %sMap Style Editor%s of de %sStyled Maps Wizard%s."

#: admin/templates/map-settings.php:271
#, php-format
msgid ""
"If you like to write the style code yourself, then you can find the "
"documentation from Google %shere%s."
msgstr ""
"Als je zelf de stijl code wil schrijven dan kun je de documentatie %shier%s "
"vinden."

#: admin/templates/map-settings.php:273
msgid "Preview Map Style"
msgstr "Map stijl voorbeeld"

#: admin/templates/map-settings.php:277
msgid "Show credits?"
msgstr "Toon credits?"

#: admin/templates/map-settings.php:277
msgid ""
"This will place a \"Search provided by WP Store Locator\" backlink below the "
"map."
msgstr ""
"Dit plaatst een \"Ondersteund door WP Store Locator\" link onder de kaart."

#: admin/templates/map-settings.php:291
msgid "User Experience"
msgstr "Gebruikers ervaring"

#: admin/templates/map-settings.php:294
msgid "Store Locator height"
msgstr "Store Locator hoogte"

#: admin/templates/map-settings.php:298
msgid "Max width for the info window content"
msgstr "Max breedte voor de info window inhoud"

#: admin/templates/map-settings.php:302
msgid "Search field width"
msgstr "Zoekveld breedte"

#: admin/templates/map-settings.php:306
msgid "Search and radius label width"
msgstr "Zoek en radius label breedte"

#: admin/templates/map-settings.php:310
msgid "Store Locator template"
msgstr "Store locator template"

#: admin/templates/map-settings.php:310
#, php-format
msgid ""
"The selected template is used with the [wpsl] shortcode. %s You can add a "
"custom template with the %swpsl_templates%s filter."
msgstr ""
"De geselecteerde template wordt gebruikt bij de [wpsl] shortcode. %s Je kunt "
"een custom template gebruiken met behulp van de %swpsl_templates%s filter."

#: admin/templates/map-settings.php:314
msgid "Hide the scrollbar?"
msgstr "Verberg de scrollbar?"

#: admin/templates/map-settings.php:318
msgid "Open links in a new window?"
msgstr "Open links in een nieuw venster?"

#: admin/templates/map-settings.php:322
msgid "Show a reset map button?"
msgstr "Toon een knop om de kaart te resetten?"

#: admin/templates/map-settings.php:326
msgid ""
"When a user clicks on \"Directions\", open a new window, and show the route "
"on google.com/maps ?"
msgstr ""
"Zodra een gebruiker op \"Route\" klikt, open een nieuwe venster en toon de "
"route op google.com/maps?"

#: admin/templates/map-settings.php:330
msgid "Show a \"More info\" link in the store listings?"
msgstr "Toon een \"Meer info\" link in de locatie lijst?"

#: admin/templates/map-settings.php:330
msgid ""
"This places a \"More Info\" link below the address and will show the phone, "
"fax, email, opening hours and description once the link is clicked."
msgstr ""
"Dit plaatst een \"Meer Info\" link onder het adres. Als een gebruiker hierop "
"klikt dan wordt het telefoon / fax nummer, email, openings tijden en "
"omschrijving getoond."

#: admin/templates/map-settings.php:335
msgid "Where do you want to show the \"More info\" details?"
msgstr "Waar wil je de  \"Meer info\" details tonen?"

#: admin/templates/map-settings.php:340
msgid ""
"Always show the contact details below the address in the search results?"
msgstr "Toon altijd de contact gegevens onder het adres in de zoek resultaten?"

#: admin/templates/map-settings.php:344
msgid "Make the contact details always clickable?"
msgstr "Maak de contact gevens klikbaar?"

#: admin/templates/map-settings.php:348
msgid "Make the store name clickable if a store URL exists?"
msgstr "Als een winkel url bestaat, maak de winkel naam dan klikbaar?"

#: admin/templates/map-settings.php:348
#, php-format
msgid ""
"If %spermalinks%s are enabled, the store name will always link to the store "
"page."
msgstr ""
"Als de %spermalinks%s zijn ingeschakeld dan zal de winkel naam altijd linken "
"naar de winkel pagina."

#: admin/templates/map-settings.php:352
msgid "Make the phone number clickable on mobile devices?"
msgstr "Maak het telefoonnummer klikbaar op mobiele apparaten?"

#: admin/templates/map-settings.php:356
msgid ""
"If street view is available for the current location, then show a \"Street "
"view\" link in the info window?"
msgstr ""
"Als voor de huidge locatie street view beschikbaar is, toon dan een \"Street "
"view\" link om vanuit de info window?"

#: admin/templates/map-settings.php:356
#, php-format
msgid ""
"Enabling this option can sometimes result in a small delay in the opening of "
"the info window. %s This happens because an API request is made to Google "
"Maps to check if street view is available for the current location."
msgstr ""
"Het activeren van deze optie kan er soms toe leiden dat er een kleine "
"vertraging optreed bij het openen van de info window. %s Dit gebeurt omdat "
"er een verzoek naar  de Google Maps API word gemaakt om te controleren ofdat "
"street view wel beschikbaar is voor de huidige locatie."

#: admin/templates/map-settings.php:360
msgid "Show a \"Zoom here\" link in the info window?"
msgstr "Toon een  \"zoom hier\" link in de info window?"

#: admin/templates/map-settings.php:360
#, php-format
msgid ""
"Clicking this link will make the map zoom in to the %s max auto zoom level "
"%s."
msgstr ""
"Als er op deze link geklikt word dan zoomt de kaart in totdat de %s max auto "
"zoom level %s bereikt is."

#: admin/templates/map-settings.php:364
msgid "On page load move the mouse cursor to the search field?"
msgstr ""
"Als de pagina wordt geladen, verplaats de muiscursor dan naar het invulveld?"

#: admin/templates/map-settings.php:364
#, php-format
msgid ""
"If the store locator is not placed at the top of the page, enabling this "
"feature can result in the page scrolling down. %s %sThis option is disabled "
"on mobile devices.%s"
msgstr ""
"Als de store locator niet bovenaan de pagina geplaatst wordt, dan kan deze "
"instelling ervoor zorgen dat de pagina naar benenden schuift tijden het "
"laden. %s %sDeze optie staat uit op mobiele apparaten.%s"

#: admin/templates/map-settings.php:368
msgid "Use the default style for the info window?"
msgstr "Gebruik de standaard style voor de info window?"

#: admin/templates/map-settings.php:368
#, php-format
msgid ""
"If the default style is disabled the %sInfoBox%s library will be used "
"instead. %s This enables you to easily change the look and feel of the info "
"window through the .wpsl-infobox css class."
msgstr ""
"Als de standaard stijl is uitgeschakeld dan wordt het %sInfoBox%s script "
"gebruikt. %s Dit script maakt het mogelijk om makkelijk het ontwerp te "
"wijzigen met behulp van de .wpsl-infobox css class."

#: admin/templates/map-settings.php:372
msgid "Hide the country in the search results?"
msgstr "Verberg het land in de zoekresultaten?"

#: admin/templates/map-settings.php:376
msgid "Hide the distance in the search results?"
msgstr "Verberg de afstand in de zoek resultaten?"

#: admin/templates/map-settings.php:380
msgid "If a user hovers over the search results the store marker"
msgstr ""
"Als een gebruiker over de zoekresultaten beweegt met zijn muis de "
"bijbehorende marker"

#: admin/templates/map-settings.php:380
#, php-format
msgid ""
"If marker clusters are enabled this option will not work as expected as long "
"as the markers are clustered. %s The bouncing of the marker won't be visible "
"at all unless a user zooms in far enough for the marker cluster to change "
"back in to individual markers. %s The info window will open as expected, but "
"it won't be clear to which marker it belongs to. "
msgstr ""
"Als de marker cluster optie actief is en de markers op de kaart als cluster "
"te zien zijn, dan werkt deze optie niet als verwacht. %s Het op en neer gaan "
"van de markers is niet zichtbaar totdat een gebruiker ver genoeg inzoomt, en "
"de marker cluster wordt omgezet naar losse markers. %s De info window wordt "
"wel geopend, maar het is niet duidelijk bij welke marker het hoort."

#: admin/templates/map-settings.php:384
msgid "Address format"
msgstr "Adres formaat"

#: admin/templates/map-settings.php:384
#, php-format
msgid ""
"You can add custom address formats with the %swpsl_address_formats%s filter."
msgstr ""
"Je kunt een nieuwe adres formaat toevoegen met de %swpsl_address_formats%s "
"filter."

#: admin/templates/map-settings.php:402
msgid "Enable marker clusters?"
msgstr "Activeer marker clusters?"

#: admin/templates/map-settings.php:402
msgid "Recommended for maps with a large amount of markers."
msgstr "Aan te raden voor kaarten met grote hoeveelheden markers."

#: admin/templates/map-settings.php:407
msgid "Max zoom level"
msgstr "Max zoom niveau"

#: admin/templates/map-settings.php:407
msgid ""
"If this zoom level is reached or exceeded, then all markers are moved out of "
"the marker cluster and shown as individual markers."
msgstr ""
"Als dit zoom niveau bereikt is of gepasseerd, dan worden alle markers uit de "
"marker cluster gehaald en als losse markers getoond."

#: admin/templates/map-settings.php:411
msgid "Cluster size"
msgstr "Cluster grote"

#: admin/templates/map-settings.php:411
#, php-format
msgid ""
"The grid size of a cluster in pixels. %s A larger number will result in a "
"lower amount of clusters and also make the algorithm run faster."
msgstr ""
"Het grid formaat van een cluster in pixels. %s Een hoger nummer zorgt er "
"voor dat er minder clusters zichtbaar zijn en het algoritme dus ook sneller "
"klaar is."

#: admin/templates/map-settings.php:426
msgid "Store Editor"
msgstr "Winkel editor"

#: admin/templates/map-settings.php:429
msgid "Default country"
msgstr "Standaard land"

#: admin/templates/map-settings.php:433
msgid "Map type for the location preview"
msgstr "Kaart type voor het lokatie voorbeeld"

#: admin/templates/map-settings.php:437
msgid "Hide the opening hours?"
msgstr "Verberg de openingstijden?"

#: admin/templates/map-settings.php:443
msgid "Opening hours input type"
msgstr "Openingstijden formaat"

#: admin/templates/map-settings.php:447
#, php-format
msgid ""
"Opening hours created in version 1.x %sare not%s automatically converted to "
"the new dropdown format."
msgstr ""
"De openingstijden die zijn aangemaakt in versie 1.x %sworden niet%s "
"automatische omgezet naar het dropdown formaat."

#: admin/templates/map-settings.php:450 admin/templates/map-settings.php:459
msgid "The default opening hours"
msgstr "De standaard openingstijden"

#: admin/templates/map-settings.php:456
msgid "Opening hours format"
msgstr "Openingstijden formaat"

#: admin/templates/map-settings.php:463
msgid ""
"The default country and opening hours are only used when a new store is "
"created. So changing the default values will have no effect on existing "
"store locations."
msgstr ""
"De standaard waardes voor het land en de openingstijden worden alleen "
"gebruikt als een nieuwe locatie wordt aangemaakt. Het wijzigen van deze "
"waardes heeft dus geen enkele invloed op de bestaande locaties."

#: admin/templates/map-settings.php:476
msgid "Permalink"
msgstr "Permalink"

#: admin/templates/map-settings.php:479
msgid "Enable permalink?"
msgstr "Activeer permalink?"

#: admin/templates/map-settings.php:484
msgid "Remove the front base from the permalink structure?"
msgstr "Verwijder de front base uit de permalink structuur."

#: admin/templates/map-settings.php:484
#, php-format
msgid ""
"The front base is set on the %spermalink settings%s page in the \"Custom "
"structure\" field. %s If a front base is set ( for example /blog/ ), then "
"enabling this option will remove it from the store locator permalinks."
msgstr ""
"De front base kan je instellen op de %sPermalink instellingen%s pagina in "
"het \"Aangepaste structuur\" veld. %s Als een front base is gebruikt "
"( bijvoorbeeld /blog/ ) dan zal met deze optie het uit de store locator "
"permalinks verwijderd worden."

#: admin/templates/map-settings.php:488
msgid "Store slug"
msgstr "Winkel slug"

#: admin/templates/map-settings.php:492
msgid "Category slug"
msgstr "Categorie slug"

#: admin/templates/map-settings.php:495
#, php-format
msgid "The permalink slugs %smust be unique%s on your site."
msgstr "De permalink slug %smoet uniek%s zijn op je site."

#: admin/templates/map-settings.php:508
msgid "Labels"
msgstr "Labels"

#: admin/templates/map-settings.php:517
#, php-format
msgid "%sWarning!%s %sWPML%s, or a plugin using the WPML API is active."
msgstr ""
"%sWaarschuwing!%s %sWPML%s, of een plugin die de WPML API  gebruikt is "
"actief."

#: admin/templates/map-settings.php:518
msgid ""
"Please use the \"String Translations\" section in the used multilingual "
"plugin to change the labels. Changing them here will have no effect as long "
"as the multilingual plugin remains active."
msgstr ""
"Gebruik het \"String Translations\" gedeelte in de vertaal plugin om de "
"labels te wijzigen. Wijzigingen die in dit gedeelte worden aangebracht "
"hebben geen effect zolang de vertaal plugin actief is."

#: admin/templates/map-settings.php:522 admin/templates/map-settings.php:523
#: frontend/templates/default.php:12
#: frontend/templates/store-listings-below.php:12 inc/wpsl-functions.php:141
msgid "Your location"
msgstr "Uw locatie"

#: admin/templates/map-settings.php:526 admin/templates/map-settings.php:527
#: frontend/templates/default.php:21
#: frontend/templates/store-listings-below.php:21 inc/wpsl-functions.php:144
msgid "Search radius"
msgstr "Zoek radius"

#: admin/templates/map-settings.php:530 admin/templates/map-settings.php:531
#: frontend/class-frontend.php:1856 inc/wpsl-functions.php:145
msgid "No results found"
msgstr "Geen resultaten gevonden"

#: admin/templates/map-settings.php:538
msgid "Searching (preloader text)"
msgstr "Aan het zoeken (preloader tekst)"

#: admin/templates/map-settings.php:539 frontend/class-frontend.php:1855
#: inc/wpsl-functions.php:143
msgid "Searching..."
msgstr "Zoeken..."

#: admin/templates/map-settings.php:542 admin/templates/map-settings.php:543
#: frontend/templates/default.php:30
#: frontend/templates/store-listings-below.php:30 inc/wpsl-functions.php:146
msgid "Results"
msgstr "Resultaten"

#: admin/templates/map-settings.php:546 admin/upgrade.php:206
#: inc/wpsl-functions.php:160
msgid "Category filter"
msgstr "Categorie filter"

#: admin/templates/map-settings.php:547 frontend/class-frontend.php:1425
msgid "Category"
msgstr "Categorie"

#: admin/templates/map-settings.php:550
msgid "Category first item"
msgstr "Eerste categorie item"

#: admin/templates/map-settings.php:551 admin/upgrade.php:367
#: frontend/class-frontend.php:1428 inc/wpsl-functions.php:161
msgid "Any"
msgstr "Alle"

#: admin/templates/map-settings.php:554 admin/templates/map-settings.php:555
#: admin/upgrade.php:59 frontend/class-frontend.php:1857
#: frontend/underscore-functions.php:138 frontend/underscore-functions.php:168
#: inc/wpsl-functions.php:147
msgid "More info"
msgstr "Meer info"

#: admin/templates/map-settings.php:558 admin/templates/map-settings.php:559
#: frontend/class-frontend.php:842 frontend/underscore-functions.php:29
#: frontend/underscore-functions.php:65 frontend/underscore-functions.php:147
#: inc/wpsl-functions.php:155
msgid "Phone"
msgstr "Telefoon"

#: admin/templates/map-settings.php:578 admin/templates/map-settings.php:579
#: frontend/class-frontend.php:1862 inc/wpsl-functions.php:140
msgid "Start location"
msgstr "Start locatie"

#: admin/templates/map-settings.php:582
msgid "Get directions"
msgstr "Toon routebeschrijving"

#: admin/templates/map-settings.php:583 frontend/class-frontend.php:875
#: frontend/class-frontend.php:1860 inc/wpsl-functions.php:148
msgid "Directions"
msgstr "Routebeschrijving"

#: admin/templates/map-settings.php:586
msgid "No directions found"
msgstr "Geen routebeschrijving beschikbaar"

#: admin/templates/map-settings.php:587 admin/upgrade.php:151
#: frontend/class-frontend.php:1861 inc/wpsl-functions.php:149
msgid "No route could be found between the origin and destination"
msgstr "Er kon geen route gevonden worden tussen het begin- en eindpunt"

#: admin/templates/map-settings.php:590 admin/templates/map-settings.php:591
#: admin/upgrade.php:77 frontend/class-frontend.php:1863
#: inc/wpsl-functions.php:150
msgid "Back"
msgstr "Terug"

#: admin/templates/map-settings.php:594 admin/templates/map-settings.php:595
#: admin/upgrade.php:143 frontend/class-frontend.php:1864
#: inc/wpsl-functions.php:151
msgid "Street view"
msgstr "Street view"

#: admin/templates/map-settings.php:598 admin/templates/map-settings.php:599
#: admin/upgrade.php:147 frontend/class-frontend.php:1865
#: inc/wpsl-functions.php:152
msgid "Zoom here"
msgstr "Zoom hier"

#: admin/templates/map-settings.php:602
msgid "General error"
msgstr "Foutmelding"

#: admin/templates/map-settings.php:603 frontend/class-frontend.php:1858
#: inc/wpsl-functions.php:153
msgid "Something went wrong, please try again!"
msgstr "Er ging iets fout, probeer het nog een keer!"

#: admin/templates/map-settings.php:606
msgid "Query limit error"
msgstr "Query limit foutmelding"

#: admin/templates/map-settings.php:606
#, php-format
msgid ""
"You can raise the %susage limit%s by obtaining an API %skey%s, and fill in "
"the \"API key\" field at the top of this page."
msgstr ""
"Je kan de %sgebruiks limiet%s verhogen door een API %ssleutel%s aan te "
"vragen en die in het  \"API sleutel\" veld bovenaan de pagina in te vullen."

#: admin/templates/map-settings.php:607 frontend/class-frontend.php:1859
#: inc/wpsl-functions.php:154
msgid "API usage limit reached"
msgstr "API gebruikslimiet bereikt"

#: admin/templates/map-settings.php:620
msgid "Tools"
msgstr "Tools"

#: admin/templates/map-settings.php:623
msgid "Enable store locator debug?"
msgstr "Activeer store locator debug?"

#: admin/templates/map-settings.php:623
#, php-format
msgid ""
"This disables the WPSL transient cache. %sThe transient cache is only used "
"if the %sLoad locations on page load%s option is enabled."
msgstr ""
"Dit schakelt het WPSL transient cache uit. %sHet transient cache wordt "
"alleen gebruikt als de %sToon alle locaties op de kaart zodra de pagina "
"geladen is%s optie is geactiveerd."

#: admin/templates/map-settings.php:627
msgid "Enable compatibility mode?"
msgstr "Activeer de compatibiliteitsmodus?"

#: admin/templates/map-settings.php:627
#, php-format
msgid ""
"If the %sbrowser console%s shows the error below, then enabling this option "
"should fix it. %s %sYou have included the Google Maps API multiple times on "
"this page. This may cause unexpected errors.%s %s This error can in some "
"situations break the store locator map."
msgstr ""
"Als de %sbrowser console%s de onderstaande foutmelding laat zien, dan kan je "
"dat oplossen door deze optie te activeren. %s %sYou have included the Google "
"Maps API multiple times on this page. This may cause unexpected errors.%s "
"%s  Deze foutmelding kan er in sommige situations voor zorgen dat de store "
"locator kaart niet goed functioneerd."

#: admin/templates/map-settings.php:631
msgid "WPSL transients"
msgstr "WPSL transients"

#: admin/templates/map-settings.php:632
msgid "Clear store locator transient cache"
msgstr "Verwijder het store locator transient cache."

#: admin/templates/map-settings.php:647
msgid "GDPR - Only load the Google Maps scripts after the user agrees to it?"
msgstr ""

#: admin/templates/map-settings.php:650
#, php-format
msgid "This option requires the %sBorlabs Cookie%s plugin."
msgstr ""

#: admin/templates/map-settings.php:652
#, php-format
msgid ""
"Make sure to wrap the Borlabs Cookie %sshortcode%s around the WPSL shortcode."
msgstr ""

#: admin/templates/map-settings.php:659
msgid "Show the Geocode API response for a location search "
msgstr ""

#: admin/templates/map-settings.php:660
msgid "Input location details"
msgstr ""

#: admin/templates/map-settings.php:680
msgid "Geocode API Response"
msgstr ""

#: admin/templates/map-settings.php:682
msgid "Note"
msgstr ""

#: admin/templates/map-settings.php:685
msgid "Location details"
msgstr ""

#: admin/templates/map-settings.php:688
msgid "API Status"
msgstr ""

#: admin/templates/map-settings.php:693
msgid "Map Preview"
msgstr ""

#: admin/templates/map-settings.php:694
msgid "API Response"
msgstr ""

#: admin/upgrade.php:73
msgid "info window"
msgstr "info window"

#: admin/upgrade.php:81
msgid "Reset"
msgstr "Herstel"

#: admin/upgrade.php:174 inc/wpsl-functions.php:133
msgid "stores"
msgstr "winkels"

#: admin/upgrade.php:178 inc/wpsl-functions.php:134
msgid "store-category"
msgstr "winkel-categorie"

#: admin/upgrade.php:449
#, php-format
msgid ""
"Because you updated WP Store Locator from version 1.x, the %s current store "
"locations need to be %sconverted%s to custom post types."
msgstr ""
"Doordat je WP Store Locator update van versie 1.x, de %s huidige winkel "
"locaties moeten worden %somgezet%s naar custom post types."

#: admin/upgrade.php:470
#, php-format
msgid ""
"The script converting the locations timed out. %s You can click the \"Start "
"Converting\" button again to restart the script. %s If there are thousands "
"of store locations left to convert and you keep seeing this message, then "
"you can try to contact your host and ask if they can increase the maximum "
"execution time. %s The plugin tried to disable the maximum execution time, "
"but if you are reading this then that failed."
msgstr ""
"Het script dat de winkel locaties omzet timed out. %s Je kunt op de \"Begin "
"met omzetten\" knop klikken om het script opnieuw te starten. %s Als er "
"duizenden winkel locaties zijn die nog omgezet moeten worden en je blijft "
"deze boodschap zien dan kun je proberen om contact op te nemen met je host "
"en vragen ofdat ze de maximum execution time kunnen verhogen. %s De plugin "
"heeft al geprobeerd om de maximum execution time uit te zetten, maar als je "
"dit leest dan is dat  mislukt."

#: admin/upgrade.php:491
msgid "Store locations to convert:"
msgstr "Locaties die omgezet worden:"

#: admin/upgrade.php:493
msgid "Start Converting"
msgstr "Begin met omzetten"

#: admin/upgrade.php:615
#, php-format
msgid ""
"All the store locations are now converted to custom post types. %s You can "
"view them on the %sAll Stores%s page."
msgstr ""
"Alle winkel locaties zijn nu omgezet naar custom post types. %s Je kunt ze "
"bekijken op de %sAlle Winkels%s pagina."

#: frontend/class-frontend.php:761
msgid ""
"If you use the [wpsl_address] shortcode outside a store page you need to set "
"the ID attribute."
msgstr ""
"Als je de [wpsl_address] shortcode op een pagina gebruikt die geen winkel "
"pagina is dan is de ID attribute verplicht."

#: frontend/class-frontend.php:916
msgid ""
"If you use the [wpsl_hours] shortcode outside a store page you need to set "
"the ID attribute."
msgstr ""
"Als je de [wpsl_hours] shortcode op een pagina gebruikt die geen winkel "
"pagina is dan is de ID attribute verplicht."

#: frontend/class-frontend.php:964
msgid ""
"If you use the [wpsl_map] shortcode outside a store page, then you need to "
"set the ID or category attribute."
msgstr ""
"Als de [wpsl_map] shortcode buiten een winkel page is geplaatst, dan moet je "
"de ID of category attribute opgeven."

#: frontend/class-frontend.php:1626
msgid "The application does not have permission to use the Geolocation API."
msgstr ""
"Deze applicatie heeft geen toestemming om de Geolocation API te gebruiken."

#: frontend/class-frontend.php:1627
msgid "Location information is unavailable."
msgstr "Informatie over de huidige locatie is niet beschikbaar."

#: frontend/class-frontend.php:1628
msgid "The geolocation request timed out."
msgstr "Het geolocation verzoek timed out."

#: frontend/class-frontend.php:1629
msgid "An unknown error occurred."
msgstr " Er heeft zich een onbekende fout voorgedaan."

#: frontend/templates/default.php:62
#: frontend/templates/store-listings-below.php:68
#, php-format
msgid "Search provided by %sWP Store Locator%s"
msgstr "Ondersteund door %sWP Store Locator%s"

#: inc/class-borlabs-cookie.php:69
msgctxt "Borlabs Cookie"
msgid ""
"To protect your personal data, your connection to Google Maps has been "
"blocked.<br>Click on <strong>Load map</strong> to unblock Google Maps.<br>By "
"loading the map you accept the privacy policy of Google.<br>More information "
"about Google's privacy policy can be found here <a href=\"https://policies."
"google.com/privacy?hl=en&amp;gl=en\" target=\"_blank\" rel=\"nofollow"
"\">Google - Privacy &amp; Terms</a> . "
msgstr ""

#: inc/class-borlabs-cookie.php:70
msgctxt "Borlabs Cookie"
msgid "Do not block Google Maps in the future anymore."
msgstr ""

#: inc/class-borlabs-cookie.php:71
msgctxt "Borlabs Cookie"
msgid "Load map"
msgstr ""

#: inc/class-post-types.php:77
msgid "Store Locator"
msgstr "Store Locator"

#: inc/class-post-types.php:78
msgid "All Stores"
msgstr "Alle winkels"

#: inc/class-post-types.php:79
msgid "Store"
msgstr "winkel"

#: inc/class-post-types.php:80 inc/class-post-types.php:83
msgid "New Store"
msgstr "Nieuwe winkel"

#: inc/class-post-types.php:81
msgid "Add New Store"
msgstr "Voeg winkel toe"

#: inc/class-post-types.php:82
msgid "Edit Store"
msgstr "Wijzig winkel"

#: inc/class-post-types.php:84
msgid "View Stores"
msgstr "Bekijk winkel"

#: inc/class-post-types.php:85
msgid "Search Stores"
msgstr "Zoek winkels"

#: inc/class-post-types.php:86
msgid "No Stores found"
msgstr "Geen winkels gevonden"

#: inc/class-post-types.php:87
msgid "No Stores found in trash"
msgstr "Geen winkels gevonden in de prullenbak"

#: inc/class-post-types.php:130 inc/class-post-types.php:140
msgid "Store Categories"
msgstr "Winkel categorieën"

#: inc/class-post-types.php:131
msgid "Store Category"
msgstr "Winkel categorie"

#: inc/class-post-types.php:132
msgid "Search Store Categories"
msgstr "Zoek winkel categorieën"

#: inc/class-post-types.php:133
msgid "All Store Categories"
msgstr "Alle winkel categorieën"

#: inc/class-post-types.php:134
msgid "Parent Store Category"
msgstr "Hoofd winkel categorie"

#: inc/class-post-types.php:135
msgid "Parent Store Category:"
msgstr "Hoofd winkel categorie:"

#: inc/class-post-types.php:136
msgid "Edit Store Category"
msgstr "Wijzig winkel categorie"

#: inc/class-post-types.php:137
msgid "Update Store Category"
msgstr "Winkel categorie bijwerken"

#: inc/class-post-types.php:138
msgid "Add New Store Category"
msgstr "Voeg winkel categorie toe"

#: inc/class-post-types.php:139
msgid "New Store Category Name"
msgstr "Naam winkel categorie"

#: inc/class-post-types.php:171
msgid "Enter store title here"
msgstr "Voer winkel naam in"

#: inc/class-post-types.php:189
msgid "Zip"
msgstr "Postcode"

#: inc/class-templates.php:76
#, php-format
msgid "No template found for %s"
msgstr "Geen template gevonden voor %s"

#: inc/class-templates.php:77
#, php-format
msgid ""
"Make sure you call the %sget_template_details%s function with the correct "
"parameters."
msgstr "Roep de %sget_template_details%s functie aan met de juiste parameters."

#: inc/wpsl-functions.php:230
msgid "Show the store list below the map"
msgstr "Toon the locatie lijst onder de kaart"

#: inc/wpsl-functions.php:247
msgid "Monday"
msgstr "Maandag"

#: inc/wpsl-functions.php:248
msgid "Tuesday"
msgstr "Dinsdag"

#: inc/wpsl-functions.php:249
msgid "Wednesday"
msgstr "Woensdag"

#: inc/wpsl-functions.php:250
msgid "Thursday"
msgstr "Donderdag"

#: inc/wpsl-functions.php:251
msgid "Friday"
msgstr "Vrijdag"

#: inc/wpsl-functions.php:252
msgid "Saturday"
msgstr "Zaterdag"

#: inc/wpsl-functions.php:253
msgid "Sunday"
msgstr "Zondag"

#: inc/wpsl-functions.php:283
#, php-format
msgid "Mon %sTue %sWed %sThu %sFri %sSat Closed %sSun Closed"
msgstr "ma %sdi %swoe %sdo %svrij %szat gesloten %szo gesloten"

#: inc/wpsl-functions.php:299
msgid "Satellite"
msgstr "Satelliet"

#: inc/wpsl-functions.php:300
msgid "Hybrid"
msgstr "Hybrid"

#: inc/wpsl-functions.php:301
msgid "Terrain"
msgstr "Terrein"

#: inc/wpsl-functions.php:316
msgid "(city) (state) (zip code)"
msgstr "(stad) (provincie) (postcode)"

#: inc/wpsl-functions.php:317
msgid "(city), (state) (zip code)"
msgstr "(stad), (provincie), (postcode)"

#: inc/wpsl-functions.php:318
msgid "(city) (zip code)"
msgstr "(stad) (postcode)"

#: inc/wpsl-functions.php:319
msgid "(city), (zip code)"
msgstr "(stad), (postcode)"

#: inc/wpsl-functions.php:320
msgid "(zip code) (city) (state)"
msgstr "(postcode) (stad) (provincie)"

#: inc/wpsl-functions.php:321
msgid "(zip code) (city)"
msgstr "(postcode) (stad)"

#~ msgid ""
#~ "There's a problem with the provided %sbrowser key%s. %s You can read more "
#~ "about how to determine the exact issue, and how to solve it %shere%s."
#~ msgstr ""
#~ "Er is een probleem met de gebruikte %sbrowser sleutel%s. %s Je kan %shier"
#~ "%s meer lezen hoe het exacte probleem te achterhalen is, en hoe het kan "
#~ "worden opgelost."

#~ msgid ""
#~ "For this option to be available you first need to set a map region and "
#~ "restrict the results to the selected region. %s You can do this in the "
#~ "%sGoogle Maps API section%s."
#~ msgstr ""
#~ "Voordat deze optie gebruikt kan worden moet er eerst een kaart regio "
#~ "gekozen worden, en de 'Limiteer de geocode resultaten tot de "
#~ "geselecteerde map regio?' optie actief zijn. %s Dit kan in het %sGoogle "
#~ "Maps API%s gedeelte."

#~ msgid ""
#~ "The front base is set on the %spermalink settings%s page in the \"Custom "
#~ "structure\" field. %s If a front base is set ( for example /blog/ ) , "
#~ "then enabling this option will remove it from the store locator "
#~ "permalinks."
#~ msgstr ""
#~ "De front base kan je instellen op de %sPermalink instellingen%s pagina in "
#~ "het \"Aangepaste structuur\" veld. %s Als een front base is gebruikt "
#~ "( bijvoorbeeld /blog/ ) dan zal met deze optie het uit de store locator "
#~ "permalinks verwijderd worden."

#~ msgid ""
#~ "The front base is set on the %spermalink settings%s page in the \"Custom "
#~ "structure\" field. %s Enabling this option will remove it ( for example /"
#~ "blog/ ) from the store locator permalinks, but keep it for all others."
#~ msgstr ""
#~ "Je kan de front base instellen op de %sPermalink instellingen%s pagina in "
#~ "het \"Aangepaste structuur\" veld. %s Het activeren van deze optie laat "
#~ "de front base ( bijvoorbeeld /blog/ ) weg uit de store locator permalinks."

#~ msgid ""
#~ "The front base is set on the %spermalink settings%s page in the \"Custom "
#~ "structure\" field ( for example /blog/ ). %s Enabling this option will "
#~ "remove it from the store locator permalinks, but keep it for all others."
#~ msgstr ""
#~ "Je kan de font base instellen op de %spermalink instellingen%s pagina in "
#~ "het \"Aangepaste structuur\" veld ( bijvoorbeeld %s"

#~ msgid "%sError message: %s"
#~ msgstr "%sFout melding: %s"

#~ msgid "Cocos Islands"
#~ msgstr "Cocoseilanden"

#~ msgid "Congo"
#~ msgstr "Congo"

#~ msgid "Macedonia"
#~ msgstr "Macedonië"

#~ msgid "Myanmar"
#~ msgstr "Myanmar"

#~ msgid ""
#~ "Safari and Chrome %srequire%s a HTTPS connection before the Geolocation "
#~ "feature works."
#~ msgstr ""
#~ "Safari en Chrome %svereisen%s een HTTPS verbinding om de geolocatie optie "
#~ "te laten werken."

#~ msgid "Enable Google Maps Compatibility Mode?"
#~ msgstr "Activeer de Google Maps compatibility mode."

#~ msgid ""
#~ "A %sserver key%s allows you to monitor the usage of the Google Maps "
#~ "%sGeocoding API%s, and is required if you need to %spurchase%s additional "
#~ "quota."
#~ msgstr ""
#~ "Een %sserver sleutel%s maakt het mogelijk om het gebruik van de Google "
#~ "Maps %sGeocoding API%s in de gaten te houden, en is verplicht als je de "
#~ "%slimiet%s wil verhogen."

#~ msgid "Optional"
#~ msgstr "Optioneel"

#~ msgid ""
#~ "A %sbrowser key%s allows you to monitor the usage of the Google Maps "
#~ "%sJavaScript API%s."
#~ msgstr ""
#~ "Een %sbrowser key%s maakt het mogelijk om het gebruik van de Google "
#~ "%sJavaScript API%s in de gaten te houden."

#~ msgid "Stores"
#~ msgstr "winkels"

#~ msgid "All %s"
#~ msgstr "Alle %s"

#~ msgid "New %s"
#~ msgstr "Nieuwe %s"

#~ msgid "Add New %s"
#~ msgstr "Nieuwe %s"

#~ msgid "Edit %s"
#~ msgstr "Bewerk %s"

#~ msgid "View %s"
#~ msgstr "Bekijk %s"

#~ msgid "Search %s"
#~ msgstr "Zoek %s"

#~ msgid "No %s found"
#~ msgstr "Geen %s gevonden"

#~ msgid "No %s found in trash"
#~ msgstr "Geen %s gevonden in de prullenbak"

#~ msgid "Please try again later."
#~ msgstr "Probeer het later nog een keer."

#~ msgid ""
#~ "Before adding the [wpsl] shortcode to a page, please don't forget to "
#~ "define a %sstart point%s. %sDismiss%s"
#~ msgstr ""
#~ "Vergeet niet voordat je de [wpsl] shortcode op een pagina plaatst, om een "
#~ "%sstart locatie%s op te geven.  %sSluit%s"

#~ msgid "General Settings"
#~ msgstr "Instellingen"

#~ msgid "API key"
#~ msgstr "API sleutel"

#~ msgid ""
#~ "A valid %sAPI key%s allows you to monitor the API usage and is required "
#~ "if you need to purchase additional quota."
#~ msgstr ""
#~ "Een geldige %sAPI sleutel%s maakt het mogelijk om het gebruik van de API "
#~ "in de gaten te houden en is verplicht als je de API limiet wil verhogen."

#~ msgid "Show the category dropdown?"
#~ msgstr "Toon de categorie dropdown?"

#~ msgid ""
#~ "This places a \"More Info\" link below the address and will show the "
#~ "phone, fax, email, opening hours and description once the link is "
#~ "clicked. %s If you for example want the contact details to always be "
#~ "visible, then please follow the instructions on %sthis%s page."
#~ msgstr ""
#~ "Dit plaatst een \"Meer info\" link onder het adres, en toont zodra er op "
#~ "de link geklikt wordt het telefoon / fax numer, email, openingstijden en "
#~ "omschrijving.  %s Als je bijvoorbeeld de contact gegevens altijd wil "
#~ "tonen, volg dan de instructies op %sdeze%s pagina."

#~ msgid ""
#~ "This will bias the geocoding results towards the selected region. %s If "
#~ "no region is selected the bias is set to the United States."
#~ msgstr ""
#~ "Dit zorgt er voor dat de geocode resultaten uit de geselecteerde regio "
#~ "voorkeur krijgen over resultaten uit andere regio's . %s Als er geen "
#~ "regio is geselecteerd dan gaat de voorkeur uit naar de Verenigde Staten."

#~ msgid ""
#~ "If you use the [wpsl_map] shortcode outside a store page you need to set "
#~ "the ID attribute."
#~ msgstr ""
#~ "Als je de [wpsl_map] shortcode op een pagina gebruikt die geen winkel "
#~ "pagina is dan is de ID attribute verplicht."

#~ msgid "Show the pan controls?"
#~ msgstr "Toon de pan controls?"

#~ msgid "Zoom control style"
#~ msgstr "Zoom bediening stijl"

#~ msgid "Small"
#~ msgstr "klein"

#~ msgid "Large"
#~ msgstr "groot"

#~ msgid "If a store url exists, make the store name clickable?"
#~ msgstr "Als een winkel url bestaat, maak de winkel naam dan klikbaar?"

#~ msgid "Slug"
#~ msgstr "Structuur"

#, fuzzy
#~ msgid "Reset Map"
#~ msgstr "Herstel"

#, fuzzy
#~ msgid "Show My Location"
#~ msgstr "Locatie"

#~ msgid "Select store search template"
#~ msgstr "Selecteer template"

#~ msgid "Design"
#~ msgstr "Ontwerp"

#~ msgid "Position of the map controls"
#~ msgstr "Positie van de kaart bediening"

#~ msgid "API Settings"
#~ msgstr "API Instellingen"

#~ msgid "Design Settings"
#~ msgstr "Design instellingen"

#~ msgid "Update Settings"
#~ msgstr "Instellingen bijwerken"

#~ msgid "Set Store Image"
#~ msgstr "Plaats winkel afbeelding"

#~ msgid "Upload"
#~ msgstr "Upload"

#~ msgid "to"
#~ msgstr "tot"

#~ msgid "Road map"
#~ msgstr "Wegenkaart"

#~ msgid "Add Period"
#~ msgstr "Periode toevoegen"

#~ msgid "Manage Stores"
#~ msgstr "Beheer Locaties"

#~ msgid "Add Store"
#~ msgstr "Locatie Toevoegen"

#~ msgid "FAQ"
#~ msgstr "FAQ"

#~ msgid "There was a problem updating the store details, please try again."
#~ msgstr ""
#~ "De locatie data kon niet worden gewijzigd, probeer het nog een keer."

#~ msgid "There was a problem saving the new store details, please try again."
#~ msgstr ""
#~ "De locatie data kon niet worden opgeslagen, probeer het nog een keer."

#~ msgid "Store succesfully added."
#~ msgstr "Locatie succesvol toegevoegd."

#~ msgid "Current Stores"
#~ msgstr "Huidige Locaties"

#~ msgid ""
#~ "One of the label fields was left empty, the default value for that field "
#~ "has been restored."
#~ msgstr "Een van de label velden was leeg, de standaard waarde is hersteld."

#~ msgid "Dismiss"
#~ msgstr "Sluiten"

#~ msgid "Active"
#~ msgstr "Actief"

#~ msgid "Inactive"
#~ msgstr "Niet actief"

#~ msgid "Edit"
#~ msgstr "Bewerk"

#~ msgid "Delete"
#~ msgstr "Verwijder"

#~ msgid "ID"
#~ msgstr "ID"

#~ msgid "Thumbnail"
#~ msgstr "Afbeelding"

#~ msgid "Name"
#~ msgstr "Naam"

#~ msgid "Status"
#~ msgstr "Status"

#~ msgid "Actions"
#~ msgstr "Acties"

#~ msgid "Activate"
#~ msgstr "Activeer"

#~ msgid "Deactivate"
#~ msgstr "Deactiveer"

#~ msgid "deactivated"
#~ msgstr "gedeactiveerd"

#~ msgid "deactivating"
#~ msgstr "gedeactiveerd"

#~ msgid "activated"
#~ msgstr "geactiveerd"

#~ msgid "activating"
#~ msgstr "activeren"

#~ msgid "There was a problem %s the store(s), please try again."
#~ msgstr ""
#~ "Er is een probleem met het %s van de locatie(s), probeer het nog een keer."

#~ msgid "Store(s) successfully %s."
#~ msgstr "Locatie(s) succesvol %s."

#~ msgid "There was a problem removing the store(s), please try again."
#~ msgstr ""
#~ "De locatie(s) konden niet worden verwijderd, probeer het nog een keer."

#~ msgid "Store(s) successfully removed."
#~ msgstr "Locatie(s) succesvol verwijderd."

#~ msgid "Are you sure you want to delete this store?"
#~ msgstr "Weet je zeker dat je deze locatie wilt verwijderen?"

#~ msgid "Cancel"
#~ msgstr "Annuleer"

#~ msgid "Address:"
#~ msgstr "Adres:"

#~ msgid "City:"
#~ msgstr "Stad:"

#~ msgid "State / Province:"
#~ msgstr "Provincie:"

#~ msgid "Extra details"
#~ msgstr "Extra informatie"

#~ msgid "Phone:"
#~ msgstr "Telefoon:"

#~ msgid "Fax:"
#~ msgstr "Fax:"

#~ msgid "Description:"
#~ msgstr "Omschrijving:"

#~ msgid "Thumbnail:"
#~ msgstr "Afbeelding:"

#~ msgid "Change thumbnail"
#~ msgstr "Wijzig afbeelding"

#~ msgid "Remove"
#~ msgstr "Verwijder"

#~ msgid "Status:"
#~ msgstr "Status:"

#~ msgid "active"
#~ msgstr "actief"

#~ msgid "inactive"
#~ msgstr "niet actief"

#~ msgid "How do I show the store locator on my page?"
#~ msgstr "Hoe plaatst ik de store locator op een pagina?"

#~ msgid ""
#~ "Add this shortcode <code>[wpsl]</code> to the page where you want to show "
#~ "the store locator."
#~ msgstr ""
#~ "Voeg deze shortcode <code>[wpsl]</code> toe aan de pagina waar je de "
#~ "store locator wil tonen."

#~ msgid ""
#~ "The map doesn't display properly. It's either broken in half or doesn't "
#~ "load at all."
#~ msgstr ""
#~ "De kaart is niet goed zichtbaar. Hij wordt niet geladen, of is maar voor "
#~ "de helft zichtbaar."

#~ msgid ""
#~ "Make sure you have defined a start point for the map under settings -> "
#~ "map settings."
#~ msgstr ""
#~ "Zorg dat er een start locatie is opgegeven op de instellingen pagina -> "
#~ "kaart instellingen."

#~ msgid ""
#~ "I get an error saying the \"sensor\" parameter specified in the request "
#~ "must be set to either \"true\" or \"false\"."
#~ msgstr ""
#~ "Ik krijg de volgende foutmelding, the \"sensor\" parameter specified in "
#~ "the request must be set to either \"true\" or \"false\"."

#~ msgid ""
#~ "Make sure you don't have any security plugins, or custom functions "
#~ "running that strip away version numbers from file paths."
#~ msgstr ""
#~ "Zorg ervoor dat je geen beveiligings plugins, of custom functies hebt die "
#~ "versie nummers van de bestands paden weghalen."

#~ msgid "The store locator doesn't load, it only shows the number 1?"
#~ msgstr "De store locator laadt niet, het toont alleen een '1'?"

#~ msgid ""
#~ "This is most likely caused by your theme using ajax navigation ( the "
#~ "loading of content without reloading the page ), or a conflict with "
#~ "another plugin. Try to disable the ajax navigation in the theme settings, "
#~ "or deactivate the plugin that enables it to see if that solves the "
#~ "problem."
#~ msgstr ""
#~ "Dit wordt waarschijnlijk veroorzaakt doordat je theme ajax navigatie "
#~ "gebruikt ( het laden van nieuwe content zonder dat de pagina zelf opnieuw "
#~ "geladen wordt ), of door een conflict met een andere plugin. Probeer de "
#~ "ajax navigatie in je theme uit te zetten, of deactiveer de plugin die de "
#~ "functionaliteit toevoegd om te kijken ofdat dat het probleem oplost."

#~ msgid ""
#~ "If you don't use ajax navigation, but do see the number 1 it's probably a "
#~ "conflict with another plugin. Try to disable the plugins one by one to "
#~ "see if one of them is causing a conflict."
#~ msgstr ""
#~ "Als je geen ajax navigatie gebruikt, maar wel het getal '1' ziet dan is "
#~ "het waarschijnlijk een conflict met een andere plugin. Probeer alle "
#~ "plugins een voor een te deactiveren om te kijken welke plugin het "
#~ "probleem veroorzaakt."

#~ msgid ""
#~ "If you find a plugin or theme that causes a conflict, please report it on "
#~ "the <a href=\"%s\">support page</a>."
#~ msgstr ""
#~ "Als je een plugin of theme tegenkomt dat een probleem veroorzaakt, meld "
#~ "het dan op de <a href=\"%s\">support pagina</a>."

#~ msgid "Why does it show the location I searched for in the wrong country?"
#~ msgstr "Waarom toont het de locatie waar ik op zocht in het verkeerde land?"

#~ msgid ""
#~ "Some location names exist in more then one country, and Google will guess "
#~ "which one you mean. This can be fixed by setting the correct \"Map Region"
#~ "\" on the settings page -> \"API Settings\"."
#~ msgstr ""
#~ "Sommige locatie namen komen in meerdere landen voor, en daardoor kan het "
#~ "gebeuren dat Google de locatie in het verkeerde land kiest. Dit kan "
#~ "opgelost worden door de juiste \"Kaart regio\" in te stellen op de "
#~ "instellingen pagina onder \"API Instellingen\"."

#~ msgid "Zoom level:"
#~ msgstr "Zoom niveau:"

#~ msgid ""
#~ "* This is the text that is placed before the search input and radius "
#~ "dropdown"
#~ msgstr ""
#~ "* Dit is de tekst die voor het zoekveld en radius dropdown geplaatst "
#~ "wordt."

#~ msgid "Default country that will be used on the \"Add Store\" page."
#~ msgstr ""
#~ "Het land dat standaard gebruikt wordt op de \"Locatie Toevoegen\" pagina."

#~ msgid "Search radius:"
#~ msgstr "Zoek radius:"

#~ msgid "No results found:"
#~ msgstr "Geen locaties gevonden:"

#~ msgid "Search:"
#~ msgstr "Zoek:"

#~ msgid "Results:"
#~ msgstr "Resultaten:"

#~ msgid "More info:"
#~ msgstr "Meer info:"

#~ msgid "Hours:"
#~ msgstr "Openingstijden:"

#~ msgid "Start location:"
#~ msgstr "Start locatie:"

#~ msgid "Back:"
#~ msgstr "Terug:"

#~ msgid "Reset:"
#~ msgstr "Herstel:"

#~ msgid "Street view:"
#~ msgstr "Street view:"

#~ msgid "Zoom here:"
#~ msgstr "Zoom hier:"
languages/wpsl-es_ES.mo000064400000145551151327220640011045 0ustar00��p�G'84�94��4�l5@6X6r6�6�6�6�6�6�6��6��7$8
<8J8a8h8p8�8	�8�8�8�8�8�8
�8p�8U9�h9H+:t:�:�:�:�:
�:�:�:�:	�:�:�:�:	;	);3;@;;F|;
�;�;�;�;
�;�;�;��;�<===="=(=0=7=?=V=_=
s=�=�=�=�=�=�=	�=�=�=�=>>>.!>
P>[>q>y>�>�>�>
�>�>�>�>??
?$?*?0?E?[?l?#q?N�?�?�?�?
@"@+@8@@@L@]@
j@u@}@�@�@�@�@�@M�@AA#A2AAAHAMA`AhA xA�A
�A�A
�A�A
�A�A�ABBB4B:B
BBMBaBgBsByB�B�B�B�B�B	C�%CDDD5DLD^DfDlDtD/}DG�D �D
E$E*E.E3E<EIEQEYE`E
gEuE�E�E�E�E�E�E
�E3�EFF F(F7F	=FGFWF^F	dFnF
vF�F	�F�F�F
�F�F�F�F�F�F'�F(G7GOGcGiG	rG|G�G	�G�G�G�GQ�G9Hb;HG�IK�Ih2J�JB�K��L��M�ON<�Ng
O^uO\�Ol1P�P�P�P	�P
�P�PQQQQ'Q3Q:QBQHQPQVQ_QfQmQ
uQ�Q�Q�Q�Q�Q
�Q�Q�Q�Q�Q�Q�Q�Q�Q�Q�Q�Q
R
R	$R
.R9RUR$^R	�R
�R�R�R�R
�R2�R4�R0S	7S	AS	KSUSZS`SdS
qS	|S�S!�S�S�S�S
�S
�S	�S�ST%T?TNTVT
]ThT5pT�T�T�T
�T
�T	�T�TY�T
?UJUZUbUhUnUzU
�U	�U�U�U	�U�U�U�U�U�UV%V:6VqVvV�V�V�V	�V�V�V�V7�V&W
BWPWd`W�W�W�W�W	XXX$X-XCX	ZXdXiXuX{X.�X��X�Y��YUZ\ZcZ
lZwZ�Z�Z�Z
�Z�Z�Z�Z4�Z+[:1[l[t[|[�[�[�[�[�[�[�[�[�[ �[\
\	\\%\2\?\F\
^\l\�\'�\
�\�\�\]5]<G]�]�]�]�]�]�]�]
�]�]^(^
1^.<^+k^�^
�^�^�^ �^!_;_Z_8g_	�_�_�_�_�_	�_�_�_X�_'K`s`(�`�`�`�`�`	�`�`�`�`aa!a'a8a
GaUa
bapa�a�a	�a�a�a�ab"b7b+Db
pb{b�b�b�b�b	�b�b�b�b�b�b�bcc
c)c/c8c<cCcKcTcYcObc2�c6�c/dHLdy�d]eMme4�eo�eD`f&�f��fmg)�g"�g��g�_h2�hKi4ei��iM<k}�kblLkln�l�'m6�m��m�snho�jo�1pO�p	qqq#q+q1q7qKq\qdqlqsq{q�q�q�q�q	�q�q�q
�q�q	r
r*r@r
Pr[rcr	przr
�r�r
�r�r�r#�r�r
s	ss6s^Es2�s�s
�s�sLtCOtE�tw�t�Qu4v1SvO�va�vu7w
�w�w�w�w�w�w	�w�wxx
xx x�/x��z�^{�5|L�|" }C}#]}�}�}"�}�}�}��}��~\|�
���
������ �6��H�
ڀ��^���/�N�V�]�
e�p�
����	��������!��	ނ�e�CV���������
��ʃӃ�ك�p������$�*�2�9�A�V�_�x���)����х�����
���#�+�6:�
q�|���
������Ԇ�
��0�@�E�\�y����������9‡L��I�Y�a�s�����������
ʈ
Ո�������� "�eC�������lj׉މ����!�	>�H�T�j�~�����������!ӊ	����
��1�8�D�J�%d�!����̋'�.��@�6�>�T�&l�����������<čV�X�g�s�z�~�����	��
������ŽҎ�����!�
4�2B�u�}�������	����ŏ̏ӏߏ	��	���	�
��'�.�5�L�3S�7��#��%�	��	�"�2�8�A�J�S�t\�^ё�0�NœZ��o���������t��E�Qșq�m��k��vf�-ݛ�&�	,�	6�@�V�v�|�����������������Ĝ˜Ԝܜ�������

�	�"�'�/�7�>�	F�P�W�_� e���
������3��
�)�� �
)�4�A�G�
Y�Dd�E�������	����!�1�B�Q�4^���
����	��
��	ʟԟ"�9
�G�]�e�
m�x�:����àɠ
Ҡ
ݠ�	��}�
��������������͡ݡ'�
�	"�,�3�;�@�#]�����5�����
��3�;�C� S�t�@z�%���������&��	ؤ�	����
��*�?�Q�	W�	a�k�8z����(�����w����
������ħݧ����"�9A�{�S��
ۨ��������!�(�5�G�T�q�
w�	������������ة+��0/�`�s�����N��P�\�n�����������ū)׫,�.�
6�JA�K��(ج�(�8?�5x�+��*ڭ�G�Z�c�p�
y�	��������l��3�
O�!Z�
|�������	����ȯٯ�����,�A�T�e�|�!��$��۰� �",�O�&a���.��ȱױ������'�.�4�:�@�W�n�v�~�������������
��	DzhѲ9:�=t�:��V��D��ʴhL�A�����G��0Ӷ��'��/ܷ<��I���G|�dĹG)��q�c����q
�Z�ڽ�Z�>���8���n������k������'�-�:�L�]�d�k�t�
z���������	�����������"�@*�k�������	����
����
������)�9�
L�
Z�e���r��A�"J�
m�{�\��H��`'�����&�;!�,]�U��k��pL�
����������"���-�=�@�C�T�\����#;Ev���5�Q��W��p6'��
�V���-GN��F7��?�0b)Y&�.���+@�7��G��#W��)��GB��$B^	��(i.k�qS�=����9D��i���tQA[ )��6]����mO
���������L��'�H�n�dC�$��f3��"c���d�W�ko�@e\Q� sg�]��_+��E�ApI��%#��YXKPN�ym�[�/UaH�ec�bL�?D�'�X�a�9�]�4R�2��<l��l&E;���=���\<moaz�1:�@�i�e��tR1A3�I�uPK�x2�K%:fj=��&N��B?7��Yz-O�����n�4gC!�5q�
v�
9}-1L�Z�MJZ�����f�"����r8�T��_4�3V!�r�� R�c�h�8�����������	�,^�F�|�0�^_��j�8�,��u`��O:D
j
>�%�J���;�"�����s��|T6*�{p��C`�bX${�n(�~d�h�0���5~y��>ko/	�>U[���J��2F�*�w��P��(lM��M,��T�����������\��g��x<��.+��/�*�S`SU}�!Zwh���VHI���%sError message: %s %s Check if your issue is covered in the %stroubleshooting%s section, if not, then please open a %ssupport ticket%s.%sError message: %s. %s Make sure the IP address mentioned in the error matches with the IP set as the %sreferrer%s for the server API key in the %sGoogle API Console%s.%sRequired field.%s %s If auto-locating the user is disabled or fails, the center of the provided city or country will be used as the initial starting point for the user.%sWarning!%s %sWPML%s, or a plugin using the WPML API is active.(city) (state) (zip code)(city) (zip code)(city), (state) (zip code)(city), (zip code)(zip code) (city)(zip code) (city) (state)12 Hours24 HoursA %sbrowser key%s allows you to monitor the usage of the Google Maps %sJavaScript API%s. %s %sRequired%s for %sapplications%s created after June 22, 2016.A %sserver key%s allows you to monitor the usage of the Google Maps %sGeocoding API%s. %s %sRequired%s for %sapplications%s created after June 22, 2016.API usage limit reachedAdd New StoreAdd New Store CategoryAdd-OnAdd-OnsAdditional InformationAddressAddress 2Address formatAfghanistanAlbaniaAlgeriaAll Store CategoriesAll StoresAll the store locations are now converted to custom post types. %s You can view them on the %sAll Stores%s page.Already Installed.Although the location data is cached after the first load, a lower number will result in the map being more responsive. %s If this field is left empty or set to 0, then all locations are loaded.Always show the contact details below the address in the search results?American SamoaAn unknown error occurred.AndorraAngolaAnguillaAntarcticaAntigua and BarbudaAnyArabicArgentinaArmeniaArubaAscension IslandAttempt to auto-locate the userAustraliaAustriaAuto adjust the zoom level to make sure all markers are visible?Automatically restrict the returned results to one or more categories?AzerbaijanBackBahamasBahrainBangladeshBarbadosBasqueBecause you updated WP Store Locator from version 1.x, the %s current store locations need to be %sconverted%s to custom post types.Before adding the [wpsl] shortcode to a page, please don't forget to define a start point on the %ssettings%s page. %sDismiss%sBelarusBelgiumBelizeBengaliBeninBermudaBhutanBoliviaBosnia and HerzegovinaBotswanaBounces up and downBouvet IslandBrazilBritish Indian Ocean TerritoryBritish Virgin IslandsBrowser keyBruneiBulgariaBulgarianBurkina FasoBurundiCambodiaCameroonCanadaCanary IslandsCannot determine the address at this location.Cape VerdeCaribbean NetherlandsCatalanCategoryCategory filterCategory filter typeCategory first itemCategory slugCayman IslandsCentral African RepublicCeuta and MelillaChadCheckbox columnsCheckboxesChileChinaChinese (Simplified)Chinese (Traditional)Christmas IslandCityClear store locator transient cacheClicking this link will make the map zoom in to the %s max auto zoom level %s.Clipperton IslandClosedCluster sizeCocos (Keeling) IslandsColombiaComing soon!ComorosCongo (DRC)Congo (Republic)Cook IslandsCosta RicaCountryCroatiaCroatianCubaCuraçaoCustom field deleted.Custom field updated.Custom map styles only work if the map type is set to "Roadmap" or "Terrain".CyprusCzechCzech RepublicCôte d'IvoireDanishDaysDeactivate LicenseDefaultDefault countryDemocratic Republic of the CongoDenmarkDirectionsDismiss this notice.Distance unitDjiboutiDocumentationDoes not respondDominicaDominican RepublicDropdownDropdowns (recommended)DutchEcuadorEdit StoreEdit Store CategoryEgyptEl SalvadorEmailEnable autocomplete?Enable category filters?Enable compatibility mode?Enable marker clusters?Enable permalink?Enable scroll wheel zooming?Enable store locator debug?Enabling this option can sometimes result in a small delay in the opening of the info window. %s This happens because an API request is made to Google Maps to check if street view is available for the current location.EnglishEnglish (Australian)English (Great Britain)Enter store title hereEquatorial GuineaEritreaErrorEstoniaEthiopiaFailed to load the add-on list from the server.Failed to publish the store. Please fill in the required store details.Falkland Islands(Islas Malvinas)Faroe IslandsFarsiFaxFijiFilipinoFilter type:FinlandFinnishFranceFrenchFrench GuianaFrench PolynesiaFrench Southern TerritoriesFridayGabonGalicianGambiaGeneral OptionsGeneral errorGeocode was not successful for the following reasonGeorgiaGermanGermanyGet directionsGhanaGibraltarGoogle Maps APIGreeceGreekGreenlandGrenadaGuadeloupeGuamGuatemalaGuernseyGuineaGuinea-BissauGujaratiGuyanaHaitiHeard and McDonald IslandsHebrewHide the country in the search results?Hide the distance in the search results?Hide the opening hours?Hide the scrollbar?HindiHondurasHong KongHour formatHoursHungarianHungaryHybridIcelandIf %spermalinks%s are enabled, the store name will always link to the store page.If a user hovers over the search results the store markerIf marker clusters are enabled this option will not work as expected as long as the markers are clustered. %s The bouncing of the marker won't be visible at all unless a user zooms in far enough for the marker cluster to change back in to individual markers. %s The info window will open as expected, but it won't be clear to which marker it belongs to. If no map language is selected the browser's prefered language is used.If nothing it set, then the start point from the %ssettings%s page is used.If street view is available for the current location, then show a "Street view" link in the info window?If the %sbrowser console%s shows the error below, then enabling this option should fix it. %s %sYou have included the Google Maps API multiple times on this page. This may cause unexpected errors.%s %s This error can in some situations break the store locator map.If the %sgeocoding%s API finds more relevant results outside of the set map region ( some location names exist in multiple regions ), the user will likely see a "No results found" message. %s To rule this out you can restrict the results to the set map region. %s You can modify the used restrictions with %sthis%s filter.If the default style is disabled the %sInfoBox%s library will be used instead. %s This enables you to easily change the look and feel of the info window through the .wpsl-infobox css class.If the store locator is not placed at the top of the page, enabling this feature can result in the page scrolling down. %s %sThis option is disabled on mobile devices.%sIf this zoom level is reached or exceeded, then all markers are moved out of the marker cluster and shown as individual markers.If you like this plugin please leave us a %s5 star%s rating.If you like to write the style code yourself, then you can find the documentation from Google %shere%s.If you use the [wpsl_address] shortcode outside a store page you need to set the ID attribute.If you use the [wpsl_hours] shortcode outside a store page you need to set the ID attribute.If you use the [wpsl_map] shortcode outside a store page, then you need to set the ID or category attribute.In the info window on the mapIn the store listingsIndiaIndonesiaIndonesianInitial zoom levelInsert Store LocatorIranIraqIrelandIsle of ManIsraelItalianItalyJamaicaJapanJapaneseJerseyJordanKannadaKazakhstanKenyaKiribatiKoreanKosovoKuwaitKyrgyzstanLabelsLaosLatitudeLatviaLatvianLebanonLeftLesothoLiberiaLibyaLicense Expiry DateLicense KeyLiechtensteinLithuaniaLithuanianLoad locations on page loadLocationLocation information is unavailable.LongitudeLuxembourgM j, Y @ G:iMacauMacedonia (FYROM)MadagascarMake the phone number clickable on mobile devices?Make the store name clickable if a store URL exists?MalawiMalayalamMalaysia Maldives MaliMaltaMapMap languageMap regionMap styleMap typeMap type for the location previewMarathiMarkersMarshall IslandsMartiniqueMauritaniaMauritiusMax auto zoom levelMax search resultsMax width for the info window contentMax zoom levelMayotteMexicoMicronesiaMoldovaMon %sTue %sWed %sThu %sFri %sSat Closed %sSun ClosedMonacoMondayMongoliaMontenegroMontserratMore infoMoroccoMost modern browsers %srequire%s a HTTPS connection before the Geolocation feature works.MozambiqueMyanmar (Burma)NamibiaNauruNepalNetherlandsNetherlands AntillesNew CaledoniaNew StoreNew Store Category NameNew ZealandNicaraguaNigerNigeriaNiueNo Stores foundNo Stores found in trashNo directions foundNo results foundNo route could be found between the origin and destinationNoneNorfolk IslandNorth KoreaNorthern Mariana IslandsNorwayNorwegianNorwegian NynorskNumber of locations to showOmanOn page load move the mouse cursor to the search field?Open links in a new window?Opening HoursOpening PeriodsOpening hours created in version 1.x %sare not%s automatically converted to the new dropdown format.Opening hours formatOpening hours input typePakistanPalauPalestinePanamaPapua New GuineaParaguayParent Store CategoryParent Store Category:PermalinkPeruPhilippinesPhonePitcairn IslandsPlease fill in all the required store details.Please provide the name of a city or country that can be used as a starting point under "Map Settings". %s This will only be used if auto-locating the user fails, or the option itself is disabled.Please try again later!Please use the "String Translations" section in the used multilingual plugin to change the labels. Changing them here will have no effect as long as the multilingual plugin remains active.PolandPolishPortugalPortuguesePortuguese (Brazil)Portuguese (Portugal)Preview LocationPreview Map StylePreview storePuerto RicoQatarQuery limit errorRecommended for maps with a large amount of markers.ResetRestrict the geocoding results to the selected map region?ResultsReunionRightRoadmapRomaniaRomanianRussiaRussianRwandaSaint HelenaSaint Kitts and NevisSaint LuciaSaint Vincent and the GrenadinesSamoaSan MarinoSatelliteSaturdaySaudi ArabiaSave ChangesSearchSearch Store CategoriesSearch StoresSearch and radius label widthSearch field widthSearch provided by %sWP Store Locator%sSearch radiusSearch radius optionsSearching (preloader text)Searching...Security check failed, reload the page and try again.Security check failed. Please reload the page and try again.Select categorySelect the used templateSelect your languageSelect your regionSenegalSerbiaSerbianServer keySet a selected category?Set selected checkboxesSettingsSeychellesShow a "More info" link in the store listings?Show a "Zoom here" link in the info window?Show a reset map button?Show credits?Show the map type control?Show the max results dropdown?Show the search radius dropdown?Show the store list below the mapShow the street view controls?Sierra LeoneSign up for the latest plugin updates and announcements.SingaporeSint MaartenSlovakSlovakiaSloveniaSlovenianSolomon IslandsSomaliaSomething went wrong connecting to the Google Geocode API: %s %s Please try again later.Something went wrong, please try again!South AfricaSouth Georgia and South Sandwich IslandsSouth KoreaSouth SudanSpainSpanishSri LankaStart ConvertingStart locationStart location markerStart pointStateStoreStore CategoriesStore CategoryStore DetailsStore EditorStore LocatorStore Locator ManagerStore Locator heightStore Locator templateStore MapStore draft updated.Store location markerStore locations to convert:Store published.Store restored to revision from %sStore saved.Store scheduled for: <strong>%1$s</strong>.Store slugStore submitted.Store updated.Street viewSudanSundaySwazilandSwedenSwedishSwitzerlandSyriaSão Tomé & PríncipeSão Tomé and PríncipeTagalogTaiwanTajikistanTamilTanzaniaTelTeluguTerrainTextareaThaiThailandThe %s license failed to deactivate, please try again later or contact support!The %s license key does not belong to this add-on.The %s license key does not have any activations left.The %s license key is expired. Please renew it.The Google Geocode API reported the following problem: error %s %s %s %sThe Google Geocode API reported the following problem: error %s %s %s Please contact %ssupport%s if the problem persists.The Google Geocode API reported the following problem: error %s %s %s Please try again later.The Google Geocoding API failed to return valid data, please try again later.The Google Geocoding API returned REQUEST_DENIED. %sThe Google Geocoding API returned no results for the supplied address. Please change the address and try again.The application does not have permission to use the Geolocation API.The code for the map style is invalid.The default country and opening hours are only used when a new store is created. So changing the default values will have no effect on existing store locations.The default opening hoursThe default value is set between the [ ].The geolocation request timed out.The grid size of a cluster in pixels. %s A larger number will result in a lower amount of clusters and also make the algorithm run faster.The map preview is based on the provided address, city and country details. %s It will ignore any custom latitude or longitude values.The map preview requires all the location details.The max results field cannot be empty, the default value has been restored.The permalink slugs %smust be unique%s on your site.The script converting the locations timed out. %s You can click the "Start Converting" button again to restart the script. %s If there are thousands of store locations left to convert and you keep seeing this message, then you can try to contact your host and ask if they can increase the maximum execution time. %s The plugin tried to disable the maximum execution time, but if you are reading this then that failed.The search radius field cannot be empty, the default value has been restored.The selected template is used with the [wpsl] shortcode. %s You can add a custom template with the %swpsl_templates%s filter.There is a new version of %1$s available. %2$sView version %3$s details%4$s or %5$supdate now%6$s.There is a new version of %1$s available. %2$sView version %3$s details%4$s.There was a problem activating the license key for the %s, please try again or contact support. Error code: %sThere's a problem with the provided %sbrowser key%s. %s You can read more about how to determine the exact issue, and how to solve it %shere%s.There's a problem with the provided %sserver key%s. %sThis disables the WPSL transient cache. %sThe transient cache is only used if the %sLoad locations on page load%s option is enabled.This places a "More Info" link below the address and will show the phone, fax, email, opening hours and description once the link is clicked.This runs after a search is made, and makes sure all the returned locations are visible in the viewport.This value sets the zoom level for the "Zoom here" link in the info window. %s It is also used to limit the zooming when the viewport of the map is changed to make all the markers fit on the screen.This will bias the %sgeocoding%s results towards the selected region. %s If no region is selected the bias is set to the United States.This will place a "Search provided by WP Store Locator" backlink below the map.ThursdayTimor-LesteTogoTokelauTongaToolsTrinidad and TobagoTristan da CunhaTuesdayTunisiaTurkeyTurkishTurkmenistanTurks and Caicos IslandsTuvaluUgandaUkraineUkrainianUnited Arab EmiratesUnited KingdomUnited StatesUpdate Store CategoryUrlUruguayUse the default style for the info window?User ExperienceUzbekistanVanuatuVatican CityVenezuelaVietnamVietnameseView StoresView storeWP Store LocatorWP Store Locator Add-OnsWP Store Locator Transients ClearedWPSL transientsWallis FutunaWednesdayWelcome to WP Store LocatorWestern SaharaWhen a user clicks on "Directions", open a new window, and show the route on google.com/maps ?Where do you want to show the "More info" details?Will open the info windowWorld viewYemenYou can add custom address formats with the %swpsl_address_formats%s filter.You can drag the marker to adjust the exact location of the marker.You can fix this by making sure the CSV file uses %sUTF-8 encoding%s.You can raise the %susage limit%s by obtaining an API %skey%s, and fill in the "API key" field at the top of this page.You can use existing map styles from %sSnazzy Maps%s or %sMap Stylr%s and paste it in the textarea below, or you can generate a custom map style through the %sMap Style Editor%s or %sStyled Maps Wizard%s.You do not have permission to install plugin updatesYou do not have permission to perform this actionYou have reached the daily allowed geocoding limit, you can read more %shere%s.You need to create %sAPI keys%s for Google Maps before you can use the store locator! %sDismiss%sYou need to provide the details for either the address, city, state or country before the API can return coordinates.Your locationZambiaZimbabweZipZip CodeZoom control positionZoom hereinfo windowkmmistore-categorystoresÅland IslandsProject-Id-Version: WP Store Locator v2.2.10
Report-Msgid-Bugs-To: 
POT-Creation-Date: 2017-12-01 13:23+0700
PO-Revision-Date: 2017-12-01 09:40-0600
Last-Translator: Jaime Smeke <hola@untaljai.me>
Language-Team: Jaime Smeke <hola@untaljai.me>
Language: es
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Plural-Forms: nplurals=2; plural=(n != 1);
X-Generator: Poedit 2.0.4
X-Poedit-SourceCharset: UTF-8
X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2
X-Poedit-Basepath: ..
X-Textdomain-Support: yes
X-Poedit-SearchPath-0: .
%sMensaje de error: %s %s Revisa si tu problema está cubierto en la sección de %ssolución de errores%s, si no, por favor abre un %sticket de soporte%s.%sMensaje de error: %s %s Asegúrate de que la dirección IP mencionada en el error sea la misma que la dirección IP establecida como %sreferrer%s para la Llave API del servidor en la %sConsola de API de Google%s.%sCampo requerido.%s %s Si la autolocalización del usuario falla, el centro de la ciudad o país establecido se usará como punto de inicio para el usuario.%s¡Advertencia!%s %sWPML%s, o un plugin usando el API de WPML está activo.(ciudad) (estado) (código postal)(ciudad) (código postal)(ciudad), (estado) (código postal)(ciudad), (código postal)(código postal) (ciudad)(código postal) (ciudad) (estado)12 horas24 horasUna %sclave de navegador%s te permite monitorear el uso del %sAPI de Geolocalización%s de Google Maps. %s %sRequerido%s para %saplicaciones%s creadas después del 22 de junio de 2016.Una %sclave de servidor%s te permite monitorear el uso del %sAPI de Geolocalización%s de Google Maps. %s %sRequerido%s para %saplicaciones%s creadas después del 22 de junio de 2016.Límite de uso de API alcanzadoAñadir TiendaAñadir categoría de tiendaExtensiónExtensionesInformación adicionalDirecciónDirección 2Formato de direcciónAfganistánAlbaniaArgeliaTodas las categoríasTodas las tiendasTodas las ubicaciones de tiendas han sido convertidas a tipos de entrada personalizados. %s Puedes verlos en la página de %sTodas las tiendas%s.Ya instalado.Aunque los datos de ubicación se guardan en caché tras la primer carga, un número más bajo resultará en un mapa más responsivo. %s Si este campo se queda vacío o está en 0 se cargarán todas las ubicaciones.¿Siempre mostrar los datos de contacto abajo de la dirección en los resultados de búsqueda?Samoa AmericanaOcurrió un error desconocido.AndorraAngolaAnguilaAntártidaAntigua y BarbudaCualquieraÁrabeArgentinaArmeniaArubaIsla AscensiónIntentar autolocalizar al usuarioAustraliaAustria¿Ajustar automáticamente el nivel de zoom para asegurarse que todos los marcadores estén visibles?¿Limitar automáticamente los resultados a una o más categorías?AzerbaiyánRegresarBahamasBahrainBangladeshBarbadosVascoAl actualizar WP Store Locutor de la versión 1.x, las %s ubicaciones de tiendas actuales deben ser %sconvertidas%s a tipos de entrada personalizados.Por favor no olvides definir un punto de inicio en la página de %sajustes%s antes de añadir el shortcode de [wpsl] a una página. %sCerrar%sBielorrusiaBélgicaBeliceBengalíBeninBermudaButánBoliviaBosnia y HerzegovinaBotswanaRebota de arriba a abajoIsla BouvetBrasilTerritorio del Océano Índico BritánicoIslas Vírgenes BritánicasClave de navegadorBruneiBulgariaBúlgaroBurkina FasoBurundiCamboyaCamerúnCanadáIslas CanariasImposible determinar la dirección en esta ubicación.Cabo VerdeCaribe HolandésCatalánCategoríaFiltro por categoríaTipo de filtro de categoríaPrimer artículo de categoríaSlug de categoríaIslas CaimánRepública Central AfricanaCeuta y MelillaChadColumnas de selecciónCaja de selección múltipleChileChinaChino (Simplificado)Chino (Tradicional)Isla NavidadCiudadBorrar el caché de transients del Localizador de tiendasHacer click aquí hará que el mapa haga zoom al %s nivel máximo de zoom%s.Isla ClippertonCerradoTamaño del grupoIslas Cocos (Keeling)Colombia¡Próximamente!ComorosCongo (RDC)Congo (República)Islas CookCosta RicaPaísCroaciaCroataCubaCuraçaoCampo personalizado eliminado.Campo personalizado actualizado.Los estilos de mapa personalizados solo funcionan en los tipos de mapa "Mapa de caminos" o "Terreno".ChipreChecoRepública ChecaCosta de MarfilDanésDíasDesactivar licenciaPredeterminadoPaís predeterminadoRepública Democrática del CongoDinamarcaDireccionesDescartar este aviso.Unidad de distanciaDjiboutiDocumentaciónNo respondeDominicaRepública DominicanaMenú desplegableMenús desplegables (recomendado)HolandésEcuadorEditar TiendaEditar categoría de tiendaEgiptoEl SalvadorEmail¿Permitir autocompletar?¿Activar los filtros por categoría?¿Activar modo de compatibilidad?¿Activar marcadores agrupados?¿Activar enlace permanente?¿Activar zoom con la rueda del ratón?¿Activar debugging de Localizador de tiendas?Activar esta opción en ocasiones puede resultar en una pequeña demora al abrir la ventana de información. %s Esto pasa porque la petición de API se hace a Google Maps para checar si la vista de calle está disponible en la ubicación actual.InglésInglés (Australiano)Inglés (Gran Bretaña)Introduce el nombre de la tienda aquíGuinea EcuatorialEritreaErrorEstoniaEtiopíaNo se pudo cargar la lista de extensiones desde el servidor.Falló la publicación de la tienda. Por favor ingresa toda la información requerida.Islas MalvinasIslas FeroeFarsíFaxFijiFilipinoTipo de filtro:FinlandiaFinlandésFranciaFrancésGuyana FrancesaPolinesia FrancesaTerritorios Franceses del SurViernesGabónGallegoGambiaOpciones generalesError generalLa geolocalización falló por la siguiente razónGeorgiaAlemánAlemaniaObtener direccionesGhanaGibraltarAPI de Google MapsGreciaGriegoGroenlandiaGranadaGuadalupeGuamGuatemalaGuernseyGuineaGuinea-BissauGujaratiGuyanaHaitíIslas Heard y McDonaldHebreo¿Esconder el país en los resultados de búsqueda?¿Esconder la distancia en los resultados de búsqueda?¿Esconder las horas de operación?¿Esconder la barra de deslizamiento?HindiHondurasHong KongFormato de horaHorasHúngaroHungríaHíbridoIslandiaSi están activados los %senlaces permanentes%s, el nombre de la tienda siempre enlazará a la página de la tienda.Si el usuario coloca el cursor encima de los resultados de búsqueda, el marcador de la tiendaSi los grupos de marcadores están activados, esta opción no funcionará adecuadamente mientras los marcadores estén agrupados. %s El rebote del marcador no será visible a menos que el usuario haga suficiente zoom para que se disuelva el grupo y aparezcan los marcadores individuales. %s La ventana de información se abrirá correctamente, pero no será claro a qué marcador pertenece esta ventana. Si no hay un idioma seleccionado, se usará el idioma preferido del navegador.Si se queda en blanco, se usará el punto de inicio definido en la página de %sajustes%s.Si la vista de calle no está disponible en la ubicación actual, ¿mostrar un enlace a “Vista de calle” en la ventana de información?Si la %sconsola de navegador%s muestra el error a continuación, soluciónalo activando esta opción. %s %sHas incluido el API de Google Maps más de una vez en esta página. Esto puede causar errores inesperados.%s %s Este error puede, en ocasiones, romper el Mapa de Tiendas.Si el API de %sgeocodificación%s encuentra resultados más relevantes fuera de la región establecida (algunos nombres de ubicaciones existen en múltiples regiones), el usuario probablemente verá un mensaje de “No se encontraron resultados”. %s Para descartar esto puedes restringir los resultados a la región del mapa establecida. %s Puedes modificar las restricciones usadas con %seste%s filtro.Si el estilo predeterminado está desactivado se usará la librería %sInfoBox%s. %s Esto te permite cambiar el estilo de la ventana de información fácilmente a través de la clase de css .wpsl-infobox.Si el Localizador de tiendas no está colocado al inicio de la página, activar esta función puede hacer que la página se deslice hacia abajo. %s %sEsta opción está desactivada en dispositivos móviles.%sSi el nivel de zoom es alcanzado o excedido, todos los marcadores se salen del grupo y son mostrados como marcadores individuales.Si te gusta este plugin, por favor déjanos una calificación de %s5 estrellas%s.Si prefieres escribir el código de estilo por tu cuenta, puedes encontrar la documentación de Google %saquí%s.Si usas el shortcode de [wpsl_address] fuera de una página de tienda necesitarás establecer el atributo ID.Si usas el shortcode de [wpsl_hours] fuera de una página de tienda necesitarás establecer el atributo ID.Si usas el shortcode de [wpsl_map] fuera de una página de tienda necesitarás establecer el atributo ID o Categoría.En la ventana de información dentro del mapaEn los listados de tiendasIndiaIndonesiaIndonesioNivel de zoom inicialInsertar Localizador de tiendasIránIrakIrlandaIsla de ManIsraelItalianoItaliaJamaicaJapónJaponésJerseyJordaniaKannadaKazajistánKeniaKiribatiCoreanoKosovoKuwaitKyrgyzstanEtiquetasLaosLatitudLetoniaLetónLíbanoIzquierdaLesotoLiberiaLibiaFecha de expiración de licenciaClave de licenciaLiechtensteinLituaniaLituanoCargar ubicaciones al terminar de cargar la páginaUbicaciónInformación de ubicación no disponible.LongitudLuxemburgoM j, Y @ G:iMacauMacedonia (FYROM)Madagascar¿Hacer el número de teléfono clickeable en dispositivos móviles?¿Hacer el nombre de la tienda clickeable si existe un Url de tienda?MalawiMalayamMalasia Maldivas MaliMaltaMapaIdioma del mapaRegión del mapaEstilo de mapaTipo de mapaTipo de mapa para la previsualización de ubicaciónMarathiMarcadoresIslas MarshallMartinicaMauritaniaMauritiusNivel de zoom máximoMáximo de resultados de búsquedaAncho máximo del contenido en la ventana de informaciónNivel máximo de zoomMayotteMéxicoMicronesiaMoldovaLun %sMar %sMiér %sJue %sVie %sSáb Cerrado %sDom CerradoMónacoLunesMongoliaMontenegroMontserratMás informaciónMarruecosLa mayoría de los navegadores modernos %srequieren%s una conexión HTTPS para permitir la funcionalidad de Geolocalización.MozambiqueMyanmar (Burma)NamibiaNauruNepalHolandaAntillas HolandesasNueva CaledoniaAñadir tiendaNombre de la nueva categoría de tiendaNueva ZelandaNicaraguaNígerNigeriaNiueNo se encontraron resultadosNo se encontraron %s en la PapeleraNo se encontraron direccionesNo se encontraron resultadosNo se encontró una ruta entre el origen y el destinoNingunoIsla de NorfolkCorea del NorteIslas Marianas del NorteNoruegaNoruegoNynorsk NoruegoNúmero de ubicaciones a mostrarOmánAl cargar la página, ¿mover el cursor a la barra de búsqueda?¿Abrir enlaces en una nueva ventana?Horarios de operaciónPeríodos de operaciónLas horas de operación creadas en la versión 1.x %sno son%s convertidas automáticamente al nuevo formato de menú desplegable.Formato de horas de operaciónTipo de ingreso de horas de operaciónPakistánPalauPalestinaPanamáPapua Nueva GuineaParaguayCategoría superiorCategoría superior:Enlace permanentePerúFilipinasTeléfonoIslas PitcairnPor favor llena todos los detalles de tienda necesarios.Por favor ingresa el nombre de una ciudad o país que pueda ser usado como punto de inicio en “Ajustes del mapa”. %s Éste solo se usará si la autolocalización del usuario falla, o si dicha opción está desactivada.¡Por favor intenta de nuevo más tarde!Por favor usa la sección de “Traducción de textos” en el plugin multilenguaje para cambiar las etiquetas. Cambiarlas aquí no servirá mientras esté activo el plugin multilenguaje.PoloniaPolacoPortugalPortuguésPortugués (Brasil)Portugués (Portugal)Previsualizar ubicaciónPrevisualizar estilo del mapaPrevisualizar tiendaPuerto RicoQatarError de límite de peticionesRecomendado para mapas con un gran número de marcadores.Restablecer¿Restringir los resultados de geocodificación a la región del mapa seleccionada?ResultadosReuniónDerechaMapa de caminosRumaniaRumanoRusiaRusoRwandaSanta HelenaSan Kitts y NevisSanta LucíaSan Vicente y las GranadinasSamoaSan MarinoSatéliteSábadoArabia SauditaGuardar cambiosBuscarBuscar categorías de tiendasBuscar TiendasAncho de las etiquetas de búsqueda y radioAncho de campo de búsquedaBúsqueda proporcionada por %sWP Store Locutor%sRadio de búsquedaOpciones de radio de búsquedaBuscando (texto de preloader)Buscando…Chequeo de seguridad fallido, por favor recarga la página e intenta de nuevo.Chequeo de seguridad fallido, por favor recarga la página e intenta nuevamente.Elegir categoríaSelecciona la plantilla usadaElige tu lenguajeElige tu regiónSenegalSerbiaSerbioClave de servidor¿Establecer una categoría seleccionada?Establecer cajas de selección seleccionadasAjustesSeychelles¿Mostrar un enlace de “Más información” en los listados de tiendas?¿Mostrar un enlace a “Hacer zoom aquí” en la ventana de información?¿Mostrar un botón de Restablecer mapa?¿Mostrar créditos?¿Mostrar los controles de tipo de mapa?¿Mostrar el menú desplegable de máximo de resultados?¿Mostrar el menú desplegable de radio de búsqueda?Mostrar la lista de tiendas debajo del mapa¿Mostrar los controles de vista de calle?Sierra LeonaRegístrate para recibir los anuncios y actualizaciones más recientes.SingapurSint MaartenEslovacoEslovaquiaEsloveniaEslovenoIslas SalomónSomaliaAlgo falló al conectarse al API de Geolocalización de Google: %s %s Por favor intenta de nuevo más tarde.Algo salió mal, ¡por favor inténtalo nuevamente!SudáfricaIslas Georgia y Sándwich del SurCorea del SurSudán del SurEspañaEspañolSri LankaIniciar conversiónPunto de partidaMarcador del punto de partidaPunto de inicioEstadoTiendaCategorías de tiendasCategoría de tiendaDetalles de tiendaEditor de tiendaLocalizador de tiendasGestor de Store LocatorAltura del Localizador de tiendasPlantilla del Localizador de tiendasMapa de tiendasBorrador de tienda actualizado.Marcador de ubicación de tiendaUbicaciones de tienda a convertir:Tienda publicada.Tienda restaurada a la revisión de %sTienda guardada.Tienda programada para: <strong>%1$s</strong>.Slug de tiendaTienda publicada.Tienda actualizada.Vista de calleSudánDomingoSwazilandiaSueciaSuecoSuizaSiriaSão Tomé y PríncipeSão Tomé y PríncipeTagalogTaiwánTaijikistánTamilTanzaniaTelTeluguTerrenoÁrea de textoTailandésTailandiaLa licencia de %s no pudo ser desactivada, ¡por favor intenta de nuevo más tarde o contacta a soporte!La clave de licencia %s no corresponde a esta extensión.La clave de licencia %s ya no tiene activaciones disponibles.La clave de licencia %s ha expirado. Por favor renuévala.El API de Geolocalización de Google reportó el siguiente problema: error %s %s %s %sEl API de Geolocalización de Google reportó el siguiente error: %s %s %s Por favor contacta a %ssoporte%s si el problema continúa.El API de Geolocalización de Google reportó el siguiente problemama: error %s %s %s Por favor inténtalo nuevamente más tarde.El API de Geolocalización de Google no devolvió datos válidos, por favor intenta de nuevo más tarde.El API de Geolocalización de Google devolvió REQUEST_DENIED. %sEl API de Geolocalización de Google no devolvió ningún resultado para la dirección provista. Por favor cambia la dirección e intenta de nuevo.Esta aplicación no tiene permiso para usar el API de Geolocalización.El código para el estilo del mapa es inválido.El país y las horas predeterminados se usan únicamente al crear una tienda nueva, así que cambiar los valores predeterminados no tiene efecto en las ubicaciones existentes.Las horas de operación predeterminadasEl valor predeterminado está puesto entre [ ].La petición de geolocalización agotó el tiempo de espera.El tamaño de cuadrícula de un grupo en pixeles. %s Un número mayor resultará en una menor cantidad de grupos, haciendo al algoritmo correr más rápido.El mapa de previsualización se basa en la dirección ingresada, ciudad y país. %s Va a ignorar cualquier valor de latitud o longitud personalizado.El mapa de previsualización requiere todos los detalles de ubicación.El campo de resultados máximos no puede estar vacío, el valor predeterminado ha sido restablecido.Los slugs de los enlaces permanentes %sdeben ser únicos%s en tu sitio.El script convirtiendo las ubicaciones agotó el tiempo de espera. %s Puedes hacer click en “Iniciar conversión” nuevamente para reiniciarlo. %s Si hay miles de ubicaciones por convertir y sigues viendo este mensaje, contacta a tu proveedor de hosting y pídele que por favor incremente el tiempo de ejecución máximo. %s El plugin trató de desactivar el tiempo máximo de ejecución, pero, si estás leyendo esto, falló.El campo de radio de búsqueda no puede estar vacío, el valor predeterminado ha sido restablecido.La plantilla seleccionada se usa con el shortcode [wpsl]. %s Puedes añadir una plantilla personalizada con el filtro %swpsl_templates%s.Una nueva versión de %1$s está disponible. %2$sVer detalles de la %3$s versión%4$s o %5$sactualizar ahora%6$s.Una nueva versión de %1$s está disponible. %2$sVer los detalles de la %3$s versión%4$s.Hubo un problema al activar la clave de licencia para %s, por favor intenta de nuevo o contacta a soporte. Código de error: %sHubo un problema con la %sllave de navegador%s proporcionada. %s Puedes leer más acerca de cómo determinar el error exacto, y cómo solucionarlo, %saquí%s.Hay un problema con la %sllave de servidor%s proporcionada. %sEsto desactiva el caché de transients de WPSL. %sEl caché de transients solo se usa cuando está activada la opción de %sCargar ubicaciones al terminar de cargar la página%s.Esto añade un enlace de “Más información” abajo de la dirección y muestra el teléfono, fax, email, horas de operación y descripción al hacer click en él.Esto corre tras efectuar una búsqueda, y se asegura de que todos los resultados sean visibles en la pantalla.Este valor define el nivel de zoom para la opción de “Hacer zoom aquí” en la ventana de información. %s También se usa para limitar el zoom cuando la ventana del mapa cambia para que quepan todos los marcadores en la pantalla.Esto inclinará los resultados de la %sgeocodificación%s hacia la región seleccionada. %s Si no hay una región seleccionada, la inclinación será hacia los Estados Unidos.Esto mostrará un backlink con el texto “Búsqueda proporcionada por WP Store Locutor” debajo del mapa.JuevesTimor-LesteTogoTokelauTongaHerramientasTrinidad y TobagoTristan da CunhaMartesTúnezTurquíaTurcoTurkmenistánIslas Turcas y CaicosTuvalúUgandaUcraniaUcranianoEmiratos Árabes UnidosReino UnidoEstados Unidos de AméricaActualizar categoría de tiendaUrlUruguay¿Usar el estilo predeterminado para la ventana de información?Experiencia de usuarioUzbekistánVanuatuCiudad del VaticanoVenezuelaVietnamVietnamitaVer TiendasVer tiendaWP Store LocutorExtensiones de WP Store LocutorTransients de WP Store Locator eliminadosTransients de WPSLWallis FutunaMiércolesBienvenido a WP Store LocatorSahara OccidentalCuando el usuario hace click en “Direcciones”, ¿abrir una nueva ventana y mostrar la ruta en google.com/maps?¿Dónde quieres mostrar los detalles de “Más información”?Abrirá la ventana de informaciónVista mundialYemenPuedes añadir formatos de dirección personalizados con el filtro %swpsl_address_formats%s.Puedes arrastrar el marcador para ajustar la dirección exacta de éste.Puedes solucionar esto asegurándote de que tu archivo CSV esté usando el %scodificado UTF-8%s.Puedes subir el %slímite de uso%s obteniendo una %sclave%s de API e introduciéndola en el campo de “Clave de API” en la parte superior de esta página.Puedes usar estilos de %sSnazzy Mapps%s o %sMap Stylr%s existentes  y pegarlos en el área de texto a continuación, o puedes generar un estilo de mapa personalizado a través del %sEditor de estilos de mapa%s o el %sAsistente de mapas estilizados%s.No tienes los permisos necesarios para actualizar el pluginNo tienes permiso para realizar esta acciónLlegaste el límite diario permitido de geolocalización, puedes leer más %saquí%s.¡Debes crear una %sLlave API%s de Google Maps antes de poder usar el Localizador de tiendas! %sDescartar%sNecesitas introducir al menos una dirección, ciudad, estado o país para que el API pueda devolver coordenadas.Tu ubicaciónZambiaZimbabweCódigo postalCódigo postalPosición de los controles de zoomHacer zoom aquíventana de infokmmicategoria-tiendatiendasIslas Ålandlanguages/wpsl.pot000064400000171030151327220640010227 0ustar00#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: WP Store Locator v2.2.22\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-03-22 12:18+0700\n"
"PO-Revision-Date: 2015-09-01 13:49+0100\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: en_US\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Poedit 1.8.11\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;"
"_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2\n"
"X-Poedit-Basepath: ..\n"
"X-Textdomain-Support: yes\n"
"X-Poedit-SearchPath-0: .\n"
"X-Poedit-SearchPathExcluded-0: admin/EDD_SL_Plugin_Updater.php\n"

#: admin/class-admin.php:121
#, php-format
msgid ""
"You need to create %sAPI keys%s for Google Maps before you can use the store "
"locator! %sDismiss%s"
msgstr ""

#: admin/class-admin.php:123
#, php-format
msgid ""
"Before adding the [wpsl] shortcode to a page, please don't forget to define "
"a start point on the %ssettings%s page. %sDismiss%s"
msgstr ""

#: admin/class-admin.php:160
msgid "Security check failed. Please reload the page and try again."
msgstr ""

#: admin/class-admin.php:179 admin/class-admin.php:180
#: admin/class-admin.php:511 admin/templates/map-settings.php:8
msgid "Settings"
msgstr ""

#: admin/class-admin.php:186 admin/class-admin.php:187
#: admin/class-admin.php:531
msgid "Add-Ons"
msgstr ""

#: admin/class-admin.php:300
msgid "Cannot determine the address at this location."
msgstr ""

#: admin/class-admin.php:301
msgid "Geocode was not successful for the following reason"
msgstr ""

#: admin/class-admin.php:302 admin/upgrade.php:471
msgid "Security check failed, reload the page and try again."
msgstr ""

#: admin/class-admin.php:303
msgid "Please fill in all the required store details."
msgstr ""

#: admin/class-admin.php:304
msgid "The map preview requires all the location details."
msgstr ""

#: admin/class-admin.php:305 admin/class-metaboxes.php:534
#: frontend/class-frontend.php:583
msgid "Closed"
msgstr ""

#: admin/class-admin.php:306
msgid "The code for the map style is invalid."
msgstr ""

#: admin/class-admin.php:307
msgid "Dismiss this notice."
msgstr ""

#: admin/class-admin.php:308
#, php-format
msgid ""
"There's a problem with the provided %sbrowser key%s. %s You will have to "
"open the %sbrowser console%s ( %sctrl%s %sshift%s %sk%s in Firefox, or %sctrl"
"%s %sshift%s %sj%s in Chrome ) to see the error details returned by the "
"Google Maps API. %s The error itself includes a link explaining the problem "
"in more detail. %s Common API errors are also covered in the "
"%stroubleshooting section%s."
msgstr ""

#: admin/class-admin.php:309
msgid "No problems found with the browser key."
msgstr ""

#: admin/class-admin.php:310 admin/templates/map-settings.php:104
msgid "Server key"
msgstr ""

#: admin/class-admin.php:311
#, php-format
msgid "No %sserver key%s found!"
msgstr ""

#: admin/class-admin.php:312 admin/templates/map-settings.php:100
msgid "Browser key"
msgstr ""

#: admin/class-admin.php:313
#, php-format
msgid "No %sbrowser key%s found!"
msgstr ""

#: admin/class-admin.php:314
msgid "and will only work for zip codes."
msgstr ""

#: admin/class-admin.php:315
#, php-format
msgid ""
"because no %smap region%s is selected the geocode API will search for "
"matching results around the world. This may result in unexpected results."
msgstr ""

#: admin/class-admin.php:316
#, php-format
msgid ""
"Google Maps didn't load correctly. Make sure you have an active %sbilling%s "
"%saccount%s for Google Maps. %s If the \"For development purposes only\" "
"text keeps showing after creating a billing account, then you will have to "
"contact %sGoogle Billing Support%s."
msgstr ""

#: admin/class-admin.php:317
#, php-format
msgid ""
"Google Maps failed to load correctly. This is likely due to a problem with "
"the provided %sbrowser key%s. %s You will have to open the %sbrowser console"
"%s ( %sctrl%s %sshift%s %sk%s in Firefox, or %sctrl%s %sshift%s %sj%s in "
"Chrome ) to see the error details returned by the Google Maps API. %s The "
"error itself includes a link explaining the problem in more detail. %s "
"Common API errors are also covered in the %stroubleshooting section%s."
msgstr ""

#: admin/class-admin.php:318
msgid "Close"
msgstr ""

#: admin/class-admin.php:332
#, php-format
msgid "with the current settings the results are %s to"
msgstr ""

#: admin/class-admin.php:466
msgid "Welcome to WP Store Locator"
msgstr ""

#: admin/class-admin.php:467
msgid "Sign up for the latest plugin updates and announcements."
msgstr ""

#: admin/class-admin.php:530
msgid "Documentation"
msgstr ""

#: admin/class-admin.php:553
#, php-format
msgid "If you like this plugin please leave us a %s5 star%s rating."
msgstr ""

#: admin/class-geocode.php:80
msgid ""
"The Google Geocoding API returned no results for the supplied address. "
"Please change the address and try again."
msgstr ""

#: admin/class-geocode.php:83
#, php-format
msgid ""
"You have reached the daily allowed geocoding limit, you can read more %shere"
"%s."
msgstr ""

#: admin/class-geocode.php:86
#, php-format
msgid "The Google Geocoding API returned REQUEST_DENIED. %s"
msgstr ""

#: admin/class-geocode.php:89
msgid ""
"The Google Geocoding API failed to return valid data, please try again later."
msgstr ""

#: admin/class-geocode.php:117
#, php-format
msgid ""
"%sError message: %s. %s Make sure the IP address mentioned in the error "
"matches with the IP set as the %sreferrer%s for the server API key in the "
"%sGoogle API Console%s."
msgstr ""

#: admin/class-geocode.php:119
#, php-format
msgid ""
"%sError message: %s %s Check if your issue is covered in the "
"%stroubleshooting%s section, if not, then please open a %ssupport ticket%s."
msgstr ""

#: admin/class-geocode.php:141
#, php-format
msgid ""
"Something went wrong connecting to the Google Geocode API: %s %s Please try "
"again later."
msgstr ""

#: admin/class-geocode.php:143
#, php-format
msgid ""
"The Google Geocode API reported the following problem: error %s %s %s Please "
"try again later."
msgstr ""

#: admin/class-geocode.php:148
#, php-format
msgid "You can fix this by making sure the CSV file uses %sUTF-8 encoding%s."
msgstr ""

#: admin/class-geocode.php:150
msgid ""
"You need to provide the details for either the address, city, state or "
"country before the API can return coordinates."
msgstr ""

#: admin/class-geocode.php:153
#, php-format
msgid ""
"The Google Geocode API reported the following problem: error %s %s %s %s"
msgstr ""

#: admin/class-geocode.php:155
#, php-format
msgid ""
"The Google Geocode API reported the following problem: error %s %s %s Please "
"contact %ssupport%s if the problem persists."
msgstr ""

#: admin/class-license-manager.php:183
#, php-format
msgid ""
"The %s license failed to deactivate, please try again later or contact "
"support!"
msgstr ""

#: admin/class-license-manager.php:209 admin/templates/add-ons.php:56
msgid "Please try again later!"
msgstr ""

#: admin/class-license-manager.php:257
#, php-format
msgid "The %s license key does not belong to this add-on."
msgstr ""

#: admin/class-license-manager.php:260
#, php-format
msgid "The %s license key does not have any activations left."
msgstr ""

#: admin/class-license-manager.php:263
#, php-format
msgid "The %s license key is expired. Please renew it."
msgstr ""

#: admin/class-license-manager.php:266
#, php-format
msgid ""
"There was a problem activating the license key for the %s, please try again "
"or contact support. Error code: %s"
msgstr ""

#: admin/class-metaboxes.php:36
msgid "Store Details"
msgstr ""

#: admin/class-metaboxes.php:37
msgid "Store Map"
msgstr ""

#: admin/class-metaboxes.php:42
msgid "Export"
msgstr ""

#: admin/class-metaboxes.php:57
msgid "Location"
msgstr ""

#: admin/class-metaboxes.php:59 inc/class-post-types.php:186
msgid "Address"
msgstr ""

#: admin/class-metaboxes.php:63
msgid "Address 2"
msgstr ""

#: admin/class-metaboxes.php:66 inc/class-post-types.php:187
msgid "City"
msgstr ""

#: admin/class-metaboxes.php:70 inc/class-post-types.php:188
msgid "State"
msgstr ""

#: admin/class-metaboxes.php:73
msgid "Zip Code"
msgstr ""

#: admin/class-metaboxes.php:76
msgid "Country"
msgstr ""

#: admin/class-metaboxes.php:83
msgid "Latitude"
msgstr ""

#: admin/class-metaboxes.php:86
msgid "Longitude"
msgstr ""

#: admin/class-metaboxes.php:89 admin/class-metaboxes.php:138
#: admin/class-metaboxes.php:153
msgid "Opening Hours"
msgstr ""

#: admin/class-metaboxes.php:91 admin/templates/map-settings.php:574
#: admin/templates/map-settings.php:575 frontend/underscore-functions.php:160
#: inc/wpsl-functions.php:159
msgid "Hours"
msgstr ""

#: admin/class-metaboxes.php:95
msgid "Additional Information"
msgstr ""

#: admin/class-metaboxes.php:97
msgid "Tel"
msgstr ""

#: admin/class-metaboxes.php:100 admin/templates/map-settings.php:562
#: admin/templates/map-settings.php:563 frontend/class-frontend.php:847
#: frontend/underscore-functions.php:32 frontend/underscore-functions.php:68
#: frontend/underscore-functions.php:150 inc/wpsl-functions.php:156
msgid "Fax"
msgstr ""

#: admin/class-metaboxes.php:103 admin/templates/map-settings.php:566
#: admin/templates/map-settings.php:567 admin/upgrade.php:198
#: frontend/class-frontend.php:851 frontend/underscore-functions.php:35
#: frontend/underscore-functions.php:71 frontend/underscore-functions.php:153
#: inc/wpsl-functions.php:157
msgid "Email"
msgstr ""

#: admin/class-metaboxes.php:106 admin/templates/map-settings.php:570
#: admin/templates/map-settings.php:571 admin/upgrade.php:202
#: frontend/class-frontend.php:856 inc/wpsl-functions.php:158
msgid "Url"
msgstr ""

#: admin/class-metaboxes.php:456
msgid "Hour format"
msgstr ""

#: admin/class-metaboxes.php:463
msgid "Days"
msgstr ""

#: admin/class-metaboxes.php:464
msgid "Opening Periods"
msgstr ""

#: admin/class-metaboxes.php:714
msgid "Failed to publish the store. Please fill in the required store details."
msgstr ""

#: admin/class-metaboxes.php:850
msgid "Preview Location"
msgstr ""

#: admin/class-metaboxes.php:851
#, php-format
msgid ""
"The map preview is based on the provided address, city and country details. "
"%s It will ignore any custom latitude or longitude values."
msgstr ""

#: admin/class-metaboxes.php:852
msgid "You can drag the marker to adjust the exact location of the marker."
msgstr ""

#: admin/class-metaboxes.php:871
msgid "Export Location Data"
msgstr ""

#: admin/class-metaboxes.php:891 admin/class-metaboxes.php:894
msgid "Store updated."
msgstr ""

#: admin/class-metaboxes.php:892
msgid "Custom field updated."
msgstr ""

#: admin/class-metaboxes.php:893
msgid "Custom field deleted."
msgstr ""

#: admin/class-metaboxes.php:895
#, php-format
msgid "Store restored to revision from %s"
msgstr ""

#: admin/class-metaboxes.php:896
msgid "Store published."
msgstr ""

#: admin/class-metaboxes.php:897
msgid "Store saved."
msgstr ""

#: admin/class-metaboxes.php:898
msgid "Store submitted."
msgstr ""

#: admin/class-metaboxes.php:900
#, php-format
msgid "Store scheduled for: <strong>%1$s</strong>."
msgstr ""

#: admin/class-metaboxes.php:901
msgid "M j, Y @ G:i"
msgstr ""

#: admin/class-metaboxes.php:903
msgid "Store draft updated."
msgstr ""

#: admin/class-metaboxes.php:909
msgid "View store"
msgstr ""

#: admin/class-metaboxes.php:915
msgid "Preview store"
msgstr ""

#: admin/class-settings.php:40
msgid "WP Store Locator Transients Cleared"
msgstr ""

#: admin/class-settings.php:373
#, php-format
msgid "There's a problem with the provided %sserver key%s. %s"
msgstr ""

#: admin/class-settings.php:396
msgid "No problems found with the server key."
msgstr ""

#: admin/class-settings.php:505
msgid ""
"The max results field cannot be empty, the default value has been restored."
msgstr ""

#: admin/class-settings.php:508
msgid ""
"The search radius field cannot be empty, the default value has been restored."
msgstr ""

#: admin/class-settings.php:511
#, php-format
msgid ""
"Please provide the name of a city or country that can be used as a starting "
"point under \"Map Settings\". %s This will only be used if auto-locating the "
"user fails, or the option itself is disabled."
msgstr ""

#: admin/class-settings.php:532
msgid "Select your language"
msgstr ""

#: admin/class-settings.php:533
msgid "English"
msgstr ""

#: admin/class-settings.php:534
msgid "Arabic"
msgstr ""

#: admin/class-settings.php:535
msgid "Basque"
msgstr ""

#: admin/class-settings.php:536
msgid "Bulgarian"
msgstr ""

#: admin/class-settings.php:537
msgid "Bengali"
msgstr ""

#: admin/class-settings.php:538
msgid "Catalan"
msgstr ""

#: admin/class-settings.php:539
msgid "Czech"
msgstr ""

#: admin/class-settings.php:540
msgid "Danish"
msgstr ""

#: admin/class-settings.php:541
msgid "German"
msgstr ""

#: admin/class-settings.php:542
msgid "Greek"
msgstr ""

#: admin/class-settings.php:543
msgid "English (Australian)"
msgstr ""

#: admin/class-settings.php:544
msgid "English (Great Britain)"
msgstr ""

#: admin/class-settings.php:545
msgid "Spanish"
msgstr ""

#: admin/class-settings.php:546
msgid "Farsi"
msgstr ""

#: admin/class-settings.php:547
msgid "Finnish"
msgstr ""

#: admin/class-settings.php:548
msgid "Filipino"
msgstr ""

#: admin/class-settings.php:549
msgid "French"
msgstr ""

#: admin/class-settings.php:550
msgid "Galician"
msgstr ""

#: admin/class-settings.php:551
msgid "Gujarati"
msgstr ""

#: admin/class-settings.php:552
msgid "Hindi"
msgstr ""

#: admin/class-settings.php:553
msgid "Croatian"
msgstr ""

#: admin/class-settings.php:554
msgid "Hungarian"
msgstr ""

#: admin/class-settings.php:555
msgid "Indonesian"
msgstr ""

#: admin/class-settings.php:556
msgid "Italian"
msgstr ""

#: admin/class-settings.php:557
msgid "Hebrew"
msgstr ""

#: admin/class-settings.php:558
msgid "Japanese"
msgstr ""

#: admin/class-settings.php:559
msgid "Kannada"
msgstr ""

#: admin/class-settings.php:560
msgid "Korean"
msgstr ""

#: admin/class-settings.php:561
msgid "Lithuanian"
msgstr ""

#: admin/class-settings.php:562
msgid "Latvian"
msgstr ""

#: admin/class-settings.php:563
msgid "Malayalam"
msgstr ""

#: admin/class-settings.php:564
msgid "Marathi"
msgstr ""

#: admin/class-settings.php:565
msgid "Dutch"
msgstr ""

#: admin/class-settings.php:566
msgid "Norwegian"
msgstr ""

#: admin/class-settings.php:567
msgid "Norwegian Nynorsk"
msgstr ""

#: admin/class-settings.php:568
msgid "Polish"
msgstr ""

#: admin/class-settings.php:569
msgid "Portuguese"
msgstr ""

#: admin/class-settings.php:570
msgid "Portuguese (Brazil)"
msgstr ""

#: admin/class-settings.php:571
msgid "Portuguese (Portugal)"
msgstr ""

#: admin/class-settings.php:572
msgid "Romanian"
msgstr ""

#: admin/class-settings.php:573
msgid "Russian"
msgstr ""

#: admin/class-settings.php:574
msgid "Slovak"
msgstr ""

#: admin/class-settings.php:575
msgid "Slovenian"
msgstr ""

#: admin/class-settings.php:576
msgid "Serbian"
msgstr ""

#: admin/class-settings.php:577
msgid "Swedish"
msgstr ""

#: admin/class-settings.php:578
msgid "Tagalog"
msgstr ""

#: admin/class-settings.php:579
msgid "Tamil"
msgstr ""

#: admin/class-settings.php:580
msgid "Telugu"
msgstr ""

#: admin/class-settings.php:581
msgid "Thai"
msgstr ""

#: admin/class-settings.php:582
msgid "Turkish"
msgstr ""

#: admin/class-settings.php:583
msgid "Ukrainian"
msgstr ""

#: admin/class-settings.php:584
msgid "Vietnamese"
msgstr ""

#: admin/class-settings.php:585
msgid "Chinese (Simplified)"
msgstr ""

#: admin/class-settings.php:586
msgid "Chinese (Traditional)"
msgstr ""

#: admin/class-settings.php:591
msgid "Select your region"
msgstr ""

#: admin/class-settings.php:592
msgid "Afghanistan"
msgstr ""

#: admin/class-settings.php:593
msgid "Albania"
msgstr ""

#: admin/class-settings.php:594
msgid "Algeria"
msgstr ""

#: admin/class-settings.php:595
msgid "American Samoa"
msgstr ""

#: admin/class-settings.php:596
msgid "Andorra"
msgstr ""

#: admin/class-settings.php:597
msgid "Angola"
msgstr ""

#: admin/class-settings.php:598
msgid "Anguilla"
msgstr ""

#: admin/class-settings.php:599
msgid "Antarctica"
msgstr ""

#: admin/class-settings.php:600
msgid "Antigua and Barbuda"
msgstr ""

#: admin/class-settings.php:601
msgid "Argentina"
msgstr ""

#: admin/class-settings.php:602
msgid "Armenia"
msgstr ""

#: admin/class-settings.php:603
msgid "Aruba"
msgstr ""

#: admin/class-settings.php:604
msgid "Ascension Island"
msgstr ""

#: admin/class-settings.php:605
msgid "Australia"
msgstr ""

#: admin/class-settings.php:606
msgid "Austria"
msgstr ""

#: admin/class-settings.php:607
msgid "Azerbaijan"
msgstr ""

#: admin/class-settings.php:608
msgid "Bahamas"
msgstr ""

#: admin/class-settings.php:609
msgid "Bahrain"
msgstr ""

#: admin/class-settings.php:610
msgid "Bangladesh"
msgstr ""

#: admin/class-settings.php:611
msgid "Barbados"
msgstr ""

#: admin/class-settings.php:612
msgid "Belarus"
msgstr ""

#: admin/class-settings.php:613
msgid "Belgium"
msgstr ""

#: admin/class-settings.php:614
msgid "Belize"
msgstr ""

#: admin/class-settings.php:615
msgid "Benin"
msgstr ""

#: admin/class-settings.php:616
msgid "Bermuda"
msgstr ""

#: admin/class-settings.php:617
msgid "Bhutan"
msgstr ""

#: admin/class-settings.php:618
msgid "Bolivia"
msgstr ""

#: admin/class-settings.php:619
msgid "Bosnia and Herzegovina"
msgstr ""

#: admin/class-settings.php:620
msgid "Botswana"
msgstr ""

#: admin/class-settings.php:621
msgid "Bouvet Island"
msgstr ""

#: admin/class-settings.php:622
msgid "Brazil"
msgstr ""

#: admin/class-settings.php:623
msgid "British Indian Ocean Territory"
msgstr ""

#: admin/class-settings.php:624
msgid "British Virgin Islands"
msgstr ""

#: admin/class-settings.php:625
msgid "Brunei"
msgstr ""

#: admin/class-settings.php:626
msgid "Bulgaria"
msgstr ""

#: admin/class-settings.php:627
msgid "Burkina Faso"
msgstr ""

#: admin/class-settings.php:628
msgid "Burundi"
msgstr ""

#: admin/class-settings.php:629
msgid "Cambodia"
msgstr ""

#: admin/class-settings.php:630
msgid "Cameroon"
msgstr ""

#: admin/class-settings.php:631
msgid "Canada"
msgstr ""

#: admin/class-settings.php:632
msgid "Canary Islands"
msgstr ""

#: admin/class-settings.php:633
msgid "Cape Verde"
msgstr ""

#: admin/class-settings.php:634
msgid "Caribbean Netherlands"
msgstr ""

#: admin/class-settings.php:635
msgid "Cayman Islands"
msgstr ""

#: admin/class-settings.php:636
msgid "Central African Republic"
msgstr ""

#: admin/class-settings.php:637
msgid "Ceuta and Melilla"
msgstr ""

#: admin/class-settings.php:638
msgid "Chad"
msgstr ""

#: admin/class-settings.php:639
msgid "Chile"
msgstr ""

#: admin/class-settings.php:640
msgid "China"
msgstr ""

#: admin/class-settings.php:641
msgid "Christmas Island"
msgstr ""

#: admin/class-settings.php:642
msgid "Clipperton Island"
msgstr ""

#: admin/class-settings.php:643
msgid "Cocos (Keeling) Islands"
msgstr ""

#: admin/class-settings.php:644
msgid "Colombia"
msgstr ""

#: admin/class-settings.php:645
msgid "Comoros"
msgstr ""

#: admin/class-settings.php:646
msgid "Congo (DRC)"
msgstr ""

#: admin/class-settings.php:647
msgid "Congo (Republic)"
msgstr ""

#: admin/class-settings.php:648
msgid "Cook Islands"
msgstr ""

#: admin/class-settings.php:649
msgid "Costa Rica"
msgstr ""

#: admin/class-settings.php:650
msgid "Croatia"
msgstr ""

#: admin/class-settings.php:651
msgid "Cuba"
msgstr ""

#: admin/class-settings.php:652
msgid "Curaçao"
msgstr ""

#: admin/class-settings.php:653
msgid "Cyprus"
msgstr ""

#: admin/class-settings.php:654
msgid "Czech Republic"
msgstr ""

#: admin/class-settings.php:655
msgid "Côte d'Ivoire"
msgstr ""

#: admin/class-settings.php:656
msgid "Denmark"
msgstr ""

#: admin/class-settings.php:657
msgid "Djibouti"
msgstr ""

#: admin/class-settings.php:658
msgid "Democratic Republic of the Congo"
msgstr ""

#: admin/class-settings.php:659
msgid "Dominica"
msgstr ""

#: admin/class-settings.php:660
msgid "Dominican Republic"
msgstr ""

#: admin/class-settings.php:661
msgid "Ecuador"
msgstr ""

#: admin/class-settings.php:662
msgid "Egypt"
msgstr ""

#: admin/class-settings.php:663
msgid "El Salvador"
msgstr ""

#: admin/class-settings.php:664
msgid "Equatorial Guinea"
msgstr ""

#: admin/class-settings.php:665
msgid "Eritrea"
msgstr ""

#: admin/class-settings.php:666
msgid "Estonia"
msgstr ""

#: admin/class-settings.php:667
msgid "Ethiopia"
msgstr ""

#: admin/class-settings.php:668
msgid "Falkland Islands(Islas Malvinas)"
msgstr ""

#: admin/class-settings.php:669
msgid "Faroe Islands"
msgstr ""

#: admin/class-settings.php:670
msgid "Fiji"
msgstr ""

#: admin/class-settings.php:671
msgid "Finland"
msgstr ""

#: admin/class-settings.php:672
msgid "France"
msgstr ""

#: admin/class-settings.php:673
msgid "French Guiana"
msgstr ""

#: admin/class-settings.php:674
msgid "French Polynesia"
msgstr ""

#: admin/class-settings.php:675
msgid "French Southern Territories"
msgstr ""

#: admin/class-settings.php:676
msgid "Gabon"
msgstr ""

#: admin/class-settings.php:677
msgid "Gambia"
msgstr ""

#: admin/class-settings.php:678
msgid "Georgia"
msgstr ""

#: admin/class-settings.php:679
msgid "Germany"
msgstr ""

#: admin/class-settings.php:680
msgid "Ghana"
msgstr ""

#: admin/class-settings.php:681
msgid "Gibraltar"
msgstr ""

#: admin/class-settings.php:682
msgid "Greece"
msgstr ""

#: admin/class-settings.php:683
msgid "Greenland"
msgstr ""

#: admin/class-settings.php:684
msgid "Grenada"
msgstr ""

#: admin/class-settings.php:685 admin/class-settings.php:687
msgid "Guam"
msgstr ""

#: admin/class-settings.php:686
msgid "Guadeloupe"
msgstr ""

#: admin/class-settings.php:688
msgid "Guatemala"
msgstr ""

#: admin/class-settings.php:689
msgid "Guernsey"
msgstr ""

#: admin/class-settings.php:690
msgid "Guinea"
msgstr ""

#: admin/class-settings.php:691
msgid "Guinea-Bissau"
msgstr ""

#: admin/class-settings.php:692
msgid "Guyana"
msgstr ""

#: admin/class-settings.php:693
msgid "Haiti"
msgstr ""

#: admin/class-settings.php:694
msgid "Heard and McDonald Islands"
msgstr ""

#: admin/class-settings.php:695
msgid "Honduras"
msgstr ""

#: admin/class-settings.php:696
msgid "Hong Kong"
msgstr ""

#: admin/class-settings.php:697
msgid "Hungary"
msgstr ""

#: admin/class-settings.php:698
msgid "Iceland"
msgstr ""

#: admin/class-settings.php:699
msgid "India"
msgstr ""

#: admin/class-settings.php:700
msgid "Indonesia"
msgstr ""

#: admin/class-settings.php:701
msgid "Iran"
msgstr ""

#: admin/class-settings.php:702
msgid "Iraq"
msgstr ""

#: admin/class-settings.php:703
msgid "Ireland"
msgstr ""

#: admin/class-settings.php:704
msgid "Isle of Man"
msgstr ""

#: admin/class-settings.php:705
msgid "Israel"
msgstr ""

#: admin/class-settings.php:706
msgid "Italy"
msgstr ""

#: admin/class-settings.php:707
msgid "Jamaica"
msgstr ""

#: admin/class-settings.php:708
msgid "Japan"
msgstr ""

#: admin/class-settings.php:709
msgid "Jersey"
msgstr ""

#: admin/class-settings.php:710
msgid "Jordan"
msgstr ""

#: admin/class-settings.php:711
msgid "Kazakhstan"
msgstr ""

#: admin/class-settings.php:712
msgid "Kenya"
msgstr ""

#: admin/class-settings.php:713
msgid "Kiribati"
msgstr ""

#: admin/class-settings.php:714
msgid "Kosovo"
msgstr ""

#: admin/class-settings.php:715
msgid "Kuwait"
msgstr ""

#: admin/class-settings.php:716
msgid "Kyrgyzstan"
msgstr ""

#: admin/class-settings.php:717
msgid "Laos"
msgstr ""

#: admin/class-settings.php:718
msgid "Latvia"
msgstr ""

#: admin/class-settings.php:719
msgid "Lebanon"
msgstr ""

#: admin/class-settings.php:720
msgid "Lesotho"
msgstr ""

#: admin/class-settings.php:721
msgid "Liberia"
msgstr ""

#: admin/class-settings.php:722
msgid "Libya"
msgstr ""

#: admin/class-settings.php:723
msgid "Liechtenstein"
msgstr ""

#: admin/class-settings.php:724
msgid "Lithuania"
msgstr ""

#: admin/class-settings.php:725
msgid "Luxembourg"
msgstr ""

#: admin/class-settings.php:726
msgid "Macau"
msgstr ""

#: admin/class-settings.php:727
msgid "Macedonia (FYROM)"
msgstr ""

#: admin/class-settings.php:728
msgid "Madagascar"
msgstr ""

#: admin/class-settings.php:729
msgid "Malawi"
msgstr ""

#: admin/class-settings.php:730
msgid "Malaysia "
msgstr ""

#: admin/class-settings.php:731
msgid "Maldives "
msgstr ""

#: admin/class-settings.php:732
msgid "Mali"
msgstr ""

#: admin/class-settings.php:733
msgid "Malta"
msgstr ""

#: admin/class-settings.php:734
msgid "Marshall Islands"
msgstr ""

#: admin/class-settings.php:735
msgid "Martinique"
msgstr ""

#: admin/class-settings.php:736
msgid "Mauritania"
msgstr ""

#: admin/class-settings.php:737
msgid "Mauritius"
msgstr ""

#: admin/class-settings.php:738
msgid "Mayotte"
msgstr ""

#: admin/class-settings.php:739
msgid "Mexico"
msgstr ""

#: admin/class-settings.php:740
msgid "Micronesia"
msgstr ""

#: admin/class-settings.php:741
msgid "Moldova"
msgstr ""

#: admin/class-settings.php:742
msgid "Monaco"
msgstr ""

#: admin/class-settings.php:743
msgid "Mongolia"
msgstr ""

#: admin/class-settings.php:744
msgid "Montenegro"
msgstr ""

#: admin/class-settings.php:745
msgid "Montserrat"
msgstr ""

#: admin/class-settings.php:746
msgid "Morocco"
msgstr ""

#: admin/class-settings.php:747
msgid "Mozambique"
msgstr ""

#: admin/class-settings.php:748
msgid "Myanmar (Burma)"
msgstr ""

#: admin/class-settings.php:749
msgid "Namibia"
msgstr ""

#: admin/class-settings.php:750
msgid "Nauru"
msgstr ""

#: admin/class-settings.php:751
msgid "Nepal"
msgstr ""

#: admin/class-settings.php:752
msgid "Netherlands"
msgstr ""

#: admin/class-settings.php:753
msgid "Netherlands Antilles"
msgstr ""

#: admin/class-settings.php:754
msgid "New Caledonia"
msgstr ""

#: admin/class-settings.php:755
msgid "New Zealand"
msgstr ""

#: admin/class-settings.php:756
msgid "Nicaragua"
msgstr ""

#: admin/class-settings.php:757
msgid "Niger"
msgstr ""

#: admin/class-settings.php:758
msgid "Nigeria"
msgstr ""

#: admin/class-settings.php:759
msgid "Niue"
msgstr ""

#: admin/class-settings.php:760
msgid "Norfolk Island"
msgstr ""

#: admin/class-settings.php:761
msgid "North Korea"
msgstr ""

#: admin/class-settings.php:762
msgid "Northern Mariana Islands"
msgstr ""

#: admin/class-settings.php:763
msgid "Norway"
msgstr ""

#: admin/class-settings.php:764
msgid "Oman"
msgstr ""

#: admin/class-settings.php:765
msgid "Pakistan"
msgstr ""

#: admin/class-settings.php:766
msgid "Palau"
msgstr ""

#: admin/class-settings.php:767
msgid "Palestine"
msgstr ""

#: admin/class-settings.php:768
msgid "Panama"
msgstr ""

#: admin/class-settings.php:769
msgid "Papua New Guinea"
msgstr ""

#: admin/class-settings.php:770
msgid "Paraguay"
msgstr ""

#: admin/class-settings.php:771
msgid "Peru"
msgstr ""

#: admin/class-settings.php:772
msgid "Philippines"
msgstr ""

#: admin/class-settings.php:773
msgid "Pitcairn Islands"
msgstr ""

#: admin/class-settings.php:774
msgid "Poland"
msgstr ""

#: admin/class-settings.php:775
msgid "Portugal"
msgstr ""

#: admin/class-settings.php:776
msgid "Puerto Rico"
msgstr ""

#: admin/class-settings.php:777
msgid "Qatar"
msgstr ""

#: admin/class-settings.php:778
msgid "Reunion"
msgstr ""

#: admin/class-settings.php:779
msgid "Romania"
msgstr ""

#: admin/class-settings.php:780
msgid "Russia"
msgstr ""

#: admin/class-settings.php:781
msgid "Rwanda"
msgstr ""

#: admin/class-settings.php:782
msgid "Saint Helena"
msgstr ""

#: admin/class-settings.php:783
msgid "Saint Kitts and Nevis"
msgstr ""

#: admin/class-settings.php:784
msgid "Saint Vincent and the Grenadines"
msgstr ""

#: admin/class-settings.php:785
msgid "Saint Lucia"
msgstr ""

#: admin/class-settings.php:786
msgid "Samoa"
msgstr ""

#: admin/class-settings.php:787
msgid "San Marino"
msgstr ""

#: admin/class-settings.php:788
msgid "São Tomé and Príncipe"
msgstr ""

#: admin/class-settings.php:789
msgid "Saudi Arabia"
msgstr ""

#: admin/class-settings.php:790
msgid "Senegal"
msgstr ""

#: admin/class-settings.php:791
msgid "Serbia"
msgstr ""

#: admin/class-settings.php:792
msgid "Seychelles"
msgstr ""

#: admin/class-settings.php:793
msgid "Sierra Leone"
msgstr ""

#: admin/class-settings.php:794
msgid "Singapore"
msgstr ""

#: admin/class-settings.php:795
msgid "Sint Maarten"
msgstr ""

#: admin/class-settings.php:796
msgid "Slovakia"
msgstr ""

#: admin/class-settings.php:797
msgid "Slovenia"
msgstr ""

#: admin/class-settings.php:798
msgid "Solomon Islands"
msgstr ""

#: admin/class-settings.php:799
msgid "Somalia"
msgstr ""

#: admin/class-settings.php:800
msgid "South Africa"
msgstr ""

#: admin/class-settings.php:801
msgid "South Georgia and South Sandwich Islands"
msgstr ""

#: admin/class-settings.php:802
msgid "South Korea"
msgstr ""

#: admin/class-settings.php:803
msgid "South Sudan"
msgstr ""

#: admin/class-settings.php:804
msgid "Spain"
msgstr ""

#: admin/class-settings.php:805
msgid "Sri Lanka"
msgstr ""

#: admin/class-settings.php:806
msgid "Sudan"
msgstr ""

#: admin/class-settings.php:807
msgid "Swaziland"
msgstr ""

#: admin/class-settings.php:808
msgid "Sweden"
msgstr ""

#: admin/class-settings.php:809
msgid "Switzerland"
msgstr ""

#: admin/class-settings.php:810
msgid "Syria"
msgstr ""

#: admin/class-settings.php:811
msgid "São Tomé & Príncipe"
msgstr ""

#: admin/class-settings.php:812
msgid "Taiwan"
msgstr ""

#: admin/class-settings.php:813
msgid "Tajikistan"
msgstr ""

#: admin/class-settings.php:814
msgid "Tanzania"
msgstr ""

#: admin/class-settings.php:815
msgid "Thailand"
msgstr ""

#: admin/class-settings.php:816
msgid "Timor-Leste"
msgstr ""

#: admin/class-settings.php:817 admin/class-settings.php:819
msgid "Tokelau"
msgstr ""

#: admin/class-settings.php:818
msgid "Togo"
msgstr ""

#: admin/class-settings.php:820
msgid "Tonga"
msgstr ""

#: admin/class-settings.php:821
msgid "Trinidad and Tobago"
msgstr ""

#: admin/class-settings.php:822
msgid "Tristan da Cunha"
msgstr ""

#: admin/class-settings.php:823
msgid "Tunisia"
msgstr ""

#: admin/class-settings.php:824
msgid "Turkey"
msgstr ""

#: admin/class-settings.php:825
msgid "Turkmenistan"
msgstr ""

#: admin/class-settings.php:826
msgid "Turks and Caicos Islands"
msgstr ""

#: admin/class-settings.php:827
msgid "Tuvalu"
msgstr ""

#: admin/class-settings.php:828
msgid "Uganda"
msgstr ""

#: admin/class-settings.php:829
msgid "Ukraine"
msgstr ""

#: admin/class-settings.php:830
msgid "United Arab Emirates"
msgstr ""

#: admin/class-settings.php:831
msgid "United Kingdom"
msgstr ""

#: admin/class-settings.php:832
msgid "United States"
msgstr ""

#: admin/class-settings.php:833
msgid "Uruguay"
msgstr ""

#: admin/class-settings.php:834
msgid "Uzbekistan"
msgstr ""

#: admin/class-settings.php:835
msgid "Vanuatu"
msgstr ""

#: admin/class-settings.php:836
msgid "Vatican City"
msgstr ""

#: admin/class-settings.php:837
msgid "Venezuela"
msgstr ""

#: admin/class-settings.php:838
msgid "Vietnam"
msgstr ""

#: admin/class-settings.php:839
msgid "Wallis Futuna"
msgstr ""

#: admin/class-settings.php:840
msgid "Western Sahara"
msgstr ""

#: admin/class-settings.php:841
msgid "Yemen"
msgstr ""

#: admin/class-settings.php:842
msgid "Zambia"
msgstr ""

#: admin/class-settings.php:843
msgid "Zimbabwe"
msgstr ""

#: admin/class-settings.php:844
msgid "Åland Islands"
msgstr ""

#: admin/class-settings.php:887
msgid "World view"
msgstr ""

#: admin/class-settings.php:890 admin/class-settings.php:1004
#: inc/wpsl-functions.php:225
msgid "Default"
msgstr ""

#: admin/class-settings.php:893 inc/wpsl-functions.php:298
msgid "Roadmap"
msgstr ""

#: admin/class-settings.php:1034
msgid "Start location marker"
msgstr ""

#: admin/class-settings.php:1036
msgid "Store location marker"
msgstr ""

#: admin/class-settings.php:1116
msgid "Textarea"
msgstr ""

#: admin/class-settings.php:1117
msgid "Dropdowns (recommended)"
msgstr ""

#: admin/class-settings.php:1125
msgid "Bounces up and down"
msgstr ""

#: admin/class-settings.php:1126
msgid "Will open the info window"
msgstr ""

#: admin/class-settings.php:1127
msgid "Does not respond"
msgstr ""

#: admin/class-settings.php:1135
msgid "In the store listings"
msgstr ""

#: admin/class-settings.php:1136
msgid "In the info window on the map"
msgstr ""

#: admin/class-settings.php:1168 admin/class-shortcode-generator.php:263
msgid "Dropdown"
msgstr ""

#: admin/class-settings.php:1169 admin/class-shortcode-generator.php:264
msgid "Checkboxes"
msgstr ""

#: admin/class-settings.php:1201
msgid "12 Hours"
msgstr ""

#: admin/class-settings.php:1202
msgid "24 Hours"
msgstr ""

#: admin/class-shortcode-generator.php:42
msgid "WP Store Locator"
msgstr ""

#: admin/class-shortcode-generator.php:42
#: admin/class-shortcode-generator.php:355
msgid "Insert Store Locator"
msgstr ""

#: admin/class-shortcode-generator.php:61
msgid "You do not have permission to perform this action"
msgstr ""

#: admin/class-shortcode-generator.php:61
msgid "Error"
msgstr ""

#: admin/class-shortcode-generator.php:233
msgid "General Options"
msgstr ""

#: admin/class-shortcode-generator.php:234 admin/templates/map-settings.php:398
msgid "Markers"
msgstr ""

#: admin/class-shortcode-generator.php:240
msgid "Select the used template"
msgstr ""

#: admin/class-shortcode-generator.php:244 admin/templates/map-settings.php:225
msgid "Start point"
msgstr ""

#: admin/class-shortcode-generator.php:244
#, php-format
msgid ""
"If nothing it set, then the start point from the %ssettings%s page is used."
msgstr ""

#: admin/class-shortcode-generator.php:249 admin/templates/map-settings.php:211
msgid "Attempt to auto-locate the user"
msgstr ""

#: admin/class-shortcode-generator.php:249 admin/templates/map-settings.php:211
#, php-format
msgid ""
"Most modern browsers %srequire%s a HTTPS connection before the Geolocation "
"feature works."
msgstr ""

#: admin/class-shortcode-generator.php:259
msgid "Category filter type"
msgstr ""

#: admin/class-shortcode-generator.php:262
msgid "None"
msgstr ""

#: admin/class-shortcode-generator.php:269
msgid "Automatically restrict the returned results to one or more categories?"
msgstr ""

#: admin/class-shortcode-generator.php:285
msgid "Set a selected category?"
msgstr ""

#: admin/class-shortcode-generator.php:290
msgid "Select category"
msgstr ""

#: admin/class-shortcode-generator.php:306
msgid "Checkbox columns"
msgstr ""

#: admin/class-shortcode-generator.php:325
msgid "Set selected checkboxes"
msgstr ""

#: admin/class-shortcode-generator.php:341 admin/templates/map-settings.php:263
msgid "Map type"
msgstr ""

#: admin/roles.php:20
msgid "Store Locator Manager"
msgstr ""

#: admin/templates/add-ons.php:21
msgid "WP Store Locator Add-Ons"
msgstr ""

#: admin/templates/add-ons.php:41
msgid "Already Installed."
msgstr ""

#: admin/templates/add-ons.php:43
msgid "Coming soon!"
msgstr ""

#: admin/templates/add-ons.php:55
msgid "Failed to load the add-on list from the server."
msgstr ""

#: admin/templates/map-settings.php:13
msgid "General"
msgstr ""

#: admin/templates/map-settings.php:18
msgid "Licenses"
msgstr ""

#: admin/templates/map-settings.php:49
msgid "Add-On"
msgstr ""

#: admin/templates/map-settings.php:50
msgid "License Key"
msgstr ""

#: admin/templates/map-settings.php:51
msgid "License Expiry Date"
msgstr ""

#: admin/templates/map-settings.php:65
msgid "Deactivate License"
msgstr ""

#: admin/templates/map-settings.php:85 admin/templates/map-settings.php:128
#: admin/templates/map-settings.php:198 admin/templates/map-settings.php:281
#: admin/templates/map-settings.php:388 admin/templates/map-settings.php:416
#: admin/templates/map-settings.php:466 admin/templates/map-settings.php:498
#: admin/templates/map-settings.php:610 admin/templates/map-settings.php:663
msgid "Save Changes"
msgstr ""

#: admin/templates/map-settings.php:97
msgid "Google Maps API"
msgstr ""

#: admin/templates/map-settings.php:100
#, php-format
msgid ""
"A %sbrowser key%s allows you to monitor the usage of the Google Maps "
"%sJavaScript API%s. %s %sRequired%s for %sapplications%s created after June "
"22, 2016."
msgstr ""

#: admin/templates/map-settings.php:104
#, php-format
msgid ""
"A %sserver key%s allows you to monitor the usage of the Google Maps "
"%sGeocoding API%s. %s %sRequired%s for %sapplications%s created after June "
"22, 2016."
msgstr ""

#: admin/templates/map-settings.php:108
msgid "Validate API keys"
msgstr ""

#: admin/templates/map-settings.php:109
msgid "Show response "
msgstr ""

#: admin/templates/map-settings.php:112
msgid "Map language"
msgstr ""

#: admin/templates/map-settings.php:112
msgid "If no map language is selected the browser's prefered language is used."
msgstr ""

#: admin/templates/map-settings.php:118
msgid "Map region"
msgstr ""

#: admin/templates/map-settings.php:118
#, php-format
msgid ""
"This will bias the %sgeocoding%s results towards the selected region. %s If "
"no region is selected the bias is set to the United States."
msgstr ""

#: admin/templates/map-settings.php:124
msgid "Restrict the geocoding results to the selected map region?"
msgstr ""

#: admin/templates/map-settings.php:124
#, php-format
msgid ""
"If the %sgeocoding%s API finds more relevant results outside of the set map "
"region ( some location names exist in multiple regions ), the user will "
"likely see a \"No results found\" message. %s To rule this out you can "
"restrict the results to the set map region. %s You can modify the used "
"restrictions with %sthis%s filter."
msgstr ""

#: admin/templates/map-settings.php:138 admin/templates/map-settings.php:534
#: admin/templates/map-settings.php:535 admin/templates/map-settings.php:686
#: frontend/templates/default.php:44
#: frontend/templates/store-listings-below.php:44 inc/wpsl-functions.php:142
msgid "Search"
msgstr ""

#: admin/templates/map-settings.php:141
msgid "Enable autocomplete?"
msgstr ""

#: admin/templates/map-settings.php:146
msgid "Force zipcode only search"
msgstr ""

#: admin/templates/map-settings.php:150
#, php-format
msgid ""
"For this option to work correctly you need to set a map region and restrict "
"the results to the selected region. %s You can do this in the %sGoogle Maps "
"API section%s."
msgstr ""

#: admin/templates/map-settings.php:158
#, php-format
msgid ""
"Zipcode only search does unfortunately not work well in combination with the "
"autocomplete option. %s It's recommended to not have both options active at "
"the same time."
msgstr ""

#: admin/templates/map-settings.php:163
msgid "Show the max results dropdown?"
msgstr ""

#: admin/templates/map-settings.php:167
msgid "Show the search radius dropdown?"
msgstr ""

#: admin/templates/map-settings.php:171
msgid "Enable category filters?"
msgstr ""

#: admin/templates/map-settings.php:176
msgid "Filter type:"
msgstr ""

#: admin/templates/map-settings.php:181
msgid "Distance unit"
msgstr ""

#: admin/templates/map-settings.php:184
msgid "km"
msgstr ""

#: admin/templates/map-settings.php:186
msgid "mi"
msgstr ""

#: admin/templates/map-settings.php:190
msgid "Max search results"
msgstr ""

#: admin/templates/map-settings.php:190 admin/templates/map-settings.php:194
msgid "The default value is set between the [ ]."
msgstr ""

#: admin/templates/map-settings.php:194
msgid "Search radius options"
msgstr ""

#: admin/templates/map-settings.php:208
msgid "Map"
msgstr ""

#: admin/templates/map-settings.php:215
msgid "Load locations on page load"
msgstr ""

#: admin/templates/map-settings.php:220
msgid "Number of locations to show"
msgstr ""

#: admin/templates/map-settings.php:220
#, php-format
msgid ""
"Although the location data is cached after the first load, a lower number "
"will result in the map being more responsive. %s If this field is left empty "
"or set to 0, then all locations are loaded."
msgstr ""

#: admin/templates/map-settings.php:225
#, php-format
msgid ""
"%sRequired field.%s %s If auto-locating the user is disabled or fails, the "
"center of the provided city or country will be used as the initial starting "
"point for the user."
msgstr ""

#: admin/templates/map-settings.php:230
msgid "Auto adjust the zoom level to make sure all markers are visible?"
msgstr ""

#: admin/templates/map-settings.php:230
msgid ""
"This runs after a search is made, and makes sure all the returned locations "
"are visible in the viewport."
msgstr ""

#: admin/templates/map-settings.php:234
msgid "Initial zoom level"
msgstr ""

#: admin/templates/map-settings.php:238
msgid "Max auto zoom level"
msgstr ""

#: admin/templates/map-settings.php:238
#, php-format
msgid ""
"This value sets the zoom level for the \"Zoom here\" link in the info "
"window. %s It is also used to limit the zooming when the viewport of the map "
"is changed to make all the markers fit on the screen."
msgstr ""

#: admin/templates/map-settings.php:242
msgid "Show the street view controls?"
msgstr ""

#: admin/templates/map-settings.php:246
msgid "Show the map type control?"
msgstr ""

#: admin/templates/map-settings.php:250
msgid "Enable scroll wheel zooming?"
msgstr ""

#: admin/templates/map-settings.php:254
msgid "Zoom control position"
msgstr ""

#: admin/templates/map-settings.php:257
msgid "Left"
msgstr ""

#: admin/templates/map-settings.php:259
msgid "Right"
msgstr ""

#: admin/templates/map-settings.php:267
msgid "Map style"
msgstr ""

#: admin/templates/map-settings.php:267
msgid ""
"Custom map styles only work if the map type is set to \"Roadmap\" or "
"\"Terrain\"."
msgstr ""

#: admin/templates/map-settings.php:270
#, php-format
msgid ""
"You can use existing map styles from %sSnazzy Maps%s or %sMap Stylr%s and "
"paste it in the textarea below, or you can generate a custom map style "
"through the %sMap Style Editor%s or %sStyled Maps Wizard%s."
msgstr ""

#: admin/templates/map-settings.php:271
#, php-format
msgid ""
"If you like to write the style code yourself, then you can find the "
"documentation from Google %shere%s."
msgstr ""

#: admin/templates/map-settings.php:273
msgid "Preview Map Style"
msgstr ""

#: admin/templates/map-settings.php:277
msgid "Show credits?"
msgstr ""

#: admin/templates/map-settings.php:277
msgid ""
"This will place a \"Search provided by WP Store Locator\" backlink below the "
"map."
msgstr ""

#: admin/templates/map-settings.php:291
msgid "User Experience"
msgstr ""

#: admin/templates/map-settings.php:294
msgid "Store Locator height"
msgstr ""

#: admin/templates/map-settings.php:298
msgid "Max width for the info window content"
msgstr ""

#: admin/templates/map-settings.php:302
msgid "Search field width"
msgstr ""

#: admin/templates/map-settings.php:306
msgid "Search and radius label width"
msgstr ""

#: admin/templates/map-settings.php:310
msgid "Store Locator template"
msgstr ""

#: admin/templates/map-settings.php:310
#, php-format
msgid ""
"The selected template is used with the [wpsl] shortcode. %s You can add a "
"custom template with the %swpsl_templates%s filter."
msgstr ""

#: admin/templates/map-settings.php:314
msgid "Hide the scrollbar?"
msgstr ""

#: admin/templates/map-settings.php:318
msgid "Open links in a new window?"
msgstr ""

#: admin/templates/map-settings.php:322
msgid "Show a reset map button?"
msgstr ""

#: admin/templates/map-settings.php:326
msgid ""
"When a user clicks on \"Directions\", open a new window, and show the route "
"on google.com/maps ?"
msgstr ""

#: admin/templates/map-settings.php:330
msgid "Show a \"More info\" link in the store listings?"
msgstr ""

#: admin/templates/map-settings.php:330
msgid ""
"This places a \"More Info\" link below the address and will show the phone, "
"fax, email, opening hours and description once the link is clicked."
msgstr ""

#: admin/templates/map-settings.php:335
msgid "Where do you want to show the \"More info\" details?"
msgstr ""

#: admin/templates/map-settings.php:340
msgid ""
"Always show the contact details below the address in the search results?"
msgstr ""

#: admin/templates/map-settings.php:344
msgid "Make the contact details always clickable?"
msgstr ""

#: admin/templates/map-settings.php:348
msgid "Make the store name clickable if a store URL exists?"
msgstr ""

#: admin/templates/map-settings.php:348
#, php-format
msgid ""
"If %spermalinks%s are enabled, the store name will always link to the store "
"page."
msgstr ""

#: admin/templates/map-settings.php:352
msgid "Make the phone number clickable on mobile devices?"
msgstr ""

#: admin/templates/map-settings.php:356
msgid ""
"If street view is available for the current location, then show a \"Street "
"view\" link in the info window?"
msgstr ""

#: admin/templates/map-settings.php:356
#, php-format
msgid ""
"Enabling this option can sometimes result in a small delay in the opening of "
"the info window. %s This happens because an API request is made to Google "
"Maps to check if street view is available for the current location."
msgstr ""

#: admin/templates/map-settings.php:360
msgid "Show a \"Zoom here\" link in the info window?"
msgstr ""

#: admin/templates/map-settings.php:360
#, php-format
msgid ""
"Clicking this link will make the map zoom in to the %s max auto zoom level "
"%s."
msgstr ""

#: admin/templates/map-settings.php:364
msgid "On page load move the mouse cursor to the search field?"
msgstr ""

#: admin/templates/map-settings.php:364
#, php-format
msgid ""
"If the store locator is not placed at the top of the page, enabling this "
"feature can result in the page scrolling down. %s %sThis option is disabled "
"on mobile devices.%s"
msgstr ""

#: admin/templates/map-settings.php:368
msgid "Use the default style for the info window?"
msgstr ""

#: admin/templates/map-settings.php:368
#, php-format
msgid ""
"If the default style is disabled the %sInfoBox%s library will be used "
"instead. %s This enables you to easily change the look and feel of the info "
"window through the .wpsl-infobox css class."
msgstr ""

#: admin/templates/map-settings.php:372
msgid "Hide the country in the search results?"
msgstr ""

#: admin/templates/map-settings.php:376
msgid "Hide the distance in the search results?"
msgstr ""

#: admin/templates/map-settings.php:380
msgid "If a user hovers over the search results the store marker"
msgstr ""

#: admin/templates/map-settings.php:380
#, php-format
msgid ""
"If marker clusters are enabled this option will not work as expected as long "
"as the markers are clustered. %s The bouncing of the marker won't be visible "
"at all unless a user zooms in far enough for the marker cluster to change "
"back in to individual markers. %s The info window will open as expected, but "
"it won't be clear to which marker it belongs to. "
msgstr ""

#: admin/templates/map-settings.php:384
msgid "Address format"
msgstr ""

#: admin/templates/map-settings.php:384
#, php-format
msgid ""
"You can add custom address formats with the %swpsl_address_formats%s filter."
msgstr ""

#: admin/templates/map-settings.php:402
msgid "Enable marker clusters?"
msgstr ""

#: admin/templates/map-settings.php:402
msgid "Recommended for maps with a large amount of markers."
msgstr ""

#: admin/templates/map-settings.php:407
msgid "Max zoom level"
msgstr ""

#: admin/templates/map-settings.php:407
msgid ""
"If this zoom level is reached or exceeded, then all markers are moved out of "
"the marker cluster and shown as individual markers."
msgstr ""

#: admin/templates/map-settings.php:411
msgid "Cluster size"
msgstr ""

#: admin/templates/map-settings.php:411
#, php-format
msgid ""
"The grid size of a cluster in pixels. %s A larger number will result in a "
"lower amount of clusters and also make the algorithm run faster."
msgstr ""

#: admin/templates/map-settings.php:426
msgid "Store Editor"
msgstr ""

#: admin/templates/map-settings.php:429
msgid "Default country"
msgstr ""

#: admin/templates/map-settings.php:433
msgid "Map type for the location preview"
msgstr ""

#: admin/templates/map-settings.php:437
msgid "Hide the opening hours?"
msgstr ""

#: admin/templates/map-settings.php:443
msgid "Opening hours input type"
msgstr ""

#: admin/templates/map-settings.php:447
#, php-format
msgid ""
"Opening hours created in version 1.x %sare not%s automatically converted to "
"the new dropdown format."
msgstr ""

#: admin/templates/map-settings.php:450 admin/templates/map-settings.php:459
msgid "The default opening hours"
msgstr ""

#: admin/templates/map-settings.php:456
msgid "Opening hours format"
msgstr ""

#: admin/templates/map-settings.php:463
msgid ""
"The default country and opening hours are only used when a new store is "
"created. So changing the default values will have no effect on existing "
"store locations."
msgstr ""

#: admin/templates/map-settings.php:476
msgid "Permalink"
msgstr ""

#: admin/templates/map-settings.php:479
msgid "Enable permalink?"
msgstr ""

#: admin/templates/map-settings.php:484
msgid "Remove the front base from the permalink structure?"
msgstr ""

#: admin/templates/map-settings.php:484
#, php-format
msgid ""
"The front base is set on the %spermalink settings%s page in the \"Custom "
"structure\" field. %s If a front base is set ( for example /blog/ ), then "
"enabling this option will remove it from the store locator permalinks."
msgstr ""

#: admin/templates/map-settings.php:488
msgid "Store slug"
msgstr ""

#: admin/templates/map-settings.php:492
msgid "Category slug"
msgstr ""

#: admin/templates/map-settings.php:495
#, php-format
msgid "The permalink slugs %smust be unique%s on your site."
msgstr ""

#: admin/templates/map-settings.php:508
msgid "Labels"
msgstr ""

#: admin/templates/map-settings.php:517
#, php-format
msgid "%sWarning!%s %sWPML%s, or a plugin using the WPML API is active."
msgstr ""

#: admin/templates/map-settings.php:518
msgid ""
"Please use the \"String Translations\" section in the used multilingual "
"plugin to change the labels. Changing them here will have no effect as long "
"as the multilingual plugin remains active."
msgstr ""

#: admin/templates/map-settings.php:522 admin/templates/map-settings.php:523
#: frontend/templates/default.php:12
#: frontend/templates/store-listings-below.php:12 inc/wpsl-functions.php:141
msgid "Your location"
msgstr ""

#: admin/templates/map-settings.php:526 admin/templates/map-settings.php:527
#: frontend/templates/default.php:21
#: frontend/templates/store-listings-below.php:21 inc/wpsl-functions.php:144
msgid "Search radius"
msgstr ""

#: admin/templates/map-settings.php:530 admin/templates/map-settings.php:531
#: frontend/class-frontend.php:1857 inc/wpsl-functions.php:145
msgid "No results found"
msgstr ""

#: admin/templates/map-settings.php:538
msgid "Searching (preloader text)"
msgstr ""

#: admin/templates/map-settings.php:539 frontend/class-frontend.php:1856
#: inc/wpsl-functions.php:143
msgid "Searching..."
msgstr ""

#: admin/templates/map-settings.php:542 admin/templates/map-settings.php:543
#: frontend/templates/default.php:30
#: frontend/templates/store-listings-below.php:30 inc/wpsl-functions.php:146
msgid "Results"
msgstr ""

#: admin/templates/map-settings.php:546 admin/upgrade.php:206
#: inc/wpsl-functions.php:160
msgid "Category filter"
msgstr ""

#: admin/templates/map-settings.php:547 frontend/class-frontend.php:1426
msgid "Category"
msgstr ""

#: admin/templates/map-settings.php:550
msgid "Category first item"
msgstr ""

#: admin/templates/map-settings.php:551 admin/upgrade.php:367
#: frontend/class-frontend.php:1429 inc/wpsl-functions.php:161
msgid "Any"
msgstr ""

#: admin/templates/map-settings.php:554 admin/templates/map-settings.php:555
#: admin/upgrade.php:59 frontend/class-frontend.php:1858
#: frontend/underscore-functions.php:138 frontend/underscore-functions.php:168
#: inc/wpsl-functions.php:147
msgid "More info"
msgstr ""

#: admin/templates/map-settings.php:558 admin/templates/map-settings.php:559
#: frontend/class-frontend.php:843 frontend/underscore-functions.php:29
#: frontend/underscore-functions.php:65 frontend/underscore-functions.php:147
#: inc/wpsl-functions.php:155
msgid "Phone"
msgstr ""

#: admin/templates/map-settings.php:578 admin/templates/map-settings.php:579
#: frontend/class-frontend.php:1863 inc/wpsl-functions.php:140
msgid "Start location"
msgstr ""

#: admin/templates/map-settings.php:582
msgid "Get directions"
msgstr ""

#: admin/templates/map-settings.php:583 frontend/class-frontend.php:876
#: frontend/class-frontend.php:1861 inc/wpsl-functions.php:148
msgid "Directions"
msgstr ""

#: admin/templates/map-settings.php:586
msgid "No directions found"
msgstr ""

#: admin/templates/map-settings.php:587 admin/upgrade.php:151
#: frontend/class-frontend.php:1862 inc/wpsl-functions.php:149
msgid "No route could be found between the origin and destination"
msgstr ""

#: admin/templates/map-settings.php:590 admin/templates/map-settings.php:591
#: admin/upgrade.php:77 frontend/class-frontend.php:1864
#: inc/wpsl-functions.php:150
msgid "Back"
msgstr ""

#: admin/templates/map-settings.php:594 admin/templates/map-settings.php:595
#: admin/upgrade.php:143 frontend/class-frontend.php:1865
#: inc/wpsl-functions.php:151
msgid "Street view"
msgstr ""

#: admin/templates/map-settings.php:598 admin/templates/map-settings.php:599
#: admin/upgrade.php:147 frontend/class-frontend.php:1866
#: inc/wpsl-functions.php:152
msgid "Zoom here"
msgstr ""

#: admin/templates/map-settings.php:602
msgid "General error"
msgstr ""

#: admin/templates/map-settings.php:603 frontend/class-frontend.php:1859
#: inc/wpsl-functions.php:153
msgid "Something went wrong, please try again!"
msgstr ""

#: admin/templates/map-settings.php:606
msgid "Query limit error"
msgstr ""

#: admin/templates/map-settings.php:606
#, php-format
msgid ""
"You can raise the %susage limit%s by obtaining an API %skey%s, and fill in "
"the \"API key\" field at the top of this page."
msgstr ""

#: admin/templates/map-settings.php:607 frontend/class-frontend.php:1860
#: inc/wpsl-functions.php:154
msgid "API usage limit reached"
msgstr ""

#: admin/templates/map-settings.php:620
msgid "Tools"
msgstr ""

#: admin/templates/map-settings.php:623
msgid "Enable store locator debug?"
msgstr ""

#: admin/templates/map-settings.php:623
#, php-format
msgid ""
"This disables the WPSL transient cache. %sThe transient cache is only used "
"if the %sLoad locations on page load%s option is enabled."
msgstr ""

#: admin/templates/map-settings.php:627
msgid "Enable compatibility mode?"
msgstr ""

#: admin/templates/map-settings.php:627
#, php-format
msgid ""
"If the %sbrowser console%s shows the error below, then enabling this option "
"should fix it. %s %sYou have included the Google Maps API multiple times on "
"this page. This may cause unexpected errors.%s %s This error can in some "
"situations break the store locator map."
msgstr ""

#: admin/templates/map-settings.php:631
msgid "WPSL transients"
msgstr ""

#: admin/templates/map-settings.php:632
msgid "Clear store locator transient cache"
msgstr ""

#: admin/templates/map-settings.php:647
msgid "GDPR - Only load Google Maps after the user agrees to it?"
msgstr ""

#: admin/templates/map-settings.php:650
#, php-format
msgid "This option requires the %sBorlabs Cookie%s plugin."
msgstr ""

#: admin/templates/map-settings.php:652
#, php-format
msgid ""
"Make sure to wrap the Borlabs Cookie %sshortcode%s around the WPSL shortcode."
msgstr ""

#: admin/templates/map-settings.php:659
msgid "Show the Geocode API response for a location search "
msgstr ""

#: admin/templates/map-settings.php:660
msgid "Input location details"
msgstr ""

#: admin/templates/map-settings.php:680
msgid "Geocode API Response"
msgstr ""

#: admin/templates/map-settings.php:682
msgid "Note"
msgstr ""

#: admin/templates/map-settings.php:685
msgid "Location details"
msgstr ""

#: admin/templates/map-settings.php:688
msgid "API Status"
msgstr ""

#: admin/templates/map-settings.php:693
msgid "Map Preview"
msgstr ""

#: admin/templates/map-settings.php:694
msgid "API Response"
msgstr ""

#: admin/upgrade.php:73
msgid "info window"
msgstr ""

#: admin/upgrade.php:81
msgid "Reset"
msgstr ""

#: admin/upgrade.php:174 inc/wpsl-functions.php:133
msgid "stores"
msgstr ""

#: admin/upgrade.php:178 inc/wpsl-functions.php:134
msgid "store-category"
msgstr ""

#: admin/upgrade.php:449
#, php-format
msgid ""
"Because you updated WP Store Locator from version 1.x, the %s current store "
"locations need to be %sconverted%s to custom post types."
msgstr ""

#: admin/upgrade.php:470
#, php-format
msgid ""
"The script converting the locations timed out. %s You can click the \"Start "
"Converting\" button again to restart the script. %s If there are thousands "
"of store locations left to convert and you keep seeing this message, then "
"you can try to contact your host and ask if they can increase the maximum "
"execution time. %s The plugin tried to disable the maximum execution time, "
"but if you are reading this then that failed."
msgstr ""

#: admin/upgrade.php:491
msgid "Store locations to convert:"
msgstr ""

#: admin/upgrade.php:493
msgid "Start Converting"
msgstr ""

#: admin/upgrade.php:615
#, php-format
msgid ""
"All the store locations are now converted to custom post types. %s You can "
"view them on the %sAll Stores%s page."
msgstr ""

#: frontend/class-frontend.php:762
msgid ""
"If you use the [wpsl_address] shortcode outside a store page you need to set "
"the ID attribute."
msgstr ""

#: frontend/class-frontend.php:917
msgid ""
"If you use the [wpsl_hours] shortcode outside a store page you need to set "
"the ID attribute."
msgstr ""

#: frontend/class-frontend.php:965
msgid ""
"If you use the [wpsl_map] shortcode outside a store page, then you need to "
"set the ID or category attribute."
msgstr ""

#: frontend/class-frontend.php:1627
msgid "The application does not have permission to use the Geolocation API."
msgstr ""

#: frontend/class-frontend.php:1628
msgid "Location information is unavailable."
msgstr ""

#: frontend/class-frontend.php:1629
msgid "The geolocation request timed out."
msgstr ""

#: frontend/class-frontend.php:1630
msgid "An unknown error occurred."
msgstr ""

#: frontend/templates/default.php:62
#: frontend/templates/store-listings-below.php:68
#, php-format
msgid "Search provided by %sWP Store Locator%s"
msgstr ""

#: inc/class-borlabs-cookie.php:68
msgctxt "Borlabs Cookie"
msgid ""
"To protect your personal data, your connection to Google Maps has been "
"blocked.<br>Click on <strong>Load map</strong> to unblock Google Maps.<br>By "
"loading the map you accept the privacy policy of Google.<br>More information "
"about Google's privacy policy can be found here <a href=\"https://policies."
"google.com/privacy?hl=en&amp;gl=en\" target=\"_blank\" rel=\"nofollow"
"\">Google - Privacy &amp; Terms</a> . "
msgstr ""

#: inc/class-borlabs-cookie.php:69
msgctxt "Borlabs Cookie"
msgid "Do not block Google Maps in the future anymore."
msgstr ""

#: inc/class-borlabs-cookie.php:70
msgctxt "Borlabs Cookie"
msgid "Load map"
msgstr ""

#: inc/class-post-types.php:77
msgid "Store Locator"
msgstr ""

#: inc/class-post-types.php:78
msgid "All Stores"
msgstr ""

#: inc/class-post-types.php:79
msgid "Store"
msgstr ""

#: inc/class-post-types.php:80 inc/class-post-types.php:83
msgid "New Store"
msgstr ""

#: inc/class-post-types.php:81
msgid "Add New Store"
msgstr ""

#: inc/class-post-types.php:82
msgid "Edit Store"
msgstr ""

#: inc/class-post-types.php:84
msgid "View Stores"
msgstr ""

#: inc/class-post-types.php:85
msgid "Search Stores"
msgstr ""

#: inc/class-post-types.php:86
msgid "No Stores found"
msgstr ""

#: inc/class-post-types.php:87
msgid "No Stores found in trash"
msgstr ""

#: inc/class-post-types.php:130 inc/class-post-types.php:140
msgid "Store Categories"
msgstr ""

#: inc/class-post-types.php:131
msgid "Store Category"
msgstr ""

#: inc/class-post-types.php:132
msgid "Search Store Categories"
msgstr ""

#: inc/class-post-types.php:133
msgid "All Store Categories"
msgstr ""

#: inc/class-post-types.php:134
msgid "Parent Store Category"
msgstr ""

#: inc/class-post-types.php:135
msgid "Parent Store Category:"
msgstr ""

#: inc/class-post-types.php:136
msgid "Edit Store Category"
msgstr ""

#: inc/class-post-types.php:137
msgid "Update Store Category"
msgstr ""

#: inc/class-post-types.php:138
msgid "Add New Store Category"
msgstr ""

#: inc/class-post-types.php:139
msgid "New Store Category Name"
msgstr ""

#: inc/class-post-types.php:171
msgid "Enter store title here"
msgstr ""

#: inc/class-post-types.php:189
msgid "Zip"
msgstr ""

#: inc/class-templates.php:76
#, php-format
msgid "No template found for %s"
msgstr ""

#: inc/class-templates.php:77
#, php-format
msgid ""
"Make sure you call the %sget_template_details%s function with the correct "
"parameters."
msgstr ""

#: inc/wpsl-functions.php:230
msgid "Show the store list below the map"
msgstr ""

#: inc/wpsl-functions.php:247
msgid "Monday"
msgstr ""

#: inc/wpsl-functions.php:248
msgid "Tuesday"
msgstr ""

#: inc/wpsl-functions.php:249
msgid "Wednesday"
msgstr ""

#: inc/wpsl-functions.php:250
msgid "Thursday"
msgstr ""

#: inc/wpsl-functions.php:251
msgid "Friday"
msgstr ""

#: inc/wpsl-functions.php:252
msgid "Saturday"
msgstr ""

#: inc/wpsl-functions.php:253
msgid "Sunday"
msgstr ""

#: inc/wpsl-functions.php:283
#, php-format
msgid "Mon %sTue %sWed %sThu %sFri %sSat Closed %sSun Closed"
msgstr ""

#: inc/wpsl-functions.php:299
msgid "Satellite"
msgstr ""

#: inc/wpsl-functions.php:300
msgid "Hybrid"
msgstr ""

#: inc/wpsl-functions.php:301
msgid "Terrain"
msgstr ""

#: inc/wpsl-functions.php:316
msgid "(city) (state) (zip code)"
msgstr ""

#: inc/wpsl-functions.php:317
msgid "(city), (state) (zip code)"
msgstr ""

#: inc/wpsl-functions.php:318
msgid "(city) (zip code)"
msgstr ""

#: inc/wpsl-functions.php:319
msgid "(city), (zip code)"
msgstr ""

#: inc/wpsl-functions.php:320
msgid "(zip code) (city) (state)"
msgstr ""

#: inc/wpsl-functions.php:321
msgid "(zip code) (city)"
msgstr ""
languages/wpsl-pt_PT.po000064400000167021151327220640011074 0ustar00msgid ""
msgstr ""
"Project-Id-Version: WP Store Locator v2.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-09-01 13:49+0100\n"
"PO-Revision-Date: 2015-09-05 13:48-0000\n"
"Last-Translator: Rúben Martins <geral@rubenmartins.pt>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.6.4\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;"
"_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2\n"
"X-Poedit-Basepath: ../\n"
"X-Textdomain-Support: yes\n"
"Language: pt_PT\n"
"X-Poedit-SearchPath-0: .\n"

#: admin/class-admin.php:118
#, php-format
msgid ""
"Before adding the [wpsl] shortcode to a page, please don't forget to define "
"a %sstart point%s. %sDismiss%s"
msgstr ""
"Antes de adicionar o shortcode [WPSL] para uma página, por favor, não se "
"esqueça de definir %sum ponto de inicio%s. %sRemover%s"

#: admin/class-admin.php:120
#, php-format
msgid ""
"Before adding the [wpsl] shortcode to a page, please don't forget to define "
"a start point on the %ssettings%s page. %sDismiss%s"
msgstr ""
"Antes de adicionar o shortcode [WPSL] para uma página, por favor, não se "
"esqueça de definir um ponto de partida na página de %sdefinições%s. %sAnular"
"%s"

#: admin/class-admin.php:150 admin/templates/map-settings.php:4
msgid "Settings"
msgstr "Definições"

#: admin/class-admin.php:264
msgid "Cannot determine the address at this location."
msgstr "Não é possível determinar o endereço nesta localização."

#: admin/class-admin.php:265
msgid "Geocode was not successful for the following reason"
msgstr "Geocodificação não foi bem sucedida pelo seguinte motivo"

#: admin/class-admin.php:266 admin/upgrade.php:393
msgid "Security check failed, reload the page and try again."
msgstr ""
"Verificação de segurança falhou, recarregue a página e tente novamente."

#: admin/class-admin.php:267
msgid "Please fill in all the required store details."
msgstr "Por favor, preencha todos os detalhes necessários da loja."

#: admin/class-admin.php:268
msgid "The map preview requires all the location details."
msgstr "A pré-visualização de mapa exige todos os detalhes da localização."

#: admin/class-admin.php:269 admin/class-metaboxes.php:504
#: frontend/class-frontend.php:483
msgid "Closed"
msgstr "Fechado"

#: admin/class-admin.php:270
msgid "The code for the map style is invalid."
msgstr "O código para o estilo de mapa é inválido."

#: admin/class-admin.php:361
msgid "Welcome to WP Store Locator"
msgstr "Bem-vindo ao WP Store Locator"

#: admin/class-admin.php:362
msgid "Sign up for the latest plugin updates and announcements."
msgstr "Registe-se para as últimas atualizações de plugin e anúncios."

#: admin/class-admin.php:406
msgid "Documentation"
msgstr "Documentação"

#: admin/class-admin.php:409
msgid "General Settings"
msgstr "Definições Gerais"

#: admin/class-admin.php:429
#, php-format
msgid "If you like this plugin please leave us a %s5 star%s rating."
msgstr ""
"Se gosta deste plugin, por favor deixe-nos uma classificação de %s5 estrelas"
"%s."

#: admin/class-geocode.php:73
msgid ""
"The Google Geocoding API returned no results for the supplied address. "
"Please change the address and try again."
msgstr ""
"O Google Geocoding API nao retornou resultados para o endereço fornecido. "
"Por favor, altere o endereço e tente novamente."

#: admin/class-geocode.php:76
#, php-format
msgid ""
"You have reached the daily allowed geocoding limit, you can read more %shere"
"%s."
msgstr ""
"Você atingiu o limite diário de geocodificação permitido, você pode ler mais "
"%saqui%s."

#: admin/class-geocode.php:79 admin/class-geocode.php:105
msgid ""
"The Google Geocoding API failed to return valid data, please try again later."
msgstr ""
"O Google Geocoding API não conseguiu retornar dados válidos, por favor, "
"tente novamente mais tarde."

#: admin/class-metaboxes.php:33
msgid "Store Details"
msgstr "Detalhes da Loja"

#: admin/class-metaboxes.php:34
msgid "Store Map"
msgstr "Mapa da Loja"

#: admin/class-metaboxes.php:48
msgid "Location"
msgstr "Localização"

#: admin/class-metaboxes.php:50 inc/class-post-types.php:162
msgid "Address"
msgstr "Morada"

#: admin/class-metaboxes.php:54
msgid "Address 2"
msgstr "Morada 2"

#: admin/class-metaboxes.php:57 inc/class-post-types.php:163
msgid "City"
msgstr "Cidade"

#: admin/class-metaboxes.php:61 inc/class-post-types.php:164
msgid "State"
msgstr "Estado"

#: admin/class-metaboxes.php:64
msgid "Zip Code"
msgstr "Código Postal"

#: admin/class-metaboxes.php:67
msgid "Country"
msgstr "País"

#: admin/class-metaboxes.php:74
msgid "Latitude"
msgstr "Latitude"

#: admin/class-metaboxes.php:77
msgid "Longitude"
msgstr "Longitude"

#: admin/class-metaboxes.php:80 admin/class-metaboxes.php:129
#: admin/class-metaboxes.php:144
msgid "Opening Hours"
msgstr "Horas de Abertura"

#: admin/class-metaboxes.php:82 admin/templates/map-settings.php:419
#: admin/templates/map-settings.php:420 frontend/underscore-functions.php:133
#: inc/wpsl-functions.php:114
msgid "Hours"
msgstr "Horas"

#: admin/class-metaboxes.php:86
msgid "Additional Information"
msgstr "Informação Adicional"

#: admin/class-metaboxes.php:88
msgid "Tel"
msgstr "Tel"

#: admin/class-metaboxes.php:91 admin/templates/map-settings.php:407
#: admin/templates/map-settings.php:408 frontend/class-frontend.php:665
#: frontend/underscore-functions.php:32 frontend/underscore-functions.php:124
#: inc/wpsl-functions.php:111
msgid "Fax"
msgstr "Fax"

#: admin/class-metaboxes.php:94 admin/templates/map-settings.php:411
#: admin/templates/map-settings.php:412 admin/upgrade.php:210
#: frontend/class-frontend.php:669 frontend/underscore-functions.php:35
#: frontend/underscore-functions.php:127 inc/wpsl-functions.php:112
msgid "Email"
msgstr "E-mail"

#: admin/class-metaboxes.php:97 admin/templates/map-settings.php:415
#: admin/templates/map-settings.php:416 admin/upgrade.php:214
#: frontend/class-frontend.php:674 inc/wpsl-functions.php:113
msgid "Url"
msgstr "Url"

#: admin/class-metaboxes.php:426
msgid "Hour format"
msgstr "Formato de horas"

#: admin/class-metaboxes.php:433
msgid "Days"
msgstr "Dias"

#: admin/class-metaboxes.php:434
msgid "Opening Periods"
msgstr "Horário de Funcionamento"

#: admin/class-metaboxes.php:681
msgid "Failed to publish the store. Please fill in the required store details."
msgstr ""
"Falha ao publicar a loja. Por favor, preencha os detalhes necessários da "
"loja."

#: admin/class-metaboxes.php:816
msgid "Preview Location"
msgstr "Pré-visualizar localização"

#: admin/class-metaboxes.php:817
#, php-format
msgid ""
"The map preview is based on the provided address, city and country details. "
"%s It will ignore any custom latitude or longitude values."
msgstr ""
"A pré-visualização do mapa é baseado no endereço, cidade e país fornecidos. "
"%s Irá ignorar quaisquer valores de latitude ou longitude personalizados."

#: admin/class-metaboxes.php:818
msgid "You can drag the marker to adjust the exact location of the marker."
msgstr "Você pode arrastar o marcador para ajustar ao local exato do marcador."

#: admin/class-metaboxes.php:838 admin/class-metaboxes.php:841
msgid "Store updated."
msgstr "Loja atualizada."

#: admin/class-metaboxes.php:839
msgid "Custom field updated."
msgstr "Campo personalizado atualizado."

#: admin/class-metaboxes.php:840
msgid "Custom field deleted."
msgstr "Campo personalizado apagado."

#: admin/class-metaboxes.php:842
#, php-format
msgid "Store restored to revision from %s"
msgstr "Loja restaurada para revisão de% s"

#: admin/class-metaboxes.php:843
msgid "Store published."
msgstr "Loja publicada."

#: admin/class-metaboxes.php:844
msgid "Store saved."
msgstr "Loja Guardada."

#: admin/class-metaboxes.php:845
msgid "Store submitted."
msgstr "Loja submetida."

#: admin/class-metaboxes.php:847
#, php-format
msgid "Store scheduled for: <strong>%1$s</strong>."
msgstr "Loja agendada para: <strong>%1$s</strong>."

#: admin/class-metaboxes.php:848
msgid "M j, Y @ G:i"
msgstr "j M, Y @ G:i"

#: admin/class-metaboxes.php:850
msgid "Store draft updated."
msgstr "Rascunho de loja atualizado."

#: admin/class-metaboxes.php:856
msgid "View store"
msgstr "Ver loja"

#: admin/class-metaboxes.php:862
msgid "Preview store"
msgstr "Pré-visualizar loja"

#: admin/class-settings.php:38
msgid "WP Store Locator Transients Cleared"
msgstr "Cache temporário de WP Store Locator apagado"

#: admin/class-settings.php:370
msgid ""
"The max results field cannot be empty, the default value has been restored."
msgstr ""
"O campo de máximo resultados não pode estar vazio, o valor padrão foi "
"restaurado."

#: admin/class-settings.php:373
msgid ""
"The search radius field cannot be empty, the default value has been restored."
msgstr ""
"O campo de raio de pesquisa não pode estar vazio, o valor padrão foi "
"restaurado."

#: admin/class-settings.php:376
#, php-format
msgid ""
"Please provide the name of a city or country that can be used as a starting "
"point under \"Map Settings\". %s This will only be used if auto-locating the "
"user fails, or the option itself is disabled."
msgstr ""
"Por favor, forneça o nome de uma cidade ou país que pode ser usado como um "
"ponto de partida em \"Definições do mapa\". %s Isso só será usado se a auto-"
"localização do utilizador falhar, ou a própria opção estiver desativada."

#: admin/class-settings.php:397
msgid "Select your language"
msgstr "Selecione o seu idioma"

#: admin/class-settings.php:398
msgid "English"
msgstr "English"

#: admin/class-settings.php:399
msgid "Arabic"
msgstr "Arabic"

#: admin/class-settings.php:400
msgid "Basque"
msgstr "Basque"

#: admin/class-settings.php:401
msgid "Bulgarian"
msgstr "Bulgarian"

#: admin/class-settings.php:402
msgid "Bengali"
msgstr "Bengali"

#: admin/class-settings.php:403
msgid "Catalan"
msgstr "Catalan"

#: admin/class-settings.php:404
msgid "Czech"
msgstr "Czech"

#: admin/class-settings.php:405
msgid "Danish"
msgstr "Danish"

#: admin/class-settings.php:406
msgid "German"
msgstr "German"

#: admin/class-settings.php:407
msgid "Greek"
msgstr "Greek"

#: admin/class-settings.php:408
msgid "English (Australian)"
msgstr "English (Australian)"

#: admin/class-settings.php:409
msgid "English (Great Britain)"
msgstr "English (Great Britain)"

#: admin/class-settings.php:410
msgid "Spanish"
msgstr "Spanish"

#: admin/class-settings.php:411
msgid "Farsi"
msgstr "Farsi"

#: admin/class-settings.php:412
msgid "Finnish"
msgstr "Finnish"

#: admin/class-settings.php:413
msgid "Filipino"
msgstr "Filipino"

#: admin/class-settings.php:414
msgid "French"
msgstr "French"

#: admin/class-settings.php:415
msgid "Galician"
msgstr "Galician"

#: admin/class-settings.php:416
msgid "Gujarati"
msgstr "Gujarati"

#: admin/class-settings.php:417
msgid "Hindi"
msgstr "Hindi"

#: admin/class-settings.php:418
msgid "Croatian"
msgstr "Croatian"

#: admin/class-settings.php:419
msgid "Hungarian"
msgstr "Hungarian"

#: admin/class-settings.php:420
msgid "Indonesian"
msgstr "Indonesian"

#: admin/class-settings.php:421
msgid "Italian"
msgstr "Italian"

#: admin/class-settings.php:422
msgid "Hebrew"
msgstr "Hebrew"

#: admin/class-settings.php:423
msgid "Japanese"
msgstr "Japanese"

#: admin/class-settings.php:424
msgid "Kannada"
msgstr "Kannada"

#: admin/class-settings.php:425
msgid "Korean"
msgstr "Korean"

#: admin/class-settings.php:426
msgid "Lithuanian"
msgstr "Lithuanian"

#: admin/class-settings.php:427
msgid "Latvian"
msgstr "Latvian"

#: admin/class-settings.php:428
msgid "Malayalam"
msgstr "Malayalam"

#: admin/class-settings.php:429
msgid "Marathi"
msgstr "Marathi"

#: admin/class-settings.php:430
msgid "Dutch"
msgstr "Dutch"

#: admin/class-settings.php:431
msgid "Norwegian"
msgstr "Norwegian"

#: admin/class-settings.php:432
msgid "Norwegian Nynorsk"
msgstr "Norwegian Nynorsk"

#: admin/class-settings.php:433
msgid "Polish"
msgstr "Polish"

#: admin/class-settings.php:434
msgid "Portuguese"
msgstr "Portuguese"

#: admin/class-settings.php:435
msgid "Portuguese (Brazil)"
msgstr "Portuguese (Brazil)"

#: admin/class-settings.php:436
msgid "Portuguese (Portugal)"
msgstr "Portuguese (Portugal)"

#: admin/class-settings.php:437
msgid "Romanian"
msgstr "Romanian"

#: admin/class-settings.php:438
msgid "Russian"
msgstr "Russian"

#: admin/class-settings.php:439
msgid "Slovak"
msgstr "Slovak"

#: admin/class-settings.php:440
msgid "Slovenian"
msgstr "Slovenian"

#: admin/class-settings.php:441
msgid "Serbian"
msgstr "Serbian"

#: admin/class-settings.php:442
msgid "Swedish"
msgstr "Swedish"

#: admin/class-settings.php:443
msgid "Tagalog"
msgstr "Tagalog"

#: admin/class-settings.php:444
msgid "Tamil"
msgstr "Tamil"

#: admin/class-settings.php:445
msgid "Telugu"
msgstr "Telugu"

#: admin/class-settings.php:446
msgid "Thai"
msgstr "Thai"

#: admin/class-settings.php:447
msgid "Turkish"
msgstr "Turkish"

#: admin/class-settings.php:448
msgid "Ukrainian"
msgstr "Ukrainian"

#: admin/class-settings.php:449
msgid "Vietnamese"
msgstr "Vietnamese"

#: admin/class-settings.php:450
msgid "Chinese (Simplified)"
msgstr "Chinese (Simplified)"

#: admin/class-settings.php:451
msgid "Chinese (Traditional)"
msgstr "Chinese (Traditional)"

#: admin/class-settings.php:456
msgid "Select your region"
msgstr "Selecione a sua região"

#: admin/class-settings.php:457
msgid "Afghanistan"
msgstr "Afghanistan"

#: admin/class-settings.php:458
msgid "Albania"
msgstr "Albania"

#: admin/class-settings.php:459
msgid "Algeria"
msgstr "Algeria"

#: admin/class-settings.php:460
msgid "American Samoa"
msgstr "American Samoa"

#: admin/class-settings.php:461
msgid "Andorra"
msgstr "Andorra"

#: admin/class-settings.php:462
msgid "Anguilla"
msgstr "Anguilla"

#: admin/class-settings.php:463
msgid "Angola"
msgstr "Angola"

#: admin/class-settings.php:464
msgid "Antigua and Barbuda"
msgstr "Antigua and Barbuda"

#: admin/class-settings.php:465
msgid "Argentina"
msgstr "Argentina"

#: admin/class-settings.php:466
msgid "Armenia"
msgstr "Armenia"

#: admin/class-settings.php:467
msgid "Aruba"
msgstr "Aruba"

#: admin/class-settings.php:468
msgid "Australia"
msgstr "Australia"

#: admin/class-settings.php:469
msgid "Austria"
msgstr "Austria"

#: admin/class-settings.php:470
msgid "Azerbaijan"
msgstr "Azerbaijan"

#: admin/class-settings.php:471
msgid "Bahamas"
msgstr "Bahamas"

#: admin/class-settings.php:472
msgid "Bahrain"
msgstr "Bahrain"

#: admin/class-settings.php:473
msgid "Bangladesh"
msgstr "Bangladesh"

#: admin/class-settings.php:474
msgid "Barbados"
msgstr "Barbados"

#: admin/class-settings.php:475
msgid "Belarus"
msgstr "Belarus"

#: admin/class-settings.php:476
msgid "Belgium"
msgstr "Belgium"

#: admin/class-settings.php:477
msgid "Belize"
msgstr "Belize"

#: admin/class-settings.php:478
msgid "Benin"
msgstr "Benin"

#: admin/class-settings.php:479
msgid "Bermuda"
msgstr "Bermuda"

#: admin/class-settings.php:480
msgid "Bhutan"
msgstr "Bhutan"

#: admin/class-settings.php:481
msgid "Bolivia"
msgstr "Bolivia"

#: admin/class-settings.php:482
msgid "Bosnia and Herzegovina"
msgstr "Bosnia and Herzegovina"

#: admin/class-settings.php:483
msgid "Botswana"
msgstr "Botswana"

#: admin/class-settings.php:484
msgid "Brazil"
msgstr "Brazil"

#: admin/class-settings.php:485
msgid "British Indian Ocean Territory"
msgstr "British Indian Ocean Territory"

#: admin/class-settings.php:486
msgid "Brunei"
msgstr "Brunei"

#: admin/class-settings.php:487
msgid "Bulgaria"
msgstr "Bulgaria"

#: admin/class-settings.php:488
msgid "Burkina Faso"
msgstr "Burkina Faso"

#: admin/class-settings.php:489
msgid "Burundi"
msgstr "Burundi"

#: admin/class-settings.php:490
msgid "Cambodia"
msgstr "Cambodia"

#: admin/class-settings.php:491
msgid "Cameroon"
msgstr "Cameroon"

#: admin/class-settings.php:492
msgid "Canada"
msgstr "Canada"

#: admin/class-settings.php:493
msgid "Cape Verde"
msgstr "Cape Verde"

#: admin/class-settings.php:494
msgid "Cayman Islands"
msgstr "Cayman Islands"

#: admin/class-settings.php:495
msgid "Central African Republic"
msgstr "Central African Republic"

#: admin/class-settings.php:496
msgid "Chad"
msgstr "Chad"

#: admin/class-settings.php:497
msgid "Chile"
msgstr "Chile"

#: admin/class-settings.php:498
msgid "China"
msgstr "China"

#: admin/class-settings.php:499
msgid "Christmas Island"
msgstr "Christmas Island"

#: admin/class-settings.php:500
msgid "Cocos Islands"
msgstr "Cocos Islands"

#: admin/class-settings.php:501
msgid "Colombia"
msgstr "Colombia"

#: admin/class-settings.php:502
msgid "Comoros"
msgstr "Comoros"

#: admin/class-settings.php:503
msgid "Congo"
msgstr "Congo"

#: admin/class-settings.php:504
msgid "Costa Rica"
msgstr "Costa Rica"

#: admin/class-settings.php:505
msgid "Côte d'Ivoire"
msgstr "Côte d'Ivoire"

#: admin/class-settings.php:506
msgid "Croatia"
msgstr "Croatia"

#: admin/class-settings.php:507
msgid "Cuba"
msgstr "Cuba"

#: admin/class-settings.php:508
msgid "Czech Republic"
msgstr "Czech Republic"

#: admin/class-settings.php:509
msgid "Denmark"
msgstr "Denmark"

#: admin/class-settings.php:510
msgid "Djibouti"
msgstr "Djibouti"

#: admin/class-settings.php:511
msgid "Democratic Republic of the Congo"
msgstr "Democratic Republic of the Congo"

#: admin/class-settings.php:512
msgid "Dominica"
msgstr "Dominica"

#: admin/class-settings.php:513
msgid "Dominican Republic"
msgstr "Dominican Republic"

#: admin/class-settings.php:514
msgid "Ecuador"
msgstr "Ecuador"

#: admin/class-settings.php:515
msgid "Egypt"
msgstr "Egypt"

#: admin/class-settings.php:516
msgid "El Salvador"
msgstr "El Salvador"

#: admin/class-settings.php:517
msgid "Equatorial Guinea"
msgstr "Equatorial Guinea"

#: admin/class-settings.php:518
msgid "Eritrea"
msgstr "Eritrea"

#: admin/class-settings.php:519
msgid "Estonia"
msgstr "Estonia"

#: admin/class-settings.php:520
msgid "Ethiopia"
msgstr "Ethiopia"

#: admin/class-settings.php:521
msgid "Fiji"
msgstr "Fiji"

#: admin/class-settings.php:522
msgid "Finland"
msgstr "Finland"

#: admin/class-settings.php:523
msgid "France"
msgstr "France"

#: admin/class-settings.php:524
msgid "French Guiana"
msgstr "French Guiana"

#: admin/class-settings.php:525
msgid "Gabon"
msgstr "Gabon"

#: admin/class-settings.php:526
msgid "Gambia"
msgstr "Gambia"

#: admin/class-settings.php:527
msgid "Germany"
msgstr "Germany"

#: admin/class-settings.php:528
msgid "Ghana"
msgstr "Ghana"

#: admin/class-settings.php:529
msgid "Greenland"
msgstr "Greenland"

#: admin/class-settings.php:530
msgid "Greece"
msgstr "Greece"

#: admin/class-settings.php:531
msgid "Grenada"
msgstr "Grenada"

#: admin/class-settings.php:532
msgid "Guam"
msgstr "Guam"

#: admin/class-settings.php:533
msgid "Guadeloupe"
msgstr "Guadeloupe"

#: admin/class-settings.php:534
msgid "Guatemala"
msgstr "Guatemala"

#: admin/class-settings.php:535
msgid "Guinea"
msgstr "Guinea"

#: admin/class-settings.php:536
msgid "Guinea-Bissau"
msgstr "Guinea-Bissau"

#: admin/class-settings.php:537
msgid "Haiti"
msgstr "Haiti"

#: admin/class-settings.php:538
msgid "Honduras"
msgstr "Honduras"

#: admin/class-settings.php:539
msgid "Hong Kong"
msgstr "Hong Kong"

#: admin/class-settings.php:540
msgid "Hungary"
msgstr "Hungary"

#: admin/class-settings.php:541
msgid "Iceland"
msgstr "Iceland"

#: admin/class-settings.php:542
msgid "India"
msgstr "India"

#: admin/class-settings.php:543
msgid "Indonesia"
msgstr "Indonesia"

#: admin/class-settings.php:544
msgid "Iran"
msgstr "Iran"

#: admin/class-settings.php:545
msgid "Iraq"
msgstr "Iraq"

#: admin/class-settings.php:546
msgid "Ireland"
msgstr "Ireland"

#: admin/class-settings.php:547
msgid "Israel"
msgstr "Israel"

#: admin/class-settings.php:548
msgid "Italy"
msgstr "Italy"

#: admin/class-settings.php:549
msgid "Jamaica"
msgstr "Jamaica"

#: admin/class-settings.php:550
msgid "Japan"
msgstr "Japan"

#: admin/class-settings.php:551
msgid "Jordan"
msgstr "Jordan"

#: admin/class-settings.php:552
msgid "Kazakhstan"
msgstr "Kazakhstan"

#: admin/class-settings.php:553
msgid "Kenya"
msgstr "Kenya"

#: admin/class-settings.php:554
msgid "Kuwait"
msgstr "Kuwait"

#: admin/class-settings.php:555
msgid "Kyrgyzstan"
msgstr "Kyrgyzstan"

#: admin/class-settings.php:556
msgid "Laos"
msgstr "Laos"

#: admin/class-settings.php:557
msgid "Latvia"
msgstr "Latvia"

#: admin/class-settings.php:558
msgid "Lebanon"
msgstr "Lebanon"

#: admin/class-settings.php:559
msgid "Lesotho"
msgstr "Lesotho"

#: admin/class-settings.php:560
msgid "Liberia"
msgstr "Liberia"

#: admin/class-settings.php:561
msgid "Libya"
msgstr "Libya"

#: admin/class-settings.php:562
msgid "Liechtenstein"
msgstr "Liechtenstein"

#: admin/class-settings.php:563
msgid "Lithuania"
msgstr "Lithuania"

#: admin/class-settings.php:564
msgid "Luxembourg"
msgstr "Luxembourg"

#: admin/class-settings.php:565
msgid "Macau"
msgstr "Macau"

#: admin/class-settings.php:566
msgid "Macedonia"
msgstr "Macedonia"

#: admin/class-settings.php:567
msgid "Madagascar"
msgstr "Madagascar"

#: admin/class-settings.php:568
msgid "Malawi"
msgstr "Malawi"

#: admin/class-settings.php:569
msgid "Malaysia "
msgstr "Malaysia "

#: admin/class-settings.php:570
msgid "Mali"
msgstr "Mali"

#: admin/class-settings.php:571
msgid "Marshall Islands"
msgstr "Marshall Islands"

#: admin/class-settings.php:572
msgid "Martinique"
msgstr "Martinique"

#: admin/class-settings.php:573
msgid "Mauritania"
msgstr "Mauritania"

#: admin/class-settings.php:574
msgid "Mauritius"
msgstr "Mauritius"

#: admin/class-settings.php:575
msgid "Mexico"
msgstr "Mexico"

#: admin/class-settings.php:576
msgid "Micronesia"
msgstr "Micronesia"

#: admin/class-settings.php:577
msgid "Moldova"
msgstr "Moldova"

#: admin/class-settings.php:578
msgid "Monaco"
msgstr "Monaco"

#: admin/class-settings.php:579
msgid "Mongolia"
msgstr "Mongolia"

#: admin/class-settings.php:580
msgid "Montenegro"
msgstr "Montenegro"

#: admin/class-settings.php:581
msgid "Montserrat"
msgstr "Montserrat"

#: admin/class-settings.php:582
msgid "Morocco"
msgstr "Morocco"

#: admin/class-settings.php:583
msgid "Mozambique"
msgstr "Mozambique"

#: admin/class-settings.php:584
msgid "Myanmar"
msgstr "Myanmar"

#: admin/class-settings.php:585
msgid "Namibia"
msgstr "Namibia"

#: admin/class-settings.php:586
msgid "Nauru"
msgstr "Nauru"

#: admin/class-settings.php:587
msgid "Nepal"
msgstr "Nepal"

#: admin/class-settings.php:588
msgid "Netherlands"
msgstr "Netherlands"

#: admin/class-settings.php:589
msgid "Netherlands Antilles"
msgstr "Netherlands Antilles"

#: admin/class-settings.php:590
msgid "New Zealand"
msgstr "New Zealand"

#: admin/class-settings.php:591
msgid "Nicaragua"
msgstr "Nicaragua"

#: admin/class-settings.php:592
msgid "Niger"
msgstr "Niger"

#: admin/class-settings.php:593
msgid "Nigeria"
msgstr "Nigeria"

#: admin/class-settings.php:594
msgid "Niue"
msgstr "Niue"

#: admin/class-settings.php:595
msgid "Northern Mariana Islands"
msgstr "Northern Mariana Islands"

#: admin/class-settings.php:596
msgid "Norway"
msgstr "Norway"

#: admin/class-settings.php:597
msgid "Oman"
msgstr "Oman"

#: admin/class-settings.php:598
msgid "Pakistan"
msgstr "Pakistan"

#: admin/class-settings.php:599
msgid "Panama"
msgstr "Panama"

#: admin/class-settings.php:600
msgid "Papua New Guinea"
msgstr "Papua New Guinea"

#: admin/class-settings.php:601
msgid "Paraguay"
msgstr "Paraguay"

#: admin/class-settings.php:602
msgid "Peru"
msgstr "Peru"

#: admin/class-settings.php:603
msgid "Philippines"
msgstr "Philippines"

#: admin/class-settings.php:604
msgid "Pitcairn Islands"
msgstr "Pitcairn Islands"

#: admin/class-settings.php:605
msgid "Poland"
msgstr "Poland"

#: admin/class-settings.php:606
msgid "Portugal"
msgstr "Portugal"

#: admin/class-settings.php:607
msgid "Qatar"
msgstr "Qatar"

#: admin/class-settings.php:608
msgid "Reunion"
msgstr "Reunion"

#: admin/class-settings.php:609
msgid "Romania"
msgstr "Romania"

#: admin/class-settings.php:610
msgid "Russia"
msgstr "Russia"

#: admin/class-settings.php:611
msgid "Rwanda"
msgstr "Rwanda"

#: admin/class-settings.php:612
msgid "Saint Helena"
msgstr "Saint Helena"

#: admin/class-settings.php:613
msgid "Saint Kitts and Nevis"
msgstr "Saint Kitts and Nevis"

#: admin/class-settings.php:614
msgid "Saint Vincent and the Grenadines"
msgstr "Saint Vincent and the Grenadines"

#: admin/class-settings.php:615
msgid "Saint Lucia"
msgstr "Saint Lucia"

#: admin/class-settings.php:616
msgid "Samoa"
msgstr "Samoa"

#: admin/class-settings.php:617
msgid "San Marino"
msgstr "San Marino"

#: admin/class-settings.php:618
msgid "São Tomé and Príncipe"
msgstr "São Tomé and Príncipe"

#: admin/class-settings.php:619
msgid "Saudi Arabia"
msgstr "Saudi Arabia"

#: admin/class-settings.php:620
msgid "Senegal"
msgstr "Senegal"

#: admin/class-settings.php:621
msgid "Serbia"
msgstr "Serbia"

#: admin/class-settings.php:622
msgid "Seychelles"
msgstr "Seychelles"

#: admin/class-settings.php:623
msgid "Sierra Leone"
msgstr "Sierra Leone"

#: admin/class-settings.php:624
msgid "Singapore"
msgstr "Singapore"

#: admin/class-settings.php:625
msgid "Slovakia"
msgstr "Slovakia"

#: admin/class-settings.php:626
msgid "Solomon Islands"
msgstr "Solomon Islands"

#: admin/class-settings.php:627
msgid "Somalia"
msgstr "Somalia"

#: admin/class-settings.php:628
msgid "South Africa"
msgstr "South Africa"

#: admin/class-settings.php:629
msgid "South Korea"
msgstr "South Korea"

#: admin/class-settings.php:630
msgid "Spain"
msgstr "Spain"

#: admin/class-settings.php:631
msgid "Sri Lanka"
msgstr "Sri Lanka"

#: admin/class-settings.php:632
msgid "Sudan"
msgstr "Sudan"

#: admin/class-settings.php:633
msgid "Swaziland"
msgstr "Swaziland"

#: admin/class-settings.php:634
msgid "Sweden"
msgstr "Sweden"

#: admin/class-settings.php:635
msgid "Switzerland"
msgstr "Switzerland"

#: admin/class-settings.php:636
msgid "Syria"
msgstr "Syria"

#: admin/class-settings.php:637
msgid "Taiwan"
msgstr "Taiwan"

#: admin/class-settings.php:638
msgid "Tajikistan"
msgstr "Tajikistan"

#: admin/class-settings.php:639
msgid "Tanzania"
msgstr "Tanzania"

#: admin/class-settings.php:640
msgid "Thailand"
msgstr "Thailand"

#: admin/class-settings.php:641
msgid "Timor-Leste"
msgstr "Timor-Leste"

#: admin/class-settings.php:642
msgid "Tokelau"
msgstr "Tokelau"

#: admin/class-settings.php:643
msgid "Togo"
msgstr "Togo"

#: admin/class-settings.php:644
msgid "Tonga"
msgstr "Tonga"

#: admin/class-settings.php:645
msgid "Trinidad and Tobago"
msgstr "Trinidad and Tobago"

#: admin/class-settings.php:646
msgid "Tunisia"
msgstr "Tunisia"

#: admin/class-settings.php:647
msgid "Turkey"
msgstr "Turkey"

#: admin/class-settings.php:648
msgid "Turkmenistan"
msgstr "Turkmenistan"

#: admin/class-settings.php:649
msgid "Tuvalu"
msgstr "Tuvalu"

#: admin/class-settings.php:650
msgid "Uganda"
msgstr "Uganda"

#: admin/class-settings.php:651
msgid "Ukraine"
msgstr "Ukraine"

#: admin/class-settings.php:652
msgid "United Arab Emirates"
msgstr "United Arab Emirates"

#: admin/class-settings.php:653
msgid "United Kingdom"
msgstr "United Kingdom"

#: admin/class-settings.php:654
msgid "United States"
msgstr "United States"

#: admin/class-settings.php:655
msgid "Uruguay"
msgstr "Uruguay"

#: admin/class-settings.php:656
msgid "Uzbekistan"
msgstr "Uzbekistan"

#: admin/class-settings.php:657
msgid "Wallis Futuna"
msgstr "Wallis Futuna"

#: admin/class-settings.php:658
msgid "Venezuela"
msgstr "Venezuela"

#: admin/class-settings.php:659
msgid "Vietnam"
msgstr "Vietnam"

#: admin/class-settings.php:660
msgid "Yemen"
msgstr "Yemen"

#: admin/class-settings.php:661
msgid "Zambia"
msgstr "Zambia"

#: admin/class-settings.php:662
msgid "Zimbabwe"
msgstr "Zimbabwe"

#: admin/class-settings.php:705
msgid "World view"
msgstr "Visão de mundo"

#: admin/class-settings.php:708 admin/class-settings.php:821
#: inc/wpsl-functions.php:179
msgid "Default"
msgstr "Padrão"

#: admin/class-settings.php:711 inc/wpsl-functions.php:252
msgid "Roadmap"
msgstr "Mapa das estradas"

#: admin/class-settings.php:851
msgid "Start location marker"
msgstr "Marcador de inicio de localização"

#: admin/class-settings.php:853
msgid "Store location marker"
msgstr "Marcador de localização da loja"

#: admin/class-settings.php:934
msgid "Textarea"
msgstr "Área de Texto"

#: admin/class-settings.php:935
msgid "Dropdowns (recommended)"
msgstr "Dropdowns (recomendado)"

#: admin/class-settings.php:943
msgid "Bounces up and down"
msgstr "Balança para cima e para baixo"

#: admin/class-settings.php:944
msgid "Will open the info window"
msgstr "Irá abrir a janela de informações"

#: admin/class-settings.php:945
msgid "Does not respond"
msgstr "Não responde"

#: admin/class-settings.php:953
msgid "In the store listings"
msgstr "Na listagem de lojas"

#: admin/class-settings.php:954
msgid "In the info window on the map"
msgstr "Na janela de informações do mapa"

#: admin/class-settings.php:1010
msgid "12 Hours"
msgstr "12 Horas"

#: admin/class-settings.php:1011
msgid "24 Hours"
msgstr "24 Horas"

#: admin/roles.php:20
msgid "Store Locator Manager"
msgstr "Gestor do Store Locator"

#: admin/templates/map-settings.php:12
msgid "Google Maps API"
msgstr "API dos Mapas do Google"

#: admin/templates/map-settings.php:15
msgid "API key"
msgstr "Chave de API"

#: admin/templates/map-settings.php:15
#, php-format
msgid ""
"A valid %sAPI key%s allows you to monitor the API usage and is required if "
"you need to purchase additional quota."
msgstr ""
"A %schave de API%s válida permite que você monitorize o uso da API e é "
"necessário se você precisar de comprar quota adicional."

#: admin/templates/map-settings.php:16
msgid "Optional"
msgstr "Opcional"

#: admin/templates/map-settings.php:19
msgid "Map language"
msgstr "Linguagem de mapa"

#: admin/templates/map-settings.php:19
msgid "If no map language is selected the browser's prefered language is used."
msgstr ""
"Se nenhum idioma de mapa é selecionado, o idioma preferido do navegador é "
"usado."

#: admin/templates/map-settings.php:25
msgid "Map region"
msgstr "Região de mapa"

#: admin/templates/map-settings.php:25
#, php-format
msgid ""
"This will bias the geocoding results towards the selected region. %s If no "
"region is selected the bias is set to the United States."
msgstr ""
"Este será os resultados de geocodificação para a região selecionada. %s Se "
"nenhuma região for selecionada, o padrão é definido para os Estados Unidos."

#: admin/templates/map-settings.php:31 admin/templates/map-settings.php:73
#: admin/templates/map-settings.php:163 admin/templates/map-settings.php:256
#: admin/templates/map-settings.php:282 admin/templates/map-settings.php:332
#: admin/templates/map-settings.php:358 admin/templates/map-settings.php:455
#: admin/templates/map-settings.php:476
msgid "Save Changes"
msgstr "Guardar alterações"

#: admin/templates/map-settings.php:41 admin/templates/map-settings.php:383
#: admin/templates/map-settings.php:384 frontend/templates/default.php:43
#: frontend/templates/store-listings-below.php:43 inc/wpsl-functions.php:97
msgid "Search"
msgstr "Pesquisar"

#: admin/templates/map-settings.php:44
msgid "Show the max results dropdown?"
msgstr "Mostrar os máximos resultados em dropdown?"

#: admin/templates/map-settings.php:48
msgid "Show the search radius dropdown?"
msgstr "Mostrar o raio de pesquisa em dropdown?"

#: admin/templates/map-settings.php:52
msgid "Show the category dropdown?"
msgstr "Mostrar a categoria em dropdown?"

#: admin/templates/map-settings.php:56
msgid "Distance unit"
msgstr "Unidade de distância"

#: admin/templates/map-settings.php:59
msgid "km"
msgstr "km"

#: admin/templates/map-settings.php:61
msgid "mi"
msgstr "mi"

#: admin/templates/map-settings.php:65
msgid "Max search results"
msgstr "Máximos resultados da pesquisa"

#: admin/templates/map-settings.php:65 admin/templates/map-settings.php:69
msgid "The default value is set between the [ ]."
msgstr "O valor padrão é definido entre [ ]."

#: admin/templates/map-settings.php:69
msgid "Search radius options"
msgstr "Opções de raio de pesquisa"

#: admin/templates/map-settings.php:83
msgid "Map"
msgstr "Mapa"

#: admin/templates/map-settings.php:86
msgid "Attempt to auto-locate the user"
msgstr "Tentativa de auto-localizar o utilizador"

#: admin/templates/map-settings.php:90
msgid "Load locations on page load"
msgstr "Carregar localizações no carregamento da página"

#: admin/templates/map-settings.php:94
msgid "Number of locations to show"
msgstr "Número de locais a mostrar"

#: admin/templates/map-settings.php:94
#, php-format
msgid ""
"Although the location data is cached after the first load, a lower number "
"will result in the map being more responsive. %s If this field is left empty "
"or set to 0, then all locations are loaded."
msgstr ""
"Embora os dados de localização são colocadas em cache depois do primeiro "
"carregamento, um número inferior irá resultar no mapa ser mais ajustável. %s "
"Se este campo for deixado em branco ou definido como 0, em seguida, todos os "
"locais serão carregados."

#: admin/templates/map-settings.php:98
msgid "Start point"
msgstr "Ponto de partida"

#: admin/templates/map-settings.php:98
#, php-format
msgid ""
"%sRequired field.%s %s If auto-locating the user is disabled or fails, the "
"center of the provided city or country will be used as the initial starting "
"point for the user."
msgstr ""
"%sCampos obrigatórios.%s %s Se a auto-localização do utilizador estiver "
"desativada ou falhar, o centro da cidade ou país fornecido será utilizado "
"como ponto de partida inicial para o utilizador."

#: admin/templates/map-settings.php:103
msgid "Initial zoom level"
msgstr "Nível de zoom inicial"

#: admin/templates/map-settings.php:107
msgid "Max auto zoom level"
msgstr "Nível de zoom máximo automático"

#: admin/templates/map-settings.php:107
#, php-format
msgid ""
"This value sets the zoom level for the \"Zoom here\" link in the info "
"window. %s It is also used to limit the zooming when the viewport of the map "
"is changed to make all the markers fit on the screen."
msgstr ""
"Esse valor define o nível de zoom para a ligação \"zoom aqui\" na janela de "
"informações. %s Também é usado para limitar o zoom quando a janela de "
"visualização do mapa é alterada para fazer todos os marcadores se ajustarem "
"ao ecran."

#: admin/templates/map-settings.php:111
msgid "Show the street view controls?"
msgstr "Mostrar controlos de vista de rua?"

#: admin/templates/map-settings.php:115
msgid "Show the pan controls?"
msgstr "Mostrar os controlos de panorâmica?"

#: admin/templates/map-settings.php:119
msgid "Show the map type control?"
msgstr "Mostrar o controlador do tipo de mapa?"

#: admin/templates/map-settings.php:123
msgid "Enable scroll wheel zooming?"
msgstr "Activar roda de scroll do zoom?"

#: admin/templates/map-settings.php:127
msgid "Zoom control position"
msgstr "Posição do controlo de Zoom"

#: admin/templates/map-settings.php:130
msgid "Left"
msgstr "Esquerda"

#: admin/templates/map-settings.php:132
msgid "Right"
msgstr "Direita"

#: admin/templates/map-settings.php:136
msgid "Zoom control style"
msgstr "Estilo de controlo de Zoom"

#: admin/templates/map-settings.php:139
msgid "Small"
msgstr "Pequeno"

#: admin/templates/map-settings.php:141
msgid "Large"
msgstr "Grande"

#: admin/templates/map-settings.php:145
msgid "Map type"
msgstr "Tipo de mapa"

#: admin/templates/map-settings.php:149
msgid "Map style"
msgstr "Estilo do mapa"

#: admin/templates/map-settings.php:149
msgid ""
"Custom map styles only work if the map type is set to \"Roadmap\" or "
"\"Terrain\"."
msgstr ""
"Estilos de mapa personalizados só funcionam se o tipo de mapa estiver "
"definido para \"Mapa de Estrada\" ou \"Terreno\"."

#: admin/templates/map-settings.php:152
#, php-format
msgid ""
"You can use existing map styles from %sSnazzy Maps%s or %sMap Stylr%s and "
"paste it in the textarea below, or you can generate a custom map style "
"through the %sMap Style Editor%s or %sStyled Maps Wizard%s."
msgstr ""
"Você pode usar estilos de mapa existente %sSnazzy Mapas%s ou%sMAP Stylr%s e "
"cole-o na área de texto abaixo, ou você pode gerar um estilo de mapa "
"personalizado através do %sMAP Editor de estilos%s ou %sAssistente de mapas"
"% s."

#: admin/templates/map-settings.php:153
#, php-format
msgid ""
"If you like to write the style code yourself, then you can find the "
"documentation from Google %shere%s."
msgstr ""
"Se você gosta de escrever os código de estilo, então você pode encontrar a "
"documentação do Google %saqui%s."

#: admin/templates/map-settings.php:155
msgid "Preview Map Style"
msgstr "Pré-visualizar estilo do mapa"

#: admin/templates/map-settings.php:159
msgid "Show credits?"
msgstr "Mostrar créditos?"

#: admin/templates/map-settings.php:159
msgid ""
"This will place a \"Search provided by WP Store Locator\" backlink below the "
"map."
msgstr ""
"Isto irá colocar a \"Pesquisa fornecida pela WP Store Locator\" backlink "
"abaixo do mapa."

#: admin/templates/map-settings.php:173
msgid "User Experience"
msgstr "Experiência de utilizador"

#: admin/templates/map-settings.php:176
msgid "Store Locator height"
msgstr "Altura do Store Locator"

#: admin/templates/map-settings.php:180
msgid "Max width for the info window content"
msgstr "Máxima largura para o conteúdo da janela de informações"

#: admin/templates/map-settings.php:184
msgid "Search field width"
msgstr "Largura do campo de pesquisa"

#: admin/templates/map-settings.php:188
msgid "Search and radius label width"
msgstr "Largura  de marcador de pesquisa e raio"

#: admin/templates/map-settings.php:192
msgid "Store Locator template"
msgstr "Modelo de Store Locator"

#: admin/templates/map-settings.php:192
#, php-format
msgid ""
"The selected template is used with the [wpsl] shortcode. %s You can add a "
"custom template with the %swpsl_templates%s filter."
msgstr ""
"O modelo selecionado é utilizado com o [WPSL] shortcode. %s Você pode "
"adicionar um modelo personalizado com o filtro %swpsl_templates%s."

#: admin/templates/map-settings.php:196
msgid "Hide the scrollbar?"
msgstr "Esconder a barra de scroll?"

#: admin/templates/map-settings.php:200
msgid "Open links in a new window?"
msgstr "Abrir links numa nova janela?"

#: admin/templates/map-settings.php:204
msgid "Show a reset map button?"
msgstr "Mostrar um botão de reposição de mapa?"

#: admin/templates/map-settings.php:208
msgid ""
"When a user clicks on \"Directions\", open a new window, and show the route "
"on google.com/maps ?"
msgstr ""
"Quando um utilizador clica em \"Como chegar\", abrir uma nova janela, e "
"mostrar a rota em google.com/maps?"

#: admin/templates/map-settings.php:212
msgid "Show a \"More info\" link in the store listings?"
msgstr "Mostrar o link \"Mais informação\" nas listas de lojas?"

#: admin/templates/map-settings.php:212
#, php-format
msgid ""
"This places a \"More Info\" link below the address and will show the phone, "
"fax, email, opening hours and description once the link is clicked. %s If "
"you for example want the contact details to always be visible, then please "
"follow the instructions on %sthis%s page."
msgstr ""
"Isto coloca um link de \"Mais Informação\" abaixo do endereço e vai mostrar "
"o telefone, fax, e-mail, horário de funcionamento e descrição uma vez que o "
"link seja clicado. %s Se você quiser, por exemplo, quiser que os dados de "
"contacto estejam sempre visíveis, siga as instruções %snesta%s página."

#: admin/templates/map-settings.php:216
msgid "Where do you want to show the \"More info\" details?"
msgstr "Onde quer mostrar os detalhes de \"Mais informação\"?"

#: admin/templates/map-settings.php:220
msgid "Make the store name clickable if a store URL exists?"
msgstr "Permitir que o nome da loja seja clicável se um link da loja existir?"

#: admin/templates/map-settings.php:220
#, php-format
msgid ""
"If %spermalinks%s are enabled, the store name will always link to the store "
"page."
msgstr ""
"Se as %sligações permanentes% s estiverem activadas, o nome da loja será "
"sempre uma ligação para as página da loja."

#: admin/templates/map-settings.php:224
msgid "Make the phone number clickable on mobile devices?"
msgstr "Fazer o número de telefone clicável em dispositivos móveis?"

#: admin/templates/map-settings.php:228
msgid ""
"If street view is available for the current location, then show a \"Street "
"view\" link in the info window?"
msgstr ""
"Se a vista da rua estiver disponível para a localização atual, em seguida, "
"mostrar um link \"Vista da Rua\" na janela de informação?"

#: admin/templates/map-settings.php:228
#, php-format
msgid ""
"Enabling this option can sometimes result in a small delay in the opening of "
"the info window. %s This happens because an API request is made to Google "
"Maps to check if street view is available for the current location."
msgstr ""
"A ativação desta opção, por vezes, pode resultar em um pequeno atraso na "
"abertura da janela de informações. %s Isso acontece porque uma solicitação "
"de API é feita para o Google Maps para verificar se vista da rua está "
"disponível para a localização atual."

#: admin/templates/map-settings.php:232
msgid "Show a \"Zoom here\" link in the info window?"
msgstr "Mostrar o link \"Zoom aqui\" na janela de informação?"

#: admin/templates/map-settings.php:232
#, php-format
msgid ""
"Clicking this link will make the map zoom in to the %s max auto zoom level "
"%s."
msgstr ""
"Ao clicar nessa ligação vai fazer o mapa ampliar ao%s nível máximo de zoom "
"automático %s."

#: admin/templates/map-settings.php:236
msgid "On page load move the mouse cursor to the search field?"
msgstr ""
"No carregamento da página mover o cursor do mouse para o campo de pesquisa?"

#: admin/templates/map-settings.php:236
#, php-format
msgid ""
"If the store locator is not placed at the top of the page, enabling this "
"feature can result in the page scrolling down. %s %sThis option is disabled "
"on mobile devices.%s"
msgstr ""
"Se o localizador de lojas não é colocado na parte superior da página, "
"activando esta funcionalidade pode resultar que a página desça. %s %sEsta "
"opção é desativada em dispositivos móveis.%s"

#: admin/templates/map-settings.php:240
msgid "Use the default style for the info window?"
msgstr "Usar o estilo padrão para a janela de informações?"

#: admin/templates/map-settings.php:240
#, php-format
msgid ""
"If the default style is disabled the %sInfoBox%s library will be used "
"instead. %s This enables you to easily change the look and feel of the info "
"window through the .wpsl-infobox css class."
msgstr ""
"Se o estilo padrão é desativado a livraria da %sCaixa de informação%s será "
"usado em seu lugar. %s Isso permite que você facilmente mude a aparência da "
"janela de informações através da classe css .wpsl-infobox."

#: admin/templates/map-settings.php:244
msgid "Hide the distance in the search results?"
msgstr "Esconder a distância nos resultados da pesquisa?"

#: admin/templates/map-settings.php:248
msgid "If a user hovers over the search results the store marker"
msgstr ""
"Se um utilizador passar sobre os resultados da pesquisa os marcadores de loja"

#: admin/templates/map-settings.php:248
#, php-format
msgid ""
"If marker clusters are enabled this option will not work as expected as long "
"as the markers are clustered. %s The bouncing of the marker won't be visible "
"at all unless a user zooms in far enough for the marker cluster to change "
"back in to individual markers. %s The info window will open as expected, but "
"it won't be clear to which marker it belongs to. "
msgstr ""
"Se o agrupamento de marcadores estiverem habilitados, esta opção não irá "
"funcionar como esperado, enquanto os marcadores estão agrupados. %s O salto "
"do marcador não será visível a todos, a menos que um utilizador se aproxime "
"suficientemente longe para o agrupamento de marcadores mudar novamente para "
"marcadores individuais. %s A janela de informações será apresentada como "
"previsto, mas não vai ser claro sobre qual marcador pertence."

#: admin/templates/map-settings.php:252
msgid "Address format"
msgstr "Formato de morada"

#: admin/templates/map-settings.php:252
#, php-format
msgid ""
"You can add custom address formats with the %swpsl_address_formats%s filter."
msgstr ""
"Você pode adicionar formatos personalizados de endereço com o filtro"
"%swpsl_address_formats%s."

#: admin/templates/map-settings.php:266
msgid "Markers"
msgstr "Marcadores"

#: admin/templates/map-settings.php:270
msgid "Enable marker clusters?"
msgstr "Ativar agrupamento de marcadores?"

#: admin/templates/map-settings.php:270
msgid "Recommended for maps with a large amount of markers."
msgstr "Recomendado para mapas com uma grande quantidade de marcadores."

#: admin/templates/map-settings.php:274
msgid "Max zoom level"
msgstr "Nível de zoom máximo"

#: admin/templates/map-settings.php:274
msgid ""
"If this zoom level is reached or exceeded, then all markers are moved out of "
"the marker cluster and shown as individual markers."
msgstr ""
"Se este nível de zoom for atingido ou ultrapassado, em seguida, todos os "
"marcadores são movidos para fora do agrupamento de marcadores e mostrados "
"como marcadores individuais."

#: admin/templates/map-settings.php:278
msgid "Cluster size"
msgstr "Tamanho de agrupamento"

#: admin/templates/map-settings.php:278
#, php-format
msgid ""
"The grid size of a cluster in pixels. %s A larger number will result in a "
"lower amount of clusters and also make the algorithm run faster."
msgstr ""
"O tamanho da grelha de um agrupamento em pixels. %s Um número maior "
"resultará em uma menor quantidade de agrupamentos e também fazer o algoritmo "
"funcionar mais rápido."

#: admin/templates/map-settings.php:292
msgid "Store Editor"
msgstr "Editor de Loja"

#: admin/templates/map-settings.php:295
msgid "Default country"
msgstr "País padrão"

#: admin/templates/map-settings.php:299
msgid "Map type for the location preview"
msgstr "Tipo de mapa para a visualização local"

#: admin/templates/map-settings.php:303
msgid "Hide the opening hours?"
msgstr "Esconder o horário de abertura?"

#: admin/templates/map-settings.php:309
msgid "Opening hours input type"
msgstr "Tipo de campo de horário de abertura"

#: admin/templates/map-settings.php:313
#, php-format
msgid ""
"Opening hours created in version 1.x %sare not%s automatically converted to "
"the new dropdown format."
msgstr ""
"Horário de abertura criado na versão 1.x %snão são%s automaticamente "
"convertidos para o novo formato de dropdown."

#: admin/templates/map-settings.php:316 admin/templates/map-settings.php:325
msgid "The default opening hours"
msgstr "Horas de abertura padrão"

#: admin/templates/map-settings.php:322
msgid "Opening hours format"
msgstr "Formato de horas de abertura"

#: admin/templates/map-settings.php:329
msgid ""
"The default country and opening hours are only used when a new store is "
"created. So changing the default values will have no effect on existing "
"store locations."
msgstr ""
"O país padrão e as horas de abertura são somente aplicadas quando uma nova "
"loja é criada. Por isso alterar os valores padrão não irá ter efeito nas "
"localizações de lojas existentes."

#: admin/templates/map-settings.php:342
msgid "Permalink"
msgstr "Link permanente"

#: admin/templates/map-settings.php:345
msgid "Enable permalink?"
msgstr "Activar links permanentes?"

#: admin/templates/map-settings.php:349
msgid "Store slug"
msgstr "URL de loja"

#: admin/templates/map-settings.php:353
msgid "Category slug"
msgstr "URL de categoria"

#: admin/templates/map-settings.php:356
#, php-format
msgid "The permalink slugs %smust be unique%s on your site."
msgstr "Os urls permanentes %sdevem ser unicos%s no seu site."

#: admin/templates/map-settings.php:368
msgid "Labels"
msgstr "Etiquetas"

#: admin/templates/map-settings.php:371 admin/templates/map-settings.php:372
#: frontend/templates/default.php:11
#: frontend/templates/store-listings-below.php:11 inc/wpsl-functions.php:96
msgid "Your location"
msgstr "Sua localização"

#: admin/templates/map-settings.php:375 admin/templates/map-settings.php:376
#: frontend/templates/default.php:20
#: frontend/templates/store-listings-below.php:20 inc/wpsl-functions.php:99
msgid "Search radius"
msgstr "Raio de pesquisa"

#: admin/templates/map-settings.php:379 admin/templates/map-settings.php:380
#: frontend/class-frontend.php:1296 inc/wpsl-functions.php:100
msgid "No results found"
msgstr "Sem resultados encontrados"

#: admin/templates/map-settings.php:387
msgid "Searching (preloader text)"
msgstr "Pesquisando (texto pré-carregado)"

#: admin/templates/map-settings.php:388 frontend/class-frontend.php:1295
#: inc/wpsl-functions.php:98
msgid "Searching..."
msgstr "Procurando"

#: admin/templates/map-settings.php:391 admin/templates/map-settings.php:392
#: frontend/templates/default.php:29
#: frontend/templates/store-listings-below.php:29 inc/wpsl-functions.php:101
msgid "Results"
msgstr "Resultados"

#: admin/templates/map-settings.php:395 admin/upgrade.php:218
#: inc/wpsl-functions.php:115
msgid "Category filter"
msgstr "Filtro de categoria"

#: admin/templates/map-settings.php:396 frontend/class-frontend.php:1082
msgid "Category"
msgstr "Categoria"

#: admin/templates/map-settings.php:399 admin/templates/map-settings.php:400
#: admin/upgrade.php:66 frontend/class-frontend.php:1297
#: frontend/underscore-functions.php:114 frontend/underscore-functions.php:141
#: inc/wpsl-functions.php:102
msgid "More info"
msgstr "Mais informação"

#: admin/templates/map-settings.php:403 admin/templates/map-settings.php:404
#: frontend/class-frontend.php:661 frontend/underscore-functions.php:29
#: frontend/underscore-functions.php:121 inc/wpsl-functions.php:110
msgid "Phone"
msgstr "Telefone"

#: admin/templates/map-settings.php:423 admin/templates/map-settings.php:424
#: frontend/class-frontend.php:1302 inc/wpsl-functions.php:95
msgid "Start location"
msgstr "Localização inicial"

#: admin/templates/map-settings.php:427
msgid "Get directions"
msgstr "Obter direcções"

#: admin/templates/map-settings.php:428 frontend/class-frontend.php:1300
#: inc/wpsl-functions.php:103
msgid "Directions"
msgstr "Direcções"

#: admin/templates/map-settings.php:431
msgid "No directions found"
msgstr "Sem direcções encontradas"

#: admin/templates/map-settings.php:432 admin/upgrade.php:163
#: frontend/class-frontend.php:1301 inc/wpsl-functions.php:104
msgid "No route could be found between the origin and destination"
msgstr "Nenhuma rota foi encontrada entre a origem e destino"

#: admin/templates/map-settings.php:435 admin/templates/map-settings.php:436
#: admin/upgrade.php:87 frontend/class-frontend.php:1303
#: inc/wpsl-functions.php:105
msgid "Back"
msgstr "Voltar"

#: admin/templates/map-settings.php:439 admin/templates/map-settings.php:440
#: admin/upgrade.php:155 frontend/class-frontend.php:1304
#: inc/wpsl-functions.php:106
msgid "Street view"
msgstr "Vista da rua"

#: admin/templates/map-settings.php:443 admin/templates/map-settings.php:444
#: admin/upgrade.php:159 frontend/class-frontend.php:1305
#: inc/wpsl-functions.php:107
msgid "Zoom here"
msgstr "Ampliar aqui"

#: admin/templates/map-settings.php:447
msgid "General error"
msgstr "Erro geral"

#: admin/templates/map-settings.php:448 frontend/class-frontend.php:1298
#: inc/wpsl-functions.php:108
msgid "Something went wrong, please try again!"
msgstr "Algo deu errado, por favor tente novamente!"

#: admin/templates/map-settings.php:451
msgid "Query limit error"
msgstr "Erro limite da consulta"

#: admin/templates/map-settings.php:451
#, php-format
msgid ""
"You can raise the %susage limit%s by obtaining an API %skey%s, and fill in "
"the \"API key\" field at the top of this page."
msgstr ""
"Você pode aumentar os limite de %sutilização% s através da obtenção de uma "
"%schave%s API, e preencher o campo \"chave API \" na parte superior da "
"página."

#: admin/templates/map-settings.php:452 frontend/class-frontend.php:1299
#: inc/wpsl-functions.php:109
msgid "API usage limit reached"
msgstr "Limite de uso de API atingido"

#: admin/templates/map-settings.php:465
msgid "Tools"
msgstr "Ferramentas"

#: admin/templates/map-settings.php:468
msgid "Enable store locator debug?"
msgstr "Activar store locator debug?"

#: admin/templates/map-settings.php:468
#, php-format
msgid ""
"This disables the WPSL transient cache. %sThe transient cache is only used "
"if the %sLoad locations on page load%s option is enabled."
msgstr ""
"Isto desativa o cache temporário do WPSL. %sO de cache temporário só é usado "
"se a opção %sCarregar localizações no carregamento da página%s estiver "
"habilitado."

#: admin/templates/map-settings.php:472
msgid "WPSL transients"
msgstr "WPSL temporário"

#: admin/templates/map-settings.php:473
msgid "Clear store locator transient cache"
msgstr "Limpar localização de lojas de cache temporário"

#: admin/upgrade.php:82
msgid "info window"
msgstr "informação de janela"

#: admin/upgrade.php:92
msgid "Reset"
msgstr "Limpar"

#: admin/upgrade.php:186 inc/wpsl-functions.php:90
msgid "stores"
msgstr "lojas"

#: admin/upgrade.php:190 inc/wpsl-functions.php:91
msgid "store-category"
msgstr "store-category"

#: admin/upgrade.php:371
#, php-format
msgid ""
"Because you updated WP Store Locator from version 1.x, the %s current store "
"locations need to be %sconverted%s to custom post types."
msgstr ""
"Porque você atualizou o WP Store Locator da versão 1.x, %sa atual "
"localização de loja precisa de ser %sconvertida%s para tipos de conteúdo "
"personalizado."

#: admin/upgrade.php:392
#, php-format
msgid ""
"The script converting the locations timed out. %s You can click the \"Start "
"Converting\" button again to restart the script. %s If there are thousands "
"of store locations left to convert and you keep seeing this message, then "
"you can try to contact your host and ask if they can increase the maximum "
"execution time. %s The plugin tried to disable the maximum execution time, "
"but if you are reading this then that failed."
msgstr ""
"O script de conversão de locais expirou. %s Você pode clicar no botão "
"\"Começar a converter\" novamente para reiniciar o script. %s Se existem "
"milhares de localizações de lojas por converter e você continua vendo esta "
"mensagem, então você pode tentar entrar em contato com seu alojamento e "
"perguntar se eles podem aumentar o tempo máximo de execução. O plugin%s "
"tentou desativar o tempo máximo de execução, mas se você está lendo isso, "
"então é porque falhou."

#: admin/upgrade.php:413
msgid "Store locations to convert:"
msgstr "Localização de lojas para converter:"

#: admin/upgrade.php:415
msgid "Start Converting"
msgstr "Iniciar a Conversão"

#: admin/upgrade.php:537
#, php-format
msgid ""
"All the store locations are now converted to custom post types. %s You can "
"view them on the %sAll Stores%s page."
msgstr ""
"Todos as localizações de lojas agora são convertidos em tipos de conteúdos "
"personalizados. %s Você pode vê-las na página %sTodas as Lojas%s."

#: frontend/class-frontend.php:599
msgid ""
"If you use the [wpsl_address] shortcode outside a store page you need to set "
"the ID attribute."
msgstr ""
"Se utilizar o shortcode [wpsl_address] fora de uma página de loja você "
"necessita de definir o atributo ID."

#: frontend/class-frontend.php:710
msgid ""
"If you use the [wpsl_hours] shortcode outside a store page you need to set "
"the ID attribute."
msgstr ""
"Se utilizar o shortcode [wpsl_hours] fora de uma página de loja você "
"necessita de definir o atributo ID."

#: frontend/class-frontend.php:759
msgid ""
"If you use the [wpsl_map] shortcode outside a store page you need to set the "
"ID attribute."
msgstr ""
"Se utilizar o shortcode [wpsl_map] fora de uma página de loja você necessita "
"de definir o atributo ID."

#: frontend/class-frontend.php:1084
msgid "Any"
msgstr "Algum"

#: frontend/class-frontend.php:1197
msgid "The application does not have permission to use the Geolocation API."
msgstr "O aplicativo não tem permissão para usar a API de Geolocalização."

#: frontend/class-frontend.php:1198
msgid "Location information is unavailable."
msgstr "As informações de localização não estão disponíveis."

#: frontend/class-frontend.php:1199
msgid "The geolocation request timed out."
msgstr "O pedido de geolocalização expirou."

#: frontend/class-frontend.php:1200
msgid "An unknown error occurred."
msgstr "Ocorreu um erro desconhecido."

#: frontend/templates/default.php:60
#: frontend/templates/store-listings-below.php:66
#, php-format
msgid "Search provided by %sWP Store Locator%s"
msgstr "Pesquisa fornecido pelo %sWP Store Locator%s"

#: inc/class-post-types.php:50
msgid "Store"
msgstr "Loja"

#: inc/class-post-types.php:51
msgid "Stores"
msgstr "Lojas"

#: inc/class-post-types.php:55
msgid "Store Locator"
msgstr "Localizador de lojas"

#: inc/class-post-types.php:56
#, php-format
msgid "All %s"
msgstr "Todos %s"

#: inc/class-post-types.php:58 inc/class-post-types.php:61
#, php-format
msgid "New %s"
msgstr "Nova %s"

#: inc/class-post-types.php:59
#, php-format
msgid "Add New %s"
msgstr "Adicionar Nova %s"

#: inc/class-post-types.php:60
#, php-format
msgid "Edit %s"
msgstr "Editar %s"

#: inc/class-post-types.php:62
#, php-format
msgid "View %s"
msgstr "Ver %s"

#: inc/class-post-types.php:63
#, php-format
msgid "Search %s"
msgstr "Procurar %s"

#: inc/class-post-types.php:64
#, php-format
msgid "No %s found"
msgstr "Sem %s encontrada"

#: inc/class-post-types.php:65
#, php-format
msgid "No %s found in trash"
msgstr "Sem %s encontrada no lixo"

#: inc/class-post-types.php:107 inc/class-post-types.php:117
msgid "Store Categories"
msgstr "Categorias de Lojas"

#: inc/class-post-types.php:108
msgid "Store Category"
msgstr "Categoria de Loja"

#: inc/class-post-types.php:109
msgid "Search Store Categories"
msgstr "Pesquisar Categorias de Lojas"

#: inc/class-post-types.php:110
msgid "All Store Categories"
msgstr "Todas as Categorias de Lojas"

#: inc/class-post-types.php:111
msgid "Parent Store Category"
msgstr "Pai da Categoria de Loja"

#: inc/class-post-types.php:112
msgid "Parent Store Category:"
msgstr "Pai da Categoria de Loja:"

#: inc/class-post-types.php:113
msgid "Edit Store Category"
msgstr "Editar Categoria de Loja"

#: inc/class-post-types.php:114
msgid "Update Store Category"
msgstr "Actualizar Categoria de Loja"

#: inc/class-post-types.php:115
msgid "Add New Store Category"
msgstr "Adicionar Nova Categoria de Loja"

#: inc/class-post-types.php:116
msgid "New Store Category Name"
msgstr "Novo Nome de Categoria de Loja"

#: inc/class-post-types.php:147
msgid "Enter store title here"
msgstr "Insira o título da loja aqui"

#: inc/class-post-types.php:165
msgid "Zip"
msgstr "Código postal"

#: inc/wpsl-functions.php:184
msgid "Show the store list below the map"
msgstr "Mostrar a lista de lojas abaixo do mapa"

#: inc/wpsl-functions.php:201
msgid "Monday"
msgstr "Segunda-Feira"

#: inc/wpsl-functions.php:202
msgid "Tuesday"
msgstr "Terça-Feira"

#: inc/wpsl-functions.php:203
msgid "Wednesday"
msgstr "Quarta-Feira"

#: inc/wpsl-functions.php:204
msgid "Thursday"
msgstr "Quinta-Feira"

#: inc/wpsl-functions.php:205
msgid "Friday"
msgstr "Sexta-Feira"

#: inc/wpsl-functions.php:206
msgid "Saturday"
msgstr "Sábado"

#: inc/wpsl-functions.php:207
msgid "Sunday"
msgstr "Domingo"

#: inc/wpsl-functions.php:237
#, php-format
msgid "Mon %sTue %sWed %sThu %sFri %sSat Closed %sSun Closed"
msgstr "Seg %sTer %sQua %sQui %sSex %sSáb Fechado %sDom Fechado"

#: inc/wpsl-functions.php:253
msgid "Satellite"
msgstr "Satélite"

#: inc/wpsl-functions.php:254
msgid "Hybrid"
msgstr "Hibrido"

#: inc/wpsl-functions.php:255
msgid "Terrain"
msgstr "Terreno"

#: inc/wpsl-functions.php:270
msgid "(city) (state) (zip code)"
msgstr "(cidade) (estado) (código postal)"

#: inc/wpsl-functions.php:271
msgid "(city), (state) (zip code)"
msgstr "(cidade), (estado) (código postal)"

#: inc/wpsl-functions.php:272
msgid "(city) (zip code)"
msgstr "(cidade) (código postal)"

#: inc/wpsl-functions.php:273
msgid "(city), (zip code)"
msgstr "(cidade), (código postal)"

#: inc/wpsl-functions.php:274
msgid "(zip code) (city) (state)"
msgstr "(código postal) (cidade) (estado)"

#: inc/wpsl-functions.php:275
msgid "(zip code) (city)"
msgstr "(código postal) (cidade)"
languages/wpsl.mo000064400000001220151327220640010031 0ustar00��$,8V9Project-Id-Version: WP Store Locator v2.0
Report-Msgid-Bugs-To: 
POT-Creation-Date: 2015-09-01 13:49+0100
PO-Revision-Date: 2015-09-01 13:49+0100
Last-Translator: 
Language-Team: 
Language: en_US
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Plural-Forms: nplurals=2; plural=n != 1;
X-Generator: Poedit 1.7.4
X-Poedit-SourceCharset: UTF-8
X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2
X-Poedit-Basepath: ../
X-Textdomain-Support: yes
X-Poedit-SearchPath-0: .
wp-store-locator.php000064400000007624151327220640010511 0ustar00<?php
/*
Plugin Name: WP Store Locator
Description: An easy to use location management system that enables users to search for nearby physical stores
Author: Tijmen Smit
Author URI: https://wpstorelocator.co/
Version: 2.2.234
Text Domain: wpsl
Domain Path: /languages/
License: GPL v3

WP Store Locator
Copyright (C) 2013 Tijmen Smit - tijmen@wpstorelocator.co

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

@package WP_Store_locator
@category Core
@author Tijmen Smit
*/

if ( !class_exists( 'WP_Store_locator' ) ) {

	class WP_Store_locator {
        
        /**
         * Class constructor
         */          
        function __construct() {
                                    
            $this->define_constants();
            $this->includes();
            $this->plugin_settings();

            // Load classes
            $this->post_types = new WPSL_Post_Types();
            $this->i18n       = new WPSL_i18n();
            $this->frontend   = new WPSL_Frontend();
            $this->templates  = new WPSL_Templates();
                        
            register_activation_hook( __FILE__, array( $this, 'install' ) );
        }
        
        /**
         * Setup plugin constants.
         *
         * @since 1.0.0
         * @return void
         */
        public function define_constants() {

            if ( !defined( 'WPSL_VERSION_NUM' ) )
                define( 'WPSL_VERSION_NUM', '2.2.234' );

            if ( !defined( 'WPSL_URL' ) )
                define( 'WPSL_URL', plugin_dir_url( __FILE__ ) );

            if ( !defined( 'WPSL_BASENAME' ) )
                define( 'WPSL_BASENAME', plugin_basename( __FILE__ ) );

            if ( !defined( 'WPSL_PLUGIN_DIR' ) )
                define( 'WPSL_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
        }
        
        /**
         * Include the required files.
         *
         * @since 2.0.0
         * @return void
         */
        public function includes() {

            require_once( WPSL_PLUGIN_DIR . 'inc/wpsl-functions.php' );
            require_once( WPSL_PLUGIN_DIR . 'inc/class-templates.php' );
            require_once( WPSL_PLUGIN_DIR . 'inc/class-post-types.php' );
            require_once( WPSL_PLUGIN_DIR . 'inc/class-i18n.php' );
            require_once( WPSL_PLUGIN_DIR . 'frontend/class-frontend.php' );

            if ( is_admin() || defined( 'WP_CLI' ) && WP_CLI ) {
                require_once( WPSL_PLUGIN_DIR . 'admin/roles.php' );
                require_once( WPSL_PLUGIN_DIR . 'admin/class-admin.php' );
            }
        }
        
        /**
         * Setup the plugin settings.
         *
         * @since 2.0.0
         * @return void
         */
        public function plugin_settings() {
            
            global $wpsl_settings, $wpsl_default_settings;
            
            $wpsl_settings         = wpsl_get_settings();
            $wpsl_default_settings = wpsl_get_default_settings();
        }
        
        /**
         * Install the plugin data.
         *
         * @since 2.0.0
         * @return void
         */
        public function install( $network_wide ) {
            require_once( WPSL_PLUGIN_DIR . 'inc/install.php' );

            wpsl_install( $network_wide );
        }
	}
	
	$GLOBALS['wpsl'] = new WP_Store_locator();
}uninstall.php000064400000006313151327220640007273 0ustar00<?php
if ( !defined( 'ABSPATH' ) && !defined( 'WP_UNINSTALL_PLUGIN ') ) {
	exit;
}

// Check if we need to run the uninstall for a single or mu installation.
if ( !is_multisite() ) {
    wpsl_uninstall();
} else {

    global $wpdb;
    
    $blog_ids = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs" );
    $original_blog_id = get_current_blog_id();
    
    foreach ( $blog_ids as $blog_id ) {
        switch_to_blog( $blog_id );
        wpsl_uninstall();  
    }
    
    switch_to_blog( $original_blog_id );
}

// Delete the table ( users who upgraded from 1.x only ), options, store locations and taxonomies from the db.
function wpsl_uninstall() {

    global $wpdb, $current_user;

    // If the 1.x table still exists we remove it.
    $wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . 'wpsl_stores' );

    // Check if we need to delete the autoload transients.
    $option_names = $wpdb->get_results( "SELECT option_name AS transient_name FROM " . $wpdb->options . " WHERE option_name LIKE ('\_transient\_wpsl\_autoload\_%')" );

    if ( $option_names ) {
        foreach ( $option_names as $option_name ) {
            $transient_name = str_replace( "_transient_", "", $option_name->transient_name );

            delete_transient( $transient_name );
        }
    }

    // Delete the options used by the plugin.
    $options = array( 'wpsl_version', 'wpsl_settings', 'wpsl_notices', 'wpsl_legacy_support', 'wpsl_flush_rewrite', 'wpsl_delete_transient', 'wpsl_convert_cpt', 'wpsl_valid_server_key' );

    foreach ( $options as $option ) {
        delete_option( $option );
    }

    delete_user_meta( $current_user->ID, 'wpsl_disable_location_warning' );
    delete_user_meta( $current_user->ID, 'wpsl_stores_per_page' ); // Not used in 2.x, but was used in 1.x

    // Disable the time limit before we start removing all the store location posts.
    @set_time_limit( 0 );

    // 'any' ignores trashed or auto-draft store location posts, so we make sure they are removed as well.
    $post_statuses = array( 'any', 'trash', 'auto-draft' );

    // Delete the 'wpsl_stores' custom post types.
    foreach ( $post_statuses as $post_status ) {
        $posts = get_posts( array( 'post_type' => 'wpsl_stores', 'post_status' => $post_status, 'posts_per_page' => -1, 'fields' => 'ids' ) );

        if ( $posts ) {
            foreach ( $posts as $post ) {
                wp_delete_post( $post, true );
            }
        }
    }

    // Delete the terms, taxonomy and term relationships for the wpsl_store_category.
    $sql = "DELETE t,tt,tr FROM $wpdb->terms AS t
         LEFT JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id
         LEFT JOIN $wpdb->term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id
             WHERE tt.taxonomy = 'wpsl_store_category'";

    $wpdb->query( $sql );

    // Remove the WPSL caps and roles.
    include_once( 'admin/roles.php' );

    wpsl_remove_caps_and_roles();

    // If the Borlabs Cookie plugin is used, then remove the 'wpstorelocator' content type.
    if ( function_exists( 'BorlabsCookieHelper' ) ) {
        BorlabsCookieHelper()->deleteBlockedContentType( 'wpstorelocator' );
    }
}css/styles.min.css000064400000035203151327220640010160 0ustar00@font-face{font-family:wpsl-fontello;src:url(../font/fontello.eot?28897909);src:url(../font/fontello.eot?28897909#iefix) format('embedded-opentype'),url(../font/fontello.woff?28897909) format('woff'),url(../font/fontello.ttf?28897909) format('truetype'),url(../font/fontello.svg?28897909#fontello) format('svg');font-weight:400;font-style:normal}#wpsl-gmap{float:right;width:66.5%;height:350px;margin-bottom:0}.wpsl-store-below #wpsl-gmap{float:none;width:100%}.wpsl-gmap-canvas{width:100%;height:300px;margin-bottom:20px}#wpsl-reset-map:hover{cursor:pointer}#wpsl-gmap div:not[class^=gv-iv],#wpsl-gmap img,.wpsl-gmap-canvas div:not[class^=gv-iv],.wpsl-gmap-canvas img{box-shadow:none!important;max-width:none!important;background:0 0}#wpsl-gmap img,.wpsl-gmap-canvas img{display:inline;opacity:1!important;max-height:none!important}#wpsl-gmap *{box-sizing:content-box!important;-webkit-box-sizing:content-box!important;-moz-box-sizing:content-box!important}#wpsl-gmap div.gm-iv-marker,.wpsl-gmap-canvas div.gm-iv-marker{backgroud-image:inherit}#wpsl-wrap{position:relative;width:100%;overflow:hidden;clear:both;margin-bottom:20px}#wpsl-search-wrap{float:left;width:100%}#wpsl-search-wrap form{margin:0;padding:0;border:none;outline:0}#wpsl-gmap #wpsl-map-controls{position:absolute;height:40px;right:10px;bottom:24px;border-radius:2px;z-index:3;font-size:14px;white-space:nowrap;overflow:hidden;box-shadow:rgba(0,0,0,.3) 0 1px 4px -1px}#wpsl-gmap #wpsl-map-controls.wpsl-street-view-exists{right:60px}#wpsl-map-controls .wpsl-direction-preloader{margin:5px 5px 0 5px}#wpsl-map-controls div{float:left;background:#fff;border-radius:2px}#wpsl-map-controls div:hover{cursor:pointer}#wpsl-wrap [class*=" wpsl-icon-"],#wpsl-wrap [class^=wpsl-icon-]{position:relative;float:left;padding:12px 13px;display:inline-block;font-family:wpsl-fontello;font-style:normal;font-weight:400;font-size:1.3em;color:#737373;speak:none;text-decoration:inherit;text-align:center;font-variant:normal;text-transform:none;line-height:1em;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}#wpsl-map-controls span{font-family:inherit;font-size:inherit}#wpsl-wrap .wpsl-icon-reset{border-radius:2px 0 0 2px;z-index:2;padding-right:4px}#wpsl-wrap .wpsl-ie .wpsl-icon-reset{margin-right:-1px}#wpsl-wrap .wpsl-icon-direction{z-index:1}#wpsl-map-controls.wpsl-reset-exists .wpsl-icon-direction{border-radius:0 2px 2px 0}#wpsl-wrap .wpsl-active-icon,#wpsl-wrap [class*=" wpsl-icon-"]:hover,#wpsl-wrap [class^=wpsl-icon-]:hover{color:#000}#wpsl-wrap [class*=" wpsl-icon-"]:focus,#wpsl-wrap [class^=wpsl-icon-]:active{outline:0}#wpsl-wrap .wpsl-in-progress,#wpsl-wrap .wpsl-in-progress:hover{color:#c6c6c6}#wpsl-gmap #wpsl-reset-map{position:absolute;display:none;right:37px;top:37px;padding:6px 14px;background:#fff!important;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:2px;z-index:3}#wpsl-reset-map:hover{cursor:pointer}.gm-style-cc{word-wrap:normal}#wpsl-search-wrap .wpsl-input,#wpsl-search-wrap .wpsl-select-wrap{display:table}#wpsl-search-btn,#wpsl-search-wrap #wpsl-radius,#wpsl-search-wrap #wpsl-results,#wpsl-search-wrap .wpsl-input input,#wpsl-search-wrap .wpsl-input label{display:table-cell}#wpsl-search-wrap label{margin-bottom:0}#wpsl-search-input{width:179px;height:auto;padding:7px 12px;font-size:100%;margin:0}#wpsl-search-btn,#wpsl-search-wrap input{border:1px solid #d2d2d2;border-radius:3px}#wpsl-search-btn{padding:7px 10px;line-height:1.428571429;font-weight:400;color:#7c7c7c;background-color:#e6e6e6;background-repeat:repeat-x;background-image:-moz-linear-gradient(top,#f4f4f4,#e6e6e6);background-image:-ms-linear-gradient(top,#f4f4f4,#e6e6e6);background-image:-webkit-linear-gradient(top,#f4f4f4,#e6e6e6);background-image:-o-linear-gradient(top,#f4f4f4,#e6e6e6);background-image:linear-gradient(top,#f4f4f4,#e6e6e6);box-shadow:0 1px 2px rgba(64,64,64,.1);text-transform:none!important}#wpsl-search-input.wpsl-error{border:1px solid #bd0028!important}.wpsl-search{margin-bottom:12px;padding:12px 12px 0 12px;background:#f4f3f3}.wpsl-search.wpsl-checkboxes-enabled{padding:12px}.wpsl-back{display:inline-block}#wpsl-result-list{width:33%;margin-right:.5%}.wpsl-store-below #wpsl-result-list{width:100%;margin:12px 0 0 0}#wpsl-direction-details,#wpsl-stores{height:350px;overflow-y:auto}#wpsl-direction-details,.wpsl-hide{display:none}#wpsl-result-list p{padding-left:10px}.wpsl-store-below #wpsl-result-list p{padding-left:0}#wpsl-result-list a{outline:0}.wpsl-direction-before{margin:14px 0 21px 0;padding-left:10px}.wpsl-store-below .wpsl-direction-before{padding-left:0}.wpsl-direction-before div{margin-top:10px}#wpsl-wrap #wpsl-result-list li{padding:10px;border-bottom:1px dotted #ccc;margin-left:0;overflow:hidden;list-style:none outside none!important;text-indent:0}#wpsl-wrap #wpsl-result-list li li{padding:0;border-bottom:0;margin-left:14px;overflow:visible}#wpsl-wrap #wpsl-result-list ul li{list-style:none!important}#wpsl-wrap #wpsl-result-list ol li{list-style:decimal!important}#wpsl-wrap.wpsl-store-below #wpsl-result-list li{padding:10px 10px 10px 0}#wpsl-result-list li p{padding-left:0;margin:0 0 20px 0}.wpsl-store-details.wpsl-store-listing{position:relative;padding-right:20px}.wpsl-store-details.wpsl-store-listing.wpsl-active-details:before,.wpsl-store-details.wpsl-store-listing:before{position:absolute;content:'';bottom:6px;right:0;border-top:5px solid #000;border-left:6px solid transparent;border-right:6px solid transparent}.wpsl-store-details.wpsl-store-listing.wpsl-active-details:before{border-bottom:5px solid #000;border-top:none;border-left:6px solid transparent;border-right:6px solid transparent}#wpsl-stores .wpsl-store-thumb{float:right;border-radius:3px;margin:7px 0 0 10px;padding:0;border:none}.wpsl-direction-index{float:left;width:8%;margin:0 5% 0 0}.wpsl-direction-txt{float:left;width:62%}.wpsl-direction-distance{float:left;width:20%;margin:0 0 0 5%}.wpsl-direction-txt span{display:block;margin-top:10px}.wpsl-country,.wpsl-street{display:block;border-bottom:none!important}.wpsl-directions{display:table;border-bottom:none!important}#wpsl-wrap #wpsl-result-list li.wpsl-preloader{position:relative;border-bottom:none;padding:10px 10px 10px 35px}.wpsl-preloader img{position:absolute;left:10px;top:50%;margin-top:-8px;box-shadow:none!important;border:none!important}.wpsl-preloader span{float:left;margin:-5px 0 0 11px}#wpsl-search-btn,#wpsl-search-wrap div{margin-right:10px;float:left}#wpsl-search-wrap .wpsl-select-wrap{position:relative;z-index:2;margin-right:0}#wpsl-search-wrap .wpsl-input-field{position:relative}#wpsl-radius,#wpsl-results{float:left;margin-right:15px}#wpsl-category{position:relative;z-index:1;clear:both}#wpsl-search-wrap .wpsl-dropdown div{position:absolute;float:none;margin:-1px 0 0 0;top:100%;left:-1px;right:-1px;border:1px solid #ccc;background:#fff;border-top:1px solid #eee;border-radius:0 0 3px 3px;opacity:0;overflow:hidden;-webkit-transition:all 150ms ease-in-out;-moz-transition:all 150ms ease-in-out;-ms-transition:all 150ms ease-in-out;transition:all 150ms ease-in-out}#wpsl-search-wrap .wpsl-dropdown.wpsl-active div{opacity:1}#wpsl-search-wrap .wpsl-input label{margin-right:0}#wpsl-radius,#wpsl-results{display:inline}#wpsl-radius{margin-right:10px}#wpsl-search-btn:hover{cursor:pointer}#wpsl-search select,#wpsl-search-wrap select{display:none}#wpsl-search-wrap div label{float:left;margin-right:10px;line-height:32px}#wpsl-results label{width:auto}#wpsl-result-list ul{list-style:none;margin:0;padding:0}.wpsl-direction-details{display:none}#wpsl-gmap .wpsl-info-window,.wpsl-gmap-canvas .wpsl-info-window{max-width:225px}.wpsl-info-window span,.wpsl-more-info-listings span{display:block}.wpsl-info-window .wpsl-no-margin{margin:0}.wpsl-more-info-listings{display:none}.wpsl-info-window span span{display:inline!important}#wpsl-wrap .wpsl-info-window p{margin:0 0 10px 0}.wpsl-store-hours{margin-top:10px}.wpsl-store-hours strong{display:block}#wpsl-gmap .wpsl-info-actions{display:block;margin:10px 0!important}.wpsl-info-actions a{float:left;margin-right:7px}.wpsl-info-actions .wpsl-zoom-here{margin-right:0}.wpsl-dropdown{position:relative;width:90px;border:1px solid #ccc;cursor:pointer;background:#fff;border-radius:3px;-webkit-user-select:none;-moz-user-select:none;user-select:none;margin-right:0!important;z-index:2}#wpsl-results .wpsl-dropdown{width:70px}.wpsl-dropdown ul{position:absolute;left:0;width:100%;height:100%;padding:0!important;margin:0!important;list-style:none;overflow:hidden}.wpsl-dropdown:hover{box-shadow:0 0 5px rgba(0,0,0,.15)}.wpsl-dropdown .wpsl-selected-item,.wpsl-dropdown li{position:relative;display:block;line-height:normal;color:#000;overflow:hidden}#wpsl-radius .wpsl-dropdown .wpsl-selected-item,#wpsl-radius .wpsl-dropdown li,#wpsl-results .wpsl-dropdown .wpsl-selected-item,#wpsl-results .wpsl-dropdown li{white-space:nowrap}.wpsl-selected-item:after{position:absolute;content:"";right:12px;top:50%;margin-top:-4px;border:6px solid transparent;border-top:8px solid #000}.wpsl-active .wpsl-selected-item:after{margin-top:-10px;border:6px solid transparent;border-bottom:8px solid #000}.wpsl-dropdown li:hover{background:#f8f9f8;position:relative;z-index:3;color:#000}.wpsl-dropdown .wpsl-selected-item,.wpsl-dropdown li,.wpsl-selected-item{list-style:none;padding:9px 12px!important;margin:0!important}.wpsl-selected-dropdown{font-weight:700}.wpsl-clearfix:after,.wpsl-clearfix:before{content:" ";display:table}.wpsl-clearfix:after{clear:both}#wpsl-wrap .wpsl-selected-item{position:static;padding-right:35px!important}#wpsl-category,.wpsl-input,.wpsl-select-wrap{position:relative;margin-bottom:10px}#wpsl-search-wrap .wpsl-scroll-required div{overflow-y:scroll}.wpsl-scroll-required ul{overflow:visible}.wpsl-provided-by{float:right;padding:5px 0;text-align:right;font-size:12px;width:100%}#wpsl-wrap .wpsl-results-only label{width:auto}.wpsl-contact-details,.wpsl-location-address,.wpsl-locations-details{margin-bottom:15px}.wpsl-contact-details{clear:both}table.wpsl-opening-hours td{vertical-align:top;padding:0 15px 0 0;text-align:left}table.wpsl-opening-hours time{display:block}table.wpsl-opening-hours{width:auto!important;font-size:100%!important}table.wpsl-opening-hours,table.wpsl-opening-hours td{border:none!important}.wpsl-gmap-canvas .wpsl-infobox{min-width:155px;max-width:350px!important;padding:10px;border-radius:4px;font-size:13px;font-weight:300;border:1px solid #ccc;background:#fff!important}.wpsl-gmap-canvas .wpsl-infobox:after,.wpsl-gmap-canvas .wpsl-infobox:before{position:absolute;content:"";left:40px;bottom:-11px}.wpsl-gmap-canvas .wpsl-infobox:after{border-left:11px solid transparent;border-right:11px solid transparent;border-top:11px solid #fff}.wpsl-gmap-canvas .wpsl-infobox:before{border-left:13px solid transparent;border-right:13px solid transparent;border-top:13px solid #ccc;bottom:-13px;left:38px}#wpsl-checkbox-filter,.wpsl-custom-checkboxes{display:block;float:left;margin:5px 0 15px;padding:0;width:100%}#wpsl-checkbox-filter li,.wpsl-custom-checkboxes li{float:left;list-style:none;margin:0 1% 0 0}#wpsl-checkbox-filter.wpsl-checkbox-1-columns li,.wpsl-custom-checkboxes.wpsl-checkbox-1-columns li{width:99%}#wpsl-checkbox-filter.wpsl-checkbox-2-columns li,.wpsl-custom-checkboxes.wpsl-checkbox-2-columns li{width:49%}#wpsl-checkbox-filter.wpsl-checkbox-3-columns li,.wpsl-custom-checkboxes.wpsl-checkbox-3-columns li{width:32%}#wpsl-checkbox-filter.wpsl-checkbox-4-columns li,.wpsl-custom-checkboxes.wpsl-checkbox-4-columns li{width:24%}#wpsl-checkbox-filter input,.wpsl-custom-checkboxes input{margin-right:5px}#wpsl-result-list .wpsl-contact-details span{display:block!important}#wpsl-search-wrap .select2{display:none!important}.rtl #wpsl-result-list{float:left}.rtl #wpsl-checkbox-filter input,.rtl .wpsl-custom-checkboxes input{margin-right:0;margin-left:5px}.rtl .wpsl-info-actions a{float:right;margin:0 0 0 7px}.rtl #wpsl-gmap .wpsl-info-window{padding-right:22px}.rtl #wpsl-wrap #wpsl-result-list li.wpsl-preloader{padding:10px 35px 10px 0}.rtl .wpsl-preloader img{left:0;right:10px}.wpsl-twentynineteen .wpsl-input{width:100%}.wpsl-twentynineteen #wpsl-search-input{line-height:1.3em}.wpsl-twentynineteen #wpsl-search-wrap label{margin-top:6px}.wpsl-twentynineteen .wpsl-dropdown{width:116px}#wpsl-results .wpsl-dropdown{width:81px}@media (max-width:825px){#wpsl-search-input{width:348px}.wpsl-results-only #wpsl-search-wrap .wpsl-dropdown{width:70px}#wpsl-search-wrap .wpsl-input{width:100%;margin-bottom:10px}#wpsl-category label,#wpsl-radius label,.wpsl-cat-results-filter #wpsl-search-wrap .wpsl-input,.wpsl-input label,.wpsl-no-filters #wpsl-search-wrap .wpsl-input,.wpsl-results-only #wpsl-search-wrap .wpsl-input{width:auto}}@media (max-width:720px){#wpsl-search-wrap .wpsl-dropdown{width:114px}}@media (max-width:675px){#wpsl-search-wrap #wpsl-search-btn{float:left;margin:0 5px 0 0}.wpsl-dropdown,.wpsl-results-only #wpsl-search-wrap .wpsl-input{width:100%}.wpsl-search{padding:2%}.wpsl-input{margin-right:0}#wpsl-gmap,#wpsl-result-list{width:49.75%}#wpsl-gmap,#wpsl-result-list{float:none;width:100%}.wpsl-direction-before{padding-left:0}#wpsl-gmap{margin-bottom:15px}#wpsl-result-list,.wpsl-cat-results-filter .wpsl-select-wrap,.wpsl-filter .wpsl-select-wrap{margin-bottom:10px}#wpsl-result-list p,#wpsl-wrap #wpsl-result-list li{padding-left:0}#wpsl-wrap #wpsl-result-list li.wpsl-preloader{padding-left:25px}.wpsl-preloader img{left:0}#wpsl-stores.wpsl-not-loaded{height:25px}#wpsl-reset-map{top:25px}#wpsl-gmap{margin-top:10px}#wpsl-category,#wpsl-search-btn,.wpsl-input,.wpsl-no-filters #wpsl-search-wrap .wpsl-input,.wpsl-select-wrap{margin-bottom:0}#wpsl-stores.wpsl-no-autoload{height:auto!important}#wpsl-checkbox-filter.wpsl-checkbox-3-columns li,#wpsl-checkbox-filter.wpsl-checkbox-4-columns li{width:49%}}@media (max-width:570px){#wpsl-search-wrap #wpsl-search-btn{margin-bottom:5px}.wpsl-search{padding:4%}#wpsl-search-input{width:98%!important}.wpsl-cat-results-filter #wpsl-search-input,.wpsl-cat-results-filter #wpsl-search-wrap .wpsl-input,.wpsl-no-results #wpsl-search-input,.wpsl-results-only #wpsl-search-input{width:100%!important}.wpsl-search-btn-wrap{margin-top:15px}.wpsl-checkboxes-enabled .wpsl-search-btn-wrap{margin-top:0}#wpsl-search-btn,#wpsl-search-wrap div{margin-right:0}#wpsl-search-wrap div label{display:block;width:100%}#wpsl-results{width:auto}.wpsl-select-wrap{width:100%}#wpsl-radius,#wpsl-results{width:50%}#wpsl-radius{margin-right:4%}#wpsl-search-wrap .wpsl-dropdown{width:96%!important}.wpsl-search-btn-wrap{clear:both}.wpsl-no-filters #wpsl-search-input,.wpsl-no-filters #wpsl-search-wrap .wpsl-input{width:100%!important}}@media (max-width:420px){#wpsl-checkbox-filter li{margin:0}#wpsl-checkbox-filter.wpsl-checkbox-1-columns li,#wpsl-checkbox-filter.wpsl-checkbox-2-columns li,#wpsl-checkbox-filter.wpsl-checkbox-3-columns li,#wpsl-checkbox-filter.wpsl-checkbox-4-columns li{width:100%}}css/styles.css000064400000051731151327220640007402 0ustar00@font-face {
    font-family: 'wpsl-fontello';
    src: url('../font/fontello.eot?28897909');
    src: url('../font/fontello.eot?28897909#iefix') format('embedded-opentype'),
         url('../font/fontello.woff?28897909') format('woff'),
         url('../font/fontello.ttf?28897909') format('truetype'),
         url('../font/fontello.svg?28897909#fontello') format('svg');
    font-weight: normal;
    font-style: normal;
}

#wpsl-gmap {
    float:right;
    width:66.5%; 
    height:350px;
    margin-bottom:0;
}

.wpsl-store-below #wpsl-gmap {
    float:none;
    width:100%;
}

.wpsl-gmap-canvas {
    width:100%;
    height:300px;
    margin-bottom:20px;
}

#wpsl-reset-map:hover {
    cursor: pointer;
}

/*
Some themes set a box-shadow or max-width for all image / 
div elements, we disable it to prevent it from messing up the map

The .gv-iv- class is used in streetview, and they should not be included.
*/
#wpsl-gmap div:not[class^="gv-iv"],
#wpsl-gmap img,
.wpsl-gmap-canvas div:not[class^="gv-iv"],
.wpsl-gmap-canvas img {
    box-shadow: none !important;
    max-width: none !important;
    background: none;
}

#wpsl-gmap img,
.wpsl-gmap-canvas img {
    display: inline;
    opacity: 1 !important;
    max-height: none !important;
}

/*
Fix a problem where the background color used
in street view mode doesn't cover the control area.
*/
#wpsl-gmap * {
    box-sizing: content-box !important;
    -webkit-box-sizing: content-box !important;
    -moz-box-sizing: content-box !important;
}

#wpsl-gmap div.gm-iv-marker,
.wpsl-gmap-canvas div.gm-iv-marker {
    backgroud-image: inherit;
}

#wpsl-wrap {
    position: relative;
    width: 100%;
    overflow: hidden;
    clear: both;
    margin-bottom: 20px;
}

#wpsl-search-wrap {
    float: left;
    width: 100%;
}

#wpsl-search-wrap form {
    margin: 0;
    padding: 0;
    border: none;
    outline: none;
}

/* Map Controls */
#wpsl-gmap #wpsl-map-controls {
    position: absolute;
    height: 40px;
    right: 10px;
    bottom: 24px;
    border-radius: 2px;
    z-index: 3;
    font-size: 14px;
    white-space: nowrap;
    overflow: hidden;
    box-shadow: rgba(0, 0, 0, 0.3) 0px 1px 4px -1px;
}

#wpsl-gmap #wpsl-map-controls.wpsl-street-view-exists {
    right: 60px;
}

#wpsl-map-controls .wpsl-direction-preloader {
    margin: 5px 5px 0 5px;
}

#wpsl-map-controls div {
    float: left;
    background: #fff;
    border-radius: 2px;
}

#wpsl-map-controls div:hover {
    cursor: pointer;
}
 
#wpsl-wrap [class^="wpsl-icon-"], 
#wpsl-wrap [class*=" wpsl-icon-"] {
    position: relative;
    float: left;
    padding: 12px 13px;
    display: inline-block;
    font-family: "wpsl-fontello";
    font-style: normal;
    font-weight: normal;
    font-size: 1.3em;
    color: #737373;
    speak: none;
    text-decoration: inherit;
    text-align: center;
    font-variant: normal;
    text-transform: none;
    line-height: 1em;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* 
 * Make sure the CSS from a theme doesn't set a different font family, or font size
 * for the font icons. Otherwise the icons either don't show, or are to large.
 */
#wpsl-map-controls span {
    font-family: inherit;
    font-size: inherit;
}

#wpsl-wrap .wpsl-icon-reset {
    border-radius: 2px 0 0 2px;
    z-index: 2;
    padding-right: 4px;
}

/* Fix the padding for the icon fonts in IE 8-11 :( */
#wpsl-wrap .wpsl-ie .wpsl-icon-reset {
    margin-right: -1px;
}

#wpsl-wrap .wpsl-icon-direction {
    z-index: 1;
}

#wpsl-map-controls.wpsl-reset-exists .wpsl-icon-direction {
    border-radius: 0 2px 2px 0;    
}

#wpsl-wrap .wpsl-active-icon,
#wpsl-wrap [class^="wpsl-icon-"]:hover,
#wpsl-wrap [class*=" wpsl-icon-"]:hover {
    color: #000;
}

#wpsl-wrap [class^="wpsl-icon-"]:active,
#wpsl-wrap [class*=" wpsl-icon-"]:focus {
    outline: 0;
}

#wpsl-wrap .wpsl-in-progress:hover,
#wpsl-wrap .wpsl-in-progress {
    color: #c6c6c6;
}

/* Map reset button */
#wpsl-gmap #wpsl-reset-map {
    position: absolute; 
    display: none;
    right: 37px; 
    top: 37px; 
    padding: 6px 14px; 
    background: #fff !important; 
    background-clip: padding-box;
    border: 1px solid rgba(0, 0, 0, 0.15);
    border-radius: 2px;
    z-index: 3;
}

#wpsl-reset-map:hover {
    cursor: pointer;
}

/* Possible fix for vertical text issue in IE9? */
.gm-style-cc {
    word-wrap:normal;
}

#wpsl-search-wrap .wpsl-input,
#wpsl-search-wrap .wpsl-select-wrap {
    display:table;
}

#wpsl-search-wrap .wpsl-input label,
#wpsl-search-wrap .wpsl-input input,
#wpsl-search-wrap #wpsl-radius,
#wpsl-search-wrap #wpsl-results,
#wpsl-search-btn {
    display:table-cell;
}

#wpsl-search-wrap label {
    margin-bottom:0;
}

#wpsl-search-input {
    width: 179px;
    height: auto;
    padding: 7px 12px;
    font-size: 100%;
    margin: 0;
}

#wpsl-search-wrap input,
#wpsl-search-btn {
    border: 1px solid #d2d2d2;
    border-radius: 3px;
}

#wpsl-search-btn {
    padding: 7px 10px;
    line-height: 1.428571429;
    font-weight: normal;
    color: #7c7c7c;
    background-color: #e6e6e6;
    background-repeat: repeat-x;
    background-image: -moz-linear-gradient(top, #f4f4f4, #e6e6e6);
    background-image: -ms-linear-gradient(top, #f4f4f4, #e6e6e6);
    background-image: -webkit-linear-gradient(top, #f4f4f4, #e6e6e6);
    background-image: -o-linear-gradient(top, #f4f4f4, #e6e6e6);
    background-image: linear-gradient(top, #f4f4f4, #e6e6e6);
    box-shadow: 0 1px 2px rgba(64, 64, 64, 0.1);
    text-transform: none !important;
}

#wpsl-search-input.wpsl-error {
    border:1px solid #bd0028 !important;
}

.wpsl-search {
    margin-bottom:12px;
    padding:12px 12px 0 12px;
    background:#f4f3f3;
}

.wpsl-search.wpsl-checkboxes-enabled {
    padding: 12px;
}

/* Result list */
.wpsl-back {
    display: inline-block;
}

#wpsl-result-list {
    width:33%;
    margin-right:0.5%;
}

.wpsl-store-below #wpsl-result-list {
    width:100%;
    margin:12px 0 0 0;
}

#wpsl-stores, 
#wpsl-direction-details {
    height:350px;
    overflow-y:auto;
}

.wpsl-hide,
#wpsl-direction-details {
    display:none;
}

#wpsl-result-list p {
    padding-left:10px;
}
.wpsl-store-below #wpsl-result-list p {
    padding-left: 0;
}

#wpsl-result-list a {
    outline:none;
}

.wpsl-direction-before {
    margin: 14px 0 21px 0;
    padding-left: 10px;
}

.wpsl-store-below .wpsl-direction-before {
    padding-left: 0;
}

.wpsl-direction-before div {
    margin-top: 10px;
}

#wpsl-wrap #wpsl-result-list li {
    padding: 10px;
    border-bottom: 1px dotted #ccc;
    margin-left: 0;
    overflow: hidden;
    list-style: none outside none !important;
    text-indent: 0;
}

#wpsl-wrap #wpsl-result-list li li {
    padding: 0;
    border-bottom: 0;
    margin-left: 14px;
    overflow: visible;
}

#wpsl-wrap #wpsl-result-list ul li {
    list-style: none !important;
}

#wpsl-wrap #wpsl-result-list ol li {
    list-style: decimal !important;
}

#wpsl-wrap.wpsl-store-below #wpsl-result-list li {
    padding: 10px 10px 10px 0;
}

#wpsl-result-list li p {
    padding-left: 0;
    margin: 0 0 20px 0;
}

.wpsl-store-details.wpsl-store-listing {
    position: relative;
    padding-right: 20px;
}

.wpsl-store-details.wpsl-store-listing:before,
.wpsl-store-details.wpsl-store-listing.wpsl-active-details:before {
    position: absolute;
    content: '';
    bottom:6px;
    right:0;
    border-top: 5px solid #000000;
    border-left: 6px solid rgba(0, 0, 0, 0);
    border-right: 6px solid rgba(0, 0, 0, 0);
}

.wpsl-store-details.wpsl-store-listing.wpsl-active-details:before {
    border-bottom: 5px solid #000000;
    border-top:none;
    border-left: 6px solid rgba(0, 0, 0, 0);
    border-right: 6px solid rgba(0, 0, 0, 0);   
}

#wpsl-stores .wpsl-store-thumb {
    float:right;
    border-radius:3px;
    margin:7px 0 0 10px;
    padding:0;
    border:none;
}

.wpsl-direction-index {
    float:left; 
    width:8%; 
    margin:0 5% 0 0;
}

.wpsl-direction-txt {
    float:left; 
    width:62%;
}

.wpsl-direction-distance {
    float:left; 
    width:20%; 
    margin:0 0 0 5%;
}

.wpsl-direction-txt span {
    display:block; 
    margin-top:10px;
}

.wpsl-street, 
.wpsl-country {
    display: block;
    border-bottom: none !important;
}

.wpsl-directions {
    display: table;
    border-bottom: none !important;
}

/* Preloader */
#wpsl-wrap #wpsl-result-list li.wpsl-preloader {
    position: relative;
    border-bottom: none;
    padding: 10px 10px 10px 35px;
}

.wpsl-preloader img {
    position: absolute;
    left: 10px;    
    top: 50%;
    margin-top: -8px;
    box-shadow:none !important; 
    border:none !important;
}

.wpsl-preloader span {
    float: left;
    margin: -5px 0 0 11px;	
}

#wpsl-search-wrap div, 
#wpsl-search-btn {
    margin-right: 10px;
    float: left;
}

#wpsl-search-wrap .wpsl-select-wrap {
    position: relative;
    z-index: 2;
    margin-right: 0;
}

#wpsl-search-wrap  .wpsl-input-field {
    position: relative;
}

#wpsl-radius, #wpsl-results {
    float: left;
    margin-right: 15px;	
}

#wpsl-category {
    position: relative;
    z-index: 1;
    clear: both;
}

#wpsl-search-wrap .wpsl-dropdown div {
    position: absolute;
    float: none;
    margin: -1px 0 0 0;
    top: 100%;
    left: -1px;
    right: -1px;
    border: 1px solid #ccc;
    background: #fff;    
    border-top: 1px solid #eee;
    border-radius: 0 0 3px 3px;
    opacity: 0;
    overflow: hidden;
    -webkit-transition: all 150ms ease-in-out;
    -moz-transition: all 150ms ease-in-out;
    -ms-transition: all 150ms ease-in-out;
    transition: all 150ms ease-in-out;
}

#wpsl-search-wrap .wpsl-dropdown.wpsl-active div {
    opacity: 1;
}

#wpsl-search-wrap .wpsl-input label {
    margin-right:0;
}

#wpsl-radius, #wpsl-results {
    display:inline;
}

#wpsl-radius {
    margin-right:10px;
}
#wpsl-search-btn:hover {
    cursor: pointer;
}

#wpsl-search-wrap select, 
#wpsl-search select {
    display:none;
}

#wpsl-search-wrap div label {
    float:left;
    margin-right:10px;
    line-height: 32px;
}

#wpsl-results label {
   width: auto;
}

#wpsl-result-list ul {
    list-style: none;
    margin: 0;
    padding: 0;
}
.wpsl-direction-details {
    display: none;
}

/* Infowindow */
#wpsl-gmap .wpsl-info-window,
.wpsl-gmap-canvas .wpsl-info-window {
    max-width:225px;
}

.wpsl-more-info-listings span,
.wpsl-info-window span {
    display:block;
}

.wpsl-info-window .wpsl-no-margin {
    margin:0;
}

/* More info details in the store listings */
.wpsl-more-info-listings {
    display:none;
}

/* Fix for Google Voice breaking the phone numbers */
.wpsl-info-window span span {
    display:inline !important;
}

#wpsl-wrap .wpsl-info-window p {
    margin: 0 0 10px 0;
}

.wpsl-store-hours {
    margin-top:10px;
}

.wpsl-store-hours strong {
    display:block;
}

#wpsl-gmap .wpsl-info-actions {
    display:block;
    margin:10px 0 !important;   
}

.wpsl-info-actions a {
    float:left;
    margin-right: 7px;
}

.wpsl-info-actions .wpsl-zoom-here {
    margin-right:0;
}

/* --- dropdowns --- */
.wpsl-dropdown {
    position: relative;
    width: 90px;
    border: 1px solid #ccc;
    cursor: pointer;
    background: #fff;
    border-radius: 3px;
    -webkit-user-select: none;
    -moz-user-select: none;
    user-select: none;
    margin-right: 0 !important;
    z-index: 2;
}

#wpsl-results .wpsl-dropdown {
    width: 70px;
}

.wpsl-dropdown ul {
    position: absolute;
    left: 0;
    width: 100%;
    height: 100%;
    padding: 0 !important;
    margin: 0 !important;
    list-style: none;
    overflow: hidden;
}

.wpsl-dropdown:hover {
    box-shadow: 0 0 5px rgba( 0, 0, 0, 0.15 );	
}

.wpsl-dropdown .wpsl-selected-item,
.wpsl-dropdown li {
    position: relative;
    display: block;
    line-height: normal;
    color: #000;
    overflow: hidden;
}

#wpsl-radius .wpsl-dropdown .wpsl-selected-item,
#wpsl-radius .wpsl-dropdown li,
#wpsl-results .wpsl-dropdown .wpsl-selected-item,
#wpsl-results .wpsl-dropdown li {
    white-space: nowrap;
}

.wpsl-selected-item:after {
    position: absolute;
    content: "";
    right: 12px;
    top: 50%;
    margin-top: -4px;
    border: 6px solid transparent;
    border-top: 8px solid #000;
}

.wpsl-active .wpsl-selected-item:after {
    margin-top: -10px;
    border: 6px solid transparent;
    border-bottom: 8px solid #000;	
}

.wpsl-dropdown li:hover {
    background: #f8f9f8;
    position: relative;
    z-index: 3;
    color: #000;
}

.wpsl-dropdown .wpsl-selected-item,
.wpsl-dropdown li,
.wpsl-selected-item {
    list-style: none;
    padding: 9px 12px !important;
    margin:0 !important;   
}

.wpsl-selected-dropdown {
    font-weight: bold;	
}

.wpsl-clearfix:before,  
.wpsl-clearfix:after {  
    content: " ";  
    display: table;  
}  

.wpsl-clearfix:after {  
    clear: both;  
} 

#wpsl-wrap .wpsl-selected-item {
    position: static;
    padding-right: 35px !important;
}

#wpsl-category, 
.wpsl-input, 
.wpsl-select-wrap {
    position: relative;
    margin-bottom: 10px;
}

#wpsl-search-wrap .wpsl-scroll-required div {
    overflow-y: scroll;
}

.wpsl-scroll-required ul {
    overflow: visible;
}

.wpsl-provided-by {
    float: right;
    padding: 5px 0;
    text-align: right;
    font-size: 12px;
    width: 100%;
}

#wpsl-wrap .wpsl-results-only label {
    width: auto;
}

/* wpsl custom post type pages */
.wpsl-locations-details,
.wpsl-location-address,
.wpsl-contact-details {
    margin-bottom: 15px;
}

.wpsl-contact-details {
    clear: both;
}

table.wpsl-opening-hours td {
    vertical-align: top;
    padding: 0 15px 0 0;
    text-align: left;
}

table.wpsl-opening-hours time {
    display:block;
}

table.wpsl-opening-hours {
    width:auto !important;
    font-size:100% !important;
}

table.wpsl-opening-hours,
table.wpsl-opening-hours td {
    border:none !important;    
}

/* Custom Infobox */
.wpsl-gmap-canvas .wpsl-infobox {
    min-width:155px;
    max-width:350px !important;
    padding:10px;
    border-radius:4px;
    font-size:13px;
    font-weight:300;
    border:1px solid #ccc;
    background:#fff !important;
}

.wpsl-gmap-canvas .wpsl-infobox:after,
.wpsl-gmap-canvas .wpsl-infobox:before {
    position:absolute;
    content:"";	
    left:40px;
    bottom:-11px;	
}

.wpsl-gmap-canvas .wpsl-infobox:after {
    border-left:11px solid transparent;
    border-right:11px solid transparent;
    border-top:11px solid #fff;	
}

.wpsl-gmap-canvas .wpsl-infobox:before {
    border-left:13px solid transparent;
    border-right:13px solid transparent;
    border-top:13px solid #ccc;
    bottom:-13px;
    left:38px;
}

#wpsl-checkbox-filter,
.wpsl-custom-checkboxes {
    display: block;
    float: left;
    margin: 5px 0 15px;
    padding: 0;
    width: 100%;
}

#wpsl-checkbox-filter li,
.wpsl-custom-checkboxes li {
    float: left;
    list-style: none;
    margin: 0 1% 0 0;
}

#wpsl-checkbox-filter.wpsl-checkbox-1-columns li,
.wpsl-custom-checkboxes.wpsl-checkbox-1-columns li {
    width: 99%;    
}

#wpsl-checkbox-filter.wpsl-checkbox-2-columns li,
.wpsl-custom-checkboxes.wpsl-checkbox-2-columns li {
    width: 49%;    
}

#wpsl-checkbox-filter.wpsl-checkbox-3-columns li,
.wpsl-custom-checkboxes.wpsl-checkbox-3-columns li {
    width: 32%;    
}

#wpsl-checkbox-filter.wpsl-checkbox-4-columns li,
.wpsl-custom-checkboxes.wpsl-checkbox-4-columns li {
    width: 24%;    
}

#wpsl-checkbox-filter input,
.wpsl-custom-checkboxes input {
    margin-right: 5px;
}

#wpsl-result-list .wpsl-contact-details span {
    display: block !important;
}

/*
Hide the select2 ( https://select2.org/ ) dropdowns to
prevent duplicate dropdowns from showing up in the search bar.
*/
#wpsl-search-wrap .select2 {
    display: none !important;
}

/*
Make a few adjustments for themes that use RTL languages
*/
.rtl #wpsl-result-list {
    float: left;
}

.rtl #wpsl-checkbox-filter input,
.rtl .wpsl-custom-checkboxes input {
    margin-right: 0;
    margin-left: 5px;
}

.rtl .wpsl-info-actions a {
    float: right;
    margin: 0 0 0 7px;
}

.rtl #wpsl-gmap .wpsl-info-window {
    padding-right: 22px;
}

.rtl #wpsl-wrap #wpsl-result-list li.wpsl-preloader {
    padding: 10px 35px 10px 0;
}

.rtl .wpsl-preloader img {
    left: 0;
    right: 10px;
}

/* Only used when the TwentyNinteen theme is active */
.wpsl-twentynineteen .wpsl-input {
    width: 100%;
}

.wpsl-twentynineteen #wpsl-search-input {
    line-height: 1.3em;
}

.wpsl-twentynineteen #wpsl-search-wrap label {
    margin-top: 6px;
}

.wpsl-twentynineteen .wpsl-dropdown {
    width: 116px;
}

#wpsl-results .wpsl-dropdown {
    width: 81px;
}

@media (max-width: 825px) {
    #wpsl-search-input {
        width: 348px;
    }

    .wpsl-results-only #wpsl-search-wrap .wpsl-dropdown {
        width: 70px;
    }
    
    #wpsl-search-wrap .wpsl-input {
        width: 100%;
        margin-bottom: 10px;
    }
    
    .wpsl-input label,
    #wpsl-radius label,
    #wpsl-category label,
    .wpsl-cat-results-filter #wpsl-search-wrap .wpsl-input,
    .wpsl-no-filters #wpsl-search-wrap .wpsl-input,
    .wpsl-results-only #wpsl-search-wrap .wpsl-input {
        width: auto;
    }
}

@media (max-width: 720px) {
    #wpsl-search-wrap .wpsl-dropdown {
        width: 114px;
    }
}

@media (max-width: 675px) {
    #wpsl-search-wrap #wpsl-search-btn {
        float: left;
        margin: 0 5px 0 0;
    }

    .wpsl-results-only #wpsl-search-wrap .wpsl-input,
    .wpsl-dropdown {
        width: 100%;
    }
    
    .wpsl-search {
        padding: 2%;
    }

    .wpsl-input {
        margin-right: 0;
    }

    #wpsl-result-list,
    #wpsl-gmap {
        width:49.75%;
    }
    
    #wpsl-result-list,
    #wpsl-gmap {
        float: none;
        width: 100%;
    }
    
    .wpsl-direction-before {
        padding-left: 0;
    }
    
    #wpsl-gmap {
        margin-bottom: 15px;
    }
    
    .wpsl-cat-results-filter .wpsl-select-wrap,
    .wpsl-filter .wpsl-select-wrap,
    #wpsl-result-list {
        margin-bottom: 10px;
    }

    #wpsl-result-list p,
    #wpsl-wrap #wpsl-result-list li {
        padding-left: 0;
    }
    
    #wpsl-wrap #wpsl-result-list li.wpsl-preloader {
        padding-left: 25px;
    }
    
    .wpsl-preloader img {
        left: 0;
    }

    #wpsl-stores.wpsl-not-loaded {
        height: 25px;
    }

    #wpsl-reset-map {
        top: 25px;
    }

    #wpsl-gmap {
        margin-top: 10px;
    } 

    .wpsl-no-filters #wpsl-search-wrap .wpsl-input,
    #wpsl-category, .wpsl-input, .wpsl-select-wrap,
    .wpsl-input, #wpsl-search-btn {
        margin-bottom: 0;
    }

    #wpsl-stores.wpsl-no-autoload {
        height: auto !important;
    }

    #wpsl-checkbox-filter.wpsl-checkbox-3-columns li,
    #wpsl-checkbox-filter.wpsl-checkbox-4-columns li {
        width: 49%;    
    }
}

@media (max-width: 570px) {
    #wpsl-search-wrap #wpsl-search-btn {
        margin-bottom: 5px;
    }

    .wpsl-search {
        padding: 4%;
    }
    
    #wpsl-search-input {
        width: 98% !important;
    }
    
    .wpsl-cat-results-filter #wpsl-search-wrap .wpsl-input,
    .wpsl-cat-results-filter #wpsl-search-input,
    .wpsl-no-results #wpsl-search-input, 
    .wpsl-results-only #wpsl-search-input {
        width: 100% !important;
    }
    
    .wpsl-search-btn-wrap {
        margin-top: 15px;
    }
    
    .wpsl-checkboxes-enabled .wpsl-search-btn-wrap {
        margin-top: 0;
    }
    
    #wpsl-search-wrap div, 
    #wpsl-search-btn {
        margin-right: 0;
    }

    #wpsl-search-wrap div label {
        display: block;
        width: 100%;
    }

    #wpsl-results {
        width:auto;
    }
    
    .wpsl-select-wrap {
        width: 100%;
    }
    
    #wpsl-radius, 
    #wpsl-results {
        width: 50%;
    }
    
    #wpsl-radius {
        margin-right: 4%;
    }
    
    #wpsl-search-wrap .wpsl-dropdown {
        width: 96% !important;
    }

    .wpsl-search-btn-wrap {
        clear: both;
    }

    .wpsl-no-filters #wpsl-search-wrap .wpsl-input,
    .wpsl-no-filters #wpsl-search-input {
        width: 100% !important;
    }
}

@media (max-width: 420px) {
    #wpsl-checkbox-filter li {
        margin: 0;
    }
    
    #wpsl-checkbox-filter.wpsl-checkbox-1-columns li,
    #wpsl-checkbox-filter.wpsl-checkbox-2-columns li,
    #wpsl-checkbox-filter.wpsl-checkbox-3-columns li,
    #wpsl-checkbox-filter.wpsl-checkbox-4-columns li {
        width: 100%;    
    }    
}admin/class-metaboxes.php000064400000111022151327220640011436 0ustar00<?php
/**
 * Handle the metaboxes
 *
 * @author Tijmen Smit
 * @since  2.0.0
 */

if ( !defined( 'ABSPATH' ) ) exit;

if ( !class_exists( 'WPSL_Metaboxes' ) ) {

    /**
     * Handle the meta boxes
     *
     * @since 2.0.0
     */
    class WPSL_Metaboxes {

        public function __construct() {
            add_action( 'add_meta_boxes',        array( $this, 'add_meta_boxes' ) );
            add_action( 'save_post',             array( $this, 'save_post' ) );
            add_action( 'post_updated_messages', array( $this, 'store_update_messages' ) );
        }

        /**
         * Add the meta boxes.
         *
         * @since 2.0.0
         * @return void
         */
        public function add_meta_boxes() {

            global $pagenow;

            add_meta_box( 'wpsl-store-details', __( 'Store Details', 'wpsl' ), array( $this, 'create_meta_fields' ), 'wpsl_stores', 'normal', 'high' );
            add_meta_box( 'wpsl-map-preview', __( 'Store Map', 'wpsl' ), array( $this, 'map_preview' ), 'wpsl_stores', 'side' );

            $enable_option = apply_filters( 'wpsl_enable_export_option', true );

            if ( $enable_option && $pagenow == 'post.php' ) {
                add_meta_box( 'wpsl-data-export', __( 'Export', 'wpsl' ), array( $this, 'export_data' ), 'wpsl_stores', 'side', 'low' );
            }
        }

        /**
         * The store locator meta box fields.
         *
         * @since 2.0.0
         * @return array $meta_fields The meta box fields used for the store details
         */
        public function meta_box_fields() {

            global $wpsl_settings;

            $meta_fields = array(
                __( 'Location', 'wpsl' ) => array(
                    'address' => array(
                        'label'    => __( 'Address', 'wpsl' ),
                        'required' => true
                    ),
                    'address2' => array(
                        'label' => __( 'Address 2', 'wpsl' )
                    ),
                    'city' => array(
                        'label'    => __( 'City', 'wpsl' ),
                        'required' => true
                    ),
                    'state' => array(
                        'label' => __( 'State', 'wpsl' )
                    ),
                    'zip' => array(
                        'label' => __( 'Zip Code', 'wpsl' )
                    ),
                    'country' => array(
                        'label'    => __( 'Country', 'wpsl' ),
                        'required' => true
                    ),
                    'country_iso' => array(
                        'type' => 'hidden'
                    ),
                    'lat' => array(
                        'label' => __( 'Latitude', 'wpsl' )
                    ),
                    'lng' => array(
                        'label' => __( 'Longitude', 'wpsl' )
                    )
                ),
                __( 'Opening Hours', 'wpsl' ) => array(
                    'hours' => array(
                        'label' => __( 'Hours', 'wpsl' ),
                        'type'  => $wpsl_settings['editor_hour_input'] //Either set to textarea or dropdown. This is defined through the 'Opening hours input format: ' option on the settings page
                    )
                ),
                __( 'Additional Information', 'wpsl' ) => array(
                    'phone' => array(
                        'label' => __( 'Tel', 'wpsl' )
                    ),
                    'fax' => array(
                        'label' => __( 'Fax', 'wpsl' )
                    ),
                    'email' => array(
                        'label' => __( 'Email', 'wpsl' )
                    ),
                    'url' => array(
                        'label' => __( 'Url', 'wpsl' )
                    )
                )
            );

            return apply_filters( 'wpsl_meta_box_fields', $meta_fields );
        }

        /**
         * Create the store locator metabox input fields.
         *
         * @since 2.0.0
         * @return void
         */
        function create_meta_fields() {

            global $wpsl_settings, $wp_version;

            $i         = 0;
            $j         = 0;
            $tab_items = '';

            wp_nonce_field( 'save_store_meta', 'wpsl_meta_nonce' );
            ?>

            <div class="wpsl-store-meta <?php if ( floatval( $wp_version ) < 3.8 ) { echo 'wpsl-pre-38'; } // Fix CSS issue with < 3.8 versions ?>">
                <?php

                // Create the tab navigation for the meta boxes.
                foreach ( $this->meta_box_fields() as $tab => $meta_fields ) {
                    $active_class = ( $i == 0 ) ? ' wpsl-active' : '';

                    if ( $wpsl_settings['hide_hours'] && $tab == __( 'Opening Hours', 'wpsl' ) ) {
                        continue;
                    } else {
                        $tab_items .= $this->meta_field_nav( $tab, $active_class );
                    }

                    $i++;
                }

                echo '<ul id="wpsl-meta-nav">' . $tab_items . '</ul>';

                // Create the input fields for the meta boxes.
                foreach ( $this->meta_box_fields() as $tab => $meta_fields ) {
                    $active_class = ( $j == 0 ) ? ' wpsl-active' : '';

                    if ( $wpsl_settings['hide_hours'] && $tab == __( 'Opening Hours', 'wpsl' ) ) {
                        continue;
                    } else {
                        echo '<div class="wpsl-tab wpsl-' . esc_attr( strtolower( str_replace( ' ', '-', $tab ) ) ) . $active_class . '">';

                        foreach ( $meta_fields as $field_key => $field_data ) {

                            // If no specific field type is set, we set it to text.
                            $field_type = ( empty( $field_data['type'] ) ) ? 'text' : $field_data['type'];
                            $args = array(
                                'key'  => $field_key,
                                'data' => $field_data
                            );

                            // Check for a class method, otherwise enable a plugin hook.
                            if ( method_exists( $this, $field_type . '_input' ) ) {
                                call_user_func( array( $this, $field_type . '_input' ), $args );
                            } else {
                                do_action( 'wpsl_metabox_' . $field_type . '_input', $args );
                            }
                        }

                        echo '</div>';
                    }

                    $j++;
                }
                ?>
            </div>
            <?php
        }

        /**
         * Create the li elements that are used in the tabs above the store meta fields.
         *
         * @since 2.0.0
         * @param  string $tab          The name of the tab
         * @param  string $active_class Either the class name or empty
         * @return string $nav_item     The HTML for the nav list
         */
        public function meta_field_nav( $tab, $active_class ) {

            $tab_lower = strtolower( str_replace( ' ', '-', $tab ) );
            $nav_item  = '<li class="wpsl-' . esc_attr( $tab_lower ) . '-tab ' . $active_class . '"><a href="#wpsl-' . esc_attr( $tab_lower ) . '">' . esc_html( $tab ) . '</a></li>';

            return $nav_item;
        }

        /**
         * Set the CSS class that tells JS it's an required input field.
         *
         * @since 2.0.0
         * @param  array       $args     The css classes
         * @param  string      $single   Whether to return just the class name, or also include the class=""
         * @return string|void $response The required CSS class or nothing
         */
        public function set_required_class( $args, $single = false ) {

            if ( isset( $args['required'] ) && ( $args['required'] ) ) {
                if ( !$single ) {
                    $response = 'class="wpsl-required"';
                } else {
                    $response = 'wpsl-required';
                }

                return $response;
            }
        }

        /**
         * Check if the current field is required.
         *
         * @since 2.0.0
         * @param  array $args The CSS classes
         * @return string|void The HTML for the required element or nothing
         */
        public function is_required_field( $args ) {

            if ( isset( $args['required'] ) && ( $args['required'] ) ) {
                $response = '<span class="wpsl-star"> *</span>';

                return $response;
            }
        }

        /**
         * Get the prefilled field data.
         *
         * @since 2.0.0
         * @param  string $field_name The name of the field to get the data for
         * @return string $field_data The field data
         */
        public function get_prefilled_field_data( $field_name ) {

            global $wpsl_settings, $pagenow;

            $field_data = '';

            // Prefilled values are only used for new pages, not when a user edits an existing page.
            if ( $pagenow == 'post.php' && isset( $_GET['action'] ) && $_GET['action'] == 'edit' ) {
                return;
            }

            $prefilled_fields = array(
                'country',
                'hours'
            );

            if ( in_array( $field_name, $prefilled_fields ) ) {
                $field_data = $wpsl_settings['editor_' . $field_name];
            }

            return $field_data;
        }

        /**
         * Create a text input field.
         *
         * @since 2.0.0
         * @param array $args The input name and label
         * @return void
         */
        public function text_input( $args ) {

            $saved_value = $this->get_store_meta( $args['key'] );

            // If there is no existing meta value, check if a prefilled value exists for the input field.
            if ( !$saved_value ) {
                $saved_value = $this->get_prefilled_field_data( $args['key'] );
            }
            ?>

            <p>
                <label for="wpsl-<?php echo esc_attr( $args['key'] ); ?>"><?php echo esc_html( $args['data']['label'] ) . ': ' . $this->is_required_field( $args['data'] ); ?></label>
                <input id="wpsl-<?php echo esc_attr( $args['key'] ); ?>" <?php echo $this->set_required_class( $args['data'] ); ?> type="text" name="wpsl[<?php echo esc_attr( $args['key'] ); ?>]" value="<?php echo esc_attr( $saved_value ); ?>" />
            </p>

            <?php
        }

        /**
         * Create a hidden input field.
         *
         * @since 2.0.0
         * @param array $args The name of the meta value
         * @return void
         */
        public function hidden_input( $args ) {

            $saved_value = $this->get_store_meta( $args['key'] );
            ?>

            <input id="wpsl-<?php echo esc_attr( $args['key'] ); ?>" type="hidden" name="wpsl[<?php echo esc_attr( $args['key'] ); ?>]" value="<?php echo esc_attr( $saved_value ); ?>" />

            <?php
        }

        /**
         * Create a textarea field.
         *
         * @since 2.0.0
         * @param array $args The textarea name and label
         * @return void
         */
        public function textarea_input( $args ) {

            $saved_value = $this->get_store_meta( $args['key'] );

            if ( $args['key'] == 'hours' && gettype( $saved_value ) !== 'string' ) {
                $saved_value = '';
            }

            // If there is no existing meta value, check if a prefilled value exists for the textarea.
            if ( !$saved_value ) {
                $prefilled_value = $this->get_prefilled_field_data( $args['key'] );

                if ( isset( $prefilled_value['textarea'] ) ) {
                    $saved_value = $prefilled_value['textarea'];
                }
            }
            ?>

            <p>
                <label for="wpsl-<?php echo esc_attr( $args['key'] ); ?>"><?php echo esc_html( $args['data']['label'] ) . ': ' . $this->is_required_field( $args['data'] ); ?></label>
                <textarea id="wpsl-<?php echo esc_attr( $args['key'] ); ?>" <?php echo $this->set_required_class( $args['data'] ); ?> name="wpsl[<?php echo esc_attr( $args['key'] ); ?>]" cols="5" rows="5"><?php echo esc_html( $saved_value ); ?></textarea>
            </p>

            <?php
        }

        /**
         * Create a wp editor field.
         *
         * @since 2.1.1
         * @param array $args The wp editor name and label
         * @return void
         */
        public function wp_editor_input( $args ) {

            $saved_value = $this->get_store_meta( $args['key'] );
            ?>

            <p>
                <label for="wpsl-<?php echo esc_attr( $args['key'] ); ?>"><?php echo esc_html( $args['data']['label'] ) . ': ' . $this->is_required_field( $args['data'] ); ?></label>
                <?php wp_editor( $saved_value, 'wpsleditor_' . wpsl_random_chars(), $settings = array('textarea_name' => 'wpsl['. esc_attr( $args['key'] ).']') ); ?>
            </p>

            <?php
        }

        /**
         * Create a checkbox field.
         *
         * @since 2.0.0
         * @param array $args The checkbox name and label
         * @return void
         */
        public function checkbox_input( $args ) {

            $saved_value = $this->get_store_meta( $args['key'] );
            ?>

            <p>
                <label for="wpsl-<?php echo esc_attr( $args['key'] ); ?>"><?php echo esc_html( $args['data']['label'] ) . ': ' . $this->is_required_field( $args['data'] ); ?></label>
                <input id="wpsl-<?php echo esc_attr( $args['key'] ); ?>" <?php echo $this->set_required_class( $args['data'] ); ?> type="checkbox" name="wpsl[<?php echo esc_attr( $args['key'] ); ?>]" <?php checked( $saved_value, true ); ?> value="1" />
            </p>

            <?php
        }

        /**
         * Create a dropdown field.
         *
         * @since 2.0.0
         * @param array $args The dropdown name and label
         * @return void
         */
        public function dropdown_input( $args ) {

            // The hour dropdown requires a different structure with multiple dropdowns.
            if ( $args['key'] == 'hours' ) {
                $this->opening_hours();
            } else {
                $option_list = $args['data']['options'];
                $saved_value = $this->get_store_meta( $args['key'] );
                ?>

                <p>
                    <label for="wpsl-<?php echo esc_attr( $args['key'] ); ?>"><?php echo esc_html( $args['data']['label'] ) . ': ' . $this->is_required_field( $args['data'] ); ?></label>
                    <select id="wpsl-<?php echo esc_attr( $args['key'] ); ?>" <?php echo $this->set_required_class( $args['data'] ); ?>  name="wpsl[<?php echo esc_attr( $args['key'] ); ?>]" autocomplete="off" />
                    <?php foreach ( $option_list as $key => $option ) { ?>
                        <option value="<?php echo esc_attr( $key ); ?>" <?php if ( isset( $saved_value ) ) { selected( $saved_value, $key ); } ?>><?php echo esc_html( $option ); ?></option>
                    <?php } ?>
                    </select>
                </p>

                <?php
            }
        }

        /**
         * Create the openings hours table with the hours as dropdowns.
         *
         * @since 2.0.0
         * @param string $location The location were the opening hours are shown.
         * @return void
         */
        public function opening_hours( $location = 'store_page' ) {

            global $wpsl_settings, $wpsl_admin, $post;

            $name          = ( $location == 'settings' ) ? 'wpsl_editor[dropdown]' : 'wpsl[hours]'; // the name of the input or select field
            $opening_days  = wpsl_get_weekdays();
            $opening_hours = '';
            $hours         = '';

            if ( $location == 'store_page' ) {
                $opening_hours = get_post_meta( $post->ID, 'wpsl_hours' );
            }

            // If we don't have any opening hours, we use the defaults.
            if ( !isset( $opening_hours[0]['monday'] ) ) {
                $opening_hours = $wpsl_settings['editor_hours']['dropdown'];
            } else {
                $opening_hours = $opening_hours[0];
            }

            // Find out whether we have a 12 or 24hr format.
            $hour_format = $this->find_hour_format( $opening_hours );

            if ( $hour_format == 24 ) {
                $hour_class = 'wpsl-twentyfour-format';
            } else {
                $hour_class = 'wpsl-twelve-format';
            }

            /*
             * Only include the 12 / 24hr dropdown switch if we are on store page,
             * otherwise just show the table with the opening hour dropdowns.
             */
            if ( $location == 'store_page' ) {
                ?>
                <p class="wpsl-hours-dropdown">
                    <label for="wpsl-editor-hour-input"><?php _e( 'Hour format', 'wpsl' ); ?>:</label>
                    <?php echo $wpsl_admin->settings_page->show_opening_hours_format( $hour_format ); ?>
                </p>
            <?php } ?>

                <table id="wpsl-store-hours" class="<?php echo $hour_class; ?>">
                    <tr>
                        <th><?php _e( 'Days', 'wpsl' ); ?></th>
                        <th><?php _e( 'Opening Periods', 'wpsl' ); ?></th>
                        <th></th>
                    </tr>
                    <?php
                    foreach ( $opening_days as $index => $day ) {
                        $i = 0;

                        if ( is_array( $opening_hours[$index] ) ) {
                            $hour_count = count( $opening_hours[$index] );
                        } else {
                            $hour_count = 0;
                        }
                        ?>
                        <tr>
                            <td class="wpsl-opening-day"><?php echo esc_html( $day ); ?></td>
                            <td id="wpsl-hours-<?php echo esc_attr( $index ); ?>" class="wpsl-opening-hours" data-day="<?php echo esc_attr( $index ); ?>">
                                <?php
                                if ( $hour_count > 0 ) {
                                    // Loop over the opening periods.
                                    while ( $i < $hour_count ) {
                                        if ( isset( $opening_hours[$index][$i] ) ) {
                                            $hours = explode( ',', $opening_hours[$index][$i] );
                                        } else {
                                            $hours = '';
                                        }

                                        // If we don't have two parts or one of them is empty, then we set the store to closed.
                                        if ( ( count( $hours ) == 2 ) && ( !empty( $hours[0] ) ) && ( !empty( $hours[1] ) ) ) {
                                            $args = array(
                                                'day'         => $index,
                                                'name'        => $name,
                                                'hour_format' => $hour_format,
                                                'hours'       => $hours
                                            );
                                            ?>
                                            <div class="wpsl-current-period <?php if ( $i > 0 ) { echo 'wpsl-multiple-periods'; } ?>">
                                                <?php echo $this->opening_hours_dropdown( $args, 'open' ); ?>
                                                <span> - </span>
                                                <?php echo $this->opening_hours_dropdown( $args, 'close' ); ?>
                                                <div class="wpsl-icon-cancel-circled"></div>
                                            </div>
                                            <?php
                                        } else {
                                            $this->show_store_closed( $name, $index );
                                        }

                                        $i++;
                                    }
                                } else {
                                    $this->show_store_closed( $name, $index );
                                }
                                ?>
                            </td>
                            <td>
                                <div class="wpsl-add-period">
                                    <div class="wpsl-icon-plus-circled"></div>
                                </div>
                            </td>
                        </tr>
                        <?php
                    }
                    ?>
                </table>
            <?php
        }

        /**
         * Show the 'store closed' message.
         *
         * @since 2.0.0
         * @param  string $name The name for the input field
         * @param  string $day  The day the store is closed
         * @return void
         */
        public function show_store_closed( $name, $day ) {
            echo '<p class="wpsl-store-closed">' . __( 'Closed', 'wpsl' ) . '<input type="hidden" name="' . esc_attr( $name ) . '[' . esc_attr( $day ) . ']" value="closed"></p>';
        }

        /**
         * Find out whether the opening hours are set in the 12 or 24hr format.
         *
         * We use this to determine the selected value for the dropdown in the store editor.
         * So a user can decide to change the opening hour format.
         *
         * @since 2.0.0
         * @param  array  $opening_hours The opening hours for the whole week
         * @return string The hour format used in the opening hours
         */
        public function find_hour_format( $opening_hours ) {

            $week_days = wpsl_get_weekdays();

            foreach ( $week_days as $key => $day ) {
                if ( isset( $opening_hours[$key][0] ) ) {
                    $time = $opening_hours[$key][0];

                    if ( ( strpos( $time, 'AM' ) !== false ) || ( strpos( $time, 'PM' ) !== false ) ) {
                        return '12';
                    } else {
                        return '24';
                    }
                }
            }
        }

        /**
         * Create the opening hours dropdown.
         *
         * @since 2.0.0
         * @param  array  $args   The data to create the opening hours dropdown
         * @param  string $period Either set to open or close
         * @return string $select The html for the dropdown
         */
        public function opening_hours_dropdown( $args, $period ) {

            $select_index  = ( $period == 'open' ) ? 0 : 1;
            $selected_time = $args['hours'][$select_index];
            $select_name   = $args['name'] . '[' . strtolower( $args['day'] ) . '_' . $period . ']';
            $open          = strtotime( '12:00am' );
            $close         = strtotime( '11:59pm' );
            $hour_interval = 900;

            if ( $args['hour_format'] == 12 ) {
                $format = 'g:i A';
            } else {
                $format = 'H:i';
            }

            $select = '<select class="wpsl-' . esc_attr( $period ) . '-hour" name="' . esc_attr( $select_name ) . '[]" autocomplete="off">';

            for ( $i = $open; $i <= $close; $i += $hour_interval ) {

                // If the selected time matches the current time then we set it to active.
                if ( $selected_time == date( $format, $i ) ) {
                    $selected = 'selected="selected"';
                } else {
                    $selected = '';
                }

                $select .= "<option value='" . date( $format, $i ) . "' $selected>" . date( $format, $i ) . "</option>";
            }

            $select .= '</select>';

            return $select;
        }

        /**
         * Get the store post meta.
         *
         * @since 2.0.0
         * @param  string     $key        The name of the meta value
         * @return mixed|void $store_meta Meta value for the store field
         */
        public function get_store_meta( $key ) {

            global $post;

            $store_meta = get_post_meta( $post->ID, 'wpsl_' . $key, true );

            if ( $store_meta ) {
                return $store_meta;
            } else {
                return;
            }
        }

        /**
         * Save the custom post data.
         *
         * @since 2.0.0
         * @param  integer $post_id store post ID
         * @return void
         */
        public function save_post( $post_id ) {

            global $wpsl_admin;

            if ( empty( $_POST['wpsl_meta_nonce'] ) || !wp_verify_nonce( $_POST['wpsl_meta_nonce'], 'save_store_meta' ) )
                return;

            if ( !isset( $_POST['post_type'] ) || 'wpsl_stores' !== $_POST['post_type'] )
                return;

            if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
                return;

            if ( is_int( wp_is_post_revision( $post_id ) ) )
                return;

            if ( !current_user_can( 'edit_post', $post_id ) )
                return;

            $this->store_data = $_POST['wpsl'];

            // Check if the hours are set through dropdowns.
            if ( isset( $this->store_data['hours'] ) && is_array( $this->store_data['hours'] ) && ( !empty( $this->store_data['hours'] ) ) ) {
                $this->store_data['hours'] = $this->format_opening_hours();
            }

            // Loop over the meta fields defined in the meta_box_fields and update the post meta data.
            foreach ( $this->meta_box_fields() as $tab => $meta_fields ) {
                foreach ( $meta_fields as $field_key => $field_data ) {

                    // Either update or delete the post meta.
                    if ( isset( $this->store_data[ $field_key ] ) && ( $this->store_data[ $field_key ] != "" ) ) {
                        if ( isset( $field_data['type'] ) && $field_data['type'] ) {
                            $field_type = $field_data['type'];
                        } else {
                            $field_type = '';
                        }

                        switch ( $field_type ) {
                            case 'thumbnail':
                                update_post_meta( $post_id, 'wpsl_' . $field_key, absint( $this->store_data[ $field_key ] ) );
                                break;
                            case 'checkbox':
                                $checkbox_val = ( isset( $this->store_data[ $field_key ] ) ) ? 1 : 0;
                                update_post_meta( $post_id, 'wpsl_' . $field_key, $checkbox_val );
                                break;
                            case 'wp_editor':
                            case 'textarea':
                                update_post_meta( $post_id, 'wpsl_' . $field_key, wp_kses_post( trim( stripslashes( $this->store_data[ $field_key ] ) ) ) );
                                break;
                            default:
                                if ( is_array( $this->store_data[ $field_key ] ) ) {
                                    if ( wpsl_is_multi_array( $this->store_data[ $field_key ] ) ) {
                                        array_walk_recursive( $this->store_data[ $field_key ], 'wpsl_sanitize_multi_array' );
                                        update_post_meta( $post_id, 'wpsl_' . $field_key, $this->store_data[ $field_key ] );
                                    } else {
                                        update_post_meta( $post_id, 'wpsl_' . $field_key, array_map( 'sanitize_text_field', $this->store_data[ $field_key ] ) );
                                    }
                                } else {
                                    update_post_meta( $post_id, 'wpsl_' . $field_key, sanitize_text_field( $this->store_data[ $field_key ] ) );
                                }
                                break;
                        }
                    } else {
                        delete_post_meta( $post_id, 'wpsl_' . $field_key );
                    }
                }
            }

            do_action( 'wpsl_save_post', $this->store_data );

            /*
             * If all the required fields contain data, then check if we need to
             * geocode the address and if we should delete the autoload transient.
             *
             * Otherwise show a notice for 'missing data' and set the post status to pending.
             */
            if ( !$this->check_missing_meta_data( $post_id ) ) {
                $wpsl_admin->geocode->check_geocode_data( $post_id, $this->store_data );
                $wpsl_admin->maybe_delete_autoload_transient( $post_id );
            } else {
                $wpsl_admin->notices->save( 'error', __( 'Failed to publish the store. Please fill in the required store details.', 'wpsl' ) );
                $this->set_post_pending( $post_id );
            }
        }

        /**
         * Loop through the opening hours and structure the data in a new array.
         *
         * @since 2.0.0
         * @return array $opening_hours The formatted opening hours
         */
        public function format_opening_hours() {

            $week_days = wpsl_get_weekdays();

            // Use the opening hours from the editor page or the add/edit store page.
            if ( isset( $_POST['wpsl_editor']['dropdown'] ) ) {
                $store_hours = $_POST['wpsl_editor']['dropdown'];
            } else if ( isset( $this->store_data['hours'] ) ) {
                $store_hours = $this->store_data['hours'];
            }

            foreach ( $week_days as $day => $value ) {
                $i       = 0;
                $periods = array();

                if ( isset( $store_hours[$day . '_open'] ) && $store_hours[$day . '_open'] ) {
                    foreach ( $store_hours[$day . '_open'] as $opening_hour ) {
                        $hours     = $this->validate_hour( $store_hours[$day.'_open'][$i] ) . ',' . $this->validate_hour( $store_hours[$day.'_close'][$i] );
                        $periods[] = $hours;
                        $i++;
                    }
                }

                $opening_hours[$day] = $periods;
            }

            return $opening_hours;
        }

        /*
         * Validate the 12 or 24 hr time format.
         *
         * @since 2.0.0
         * @param string $hour The opening hour
         * @return boolean true if the $hour format is valid
         */
        public function validate_hour( $hour ) {

            global $wpsl_settings;

            /*
             * On the add/edit store we can always use the $wpsl_settings value.
             * But if validate_hour is called from the settings page then we
             * should use the $_POST value to make sure we have the correct value.
             */
            if ( isset( $_POST['wpsl_editor']['hour_format'] ) ) {
                $hour_format = ( $_POST['wpsl_editor']['hour_format'] == 12 ) ? 12 : 24;
            } else {
                $hour_format = $wpsl_settings['editor_hour_format'];
            }

            if ( $hour_format == 12 ) {
                $format = 'g:i A';
            } else {
                $format = 'H:i';
            }

            if ( date( $format, strtotime( $hour ) ) == $hour ) {
                return $hour;
            }
        }

        /**
         * Set the post status to pending instead of publish.
         *
         * @since 2.0.0
         * @param integer $post_id store post ID
         * @return void
         */
        public function set_post_pending( $post_id ) {

            global $wpdb;

            $wpdb->update( $wpdb->posts, array( 'post_status' => 'pending' ), array( 'ID' => $post_id ) );

            add_filter( 'redirect_post_location', array( $this, 'remove_message_arg' ) );
        }

        /**
         * Remove the message query arg.
         *
         * If one or more of the required fields are empty, we show a custom msg.
         * So no need for the normal post update messages arg.
         *
         * @since 2.0.0
         * @param string $location The destination url
         * @return void
         */
        public function remove_message_arg( $location ) {
            return remove_query_arg( 'message', $location );
        }

        /**
         * Make sure all the required post meta fields contain data.
         *
         * @since 2.0.0
         * @param integer $post_id store post ID
         * @return boolean
         */
        public function check_missing_meta_data( $post_id ) {

            foreach ( $this->meta_box_fields() as $tab => $meta_fields ) {
                foreach ( $meta_fields as $field_key => $field_data ) {

                    if ( isset( $field_data['required'] ) && $field_data['required'] ) {
                        $post_meta = get_post_meta( $post_id, 'wpsl_' . $field_key, true );

                        if ( empty( $post_meta ) ) {
                            return true;
                        }
                    }
                }
            }
        }

        /**
         * The html for the map preview in the sidebar.
         *
         * @since 2.0.0
         * @return void
         */
        public function map_preview() {
            ?>
            <div id="wpsl-gmap-wrap"></div>
            <p class="wpsl-submit-wrap">
                <a id="wpsl-lookup-location" class="button-primary" href="#wpsl-meta-nav"><?php _e( 'Preview Location', 'wpsl' ); ?></a>
                <span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'The map preview is based on the provided address, city and country details. %s It will ignore any custom latitude or longitude values.', 'wpsl' ), '<br><br>' ); ?></span></span>
                <em class="wpsl-desc"><?php _e( 'You can drag the marker to adjust the exact location of the marker.', 'wpsl' ); ?></em>
            </p>
            <?php
        }

        /**
         * The html for the export details section in the sidebar.
         *
         * @since 2.2.15
         * @return void
         */
        public function export_data() {

            global $post;

            $link_url = wp_nonce_url( admin_url( 'post.php?'. $_SERVER['QUERY_STRING'] . '&wpsl_data_export=1' ), 'wpsl_export_' . $post->ID, 'wpsl_export_nonce' );

            ?>
            <p class="wpsl-submit-wrap">
                <a id="wpsl-export-data" class="button-primary" href="<?php echo esc_url( $link_url ); ?>"><?php _e( 'Export Location Data', 'wpsl' ); ?></a>
            </p>
            <?php
        }

        /**
         * Store update messages.
         *
         * @since 2.0.0
         * @param  array $messages Existing post update messages.
         * @return array $messages Amended post update messages with new CPT update messages.
         */
        function store_update_messages( $messages ) {

            $post             = get_post();
            $post_type        = get_post_type( $post );
            $post_type_object = get_post_type_object( $post_type );

            $messages['wpsl_stores'] = array(
                0  => '', // Unused. Messages start at index 1.
                1  => __( 'Store updated.', 'wpsl' ),
                2  => __( 'Custom field updated.', 'wpsl' ),
                3  => __( 'Custom field deleted.', 'wpsl' ),
                4  => __( 'Store updated.', 'wpsl' ),
                5  => isset( $_GET['revision'] ) ? sprintf( __( 'Store restored to revision from %s', 'wpsl' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
                6  => __( 'Store published.', 'wpsl' ),
                7  => __( 'Store saved.', 'wpsl' ),
                8  => __( 'Store submitted.', 'wpsl' ),
                9  => sprintf(
                    __( 'Store scheduled for: <strong>%1$s</strong>.', 'wpsl' ),
                    date_i18n( __( 'M j, Y @ G:i', 'wpsl' ), strtotime( $post->post_date ) )
                ),
                10 => __( 'Store draft updated.', 'wpsl' )
            );

            if ( ( 'wpsl_stores' == $post_type ) && ( $post_type_object->publicly_queryable ) ) {
                $permalink = get_permalink( $post->ID );

                $view_link = sprintf( ' <a href="%s">%s</a>', esc_url( $permalink ), __( 'View store', 'wpsl' ) );
                $messages[ $post_type ][1] .= $view_link;
                $messages[ $post_type ][6] .= $view_link;
                $messages[ $post_type ][9] .= $view_link;

                $preview_permalink = add_query_arg( 'preview', 'true', $permalink );
                $preview_link = sprintf( ' <a target="_blank" href="%s">%s</a>', esc_url( $preview_permalink ), __( 'Preview store', 'wpsl' ) );
                $messages[ $post_type ][8]  .= $preview_link;
                $messages[ $post_type ][10] .= $preview_link;
            }

            return $messages;
        }

    }
}admin/class-admin.php000064400000064010151327220640010543 0ustar00<?php
/**
 * Admin class
 *
 * @author Tijmen Smit
 * @since  1.0.0
 */

if ( !defined( 'ABSPATH' ) ) exit;

if ( !class_exists( 'WPSL_Admin' ) ) {

    /**
     * Handle the backend of the store locator
     *
     * @since 1.0.0
     */
	class WPSL_Admin {

        /**
         * @since 2.0.0
         * @var WPSL_Metaboxes
         */
        public $metaboxes;

        /**
         * @since 2.0.0
         * @var WPSL_Geocode
         */
        public $geocode;

        /**
         * @since 2.0.0
         * @var WPSL_Notices
         */
        public $notices;

        /**
         * @since 2.0.0
         * @var WPSL_Settings
         */
        public $settings_page;

        /**
         * Class constructor
         */
		function __construct() {

            $this->includes();

            add_action( 'init',                                 array( $this, 'init' ) );
            add_action( 'admin_menu',                           array( $this, 'create_admin_menu' ) );
            add_action( 'admin_init',                           array( $this, 'setting_warnings' ) );
            add_action( 'delete_post',                          array( $this, 'maybe_delete_autoload_transient' ) );
            add_action( 'wp_trash_post',                        array( $this, 'maybe_delete_autoload_transient' ) );
            add_action( 'untrash_post',                         array( $this, 'maybe_delete_autoload_transient' ) );
            add_action( 'admin_enqueue_scripts',                array( $this, 'admin_scripts' ) );
            add_filter( 'plugin_row_meta',                      array( $this, 'add_plugin_meta_row' ), 10, 2 );
            add_filter( 'plugin_action_links_' . WPSL_BASENAME, array( $this, 'add_action_links' ), 10, 2 );
            add_filter( 'admin_footer_text',                    array( $this, 'admin_footer_text' ), 1 );
            add_action( 'wp_loaded',                            array( $this, 'disable_setting_notices' ) );

            add_action( 'wp_ajax_validate_server_key',          array( $this, 'ajax_validate_server_key' ) );
            add_action( 'wp_ajax_nopriv_validate_server_key',   array( $this, 'ajax_validate_server_key' ) );
		}

        /**
         * @since 2.2.234
         * @return void
         */
		public function ajax_validate_server_key() {
            $this->settings_page->ajax_validate_server_key();
        }

        /**
         * Include the required files.
         *
         * @since 2.0.0
         * @return void
         */
        public function includes() {
            require_once( WPSL_PLUGIN_DIR . 'admin/class-shortcode-generator.php' );
            require_once( WPSL_PLUGIN_DIR . 'admin/class-notices.php' );
            require_once( WPSL_PLUGIN_DIR . 'admin/class-license-manager.php' );
            require_once( WPSL_PLUGIN_DIR . 'admin/class-metaboxes.php' );
            require_once( WPSL_PLUGIN_DIR . 'admin/class-geocode.php' );
            require_once( WPSL_PLUGIN_DIR . 'admin/class-settings.php' );
            require_once( WPSL_PLUGIN_DIR . 'admin/upgrade.php' );
            require_once( WPSL_PLUGIN_DIR . 'admin/data-export.php' );
		}

        /**
         * Init the classes.
         *
         * @since 2.0.0
         * @return void
         */
		public function init() {
            $this->notices       = new WPSL_Notices();
            $this->metaboxes     = new WPSL_Metaboxes();
            $this->geocode       = new WPSL_Geocode();
            $this->settings_page = new WPSL_Settings();
		}

        /**
         * Check if we need to show warnings after
         * the user installed the plugin.
         *
         * @since 1.0.0
         * @todo move to class-notices?
         * @return void
         */
		public function setting_warnings() {

            global $current_user, $wpsl_settings;

            $this->setting_warning = array();

            // The fields settings field to check for data.
            $warnings = array(
                'start_latlng'    => 'location',
                'api_browser_key' => 'key'
            );

            if ( ( current_user_can( 'install_plugins' ) ) && is_admin() ) {
                foreach ( $warnings as $setting_name => $warning ) {
                    if ( empty( $wpsl_settings[$setting_name] ) && !get_user_meta( $current_user->ID, 'wpsl_disable_' . $warning . '_warning' ) ) {
                        if ( $warning == 'key' ) {
                            $this->setting_warning[$warning] = sprintf( __( "You need to create %sAPI keys%s for Google Maps before you can use the store locator! %sDismiss%s", "wpsl" ), '<a href="https://wpstorelocator.co/document/create-google-api-keys/">', "</a>", "<a href='" . esc_url( wp_nonce_url( add_query_arg( 'wpsl-notice', 'key' ), 'wpsl_notices_nonce', '_wpsl_notice_nonce' ) ) . "'>", "</a>" );
                        } else {
                            $this->setting_warning[$warning] = sprintf( __( "Before adding the [wpsl] shortcode to a page, please don't forget to define a start point on the %ssettings%s page. %sDismiss%s", "wpsl" ), "<a href='" . admin_url( 'edit.php?post_type=wpsl_stores&page=wpsl_settings' ) . "'>", "</a>", "<a href='" . esc_url( wp_nonce_url( add_query_arg( 'wpsl-notice', 'location' ), 'wpsl_notices_nonce', '_wpsl_notice_nonce' ) ) . "'>", "</a>" );
                        }
                    }
                }

                if ( $this->setting_warning ) {
                    add_action( 'admin_notices', array( $this, 'show_warning' ) );
                }
            }
		}

       /**
        * Show the admin warnings
        *
        * @since 1.2.0
        * @return void
        */
        public function show_warning() {
            foreach ( $this->setting_warning as $k => $warning ) {
                echo "<div id='message' class='error'><p>" . $warning .  "</p></div>";
            }
        }

        /**
         * Disable notices about the plugin settings.
         *
         * @todo move to class-notices?
         * @since 2.2.3
         * @return void
         */
        public function disable_setting_notices() {

            global $current_user;

            if ( isset( $_GET['wpsl-notice'] ) && isset( $_GET['_wpsl_notice_nonce'] ) ) {

                if ( !wp_verify_nonce( $_GET['_wpsl_notice_nonce'], 'wpsl_notices_nonce' ) ) {
                    wp_die( __( 'Security check failed. Please reload the page and try again.', 'wpsl' ) );
                }

                $notice = sanitize_text_field( $_GET['wpsl-notice'] );

                add_user_meta( $current_user->ID, 'wpsl_disable_' . $notice . '_warning', 'true', true );
            }
        }

        /**
         * Add the admin menu pages.
         *
         * @since 1.0.0
         * @return void
         */
		public function create_admin_menu() {

            $sub_menus = apply_filters( 'wpsl_sub_menu_items', array(
                    array(
                        'page_title'  => __( 'Settings', 'wpsl' ),
                        'menu_title'  => __( 'Settings', 'wpsl' ),
                        'caps'        => 'manage_wpsl_settings',
                        'menu_slug'   => 'wpsl_settings',
                        'function'    => array( $this, 'load_template' )
                    ),
                    array(
                        'page_title'  => __( 'Add-Ons', 'wpsl' ),
                        'menu_title'  => __( 'Add-Ons', 'wpsl' ),
                        'caps'        => 'manage_wpsl_settings',
                        'menu_slug'   => 'wpsl_add_ons',
                        'function'    => array( $this, 'load_template' )
                    )
                )
            );

            if ( count( $sub_menus ) ) {
                foreach ( $sub_menus as $sub_menu ) {
                    add_submenu_page( 'edit.php?post_type=wpsl_stores', $sub_menu['page_title'], $sub_menu['menu_title'], $sub_menu['caps'], $sub_menu['menu_slug'], $sub_menu['function'] );
                }
            }
        }

        /**
         * Load the correct page template.
         *
         * @since 2.1.0
         * @return void
         */
        public function load_template() {

            switch ( $_GET['page'] ) {
                case 'wpsl_settings':
                    require 'templates/map-settings.php';
                break;
                case 'wpsl_add_ons':
                    require 'templates/add-ons.php';
                break;
            }
        }

        /**
         * Check if we need to delete the autoload transient.
         *
         * This is called when a post it saved, deleted, trashed or untrashed.
         *
         * @since 2.0.0
         * @return void
         */
        public function maybe_delete_autoload_transient( $post_id ) {

            global $wpsl_settings;

            if ( isset( $wpsl_settings['autoload'] ) && $wpsl_settings['autoload'] && get_post_type( $post_id ) == 'wpsl_stores' ) {
				$this->delete_autoload_transient();
            }
        }

        /**
         * Delete the transients that are used on the front-end
         * if the autoload option is enabled.
         *
         * The transient names used by the store locator are partly dynamic.
         * They always start with wpsl_autoload_, followed by the number of
         * stores to load and ends with the language code.
         *
         * So you get wpsl_autoload_20_de if the language is set to German
         * and 20 stores are set to show on page load.
         *
         * The language code has to be included in case a multilingual plugin is used.
         * Otherwise it can happen the user switches to Spanish,
         * but ends up seeing the store data in the wrong language.
         *
         * @since 2.0.0
         * @return void
         */
        public function delete_autoload_transient() {

            global $wpdb;

            $option_names = $wpdb->get_results( "SELECT option_name AS transient_name FROM " . $wpdb->options . " WHERE option_name LIKE ('\_transient\_wpsl\_autoload\_%')" );

            if ( $option_names ) {
                foreach ( $option_names as $option_name ) {
                    $transient_name = str_replace( "_transient_", "", $option_name->transient_name );

                    delete_transient( $transient_name );
                }
            }
        }

        /**
         * Check if we can use a font for the plugin icon.
         *
         * This is supported by WP 3.8 or higher
         *
         * @since 1.0.0
         * @return void
         */
        private function check_icon_font_usage() {

            global $wp_version;

            if ( ( version_compare( $wp_version, '3.8', '>=' ) == TRUE ) ) {
                $min = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';

                wp_enqueue_style( 'wpsl-admin-38', plugins_url( '/css/style-3.8'. $min .'.css', __FILE__ ), false );
            }
        }

        /**
         * The text messages used in wpsl-admin.js.
         *
         * @since 1.2.20
         * @return array $admin_js_l10n The texts used in the wpsl-admin.js
         */
        public function admin_js_l10n() {

            global $wpsl_settings;

            $admin_js_l10n = array(
                'noAddress'         => __( 'Cannot determine the address at this location.', 'wpsl' ),
                'geocodeFail'       => __( 'Geocode was not successful for the following reason', 'wpsl' ),
                'securityFail'      => __( 'Security check failed, reload the page and try again.', 'wpsl' ),
                'requiredFields'    => __( 'Please fill in all the required store details.', 'wpsl' ),
                'missingGeoData'    => __( 'The map preview requires all the location details.', 'wpsl' ),
                'closedDate'        => __( 'Closed', 'wpsl' ),
                'styleError'        => __( 'The code for the map style is invalid.', 'wpsl' ),
                'dismissNotice'     => __( 'Dismiss this notice.', 'wpsl' ),
                'browserKeyError'   => sprintf( __( 'There\'s a problem with the provided %sbrowser key%s. %s You will have to open the %sbrowser console%s ( %sctrl%s %sshift%s %sk%s in Firefox, or %sctrl%s %sshift%s %sj%s in Chrome ) to see the error details returned by the Google Maps API. %s The error itself includes a link explaining the problem in more detail. %s Common API errors are also covered in the %stroubleshooting section%s.', 'wpsl' ), '<a target="_blank" href="https://wpstorelocator.co/document/create-google-api-keys/#browser-key">','</a>', '<br><br>', '<a target="_blank" href="https://codex.wordpress.org/Using_Your_Browser_to_Diagnose_JavaScript_Errors#Step_3:_Diagnosis">', '</a>', '<kbd>', '</kbd>', '<kbd>', '</kbd>','<kbd>', '</kbd>', '<kbd>', '</kbd>', '<kbd>', '</kbd>','<kbd>', '</kbd>', '<br><br>', '<br><br>', '<a target="_blank" href="https://wpstorelocator.co/document/create-google-api-keys/#api-errors">', '</a>' ),
                'browserKeySuccess' => __( 'No problems found with the browser key.', 'wpsl' ),
                'serverKey'         => __( 'Server key', 'wpsl' ),
                'serverKeyMissing'  => sprintf( __( 'No %sserver key%s found!' ), '<a target="_blank" href="https://wpstorelocator.co/document/create-google-api-keys/#server-key">', '</a>' ),
                'browserKey'        => __( 'Browser key', 'wpsl' ),
                'browserKeyMissing' => sprintf( __( 'No %sbrowser key%s found!' ), '<a target="_blank" href="https://wpstorelocator.co/document/create-google-api-keys/#browser-key">', '</a>' ),
                'restrictedZipCode' => __( 'and will only work for zip codes.', 'wpsl' ),
                'noRestriction'     => sprintf( __( 'because no %smap region%s is selected the geocode API will search for matching results around the world. This may result in unexpected results.'), '<a class="wpsl-region-href" href="#wpsl-tabs">', '</a>' ),
                'loadingError'      => sprintf( __( 'Google Maps didn\'t load correctly. Make sure you have an active %sbilling%s %saccount%s for Google Maps. %s If the "For development purposes only" text keeps showing after creating a billing account, then you will have to contact %sGoogle Billing Support%s.', 'wpsl' ), '<a target="_blank" href="https://wpstorelocator.co/document/create-google-api-keys/#billing">', '</a>', '<a href="http://g.co/dev/maps-no-account">', '</a>', '<br><br>', '<a target="_blank" href="https://cloud.google.com/support/billing/">', '</a>' ),
                'loadingFailed'     => sprintf( __( 'Google Maps failed to load correctly. This is likely due to a problem with the provided %sbrowser key%s. %s You will have to open the %sbrowser console%s ( %sctrl%s %sshift%s %sk%s in Firefox, or %sctrl%s %sshift%s %sj%s in Chrome ) to see the error details returned by the Google Maps API. %s The error itself includes a link explaining the problem in more detail. %s Common API errors are also covered in the %stroubleshooting section%s.', 'wpsl' ), '<a target="_blank" href="https://wpstorelocator.co/document/create-google-api-keys/#browser-key">','</a>', '<br><br>', '<a target="_blank" href="https://codex.wordpress.org/Using_Your_Browser_to_Diagnose_JavaScript_Errors#Step_3:_Diagnosis">', '</a>', '<kbd>', '</kbd>', '<kbd>', '</kbd>','<kbd>', '</kbd>', '<kbd>', '</kbd>', '<kbd>', '</kbd>','<kbd>', '</kbd>', '<br><br>', '<br><br>', '<a target="_blank" href="https://wpstorelocator.co/document/create-google-api-keys/#api-errors">', '</a>' ),
                'close'             => __( 'Close', 'wpsl' ),
            );

            /**
             * This text is only shown when the user checks the API response
             * for a provided address ( tools section ), and a map region is selected.
             */
            if ( $wpsl_settings['api_region'] ) {
                if ( $wpsl_settings['api_geocode_component'] ) {
                    $restriction_type = 'restricted';
                } else {
                    $restriction_type = 'biased';
                }

                $admin_js_l10n['resultsWarning'] = sprintf( __( 'with the current settings the results are %s to' ), $restriction_type );
            }

            return $admin_js_l10n;
        }

        /**
         * Plugin settings that are used in the wpsl-admin.js.
         *
         * @since 2.0.0
         * @return array $settings_js The settings used in the wpsl-admin.js
         */
        public function js_settings() {

            global $wpsl_settings;

            $js_settings = array(
                'hourFormat'     => $wpsl_settings['editor_hour_format'],
                'defaultLatLng'  => $this->get_default_lat_lng(),
                'defaultZoom'    => 6,
                'mapType'        => $wpsl_settings['editor_map_type'],
                'requiredFields' => array( 'address', 'city', 'country' ),
                'ajaxurl'        => wpsl_get_ajax_url(),
                'url'            => WPSL_URL,
                'storeMarker'    => $wpsl_settings['store_marker']
            );

            // Make sure that the Geocode API testing tool correctly restricts the results if required.
            if ( $wpsl_settings['api_region'] && $wpsl_settings['api_geocode_component'] ) {
                $geocode_components = array();
                $geocode_components['country'] = strtoupper( $wpsl_settings['api_region'] );

                if ( $wpsl_settings['force_postalcode'] ) {
                    $geocode_components['postalCode'] = '';
                }

                $js_settings['geocodeComponents'] = $geocode_components;
            }

            return apply_filters( 'wpsl_admin_js_settings', $js_settings );
        }

        /**
         * Get the coordinates that are used to
         * show the map on the settings page.
         *
         * @since 2.2.5
         * @return string $startLatLng The start coordinates
         */
        public function get_default_lat_lng() {

            global $wpsl_settings;

            $startLatLng = $wpsl_settings['start_latlng'];

            // If no start coordinates exists, then set the default to Holland.
            if ( !$startLatLng ) {
                $startLatLng = '52.378153,4.899363';
            }

            return $startLatLng;
        }

        /**
         * Add the required admin script.
         *
         * @since 1.0.0
         * @return void
         */
		public function admin_scripts() {

            $min = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';

            // Always load the main js admin file to make sure the "dismiss" link in the location notice works.
            wp_enqueue_script( 'wpsl-admin-js', plugins_url( '/js/wpsl-admin'. $min .'.js', __FILE__ ), array( 'jquery' ), WPSL_VERSION_NUM, true );

            $this->maybe_show_pointer();
            $this->check_icon_font_usage();

            // Only enqueue the rest of the css/js files if we are on a page that belongs to the store locator.
            if ( ( get_post_type() == 'wpsl_stores' ) || ( isset( $_GET['post_type'] ) && ( $_GET['post_type'] == 'wpsl_stores' ) ) ) {

                // Make sure no other Google Map scripts can interfere with the one from the store locator.
                wpsl_deregister_other_gmaps();

                wp_enqueue_style( 'jquery-style', '//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/themes/smoothness/jquery-ui.css' );
                wp_enqueue_style( 'wpsl-admin-css', plugins_url( '/css/style'. $min .'.css', __FILE__ ), false );

                wp_enqueue_media();
                wp_enqueue_script( 'jquery-ui-dialog' );
                wp_enqueue_script( 'jquery-ui-tabs' );
                wp_enqueue_script( 'wpsl-gmap', ( '//maps.google.com/maps/api/js' . wpsl_get_gmap_api_params( 'browser_key' ) ), false, WPSL_VERSION_NUM, true );

                wp_enqueue_script( 'wpsl-queue', plugins_url( '/js/ajax-queue'. $min .'.js', __FILE__ ), array( 'jquery' ), WPSL_VERSION_NUM, true );
                wp_enqueue_script( 'wpsl-retina', plugins_url( '/js/retina'. $min .'.js', __FILE__ ), array( 'jquery' ), WPSL_VERSION_NUM, true );

                wp_localize_script( 'wpsl-admin-js', 'wpslL10n',     $this->admin_js_l10n() );
                wp_localize_script( 'wpsl-admin-js', 'wpslSettings', $this->js_settings() );
            }
        }

        /**
         * Check if we need to show the wpsl pointer.
         *
         * @since 2.0.0
         * @return void
         */
        public function maybe_show_pointer() {

            $disable_pointer = apply_filters( 'wpsl_disable_welcome_pointer', false );

            if ( $disable_pointer ) {
                return;
            }

            $dismissed_pointers = explode( ',', (string) get_user_meta( get_current_user_id(), 'dismissed_wp_pointers', true ) );

            // If the user hasn't dismissed the wpsl pointer, enqueue the script and style, and call the action hook.
            if ( !in_array( 'wpsl_signup_pointer', $dismissed_pointers ) ) {
                wp_enqueue_style( 'wp-pointer' );
                wp_enqueue_script( 'wp-pointer' );

                add_action( 'admin_print_footer_scripts', array( $this, 'welcome_pointer_script' ) );
            }
        }

        /**
         * Add the script for the welcome pointer.
         *
         * @since 2.0.0
         * @return void
         */
        public function welcome_pointer_script() {

            $pointer_content = '<h3>' . __( 'Welcome to WP Store Locator', 'wpsl' ) . '</h3>';
            $pointer_content .= '<p>' . __( 'Sign up for the latest plugin updates and announcements.', 'wpsl' ) . '</p>';
            $pointer_content .= '<div id="mc_embed_signup" class="wpsl-mc-wrap" style="padding:0 15px; margin-bottom:13px;"><form action="//wpstorelocator.us10.list-manage.com/subscribe/post?u=34e4c75c3dc990d14002e19f6&amp;id=4be03427d7" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate><div id="mc_embed_signup_scroll"><input type="email" value="" name="EMAIL" class="email" id="mce-EMAIL" placeholder="email address" required style="margin-right:5px;width:230px;"><input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" class="button"><div style="position: absolute; left: -5000px;"><input type="text" name="b_34e4c75c3dc990d14002e19f6_4be03427d7" tabindex="-1" value=""></div></div></form></div>';
            ?>

            <script type="text/javascript">
			//<![CDATA[
			jQuery( document ).ready( function( $ ) {
                $( '#menu-posts-wpsl_stores' ).pointer({
                    content: '<?php echo $pointer_content; ?>',
                    position: {
                        edge: 'left',
                        align: 'center'
                    },
                    pointerWidth: 350,
                    close: function () {
                        $.post( ajaxurl, {
                            pointer: 'wpsl_signup_pointer',
                            action: 'dismiss-wp-pointer'
                        });
                    }
                }).pointer( 'open' );

                // If a user clicked the "subscribe" button trigger the close button for the pointer.
                $( ".wpsl-mc-wrap #mc-embedded-subscribe" ).on( "click", function() {
                    $( ".wp-pointer .close" ).trigger( "click" );
                });
            });
            //]]>
            </script>

            <?php
        }

        /**
         * Add link to the plugin action row.
         *
         * @since 2.0.0
         * @param  array  $links The existing action links
         * @param  string $file  The file path of the current plugin
         * @return array  $links The modified links
         */
        public function add_action_links( $links, $file ) {

            if ( strpos( $file, 'wp-store-locator.php' ) !== false ) {
                $settings_link = '<a href="' . admin_url( 'edit.php?post_type=wpsl_stores&page=wpsl_settings' ) . '" title="View WP Store Locator Settings">' . __( 'Settings', 'wpsl' ) . '</a>';
                array_unshift( $links, $settings_link );
            }

            return $links;
        }

        /**
         * Add links to the plugin meta row.
         *
         * @since 2.1.1
         * @param  array  $links The existing meta links
         * @param  string $file  The file path of the current plugin
         * @return array  $links The modified meta links
         */
        public function add_plugin_meta_row( $links, $file ) {

            if ( strpos( $file, 'wp-store-locator.php' ) !== false ) {
                $new_links = array(
                    '<a href="https://wpstorelocator.co/documentation/" title="View Documentation">'. __( 'Documentation', 'wpsl' ).'</a>',
                    '<a href="https://wpstorelocator.co/add-ons/" title="View Add-Ons">'. __( 'Add-Ons', 'wpsl' ).'</a>'
                );

                $links = array_merge( $links, $new_links );
            }

            return $links;
        }

        /**
         * Change the footer text on the settings page.
         *
         * @since 2.0.0
         * @param  string $text The current footer text
         * @return string $text Either the original or modified footer text
         */
        public function admin_footer_text( $text ) {

            $current_screen = get_current_screen();

            // Only modify the footer text if we are on the settings page of the wp store locator.
            if ( isset( $current_screen->id ) && $current_screen->id == 'wpsl_stores_page_wpsl_settings' ) {
                $text = sprintf( __( 'If you like this plugin please leave us a %s5 star%s rating.', 'wpsl' ), '<a href="https://wordpress.org/support/view/plugin-reviews/wp-store-locator?filter=5#postform" target="_blank"><strong>', '</strong></a>' );
            }

            return $text;
        }
    }

	$GLOBALS['wpsl_admin'] = new WPSL_Admin();
}admin/class-geocode.php000064400000033203151327220640011060 0ustar00<?php
/**
 * Geocode store locations
 *
 * @author Tijmen Smit
 * @since  2.0.0
 */

if ( !defined( 'ABSPATH' ) ) exit;

if ( !class_exists( 'WPSL_Geocode' ) ) {
        
	class WPSL_Geocode {
                
        /** 
         * Check if we need to run a geocode request or use the current location data.
         * 
         * The latlng value is only present if the user provided it himself, or used the preview
         * on the map. Otherwise the latlng will be missing and we need to geocode the supplied address.
         * 
         * @since 2.0.0
         * @param  integer $post_id    Store post ID
         * @param  array   $store_data The store data
         * @return void
         */
		public function check_geocode_data( $post_id, $store_data ) {
            
            $location_data = array();
            
            // Check if the latlng data is valid.
            $latlng = $this->validate_latlng( $store_data['lat'], $store_data['lng'] );

            // If we don't have a valid latlng value, we geocode the supplied address to get one.
            if ( !$latlng ) {
                $response = $this->geocode_location( $post_id, $store_data );
                
                if ( empty( $response ) ) {
                    return;
                }
                
                $location_data['country_iso'] = $response['country_iso'];
                $location_data['latlng']      = $response['latlng'];
            } else {
                $location_data['latlng']      = $latlng;
            }

            // Restrict the latlng to a max of 6 decimals.
            $location_data['latlng'] = $this->format_latlng( $location_data['latlng'] );

            $location_data['lat'] = $location_data['latlng']['lat'];
            $location_data['lng'] = $location_data['latlng']['lng'];
            
            $this->save_store_location( $post_id, $location_data );
        }
        
        /** 
         * Geocode the store location.
         * 
         * @since 1.0.0
         * @param  integer $post_id    Store post ID
         * @param  array   $store_data The submitted store data ( address, city, country etc )
         * @return void
         */
		public function geocode_location( $post_id, $store_data ) {
                        
			$geocode_response = $this->get_latlng( $store_data );

            if ( isset( $geocode_response['status'] ) ) {
                switch ( $geocode_response['status'] ) {
                    case 'OK':
                        $country = $this->filter_country_name( $geocode_response );

                        $location_data = array(
                            'country_iso' => $country['short_name'],
                            'latlng'      => $this->format_latlng( $geocode_response['results'][0]['geometry']['location'] )
                        );

                        return $location_data;
                    case 'ZERO_RESULTS':
                        $msg = __( 'The Google Geocoding API returned no results for the supplied address. Please change the address and try again.', 'wpsl' );
                        break;
                    case 'OVER_QUERY_LIMIT':
                        $msg = sprintf( __( 'You have reached the daily allowed geocoding limit, you can read more %shere%s.', 'wpsl' ), '<a target="_blank" href="https://developers.google.com/maps/documentation/geocoding/#Limits">', '</a>' );
                        break;
                    case 'REQUEST_DENIED':
                        $msg = sprintf( __( 'The Google Geocoding API returned REQUEST_DENIED. %s', 'wpsl' ), $this->check_geocode_error_msg( $geocode_response ) );
                        break;
                    default:
                        $msg = __( 'The Google Geocoding API failed to return valid data, please try again later.', 'wpsl' );
                        break;
                }
            } else {
                $msg = $geocode_response;
            }
            
            // Handle the geocode code errors messages.
            if ( !empty( $msg ) ) {
                $this->geocode_failed( $msg, $post_id );
            }
		}
        
        /**
         * Check if the response from the Geocode API contains an error message.
         * 
         * @since 2.1.0
         * @param  array  $geocode_response The response from the Geocode API.
         * @return string $error_msg        The error message, or empty if none exists.  
         */
        public function check_geocode_error_msg( $geocode_response, $inc_breaks = true ) {
            
            $breaks = ( $inc_breaks ) ? '<br><br>' : '';
            
            if ( isset( $geocode_response['error_message'] ) && $geocode_response['error_message'] ) {

                // If the problem is IP based, then show a different error msg.
                if ( strpos( $geocode_response['error_message'], 'IP' ) !== false  ) {
                    $error_msg = sprintf( __( '%sError message: %s. %s Make sure the IP address mentioned in the error matches with the IP set as the %sreferrer%s for the server API key in the %sGoogle API Console%s.', 'wpsl' ), $breaks, $this->clickable_error_links( $geocode_response['error_message'] ), $breaks, '<a href="https://wpstorelocator.co/document/create-google-api-keys/#server-key-referrer">', '</a>', '<a href="https://console.developers.google.com">', '</a>' );
                } else {
                    $error_msg = sprintf( __( '%sError message: %s %s Check if your issue is covered in the %stroubleshooting%s section, if not, then please open a %ssupport ticket%s.', 'wpsl' ),  $breaks, $this->clickable_error_links( $geocode_response['error_message'] ), $breaks, '<a href="https://wpstorelocator.co/document/create-google-api-keys/#troubleshooting">', '</a>', '<a href="https://wpstorelocator.co/support/">', '</a>' );
                }
            } else {
                $error_msg = '';
            }
            
            return $error_msg;
        }
        
        /** 
         * Make the API call to Google to geocode the address.
         * 
         * @since 1.0.0
         * @param  array        $store_data   The store data
         * @return array|string $geo_response The response from the Google Geocode API, or the wp_remote_get error message.
         */
        public function get_latlng( $store_data ) {

            $address  = $this->create_geocode_address( $store_data );
            $response = wpsl_call_geocode_api( $address );

            if ( is_wp_error( $response ) ) {
                $geo_response = sprintf( __( 'Something went wrong connecting to the Google Geocode API: %s %s Please try again later.', 'wpsl' ), $response->get_error_message(), '<br><br>' );
            } else if ( $response['response']['code'] == 500 ) {
                $geo_response = sprintf( __( 'The Google Geocode API reported the following problem: error %s %s %s Please try again later.', 'wpsl' ), $response['response']['code'], $response['response']['message'], '<br><br>' );
            } else if ( $response['response']['code'] == 400 ) {

                // Check on which page the 400 error was triggered, and based on that adjust the msg.
                if ( isset( $_GET['page'] ) && $_GET['page'] == 'wpsl_csv' ) {
                    $data_issue = sprintf( __( 'You can fix this by making sure the CSV file uses %sUTF-8 encoding%s.', 'wpsl' ), '<a href="https://wpstorelocator.co/document/csv-manager/#utf8">', '</a>' );
                } else if ( !$address ) {
                    $data_issue = __( 'You need to provide the details for either the address, city, state or country before the API can return coordinates.', 'wpsl' ); // this is only possible if the required fields are disabled with custom code.
                }

                $geo_response = sprintf( __( 'The Google Geocode API reported the following problem: error %s %s %s %s', 'wpsl' ), $response['response']['code'], $response['response']['message'], '<br><br>', $data_issue );
            } else if ( $response['response']['code'] != 200 ) {
                $geo_response = sprintf( __( 'The Google Geocode API reported the following problem: error %s %s %s Please contact %ssupport%s if the problem persists.', 'wpsl' ), $response['response']['code'], $response['response']['message'], '<br><br>', '<a href="https://wpstorelocator.co/support/">', '</a>' );
            } else {
                $geo_response = json_decode( $response['body'], true );
            }

            return $geo_response;
        }
        
        /** 
         * Create the address we need to Geocode.
         * 
         * @since 2.1.0
         * @param  array  $store_data      The provided store data
         * @return string $geocode_address The address we are sending to the Geocode API separated by ,
         */
        public function create_geocode_address( $store_data ) {
            
            $address       = array();
            $address_parts = array( 'address', 'city', 'state', 'zip', 'country' );
            
            foreach ( $address_parts as $address_part ) {
                if ( isset( $store_data[$address_part] ) && $store_data[$address_part] ) {
                    $address[] = trim( $store_data[$address_part] );
                }
            }

            $geocode_address = implode( ',', $address );

            return $geocode_address;
        }
        
        /** 
         * If there is a problem with the geocoding then we save the notice and change the post status to pending.
         * 
         * @since 2.0.0
         * @param  string  $msg     The geocode error message
         * @param  integer $post_id Store post ID
         * @return void
         */
        public function geocode_failed( $msg, $post_id ) {
            
            global $wpsl_admin;
            
            $wpsl_admin->notices->save( 'error', $msg );
            $wpsl_admin->metaboxes->set_post_pending( $post_id );
        }

        /** 
         * Save the store location data.
         * 
         * @since 2.0.0
         * @param  integer $post_id       Store post ID
         * @param  array   $location_data The country code and latlng
         * @return void
         */
		public function save_store_location( $post_id, $location_data ) {
            
            if ( isset( $location_data['country_iso'] ) && ( !empty( $location_data['country_iso'] ) ) ) {
                update_post_meta( $post_id, 'wpsl_country_iso', $location_data['country_iso'] );
            }
            
            update_post_meta( $post_id, 'wpsl_lat', $location_data['latlng']['lat'] );
            update_post_meta( $post_id, 'wpsl_lng', $location_data['latlng']['lng'] );
        }
        
        /** 
         * Make sure the latlng value has a max of 6 decimals.
         * 
         * @since 2.0.0
         * @param  array $latlng The latlng data
         * @return array $latlng The formatted latlng
         */
		public function format_latlng( $latlng ) {
            
            foreach ( $latlng as $key => $value ) {
                if ( strlen( substr( strrchr( $value, '.' ), 1 ) ) > 6 ) {
                    $latlng[$key] = round( $value, 6 );
                }
            }
            
            return $latlng;
        }

        /**
         * Filter out the two letter country code from the Geocode API response.
         *
         * @since 1.0.0
         * @param  array $response The full API geocode response
         * @return array $country  The country ISO code and full name
         */
        public function filter_country_name( $response ) {

            $length = count( $response['results'][0]['address_components'] );

            $country = array();

            // Loop over the address components until we find the country, political part.
            for ( $i = 0; $i < $length; $i++ ) {
                $address_component = $response['results'][0]['address_components'][$i]['types'];

                if ( $address_component[0] == 'country' && $address_component[1] == 'political' ) {
                    $country = $response['results'][0]['address_components'][$i];

                    break;
                }
            }

            return $country;
        }
        
        /** 
         * Validate the latlng values.
         * 
         * @since 1.0.0
         * @param  string        $lat    The latitude value
         * @param  string        $lng    The longitude value
         * @return boolean|array $latlng The validated latlng values or false if it fails
         */
		public function validate_latlng( $lat, $lng ) {
            
            if ( !is_numeric( $lat ) || ( $lat > 90 ) || ( $lat < -90 ) ) {
                return false;
            }

            if ( !is_numeric( $lng ) || ( $lng > 180 ) || ( $lng < -180 ) ) {
                return false;
            }

            $latlng = array( 
                'lat' => $lat,
                'lng' => $lng
            );

            return $latlng;
		}

		/**
         * Error messages returned by the Google Maps API
         * don't always contain clickable links.
         *
         * They now just look like this http://g.co/dev/maps-no-account
         * and are not clickable. To change this we wrap an href around it.
         *
         * @since 2.2.22
         * @return void
         */
		public function clickable_error_links( $msg ) {

            // Make sure the URLS aren't clickable yet. They aren't at the moment, but maybe Google changes this in the future.
            if ( strpos( $msg,'href' ) === false ) {
                preg_match_all( '#\bhttp(s?)?://[^,\s()<>]+(?:\([\w\d]+\)|([^,[:punct:]\s]|/))#', $msg, $match );

                foreach ( $match[0] as $k => $url ) {
                    $msg = str_replace( $url, '<a href="' . esc_url( $url ) . '">' . esc_html( $url ) . '</a>', $msg );
                }
            }

            return $msg;
        }
    }
}admin/upgrade.php000064400000063211151327220640010001 0ustar00<?php
add_action( 'admin_init', 'wpsl_check_upgrade' );
add_action( 'admin_init', 'wpsl_cpt_update_state' );

/**
 * If the db doesn't hold the current version, run the upgrade procedure
 *
 * @since 1.2
 * @return void
 */
function wpsl_check_upgrade() {
    
    global $wpsl_settings;

    $current_version = get_option( 'wpsl_version' );
   
    if ( version_compare( $current_version, WPSL_VERSION_NUM, '==' ) )
        return;

    if ( version_compare( $current_version, '1.1', '<' ) ) {
        if ( is_array( $wpsl_settings ) ) {
            if ( empty( $wpsl_settings['reset_map'] ) ) {
                $wpsl_settings['reset_map'] = 0;
            }

            if ( empty( $wpsl_settings['auto_load'] ) ) {
                $wpsl_settings['auto_load'] = 1;
            }	

            if ( empty( $wpsl_settings['new_window'] ) ) {
                $wpsl_settings['new_window'] = 0;
            }  

            update_option( 'wpsl_settings', $wpsl_settings );
        } 
    }

    if ( version_compare( $current_version, '1.2', '<' ) ) {
        if ( is_array( $wpsl_settings ) ) {
            if ( empty( $wpsl_settings['store_below'] ) ) {
                $wpsl_settings['store_below'] = 0;
            }	

            if ( empty( $wpsl_settings['direction_redirect'] ) ) {
                $wpsl_settings['direction_redirect'] = 0;
            }    

            update_option( 'wpsl_settings', $wpsl_settings );
        } 
    }

    if ( version_compare( $current_version, '1.2.11', '<' ) ) {
        if ( is_array( $wpsl_settings ) ) {
            if ( empty( $wpsl_settings['more_info'] ) ) {
                $wpsl_settings['more_info'] = 0;
            }

            if ( empty( $wpsl_settings['more_label'] ) ) {
                $wpsl_settings['more_label'] = __( 'More info', 'wpsl' );
            }

            if ( empty( $wpsl_settings['mouse_focus'] ) ) {
                $wpsl_settings['mouse_focus'] = 0;
            }	

            update_option( 'wpsl_settings', $wpsl_settings );
        } 
    }

    if ( version_compare( $current_version, '1.2.12', '<' ) ) {
        if ( is_array( $wpsl_settings ) ) {
            if ( empty( $wpsl_settings['more_info_location'] ) ) {
                $wpsl_settings['more_info_location'] = __( 'info window', 'wpsl' ); 
            }

            if ( empty( $wpsl_settings['back_label'] ) ) {
                $wpsl_settings['back_label'] = __( 'Back', 'wpsl' );
            }

            if ( empty( $wpsl_settings['reset_label'] ) ) {
                $wpsl_settings['reset_label'] = __( 'Reset', 'wpsl' );
            }                  

            if ( empty( $wpsl_settings['store_below_scroll'] ) ) {
                $wpsl_settings['store_below_scroll'] = 0;
            }  

            update_option( 'wpsl_settings', $wpsl_settings );
        } 
    }   

    if ( version_compare( $current_version, '1.2.20', '<' ) ) {

        global $wpdb;
        
        $wpsl_table = $wpdb->prefix . 'wpsl_stores';

        // Rename the street field to address.
        $wpdb->query( "ALTER TABLE $wpsl_table CHANGE street address VARCHAR(255)" );

        // Add the second address field.
        $wpdb->query( "ALTER TABLE $wpsl_table ADD address2 VARCHAR(255) NULL AFTER address" );

        if ( is_array( $wpsl_settings ) ) {
            if ( empty( $wpsl_settings['store_url'] ) ) {
                $wpsl_settings['store_url'] = 0;
            }

            if ( empty( $wpsl_settings['phone_url'] ) ) {
                $wpsl_settings['phone_url'] = 0;
            }

            if ( empty( $wpsl_settings['marker_clusters'] ) ) {
                $wpsl_settings['marker_clusters'] = 0;
            }

            if ( empty( $wpsl_settings['cluster_zoom'] ) ) {
                $wpsl_settings['cluster_zoom'] = 0;
            }

            if ( empty( $wpsl_settings['cluster_size'] ) ) {
                $wpsl_settings['cluster_size'] = 0;
            }

            if ( empty( $wpsl_settings['template_id'] ) ) {
                $wpsl_settings['template_id'] = ( $wpsl_settings['store_below'] ) ? 1 : 0;
                unset( $wpsl_settings['store_below'] );
            }

            if ( empty( $wpsl_settings['marker_streetview'] ) ) {
                $wpsl_settings['marker_streetview'] = 0;
            }

            if ( empty( $wpsl_settings['marker_zoom_to'] ) ) {
                $wpsl_settings['marker_zoom_to'] = 0;
            }

            if ( !isset( $wpsl_settings['editor_country'] ) ) {
                $wpsl_settings['editor_country'] = '';
            }

            if ( empty( $wpsl_settings['street_view_label'] ) ) {
                $wpsl_settings['street_view_label'] = __( 'Street view', 'wpsl' );
            }

            if ( empty( $wpsl_settings['zoom_here_label'] ) ) {
                $wpsl_settings['zoom_here_label'] = __( 'Zoom here', 'wpsl' );
            }

            if ( empty( $wpsl_settings['no_directions_label'] ) ) {
                $wpsl_settings['no_directions_label'] = __( 'No route could be found between the origin and destination', 'wpsl' );
            }

            update_option( 'wpsl_settings', $wpsl_settings );
        }
    }

    if ( version_compare( $current_version, '2.0', '<' ) ) {
        
        global $wpdb;
        
        $wpsl_table = $wpdb->prefix . 'wpsl_stores';
        
        if ( is_array( $wpsl_settings ) ) {
            if ( empty( $wpsl_settings['radius_dropdown'] ) ) {
                $wpsl_settings['radius_dropdown'] = 1;
            }
            
            if ( empty( $wpsl_settings['permalinks'] ) ) {
                $wpsl_settings['permalinks'] = 0;
            }

            if ( empty( $wpsl_settings['permalink_slug'] ) ) {
                $wpsl_settings['permalink_slug'] = __( 'stores', 'wpsl' );
            }
            
            if ( empty( $wpsl_settings['category_slug'] ) ) {
                $wpsl_settings['category_slug'] = __( 'store-category', 'wpsl' );
            }
           
            if ( empty( $wpsl_settings['editor_hours'] ) ) {
                $wpsl_settings['editor_hours'] = wpsl_default_opening_hours();
            }
            
            if ( empty( $wpsl_settings['editor_hour_format'] ) ) {
                $wpsl_settings['editor_hour_format'] = 12;
            }
            
            if ( empty( $wpsl_settings['editor_map_type'] ) ) {
                $wpsl_settings['editor_map_type'] = 'roadmap';
            }
            
            if ( empty( $wpsl_settings['infowindow_style'] ) ) {
                $wpsl_settings['infowindow_style'] = 'default';
            }
            
            if ( empty( $wpsl_settings['email_label'] ) ) {
                $wpsl_settings['email_label'] = __( 'Email', 'wpsl' );
            }
            
            if ( empty( $wpsl_settings['url_label'] ) ) {
                $wpsl_settings['url_label'] = __( 'Url', 'wpsl' );
            }
            
            if ( empty( $wpsl_settings['category_label'] ) ) {
                $wpsl_settings['category_label'] = __( 'Category filter', 'wpsl' );
            }
            
            if ( empty( $wpsl_settings['show_credits'] ) ) {
                $wpsl_settings['show_credits'] = 0;
            }
            
            if ( empty( $wpsl_settings['autoload_limit'] ) ) {
                $wpsl_settings['autoload_limit'] = 50;
            }
            
            if ( empty( $wpsl_settings['scrollwheel'] ) ) {
                $wpsl_settings['scrollwheel'] = 1;
            }
            
            if ( empty( $wpsl_settings['type_control'] ) ) {
                $wpsl_settings['type_control'] = 0;
            }

            if ( empty( $wpsl_settings['hide_hours'] ) ) {
                $wpsl_settings['hide_hours'] = 0;
            }
            
            // Either correct the existing map style format from the 2.0 beta or set it to empty.
            if ( isset( $wpsl_settings['map_style'] ) && is_array( $wpsl_settings['map_style'] ) && isset( $wpsl_settings['map_style']['id'] ) ) {
                switch( $wpsl_settings['map_style']['id'] ) {
                    case 'custom':
                        $map_style = $wpsl_settings['map_style']['custom_json'];
                        break;
                    case 'default':
                        $map_style = '';
                        break;
                    default:
                        $map_style = $wpsl_settings['map_style']['theme_json'];
                        break;
                }

                $wpsl_settings['map_style'] = $map_style;
            } else {
                $wpsl_settings['map_style'] = '';
            }
                        
            if ( empty( $wpsl_settings['autoload'] ) ) {
                $wpsl_settings['autoload'] = $wpsl_settings['auto_load'];
                unset( $wpsl_settings['auto_load'] );
            }
            
            if ( empty( $wpsl_settings['address_format'] ) ) {
                $wpsl_settings['address_format'] = 'city_state_zip';
            }
            
            if ( empty( $wpsl_settings['auto_zoom_level'] ) ) {
                $wpsl_settings['auto_zoom_level'] = 15;
            }
            
            if ( empty( $wpsl_settings['hide_distance'] ) ) {
                $wpsl_settings['hide_distance'] = 0;
            }
            
            if ( empty( $wpsl_settings['debug'] ) ) {
                $wpsl_settings['debug'] = 0;
            }
            
            if ( empty( $wpsl_settings['category_dropdown'] ) ) {
                $wpsl_settings['category_dropdown'] = 0;
            }
           
            /* 
             * Replace marker_bounce with marker_effect to better reflect what the option contains.
             * 
             * If a user hovers over the result list then either the corresponding marker will bounce,
             * the info window will open, or nothing will happen. 
             * 
             * The default behaviour is that the marker will bounce.
             */            
            if ( empty( $wpsl_settings['marker_effect'] ) ) {
                $wpsl_settings['marker_effect'] = ( $wpsl_settings['marker_bounce'] ) ? 'bounce' : 'ignore';
                unset( $wpsl_settings['marker_bounce'] );
            }
                        
            /* 
             * The default input for the opening hours is set to textarea for current users, 
             * for new users it will be set to dropdown ( easier to format in a table output and to use with schema.org in the future ).  
             */
            if ( empty( $wpsl_settings['editor_hour_input'] ) ) {
                $wpsl_settings['editor_hour_input'] = 'textarea';
            }
            
            // Rename store_below_scroll to listing_below_no_scroll, it better reflects what it does.
            if ( empty( $wpsl_settings['listing_below_no_scroll'] ) && isset( $wpsl_settings['store_below_scroll'] ) ) {
                $wpsl_settings['listing_below_no_scroll'] = $wpsl_settings['store_below_scroll'];
                unset( $wpsl_settings['store_below_scroll'] );
            }
            
            // Change the template ids from number based to name based.
            if ( is_numeric( $wpsl_settings['template_id'] ) ) {
                $wpsl_settings['template_id'] = ( !$wpsl_settings['template_id'] ) ? 'default' : 'below_map';
            }

            $replace_data = array(
                'max_results'   => $wpsl_settings['max_results'],
                'search_radius' => $wpsl_settings['search_radius']
            );

            /* 
             * Replace the () with [], this fixes an issue with the mod_security module that is installed on some servers. 
             * It triggerd a 'Possible SQL injection attack' warning probably because of the int,(int) format of the data.
             */
            foreach ( $replace_data as $index => $option_value ) {
                $wpsl_settings[$index] = str_replace( array( '(', ')' ), array( '[', ']' ), $option_value );
            }
            
            // The reset button now uses an icon instead of text, so no need for the label anymore.
            unset( $wpsl_settings['reset_label'] );

            update_option( 'wpsl_settings', $wpsl_settings ); 
            
            /* 
             * Users upgrading from 1.x will be given the choice between the textarea or 
             * dropdowns for the opening hours. 
             * 
             * New users don't get that choice, they will only get the dropdowns. 
             * 
             * The wpsl_legacy_support option is used to determine if we need to show both options.
             */
            update_option( 'wpsl_legacy_support', 1 ); 
                           
            // Add the WPSL roles and caps.
            wpsl_add_roles();
            wpsl_add_caps();

            // If there is a wpsl_stores table, then we need to convert all the locations to the 'wpsl_stores' custom post type.
            if ( $wpdb->get_var( "SHOW TABLES LIKE '$wpsl_table'" ) && version_compare( $current_version, '1.9', '<' ) ) { 
                if ( wpsl_remaining_cpt_count() ) {
                    update_option( 'wpsl_convert_cpt', 'in_progress' );
                }
            }
        }
    }
    
    /*
     * Both map options are no longer supported in 3.22 of the Google Maps API.
     * See: https://developers.google.com/maps/articles/v322-controls-diff
     */
    if ( version_compare( $current_version, '2.0.3', '<' ) ) {
        unset( $wpsl_settings['control_style'] );
        unset( $wpsl_settings['pan_controls'] );

        update_option( 'wpsl_settings', $wpsl_settings ); 
    }

    if ( version_compare( $current_version, '2.1.0', '<' ) ) {
        if ( !isset( $wpsl_settings['api_geocode_component'] ) ) {
            $wpsl_settings['api_geocode_component'] = 0;
        }

        update_option( 'wpsl_settings', $wpsl_settings ); 
    }
    
    if ( version_compare( $current_version, '2.2', '<' ) ) {
        $wpsl_settings['autocomplete'] = 0;
        $wpsl_settings['category_default_label'] = __( 'Any', 'wpsl' );

        // Rename the 'zoom_name' and 'zoom_latlng' to 'start_name' and 'start_latlng'.
        if ( isset( $wpsl_settings['zoom_name'] ) ) {
            $wpsl_settings['start_name'] = $wpsl_settings['zoom_name'];
            unset( $wpsl_settings['zoom_name'] );
        }

        if ( isset( $wpsl_settings['zoom_latlng'] ) ) {
            $wpsl_settings['start_latlng'] = $wpsl_settings['zoom_latlng'];
            unset( $wpsl_settings['zoom_latlng'] );
        }

        if ( isset( $wpsl_settings['category_dropdown'] ) ) {
            $wpsl_settings['category_filter'] = $wpsl_settings['category_dropdown'];
            unset( $wpsl_settings['category_dropdown'] );
        }
        
        // We now have separate browser and server key fields, and assume the existing key is a server key.
        if ( isset( $wpsl_settings['api_key'] ) ) {
            $wpsl_settings['api_server_key'] = $wpsl_settings['api_key'];
            unset( $wpsl_settings['api_key'] );
        }
        
        $wpsl_settings['api_browser_key']      = '';
        $wpsl_settings['category_filter_type'] = 'dropdown';
        $wpsl_settings['hide_country']         = 0;
        $wpsl_settings['show_contact_details'] = 0;
        
        update_option( 'wpsl_settings', $wpsl_settings ); 
    }
    
    if ( version_compare( $current_version, '2.2.4', '<' ) ) {
        $wpsl_settings['deregister_gmaps'] = 0;
        
        update_option( 'wpsl_settings', $wpsl_settings ); 
    }

    if ( version_compare( $current_version, '2.2.9', '<' ) ) {
        $wpsl_settings['run_fitbounds'] = 1;

        update_option( 'wpsl_settings', $wpsl_settings );
    }

    if ( version_compare( $current_version, '2.2.13', '<' ) ) {
        $wpsl_settings['clickable_contact_details'] = 0;

        update_option( 'wpsl_settings', $wpsl_settings );
    }

    if ( version_compare( $current_version, '2.2.20', '<' ) ) {
        $wpsl_settings['force_postalcode'] = 0;
        $wpsl_settings['permalink_remove_front'] = 0;

        update_option( 'wpsl_settings', $wpsl_settings );
    }

    if ( version_compare( $current_version, '2.2.22', '<' ) ) {
        $wpsl_settings['delay_loading'] = 0;

        update_option( 'wpsl_settings', $wpsl_settings );
    }

    update_option( 'wpsl_version', WPSL_VERSION_NUM );
}

/**
 * Check if we need to show the notice that tells users that the store locations
 * need to be converted to custom post types before the update from 1.x to 2.x is complete.
 * 
 * @since 2.0
 * @return void
 */
function wpsl_cpt_update_state() {

    global $wpsl_admin;
    
    $conversion_state = get_option( 'wpsl_convert_cpt' );
    
    if ( $conversion_state == 'in_progress' ) {
        if ( ( !defined( 'DOING_AJAX' ) || !DOING_AJAX ) ) {
            $remaining = wpsl_remaining_cpt_count();
            $wpsl_admin->notices->save( 'error', sprintf( __( 'Because you updated WP Store Locator from version 1.x, the %s current store locations need to be %sconverted%s to custom post types.', 'wpsl' ), "<span class='wpsl-cpt-remaining'>" . $remaining . "</span>", "<a href='#' id='wpsl-cpt-dialog'>", "</a>" ) );        
        
            add_action( 'admin_footer',  'wpsl_cpt_dialog_html' );
        }

        add_action( 'admin_enqueue_scripts',     'wpsl_convert_cpt_js' );	
        add_action( 'wp_ajax_convert_cpt',       'wpsl_convert_cpt' );
        add_action( 'wp_ajax_convert_cpt_count', 'wpsl_convert_cpt_count' );
    }
}

/**
 * Include the js file that handles the ajax request to 
 * start converting the 1.x store locations to custom post types.
 * 
 * @since 2.0
 * @return void
 */
function wpsl_convert_cpt_js() {

    $cpt_js_l10n = array(
        'timeout'      => sprintf( __( 'The script converting the locations timed out. %s You can click the "Start Converting" button again to restart the script. %s If there are thousands of store locations left to convert and you keep seeing this message, then you can try to contact your host and ask if they can increase the maximum execution time. %s The plugin tried to disable the maximum execution time, but if you are reading this then that failed.', 'wpsl' ), '<br><br>', '<br><br>', '<br><br>' ),
        'securityFail' => __( 'Security check failed, reload the page and try again.', 'wpsl' )
    );

    wp_enqueue_script( 'jquery-ui-dialog' );
    wp_enqueue_script( 'wpsl-queue', plugins_url( '/js/ajax-queue.js', __FILE__ ), array( 'jquery' ), false ); 
    wp_enqueue_script( 'wpsl-cpt-js', plugins_url( '/js/wpsl-cpt-upgrade.js', __FILE__ ), array( 'jquery' ), false );
    wp_localize_script( 'wpsl-cpt-js', 'wpslCptConversion', $cpt_js_l10n );
}

/**
 * The html for the lightbox
 * 
 * @since 2.0
 * @return void
 */
function wpsl_cpt_dialog_html() {

    ?>
    <div id="wpsl-cpt-lightbox" style="display:none;">
        <span class="tb-close-icon"></span>
        <p class="wpsl-cpt-remaining"><?php _e( 'Store locations to convert:', 'wpsl' ); echo '<span></span>'; ?></p>
        <div class="wslp-cpt-fix-wrap">
            <input id="wpsl-start-cpt-conversion" class="button-primary" type="submit" value="<?php _e( 'Start Converting', 'wpsl' ); ?>" >
            <img class="wpsl-preloader" alt="preloader" src="<?php echo WPSL_URL . 'img/ajax-loader.gif'; ?>" />
        </div>
        <input type="hidden" name="wpsl-cpt-fix-nonce" value="<?php echo wp_create_nonce( 'wpsl-cpt-fix' ); ?>" />
        <input type="hidden" name="wpsl-cpt-conversion-count" value="<?php echo wp_create_nonce( 'wpsl-cpt-count' ); ?>" />
    </div>
    <div id="wpsl-cpt-overlay" style="display:none;"></div>
    <style>
        .wslp-cpt-fix-wrap {
            float:left;
            clear:both;
            width:100%;
            margin:0 0 15px 0;
        }

        #wpsl-cpt-lightbox .wpsl-cpt-remaining span {
            margin-left:5px;
        }

        #wpsl-start-cpt-conversion {
            float:left;
        }

        .wslp-cpt-fix-wrap .wpsl-preloader,
        .wslp-cpt-fix-wrap span {
            float:left;
            margin:8px 0 0 10px;    
        }

        .wslp-cpt-fix-wrap .wpsl-preloader {
            display: none;
        }
        
        #wpsl-cpt-lightbox {
            position:fixed;
            width:450px;
            left:50%;
            right:50%;
            top:3.8em;
            padding:15px;
            background:none repeat scroll 0 0 #fff;
            border-radius:3px;
            margin-left:-225px;
            z-index: 9999;
        }
        
        #wpsl-cpt-overlay {
            position:fixed;
            right:0;
            top:0;
            z-index:9998;
            background:none repeat scroll 0 0 #000;
            bottom:0;
            left:0;
            opacity:0.5;
        }
        
        .tb-close-icon {
            color: #666;
            text-align: center;
            line-height: 29px;
            width: 29px;
            height: 29px;
            position: absolute;
            top: 0;
            right: 0;
        }

        .tb-close-icon:before {
            content: '\f158';
            font: normal 20px/29px 'dashicons';
            speak: none;
            -webkit-font-smoothing: antialiased;
            -moz-osx-font-smoothing: grayscale;
        }

        .tb-close-icon:hover {
            color: #999 !important;
            cursor: pointer;
        }
    </style>
    <?php    
}

/**
 * Handle the ajax call to start converting the
 * store locations to custom post types.
 * 
 * @since 2.0
 * @return void|string json on completion
 */
function wpsl_convert_cpt() {
    
    if ( !current_user_can( 'manage_options' ) )
        die( '-1' );
    check_ajax_referer( 'wpsl-cpt-fix' );

    // Start the cpt coversion.
    wpsl_cpt_conversion();

    exit();
}

/**
 * Get the amount of locations that still need to be converted.
 * 
 * @since 2.0
 * @return string json The amount of locations that still need to be converted
 */
function wpsl_convert_cpt_count() {
   
    if ( !current_user_can( 'manage_options' ) )
        die( '-1' );
    check_ajax_referer( 'wpsl-cpt-count' );
    
    $remaining_count = wpsl_remaining_cpt_count();
        
    $response['success'] = true;
    
    if ( $remaining_count ) {
        $response['count'] = $remaining_count;
    } else {
        $response['url'] = sprintf( __( 'All the store locations are now converted to custom post types. %s You can view them on the %sAll Stores%s page.', 'wpsl' ), '<br><br>', '<a href="' . admin_url( 'edit.php?post_type=wpsl_stores' ) . '">', '</a>' );
        
        delete_option( 'wpsl_convert_cpt' );
    }
    
    wp_send_json( $response );
    
    exit();
}

/**
 * Return the difference between the number of existing wpsl custom post types, 
 * and the number of records in the old wpsl_stores database.
 * 
 * @since 2.0
 * @return int|boolean $remaining The amount of locations that still need to be converted
 */
function wpsl_remaining_cpt_count() {
    
    global $wpdb;
    
    $table = $wpdb->prefix . 'wpsl_stores';
    $count = wp_count_posts( 'wpsl_stores' );
    
    if ( isset( $count->publish ) && isset( $count->draft ) ) {
        $cpt_count = $count->publish + $count->draft;
    } else {
        $cpt_count = 0;
    }
    
    $db_count   = $wpdb->get_var( "SELECT COUNT(wpsl_id) FROM $table" );
    $difference = $db_count - $cpt_count;
    
    /* 
     * This prevents users who used the 2.0 beta, and later added 
     * more stores from seeing the upgrade notice again.
     */
    $remaining = ( $difference < 0 ) ? false : $difference;
                    
    return $remaining;
}

/**
 * Convert the existing locations to custom post types.
 * 
 * @since 2.0
 * @return void|boolean True if the conversion is completed
 */
function wpsl_cpt_conversion() {
    
    global $wpdb;
    
    // Try to disable the time limit to prevent timeouts.
    @set_time_limit( 0 );

    $meta_keys  = array( 'address', 'address2', 'city', 'state', 'zip', 'country', 'country_iso', 'lat', 'lng', 'phone', 'fax', 'url', 'email', 'hours' );
    $offset     = wpsl_remaining_cpt_count();
    $wpsl_table = $wpdb->prefix . 'wpsl_stores';
    $stores     = $wpdb->get_results( "(SELECT * FROM $wpsl_table ORDER BY wpsl_id DESC LIMIT $offset) ORDER BY wpsl_id ASC" );
    
    foreach ( $stores as $store ) {
        
        // Make sure we set the correct post status.
        if ( $store->active ) {
            $post_status = 'publish';
        } else {
            $post_status = 'draft';
        }
        
        $post = array (
            'post_type'    => 'wpsl_stores',
            'post_status'  => $post_status,
            'post_title'   => $store->store,
            'post_content' => $store->description              
        );

        $post_id = wp_insert_post( $post );

        if ( $post_id ) {
            
            // Save the data from the wpsl_stores db table as post meta data.
            foreach ( $meta_keys as $meta_key ) {
                if ( isset( $store->{$meta_key} ) && !empty( $store->{$meta_key} ) ) {
                    update_post_meta( $post_id, 'wpsl_' . $meta_key, $store->{$meta_key} );
                }
            }
            
            // If we have a thumb ID set the post thumbnail for the inserted post.
            if ( $store->thumb_id ) {
                set_post_thumbnail( $post_id, $store->thumb_id );
            }
        }
    }
}admin/data-export.php000064400000005541151327220640010604 0ustar00<?php
add_action( 'admin_init', 'wpsl_single_location_export' );

/**
 * Handle the export of a single store location.
 *
 * Creates a CSV file holding the location details
 * that can be handed over in case a GDPR related
 * data access request is received.
 *
 * @since 2.2.15
 * @return void
 */
function wpsl_single_location_export() {

    global $wpsl_admin; // From the WPSL plugin

    if ( isset( $_GET['wpsl_data_export'] ) && isset( $_GET['wpsl_export_nonce'] ) ) {
        $post_id = absint( $_GET['post'] );

        if ( !wp_verify_nonce( $_GET['wpsl_export_nonce'], 'wpsl_export_' . $post_id ) )
            return;

        if ( is_int( wp_is_post_revision( $post_id ) ) )
            return;

        if ( !current_user_can( 'edit_post', $post_id ) )
            return;

        $meta_fields  = array();
        $wp_field_map = array(
            'wpsl_id'     => 'ID',
            'name'        => 'post_title',
            'status'      => 'post_status',
            'permalink'   => 'post_name',
            'description' => 'post_content',
            'excerpt'     => 'post_excerpt',
            'author'      => 'post_author',
            'date'        => 'post_date'
        );

        $meta_box_fields = $wpsl_admin->metaboxes->meta_box_fields();
        $fields          = array_keys( $wp_field_map );
        array_push( $fields, 'image', 'category', 'tags' );

        foreach ( $meta_box_fields as $k => $field_section ) {
            foreach ( $field_section as $field_name => $field_value ) {
                $meta_fields[] = $field_name;
            }
        }

        $meta_data   = get_post_custom( $post_id );
        $post_meta   = array();

        // Loop over the wpsl meta fields, and collect the meta data.
        foreach ( $meta_fields as $meta_field ) {
            if ( $meta_field !== 'hours' ) {
                if ( isset( $meta_data['wpsl_' . $meta_field][0] ) ) {
                    $post_meta['data'][$meta_field] = $meta_data['wpsl_' . $meta_field][0];
                } else {
                    $post_meta['data'][$meta_field] = '';
                }

                $post_meta['headers'][] = $meta_field;
            }
        }

        // Make it possible to add additional custom data from for example ACF
        $post_meta = apply_filters( 'wpsl_single_location_export_data', $post_meta, $post_id );

        if ( $post_meta ) {
            $file_name = 'wpsl-export-' . $post_id . '-' . date('Ymd' ) . '.csv';

            // Set the download headers for the CSV file.
            header( 'Content-Type: text/csv; charset=utf-8' );
            header( 'Content-Disposition: attachment; filename=' . $file_name . '' );

            $output = fopen( 'php://output', 'w' );

            fputcsv( $output, $post_meta['headers'] );
            fputcsv( $output, $post_meta['data'] );

            fclose( $output );
        }

        exit();
    }
}admin/font/fontello.svg000064400000003153151327220640011151 0ustar00<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Copyright (C) 2015 by original authors @ fontello.com</metadata>
<defs>
<font id="fontello" horiz-adv-x="1000" >
<font-face font-family="fontello" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
<missing-glyph horiz-adv-x="1000" />
<glyph glyph-name="location" unicode="&#xe801;" d="m429 493q0 59-42 101t-101 42-101-42-42-101 42-101 101-42 101 42 42 101z m142 0q0-61-18-100l-203-432q-9-18-27-29t-37-11-38 11-26 29l-204 432q-18 39-18 100 0 118 84 202t202 84 202-84 83-202z" horiz-adv-x="571.4" />
<glyph glyph-name="attention-circled" unicode="&#xe802;" d="m429 779q116 0 215-58t156-156 57-215-57-215-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58z m71-696v106q0 8-5 13t-12 5h-107q-8 0-13-5t-6-13v-106q0-8 6-13t13-6h107q7 0 12 6t5 13z m-1 192l10 346q0 7-6 10-5 5-13 5h-123q-8 0-13-5-6-3-6-10l10-346q0-6 5-10t14-4h103q8 0 13 4t6 10z" horiz-adv-x="857.1" />
<glyph glyph-name="cancel-circle" unicode="&#xe803;" d="m1000 349q0-136-67-251t-182-182-251-67-251 67-182 182-67 251 67 251 182 182 251 67 251-67 182-182 67-251z m-339-232l71 71-161 161 161 161-71 71-161-161-161 161-71-71 161-161-161-161 71-71 161 161z" horiz-adv-x="1000" />
<glyph glyph-name="plus-circle" unicode="&#xe805;" d="m1000 349q0-136-67-251t-182-182-251-67-251 67-182 182-67 251 67 251 182 182 251 67 251-67 182-182 67-251z m-440-58h235v118h-235v235h-118v-235h-236v-118h236v-236h118v236z" horiz-adv-x="1000" />
</font>
</defs>
</svg>admin/font/fontello.eot000064400000012314151327220640011140 0ustar00�$�LP)��fontelloRegularVersion 1.0fontello�`OS/2>*I	�Vcmap���DRcvt ,
fpgm���Y8pgasp$glyf4��k��head��T6hhea�U�$hmtxL�loca�Y�maxp��� name̝��postb����cprep�k��{v�z��z��1PfEd@��R�jZQ�L0�����������<�-+4&"267"&'&5462�TvTTvT��	$&&����;TTvTT;='�P�'=v������Y.
�*!-+2".>54&+"326'4'&+";26�t�rr���nz��
k
k

{

	g
t���tt���t�Hj

j
�Z���i�Q�
	-+ .> 7'7''7���憆���G��G��G��G�]�憆�憆�G��G��G��G��i�Q�	-+ .> 35#5##33���憆��H��v��v]�憆�憆��v��v���)_<���Y}��YSs���i�QR�jZ�����;Y��0|��/sp�55=DLT_
+g�	j�			-	=	M	c	
Vs	&�Copyright (C) 2015 by original authors @ fontello.comfontelloRegularfontellofontelloVersion 1.0fontelloGenerated by svg2ttf from Fontello project.http://fontello.comCopyright (C) 2015 by original authors @ fontello.comfontelloRegularfontellofontelloVersion 1.0fontelloGenerated by svg2ttf from Fontello project.http://fontello.com
locationattention-circled
cancel-circleplus-circle���, �UXEY  K�QK�SZX�4�(Y`f �UX�%a�cc#b!!�Y�C#D�C`B-�,� `f-�, d ��P�&Z�(
CEcER[X!#!�X �PPX!�@Y �8PX!�8YY �
CEcEad�(PX!�
CEcE �0PX!�0Y ��PX f ��a �
PX` � PX!�
` �6PX!�6``YYY�+YY#�PXeYY-�, E �%ad �CPX�#B�#B!!Y�`-�,#!#! d�bB �#B�
CEc�
C�`Ec�*! �C � ��+�0%�&QX`PaRYX#Y! �@SX�+!�@Y#�PXeY-�,�C+�C`B-�,�#B# �#Ba�bf�c�`�*-�,  E �Cc�b �PX�@`Yf�c`D�`-�,�CEB*!�C`B-�	,�C#D�C`B-�
,  E �+#�C�%` E�#a d � PX!��0PX� �@YY#�PXeY�%#aDD�`-�,  E �+#�C�%` E�#a d�$PX��@Y#�PXeY�%#aDD�`-�, �#B�
EX!#!Y*!-�
,�E�daD-�,�`  �CJ�PX �#BY�
CJ�RX �
#BY-�, �bf�c �c�#a�C` �` �#B#-�,KTX�dDY$�
e#x-�,KQXKSX�dDY!Y$�e#x-�,�CUX�C�aB�+Y�C�%B�%B�
%B�# �%PX�C`�%B�� �#a�*!#�a �#a�*!�C`�%B�%a�*!Y�CG�
CG`�b �PX�@`Yf�c �Cc�b �PX�@`Yf�c`�#D�C�>�C`B-�,�ETX�#B E�#B�
#�`B `�a�BB�`�+�r+"Y-�,�+-�,�+-�,�+-�,�+-�,�+-�,�+-�,�+-�,�+-�,�+-�,�	+-�,�
+�ETX�#B E�#B�
#�`B `�a�BB�`�+�r+"Y-�,�+-� ,�+-�!,�+-�",�+-�#,�+-�$,�+-�%,�+-�&,�+-�',�+-�(,�	+-�), <�`-�*, `�` C#�`C�%a�`�)*!-�+,�*+�**-�,,  G  �Cc�b �PX�@`Yf�c`#a8# �UX G  �Cc�b �PX�@`Yf�c`#a8!Y-�-,�ETX��,*�0"Y-�.,�
+�ETX��,*�0"Y-�/, 5�`-�0,�Ec�b �PX�@`Yf�c�+�Cc�b �PX�@`Yf�c�+��D>#8�/*-�1, < G �Cc�b �PX�@`Yf�c`�Ca8-�2,.<-�3, < G �Cc�b �PX�@`Yf�c`�Ca�Cc8-�4,�% . G�#B�%I��G#G#a Xb!Y�#B�3*-�5,��%�%G#G#a�	C+e�.#  <�8-�6,��%�% .G#G#a �#B�	C+ �`PX �@QX�  �&YBB# �C �#G#G#a#F`�C�b �PX�@`Yf�c` �+ ��a �C`d#�CadPX�Ca�C`Y�%�b �PX�@`Yf�ca#  �&#Fa8#�CF�%�CG#G#a` �C�b �PX�@`Yf�c`# �+#�C`�+�%a�%�b �PX�@`Yf�c�&a �%`d#�%`dPX!#!Y#  �&#Fa8Y-�7,�   �& .G#G#a#<8-�8,� �#B   F#G�+#a8-�9,��%�%G#G#a�TX. <#!�%�%G#G#a �%�%G#G#a�%�%I�%a�cc# Xb!Yc�b �PX�@`Yf�c`#.#  <�8#!Y-�:,� �C .G#G#a `� `f�b �PX�@`Yf�c#  <�8-�;,# .F�%FRX <Y.�++-�<,# .F�%FPX <Y.�++-�=,# .F�%FRX <Y# .F�%FPX <Y.�++-�>,�5+# .F�%FRX <Y.�++-�?,�6+�  <�#B�8# .F�%FRX <Y.�++�C.�++-�@,��%�& .G#G#a�	C+# < .#8�++-�A,�%B��%�% .G#G#a �#B�	C+ �`PX �@QX�  �&YBB# G�C�b �PX�@`Yf�c` �+ ��a �C`d#�CadPX�Ca�C`Y�%�b �PX�@`Yf�ca�%Fa8# <#8!  F#G�+#a8!Y�++-�B,�5+.�++-�C,�6+!#  <�#B#8�++�C.�++-�D,� G�#B�.�1*-�E,� G�#B�.�1*-�F,��2*-�G,�4*-�H,�E# . F�#a8�++-�I,�#B�H+-�J,�A+-�K,�A+-�L,�A+-�M,�A+-�N,�B+-�O,�B+-�P,�B+-�Q,�B+-�R,�>+-�S,�>+-�T,�>+-�U,�>+-�V,�@+-�W,�@+-�X,�@+-�Y,�@+-�Z,�C+-�[,�C+-�\,�C+-�],�C+-�^,�?+-�_,�?+-�`,�?+-�a,�?+-�b,�7+.�++-�c,�7+�;+-�d,�7+�<+-�e,��7+�=+-�f,�8+.�++-�g,�8+�;+-�h,�8+�<+-�i,�8+�=+-�j,�9+.�++-�k,�9+�;+-�l,�9+�<+-�m,�9+�=+-�n,�:+.�++-�o,�:+�;+-�p,�:+�<+-�q,�:+�=+-�r,�	EX!#!YB+�e�$Px�0-K��RX��Y��cp�B�*�B�*�B�*�B�	*�B�	*�D�$�QX�@�X�dD�&�QX��@�cTX�DYYYY�*������Dadmin/font/fontello.ttf000064400000012044151327220640011146 0ustar00�`OS/2>*I	�Vcmap���DRcvt ,
fpgm���Y8pgasp$glyf4��k��head��T6hhea�U�$hmtxL�loca�Y�maxp��� name̝��postb����cprep�k��{v�z��z��1PfEd@��R�jZQ�L0�����������<�-+4&"267"&'&5462�TvTTvT��	$&&����;TTvTT;='�P�'=v������Y.
�*!-+2".>54&+"326'4'&+";26�t�rr���nz��
k
k

{

	g
t���tt���t�Hj

j
�Z���i�Q�
	-+ .> 7'7''7���憆���G��G��G��G�]�憆�憆�G��G��G��G��i�Q�	-+ .> 35#5##33���憆��H��v��v]�憆�憆��v��v���)_<���Y}��YSs���i�QR�jZ�����;Y��0|��/sp�55=DLT_
+g�	j�			-	=	M	c	
Vs	&�Copyright (C) 2015 by original authors @ fontello.comfontelloRegularfontellofontelloVersion 1.0fontelloGenerated by svg2ttf from Fontello project.http://fontello.comCopyright (C) 2015 by original authors @ fontello.comfontelloRegularfontellofontelloVersion 1.0fontelloGenerated by svg2ttf from Fontello project.http://fontello.com
locationattention-circled
cancel-circleplus-circle���, �UXEY  K�QK�SZX�4�(Y`f �UX�%a�cc#b!!�Y�C#D�C`B-�,� `f-�, d ��P�&Z�(
CEcER[X!#!�X �PPX!�@Y �8PX!�8YY �
CEcEad�(PX!�
CEcE �0PX!�0Y ��PX f ��a �
PX` � PX!�
` �6PX!�6``YYY�+YY#�PXeYY-�, E �%ad �CPX�#B�#B!!Y�`-�,#!#! d�bB �#B�
CEc�
C�`Ec�*! �C � ��+�0%�&QX`PaRYX#Y! �@SX�+!�@Y#�PXeY-�,�C+�C`B-�,�#B# �#Ba�bf�c�`�*-�,  E �Cc�b �PX�@`Yf�c`D�`-�,�CEB*!�C`B-�	,�C#D�C`B-�
,  E �+#�C�%` E�#a d � PX!��0PX� �@YY#�PXeY�%#aDD�`-�,  E �+#�C�%` E�#a d�$PX��@Y#�PXeY�%#aDD�`-�, �#B�
EX!#!Y*!-�
,�E�daD-�,�`  �CJ�PX �#BY�
CJ�RX �
#BY-�, �bf�c �c�#a�C` �` �#B#-�,KTX�dDY$�
e#x-�,KQXKSX�dDY!Y$�e#x-�,�CUX�C�aB�+Y�C�%B�%B�
%B�# �%PX�C`�%B�� �#a�*!#�a �#a�*!�C`�%B�%a�*!Y�CG�
CG`�b �PX�@`Yf�c �Cc�b �PX�@`Yf�c`�#D�C�>�C`B-�,�ETX�#B E�#B�
#�`B `�a�BB�`�+�r+"Y-�,�+-�,�+-�,�+-�,�+-�,�+-�,�+-�,�+-�,�+-�,�+-�,�	+-�,�
+�ETX�#B E�#B�
#�`B `�a�BB�`�+�r+"Y-�,�+-� ,�+-�!,�+-�",�+-�#,�+-�$,�+-�%,�+-�&,�+-�',�+-�(,�	+-�), <�`-�*, `�` C#�`C�%a�`�)*!-�+,�*+�**-�,,  G  �Cc�b �PX�@`Yf�c`#a8# �UX G  �Cc�b �PX�@`Yf�c`#a8!Y-�-,�ETX��,*�0"Y-�.,�
+�ETX��,*�0"Y-�/, 5�`-�0,�Ec�b �PX�@`Yf�c�+�Cc�b �PX�@`Yf�c�+��D>#8�/*-�1, < G �Cc�b �PX�@`Yf�c`�Ca8-�2,.<-�3, < G �Cc�b �PX�@`Yf�c`�Ca�Cc8-�4,�% . G�#B�%I��G#G#a Xb!Y�#B�3*-�5,��%�%G#G#a�	C+e�.#  <�8-�6,��%�% .G#G#a �#B�	C+ �`PX �@QX�  �&YBB# �C �#G#G#a#F`�C�b �PX�@`Yf�c` �+ ��a �C`d#�CadPX�Ca�C`Y�%�b �PX�@`Yf�ca#  �&#Fa8#�CF�%�CG#G#a` �C�b �PX�@`Yf�c`# �+#�C`�+�%a�%�b �PX�@`Yf�c�&a �%`d#�%`dPX!#!Y#  �&#Fa8Y-�7,�   �& .G#G#a#<8-�8,� �#B   F#G�+#a8-�9,��%�%G#G#a�TX. <#!�%�%G#G#a �%�%G#G#a�%�%I�%a�cc# Xb!Yc�b �PX�@`Yf�c`#.#  <�8#!Y-�:,� �C .G#G#a `� `f�b �PX�@`Yf�c#  <�8-�;,# .F�%FRX <Y.�++-�<,# .F�%FPX <Y.�++-�=,# .F�%FRX <Y# .F�%FPX <Y.�++-�>,�5+# .F�%FRX <Y.�++-�?,�6+�  <�#B�8# .F�%FRX <Y.�++�C.�++-�@,��%�& .G#G#a�	C+# < .#8�++-�A,�%B��%�% .G#G#a �#B�	C+ �`PX �@QX�  �&YBB# G�C�b �PX�@`Yf�c` �+ ��a �C`d#�CadPX�Ca�C`Y�%�b �PX�@`Yf�ca�%Fa8# <#8!  F#G�+#a8!Y�++-�B,�5+.�++-�C,�6+!#  <�#B#8�++�C.�++-�D,� G�#B�.�1*-�E,� G�#B�.�1*-�F,��2*-�G,�4*-�H,�E# . F�#a8�++-�I,�#B�H+-�J,�A+-�K,�A+-�L,�A+-�M,�A+-�N,�B+-�O,�B+-�P,�B+-�Q,�B+-�R,�>+-�S,�>+-�T,�>+-�U,�>+-�V,�@+-�W,�@+-�X,�@+-�Y,�@+-�Z,�C+-�[,�C+-�\,�C+-�],�C+-�^,�?+-�_,�?+-�`,�?+-�a,�?+-�b,�7+.�++-�c,�7+�;+-�d,�7+�<+-�e,��7+�=+-�f,�8+.�++-�g,�8+�;+-�h,�8+�<+-�i,�8+�=+-�j,�9+.�++-�k,�9+�;+-�l,�9+�<+-�m,�9+�=+-�n,�:+.�++-�o,�:+�;+-�p,�:+�<+-�q,�:+�=+-�r,�	EX!#!YB+�e�$Px�0-K��RX��Y��cp�B�*�B�*�B�*�B�	*�B�	*�D�$�QX�@�X�dD�&�QX��@�cTX�DYYYY�*������Dadmin/font/fontello.woff000064400000005620151327220640011314 0ustar00wOFF�$OS/2DDV>*I	cmap�;R���cvt �

fpgm��p���Ygaspdglyfla�4��khead�56��hhea	$�Uhmtx	(Lloca	<�Ymaxp	H  ��name	hw�̝post
�Ecb���prep(e{�k�x�c`d.c�����TŴ����B3>`0ddb``b`ef�
�\S^0�`e�����0(���B�x�c```f�`F���| ��L ��/X���!,	�P]`���0���	�x��VisG��a�6>�6�Y�r�vV����J���B�]Kv�O���^�T�o����`'UT(J����L��^�В�^X���|)��6id�IH7lZ��C��)SL�.��h�Ծ�8$"��u�%����$�C�2Z�%�jRn�Iw�����Q��	%5��C�-�¨E2푒6-��_IZ��+�|�%��$�ƛa��g�V��vE�M�E�D3<�"��Zb�\1A@��R^�4�|��{��
q�v��%?�ο$�z��%�@vd{�+�"��
㦝lG���t}'�#����Q^�h�vE�'���W�X�	e��j�|ʗ<Ւ��Z/sb_��GL�k&Ȃ�N����c����],!�8���J�F)a��$m9���E��zGL��:-�-a�N��Kg�I�;1��������x4��L�N��єQJ:<����$�����ʣil3c$�P��si*�e'�4�<�ћ�a�kעE�<P�=zOon��;=��?k�gu*���0���J|�v�IѺ~z�&�C�*�-6Ô�C�~��cK��kl���+�}�DȤ���/�)L��UPݴֵ,��jV�Td�!M+_�iM9}c_�8���KL	���������%�4��f]��uj�]��l��4�}���~��<��:ak�t��:-��H�cl/hA��;r�\���u�K��B l�"a��@�~�@�.#�����~*i;�E��9��en*WSɥ��F�6�)r���xV�+��7���@�D��I�|T�㏮hy�Ĺ�U{s\�e�X�S�ښ��W�ydry#Г�D�&����G���k�~�EY�
����Q��P
\�33��e���!�~�7܃NYIY�`��׏e���'X�b���[ዌ�J�Ef){>�y�0*�a�
\���{��M�L�e���Ǚ ��c0o�� $L]���)����`�)��CTo��p{�}��kW��M�m�F��P�[���'���@U!MŸ��K#�j�a\��F2N����
˲�G�wJ�e �H�GG?��B�Թ��(n�;��Aib����⠔w��eVmS��Sך�ū�ͣ�{��'r�4�tO��U����Y����L.�����ͥ��e\��v0,0�ߡ�W�q�<W�
��H�����b�8G���1L����{��n���2]�]�������f�pC�
���Z��
|�:=�܎���
�`�b��Z��)��|��s�0h2��sl3g
`�9v��`�9�`�:���a2�A�O�<e�����k�0��9��e��9�0��tk(s�t�mP����8�T���ao�0��?j�=���C�� ��bS�tgH�����AL�� �>�/�r��_F�K��.6����@���x�e�OKQ�ߝǼ�|��8
BLc$�ga��e���֑B�Y�~h}71!ѦM!��I����L ���.ν��9HBhї�p1��ؽ'������%�n���8dM�M�T�t�5�F0��[d�4��O}���Z�R�E��U�Bx1[��Q�C�������F� 0�4��wA�A�.�y����Q��"U�@��R�
Xe�u��p�zN.�8m11ڢ8��%�	�S�q�3�t~֬�d��f����2��[�
{��1>r���k�e
��A&
�GPA
j8x��_#�Ab��{���r��j�?7�.A�U���ϑ�v��i9��W8��ĝN�?�g7��{�x�c`d``�G_�:���|e�f~a�Y�B���?��s ����4x�c`d``�������_ 	A��"��;Y��0|��/spx�u��J�@F�ik�T�zWR��F
���M�n%�i��f�dZ�k�>�/�5�����̹g�ܹ�8�76W�φ�m��C<8.�?:�����W�U�7�5�"r\�>XAU�M��X�L�:.�D]9.��9���R�8���k��q�ꫯ�+�D��F�F:�vW�+�TI��/l�M.=��̆i��@϶<�E�m�G���I�km�S��Ʒ�z��:�Ndb�L.C�FO�z���f��~�Cc�UA���c-��#cf37Y	2�Hi|,�".fr�=>FmȌ��!�{�燤��SV1{����#)��/���f=��"�/�o�9�ܭCk�jݥ)�vj�c=7�	��T,�=������d�Mx�c`b�.쀕����������#'?9�$3?O0��$5��M�,J�IM�MN�KŃr�rJ��lD��x�c��p"(b##c_�Ɲ�X�620hAhz''2���e�
cG`������).�@�]
�,�! %�@���Gk��
,��\�"�admin/templates/map-settings.php000064400000201353151327220640012764 0ustar00<?php
if ( !defined( 'ABSPATH' ) ) exit;

global $wpdb, $wpsl, $wpsl_admin, $wp_version, $wpsl_settings;
?>

<div id="wpsl-wrap" class="wrap wpsl-settings <?php if ( floatval( $wp_version ) < 3.8 ) { echo 'wpsl-pre-38'; } // Fix CSS issue with < 3.8 versions ?>">
	<h2>WP Store Locator <?php _e( 'Settings', 'wpsl' ); ?></h2>

    <?php
    settings_errors();

    $tabs          = apply_filters( 'wpsl_settings_tab', array( 'general' => __( 'General', 'wpsl' ) ) );
    $wpsl_licenses = apply_filters( 'wpsl_license_settings', array() );
    $current_tab   = isset( $_GET['tab'] ) ? $_GET['tab'] : '';

    if ( $wpsl_licenses ) {
        $tabs['licenses'] = __( 'Licenses', 'wpsl' );
    }

    // Default to the general tab if an unknow tab value is set
    if ( !array_key_exists( $current_tab, $tabs ) ) {
        $current_tab = 'general';
    }

    if ( count( $tabs ) > 1 ) {
        echo '<h2 id="wpsl-tabs" class="nav-tab-wrapper">';

        foreach ( $tabs as $tab_key => $tab_name ) {
            if ( !$current_tab && $tab_key == 'general' || $current_tab == $tab_key ) {
                $active_tab = 'nav-tab-active';
            } else {
                $active_tab = '';
            }

            echo '<a class="nav-tab ' . $active_tab . '" title="' . esc_attr( $tab_name ) . '" href="' . admin_url( 'edit.php?post_type=wpsl_stores&page=wpsl_settings&tab=' . $tab_key ) . '">' . esc_attr( $tab_name ) . '</a>';
        }

        echo '</h2>';
    }
        
    if ( $wpsl_licenses && $current_tab == 'licenses' ) {
        ?>

        <form action="" method="post">
            <table class="wp-list-table widefat">
                <thead>
                    <tr>
                        <th scope="col"><?php _e( 'Add-On', 'wpsl' ); ?></th>
                        <th scope="col"><?php _e( 'License Key', 'wpsl' ); ?></th>
                        <th scope="col"><?php _e( 'License Expiry Date', 'wpsl' ); ?></th>
                    </tr>
                </thead>
                <tbody id="the-list">
                    <?php
                    foreach ( $wpsl_licenses as $wpsl_license ) {
                        $key = ( $wpsl_license['status'] == 'valid' ) ? esc_attr( $wpsl_license['key'] ) : '';
                        
                        echo '<tr>';
                        echo '<td>' . esc_html( $wpsl_license['name'] ) . '</td>';
                        echo '<td>';
                        echo '<input type="text" value="' . $key . '" name="wpsl_licenses[' . esc_attr( $wpsl_license['short_name'] ) . ']" />';
                        
                        if ( $wpsl_license['status'] == 'valid' ) {
                           echo '<input type="submit" class="button-secondary" name="' . esc_attr( $wpsl_license['short_name'] ) . '_license_key_deactivate" value="' . __( 'Deactivate License',  'wpsl' ) . '"/>';
                        }
                        
                        wp_nonce_field( $wpsl_license['short_name'] . '_license-nonce', $wpsl_license['short_name'] . '_license-nonce' );
                        
                        echo '</td>';
                        echo '<td>';
                        
                        if ( $wpsl_license['expiration'] && $wpsl_license['status'] == 'valid' ) {
                            echo esc_html( date_i18n( get_option( 'date_format' ), strtotime( $wpsl_license['expiration'] ) ) );
                        }
                        
                        echo '</td>';
                        echo '</tr>';
                    }
                    ?>
                </tbody>
            </table>

            <p class="submit">
                <input type="submit" value="<?php _e( 'Save Changes', 'wpsl' ); ?>" class="button button-primary" id="submit" name="submit">
            </p>
        </form>
    <?php
    } else if ( $current_tab == 'general' || !$current_tab ) {
    ?>
    
    <div id="general">
        <form id="wpsl-settings-form" method="post" action="options.php" autocomplete="off" accept-charset="utf-8">
            <div class="postbox-container">
                <div class="metabox-holder">
                    <div id="wpsl-api-settings" class="postbox">
                        <h3 class="hndle"><span><?php _e( 'Google Maps API', 'wpsl' ); ?></span></h3>
                        <div class="inside">
                            <p>
                                <label for="wpsl-api-browser-key"><?php _e( 'Browser key', 'wpsl' ); ?>:<span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'A %sbrowser key%s allows you to monitor the usage of the Google Maps %sJavaScript API%s. %s %sRequired%s for %sapplications%s created after June 22, 2016.', 'wpsl' ), '<a href="https://wpstorelocator.co/document/create-google-api-keys/#browser-key" target="_blank">', '</a>', '<a href="https://developers.google.com/maps/documentation/javascript/">', '</a>', '<br><br>', '<strong>', '</strong>', '<a href="https://googlegeodevelopers.blogspot.nl/2016/06/building-for-scale-updates-to-google.html">', '</a>' ); ?></span></span></label>
                                <input type="text" value="<?php echo esc_attr( $wpsl_settings['api_browser_key'] ); ?>" name="wpsl_api[browser_key]" class="textinput" id="wpsl-api-browser-key">
                            </p>
                            <p>
                                <label for="wpsl-api-server-key"><?php _e( 'Server key', 'wpsl' ); ?>:<span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'A %sserver key%s allows you to monitor the usage of the Google Maps %sGeocoding API%s. %s %sRequired%s for %sapplications%s created after June 22, 2016.', 'wpsl' ), '<a href="https://wpstorelocator.co/document/create-google-api-keys/#server-key" target="_blank">', '</a>', '<a href="https://developers.google.com/maps/documentation/geocoding/intro">', '</a>', '<br><br>', '<strong>', '</strong>', '<a href="https://googlegeodevelopers.blogspot.nl/2016/06/building-for-scale-updates-to-google.html">', '</a>' ); ?></span></span></label> 
                                <input type="text" value="<?php echo esc_attr( $wpsl_settings['api_server_key'] ); ?>" name="wpsl_api[server_key]"  class="textinput<?php if ( !get_option( 'wpsl_valid_server_key' ) ) { echo ' wpsl-validate-me wpsl-error'; } ?>" id="wpsl-api-server-key">
                            </p>
                            <p>
                                <label for="wpsl-verify-keys"><?php _e( 'Validate API keys', 'wpsl' ); ?></label>
                                <a id="wpsl-verify-keys" class="button" href="#"><?php _e( 'Show response', 'wpsl' ); ?></a>
                            </p>
                            <p>
                                <label for="wpsl-api-language"><?php _e( 'Map language', 'wpsl' ); ?>:<span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php _e( 'If no map language is selected the browser\'s prefered language is used.', 'wpsl' ); ?></span></span></label> 
                                <select id="wpsl-api-language" name="wpsl_api[language]">
                                    <?php echo $wpsl_admin->settings_page->get_api_option_list( 'language' ); ?>          	
                                </select>
                            </p>
                            <p>
                                <label for="wpsl-api-region"><?php _e( 'Map region', 'wpsl' ); ?>:<span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'This will bias the %sgeocoding%s results towards the selected region. %s If no region is selected the bias is set to the United States.', 'wpsl' ), '<a href="https://developers.google.com/maps/documentation/javascript/geocoding#Geocoding">', '</a>', '<br><br>' ); ?></span></span></label> 
                                <select id="wpsl-api-region" name="wpsl_api[region]">
                                    <?php echo $wpsl_admin->settings_page->get_api_option_list( 'region' ); ?>
                                </select>
                            </p>
                            <p id="wpsl-geocode-component" <?php if ( !$wpsl_settings['api_region'] ) { echo 'style="display:none;"'; } ?>>
                                <label for="wpsl-api-component"><?php _e( 'Restrict the geocoding results to the selected map region?', 'wpsl' ); ?><span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'If the %sgeocoding%s API finds more relevant results outside of the set map region ( some location names exist in multiple regions ), the user will likely see a "No results found" message. %s To rule this out you can restrict the results to the set map region. %s You can modify the used restrictions with %sthis%s filter.', 'wpsl' ), '<a href="https://developers.google.com/maps/documentation/javascript/geocoding#Geocoding">', '</a>', '<br><br>', '<br><br>', '<a href="http://wpstorelocator.co/document/wpsl_geocode_components">', '</a>' ); ?></span></span></label> 
                                <input type="checkbox" value="" <?php checked( $wpsl_settings['api_geocode_component'], true ); ?> name="wpsl_api[geocode_component]" id="wpsl-api-component">
                            </p>
                            <p class="submit">
                                <input type="submit" value="<?php _e( 'Save Changes', 'wpsl' ); ?>" class="button-primary">
                            </p>
                        </div>
                    </div>
                </div>
            </div>

            <div class="postbox-container">
                <div class="metabox-holder">
                    <div id="wpsl-search-settings" class="postbox">
                        <h3 class="hndle"><span><?php _e( 'Search', 'wpsl' ); ?></span></h3>
                        <div class="inside">
                            <p>
                                <label for="wpsl-search-autocomplete"><?php _e( 'Enable autocomplete?', 'wpsl' ); ?></label>
                                <input type="checkbox" value="" <?php checked( $wpsl_settings['autocomplete'], true ); ?> name="wpsl_search[autocomplete]" id="wpsl-search-autocomplete">
                            </p>
                            <?php $autocomplete_warning = false; ?>
                            <p>
                                <label for="wpsl-force-postalcode"><?php _e( 'Force zipcode only search', 'wpsl' ); ?>:
                                    <?php
                                    if ( $wpsl_settings['force_postalcode'] && ( !$wpsl_settings['api_geocode_component'] || !$wpsl_settings['api_region'] ) ) {
                                    ?>
                                        <span class="wpsl-info wpsl-required-setting"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'For this option to work correctly you need to set a map region and restrict the results to the selected region. %s You can do this in the %sGoogle Maps API section%s.', 'wpsl' ), '<br><br>', '<a href="#wpsl-api-settings">', '</a>' ); ?></span></span>
                                    <?php
                                    }

                                    if ( $wpsl_settings['autocomplete'] && $wpsl_settings['force_postalcode'] ) {
                                        $autocomplete_warning = true;
                                    }
                                    ?>
                                    <span class="wpsl-info <?php if ( !$autocomplete_warning ) { echo 'wpsl-hide'; } ?> wpsl-required-setting wpsl-info-zip-only"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( "Zipcode only search does unfortunately not work well in combination with the autocomplete option. %s It's recommended to not have both options active at the same time.", "wpsl" ), "<br><br>" ); ?></span></span>
                                </label>
                                <input type="checkbox" value="" <?php checked( $wpsl_settings['force_postalcode'], true ); ?> name="wpsl_search[force_postalcode]" id="wpsl-force-postalcode">
                            </p>
                            <p>
                                <label for="wpsl-results-dropdown"><?php _e( 'Show the max results dropdown?', 'wpsl' ); ?></label>
                                <input type="checkbox" value="" <?php checked( $wpsl_settings['results_dropdown'], true ); ?> name="wpsl_search[results_dropdown]" id="wpsl-results-dropdown">
                            </p>
                            <p>
                                <label for="wpsl-radius-dropdown"><?php _e( 'Show the search radius dropdown?', 'wpsl' ); ?></label>
                                <input type="checkbox" value="" <?php checked( $wpsl_settings['radius_dropdown'], true ); ?> name="wpsl_search[radius_dropdown]" id="wpsl-radius-dropdown">
                            </p>
                            <p>
                                <label for="wpsl-category-filters"><?php _e( 'Enable category filters?', 'wpsl' ); ?></label>
                                <input type="checkbox" value="" <?php checked( $wpsl_settings['category_filter'], true ); ?> name="wpsl_search[category_filter]" id="wpsl-category-filters" class="wpsl-has-conditional-option">
                            </p>
                            <div class="wpsl-conditional-option" <?php if ( !$wpsl_settings['category_filter'] ) { echo 'style="display:none;"'; } ?>>
                                <p>
                                    <label for="wpsl-cat-filter-types"><?php _e( 'Filter type:', 'wpsl' ); ?></label>
                                    <?php echo $wpsl_admin->settings_page->create_dropdown( 'filter_types' ); ?>           
                                </p>
                            </div>
                            <p>
                                <label for="wpsl-distance-unit"><?php _e( 'Distance unit', 'wpsl' ); ?>:</label>                          
                                <span class="wpsl-radioboxes">
                                    <input type="radio" autocomplete="off" value="km" <?php checked( 'km', $wpsl_settings['distance_unit'] ); ?> name="wpsl_search[distance_unit]" id="wpsl-distance-km">
                                    <label for="wpsl-distance-km"><?php _e( 'km', 'wpsl' ); ?></label>
                                    <input type="radio" autocomplete="off" value="mi" <?php checked( 'mi', $wpsl_settings['distance_unit'] ); ?> name="wpsl_search[distance_unit]" id="wpsl-distance-mi">
                                    <label for="wpsl-distance-mi"><?php _e( 'mi', 'wpsl' ); ?></label>
                                </span>
                            </p>
                            <p>
                                <label for="wpsl-max-results"><?php _e( 'Max search results', 'wpsl' ); ?>:<span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php _e( 'The default value is set between the [ ].', 'wpsl' ); ?></span></span></label>
                                <input type="text" value="<?php echo esc_attr( $wpsl_settings['max_results'] ); ?>" name="wpsl_search[max_results]" class="textinput" id="wpsl-max-results">
                            </p>
                            <p>
                                <label for="wpsl-search-radius"><?php _e( 'Search radius options', 'wpsl' ); ?>:<span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php _e( 'The default value is set between the [ ].', 'wpsl' ); ?></span></span></label>
                                <input type="text" value="<?php echo esc_attr( $wpsl_settings['search_radius'] ); ?>" name="wpsl_search[radius]" class="textinput" id="wpsl-search-radius">
                            </p>
                            <p class="submit">
                                <input type="submit" value="<?php _e( 'Save Changes', 'wpsl' ); ?>" class="button-primary">
                            </p>
                        </div>        
                    </div>   
                </div>  
            </div>

            <div class="postbox-container">
                <div class="metabox-holder">
                    <div id="wpsl-map-settings" class="postbox">
                        <h3 class="hndle"><span><?php _e( 'Map', 'wpsl' ); ?></span></h3>
                        <div class="inside">
                            <p>
                                <label for="wpsl-auto-locate"><?php _e( 'Attempt to auto-locate the user', 'wpsl' ); ?>:<span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'Most modern browsers %srequire%s a HTTPS connection before the Geolocation feature works.', 'wpsl' ), '<a href="https://wpstorelocator.co/document/html-5-geolocation-not-working/">', '</a>' ); ?></span></span></label>
                                <input type="checkbox" value="" <?php checked( $wpsl_settings['auto_locate'], true ); ?> name="wpsl_map[auto_locate]" id="wpsl-auto-locate">
                            </p>
                            <p>
                                <label for="wpsl-autoload"><?php _e( 'Load locations on page load', 'wpsl' ); ?>:</label> 
                                <input type="checkbox" value="" <?php checked( $wpsl_settings['autoload'], true ); ?> name="wpsl_map[autoload]" id="wpsl-autoload" class="wpsl-has-conditional-option">
                            </p>
                            <div class="wpsl-conditional-option" <?php if ( !$wpsl_settings['autoload'] ) { echo 'style="display:none;"'; } ?>>
                                <p>
                                    <label for="wpsl-autoload-limit"><?php _e( 'Number of locations to show', 'wpsl' ); ?>:<span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'Although the location data is cached after the first load, a lower number will result in the map being more responsive. %s If this field is left empty or set to 0, then all locations are loaded.', 'wpsl' ), '<br><br>' ); ?></span></span></label>
                                    <input type="text" value="<?php echo esc_attr( $wpsl_settings['autoload_limit'] ); ?>" name="wpsl_map[autoload_limit]" class="textinput" id="wpsl-autoload-limit">
                                </p>
                            </div>
                            <p>
                                <label for="wpsl-start-name"><?php _e( 'Start point', 'wpsl' ); ?>:<span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( '%sRequired field.%s %s If auto-locating the user is disabled or fails, the center of the provided city or country will be used as the initial starting point for the user.', 'wpsl' ), '<strong>', '</strong>', '<br><br>' ); ?></span></span></label> 
                                <input type="text" value="<?php echo esc_attr( $wpsl_settings['start_name'] ); ?>" name="wpsl_map[start_name]" class="textinput" id="wpsl-start-name">
                                <input type="hidden" value="<?php echo esc_attr( $wpsl_settings['start_latlng'] ); ?>" name="wpsl_map[start_latlng]" id="wpsl-latlng" />
                            </p>
                            <p>
                                <label for="wpsl-run-fitbounds"><?php _e( 'Auto adjust the zoom level to make sure all markers are visible?', 'wpsl' ); ?><span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php _e( 'This runs after a search is made, and makes sure all the returned locations are visible in the viewport.', 'wpsl' ); ?></span></span></label>
                                <input type="checkbox" value="" <?php checked( $wpsl_settings['run_fitbounds'], true ); ?> name="wpsl_map[run_fitbounds]" id="wpsl-run-fitbounds">
                            </p>
                            <p>
                                <label for="wpsl-zoom-level"><?php _e( 'Initial zoom level', 'wpsl' ); ?>:</label> 
                                <?php echo $wpsl_admin->settings_page->show_zoom_levels(); ?>
                            </p>
                            <p>
                                <label for="wpsl-max-zoom-level"><?php _e( 'Max auto zoom level', 'wpsl' ); ?>:<span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'This value sets the zoom level for the "Zoom here" link in the info window. %s It is also used to limit the zooming when the viewport of the map is changed to make all the markers fit on the screen.', 'wpsl' ), '<br><br>' ); ?></span></span></label> 
                                <?php echo $wpsl_admin->settings_page->create_dropdown( 'max_zoom_level' ); ?>
                            </p> 
                            <p>
                                <label for="wpsl-streetview"><?php _e( 'Show the street view controls?', 'wpsl' ); ?></label> 
                                <input type="checkbox" value="" <?php checked( $wpsl_settings['streetview'], true ); ?> name="wpsl_map[streetview]" id="wpsl-streetview">
                            </p>
                            <p>
                                <label for="wpsl-type-control"><?php _e( 'Show the map type control?', 'wpsl' ); ?></label> 
                                <input type="checkbox" value="" <?php checked( $wpsl_settings['type_control'], true ); ?> name="wpsl_map[type_control]" id="wpsl-type-control">
                            </p>
                            <p>
                                <label for="wpsl-scollwheel-zoom"><?php _e( 'Enable scroll wheel zooming?', 'wpsl' ); ?></label> 
                                <input type="checkbox" value="" <?php checked( $wpsl_settings['scrollwheel'], true ); ?> name="wpsl_map[scrollwheel]" id="wpsl-scollwheel-zoom">
                            </p>
                            <p>
                                <label><?php _e( 'Zoom control position', 'wpsl' ); ?>:</label>
                                <span class="wpsl-radioboxes">
                                    <input type="radio" autocomplete="off" value="left" <?php checked( 'left', $wpsl_settings['control_position'], true ); ?> name="wpsl_map[control_position]" id="wpsl-control-left">
                                    <label for="wpsl-control-left"><?php _e( 'Left', 'wpsl' ); ?></label>
                                    <input type="radio" autocomplete="off" value="right" <?php checked( 'right', $wpsl_settings['control_position'], true ); ?> name="wpsl_map[control_position]" id="wpsl-control-right">
                                    <label for="wpsl-control-right"><?php _e( 'Right', 'wpsl' ); ?></label>
                                </span>
                            </p>
                            <p>
                                <label for="wpsl-map-type"><?php _e( 'Map type', 'wpsl' ); ?>:</label> 
                                <?php echo $wpsl_admin->settings_page->create_dropdown( 'map_types' ); ?>
                            </p>
                            <p>
                                <label for="wpsl-map-style"><?php _e( 'Map style', 'wpsl' ); ?>:<span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php _e( 'Custom map styles only work if the map type is set to "Roadmap" or "Terrain".', 'wpsl' ); ?></span></span></label>
                            </p>
                            <div class="wpsl-style-input">
                                <p><?php echo sprintf( __( 'You can use existing map styles from %sSnazzy Maps%s or %sMap Stylr%s and paste it in the textarea below, or you can generate a custom map style through the %sMap Style Editor%s or %sStyled Maps Wizard%s.', 'wpsl' ), '<a target="_blank" href="http://snazzymaps.com">', '</a>', '<a target="_blank" href="http://mapstylr.com">', '</a>', '<a target="_blank" href="http://mapstylr.com/map-style-editor/">', '</a>', '<a target="_blank" href="http://gmaps-samples-v3.googlecode.com/svn/trunk/styledmaps/wizard/index.html">', '</a>' ); ?></p> 
                                <p><?php echo sprintf( __( 'If you like to write the style code yourself, then you can find the documentation from Google %shere%s.', 'wpsl' ), '<a target="_blank" href="https://developers.google.com/maps/documentation/javascript/styling">', '</a>' ); ?></p>
                                <textarea id="wpsl-map-style" name="wpsl_map[map_style]"><?php echo strip_tags( stripslashes( json_decode( $wpsl_settings['map_style'] ) ) ); ?></textarea>
                                <input type="submit" value="<?php _e( 'Preview Map Style', 'wpsl' ); ?>" class="button-primary" name="wpsl-style-preview" id="wpsl-style-preview">
                            </div>
                            <div id="wpsl-gmap-wrap" class="wpsl-styles-preview"></div>
                            <p>
                               <label for="wpsl-show-credits"><?php _e( 'Show credits?', 'wpsl' ); ?><span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php _e( 'This will place a "Search provided by WP Store Locator" backlink below the map.', 'wpsl' ); ?></span></span></label> 
                               <input type="checkbox" value="" <?php checked( $wpsl_settings['show_credits'], true ); ?> name="wpsl_credits" id="wpsl-show-credits">
                            </p>
                            <p class="submit">
                                <input type="submit" value="<?php _e( 'Save Changes', 'wpsl' ); ?>" class="button-primary">
                            </p>
                        </div>        
                    </div>   
                </div>  
            </div>

            <div class="postbox-container">
                <div class="metabox-holder">
                    <div id="wpsl-user-experience" class="postbox">
                        <h3 class="hndle"><span><?php _e( 'User Experience', 'wpsl' ); ?></span></h3>
                        <div class="inside">
                            <p>
                                <label for="wpsl-design-height"><?php _e( 'Store Locator height', 'wpsl' ); ?>:</label> 
                                <input size="3" value="<?php echo esc_attr( $wpsl_settings['height'] ); ?>" id="wpsl-design-height" name="wpsl_ux[height]"> px
                            </p> 
                            <p>
                                <label for="wpsl-infowindow-width"><?php _e( 'Max width for the info window content', 'wpsl' ); ?>:</label> 
                                <input size="3" value="<?php echo esc_attr( $wpsl_settings['infowindow_width'] ); ?>" id="wpsl-infowindow-width" name="wpsl_ux[infowindow_width]"> px
                            </p>
                            <p>
                                <label for="wpsl-search-width"><?php _e( 'Search field width', 'wpsl' ); ?>:</label> 
                                <input size="3" value="<?php echo esc_attr( $wpsl_settings['search_width'] ); ?>" id="wpsl-search-width" name="wpsl_ux[search_width]"> px
                            </p>
                            <p>
                                <label for="wpsl-label-width"><?php _e( 'Search and radius label width', 'wpsl' ); ?>:</label> 
                                <input size="3" value="<?php echo esc_attr( $wpsl_settings['label_width'] ); ?>" id="wpsl-label-width" name="wpsl_ux[label_width]"> px
                            </p> 
                            <p>
                               <label for="wpsl-store-template"><?php _e( 'Store Locator template', 'wpsl' ); ?>:<span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'The selected template is used with the [wpsl] shortcode. %s You can add a custom template with the %swpsl_templates%s filter.', 'wpsl' ), '<br><br>', '<a href="http://wpstorelocator.co/document/wpsl_templates/">', '</a>' ); ?></span></span></label> 
                               <?php echo $wpsl_admin->settings_page->show_template_options(); ?>
                            </p>
                            <p id="wpsl-listing-below-no-scroll" <?php if ( $wpsl_settings['template_id'] != 'below_map' ) { echo 'style="display:none;"'; } ?>>
                                <label for="wpsl-more-info-list"><?php _e( 'Hide the scrollbar?', 'wpsl' ); ?></label>
                                <input type="checkbox" value="" <?php checked( $wpsl_settings['listing_below_no_scroll'], true ); ?> name="wpsl_ux[listing_below_no_scroll]" id="wpsl-listing-below-no-scroll">
                            </p>
                            <p>
                               <label for="wpsl-new-window"><?php _e( 'Open links in a new window?', 'wpsl' ); ?></label> 
                               <input type="checkbox" value="" <?php checked( $wpsl_settings['new_window'], true ); ?> name="wpsl_ux[new_window]" id="wpsl-new-window">
                            </p>
                            <p>
                               <label for="wpsl-reset-map"><?php _e( 'Show a reset map button?', 'wpsl' ); ?></label> 
                               <input type="checkbox" value="" <?php checked( $wpsl_settings['reset_map'], true ); ?> name="wpsl_ux[reset_map]" id="wpsl-reset-map">
                            </p> 
                            <p>
                               <label for="wpsl-direction-redirect"><?php _e( 'When a user clicks on "Directions", open a new window, and show the route on google.com/maps ?', 'wpsl' ); ?></label> 
                               <input type="checkbox" value="" <?php checked( $wpsl_settings['direction_redirect'], true ); ?> name="wpsl_ux[direction_redirect]" id="wpsl-direction-redirect">
                            </p>
                            <p>
                               <label for="wpsl-more-info"><?php _e( 'Show a "More info" link in the store listings?', 'wpsl' ); ?><span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'This places a "More Info" link below the address and will show the phone, fax, email, opening hours and description once the link is clicked.', 'wpsl' ) ); ?></span></span></label> 
                               <input type="checkbox" value="" <?php checked( $wpsl_settings['more_info'], true ); ?> name="wpsl_ux[more_info]" id="wpsl-more-info" class="wpsl-has-conditional-option">
                            </p>   
                            <div class="wpsl-conditional-option" <?php if ( !$wpsl_settings['more_info'] ) { echo 'style="display:none;"'; } ?>>
                                <p>
                                    <label for="wpsl-more-info-list"><?php _e( 'Where do you want to show the "More info" details?', 'wpsl' ); ?></label>
                                    <?php echo $wpsl_admin->settings_page->create_dropdown( 'more_info' ); ?>
                                </p>
                            </div>
                            <p>
                               <label for="wpsl-contact-details"><?php _e( 'Always show the contact details below the address in the search results?', 'wpsl' ); ?></label> 
                               <input type="checkbox" value="" <?php checked( $wpsl_settings['show_contact_details'], true ); ?> name="wpsl_ux[show_contact_details]" id="wpsl-contact-details">
                            </p>
                            <p>
                                <label for="wpsl-clickable-contact-details"><?php _e( 'Make the contact details always clickable?', 'wpsl' ); ?></label>
                                <input type="checkbox" value="" <?php checked( $wpsl_settings['clickable_contact_details'], true ); ?> name="wpsl_ux[clickable_contact_details]" id="wpsl-clickable-contact-details">
                            </p>
                            <p>
                               <label for="wpsl-store-url"><?php _e( 'Make the store name clickable if a store URL exists?', 'wpsl' ); ?><span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'If %spermalinks%s are enabled, the store name will always link to the store page.', 'wpsl' ), '<a href="' . admin_url( 'edit.php?post_type=wpsl_stores&page=wpsl_settings#wpsl-permalink-settings' ) . '">', '</a>' ); ?></span></span></label> 
                               <input type="checkbox" value="" <?php checked( $wpsl_settings['store_url'], true ); ?> name="wpsl_ux[store_url]" id="wpsl-store-url">
                            </p>
                            <p>
                               <label for="wpsl-phone-url"><?php _e( 'Make the phone number clickable on mobile devices?', 'wpsl' ); ?></label> 
                               <input type="checkbox" value="" <?php checked( $wpsl_settings['phone_url'], true ); ?> name="wpsl_ux[phone_url]" id="wpsl-phone-url">
                            </p>
                            <p>
                               <label for="wpsl-marker-streetview"><?php _e( 'If street view is available for the current location, then show a "Street view" link in the info window?', 'wpsl' ); ?><span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'Enabling this option can sometimes result in a small delay in the opening of the info window. %s This happens because an API request is made to Google Maps to check if street view is available for the current location.', 'wpsl' ), '<br><br>' ); ?></span></span></label> 
                               <input type="checkbox" value="" <?php checked( $wpsl_settings['marker_streetview'], true ); ?> name="wpsl_ux[marker_streetview]" id="wpsl-marker-streetview">
                            </p>
                            <p>
                               <label for="wpsl-marker-zoom-to"><?php _e( 'Show a "Zoom here" link in the info window?', 'wpsl' ); ?><span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'Clicking this link will make the map zoom in to the %s max auto zoom level %s.', 'wpsl' ), '<a href="#wpsl-zoom-level">', '</a>' ); ?></span></span></label> 
                               <input type="checkbox" value="" <?php checked( $wpsl_settings['marker_zoom_to'], true ); ?> name="wpsl_ux[marker_zoom_to]" id="wpsl-marker-zoom-to">
                            </p>
                            <p>
                               <label for="wpsl-mouse-focus"><?php _e( 'On page load move the mouse cursor to the search field?', 'wpsl' ); ?><span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'If the store locator is not placed at the top of the page, enabling this feature can result in the page scrolling down. %s %sThis option is disabled on mobile devices.%s', 'wpsl' ), '<br><br>', '<em>', '</em>' ); ?></span></span></label> 
                               <input type="checkbox" value="" <?php checked( $wpsl_settings['mouse_focus'], true ); ?> name="wpsl_ux[mouse_focus]" id="wpsl-mouse-focus">
                            </p>
                            <p>
                               <label for="wpsl-infowindow-style"><?php _e( 'Use the default style for the info window?', 'wpsl' ); ?><span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'If the default style is disabled the %sInfoBox%s library will be used instead. %s This enables you to easily change the look and feel of the info window through the .wpsl-infobox css class.', 'wpsl' ), '<a href="http://google-maps-utility-library-v3.googlecode.com/svn/trunk/infobox/docs/reference.html" target="_blank">', '</a>', '<br><br>' ); ?></span></span></label> 
                               <input type="checkbox" value="default" <?php checked( $wpsl_settings['infowindow_style'], 'default' ); ?> name="wpsl_ux[infowindow_style]" id="wpsl-infowindow-style">
                            </p>
                            <p>
                               <label for="wpsl-hide-country"><?php _e( 'Hide the country in the search results?', 'wpsl' ); ?></label> 
                               <input type="checkbox" value="" <?php checked( $wpsl_settings['hide_country'], true ); ?> name="wpsl_ux[hide_country]" id="wpsl-hide-country">
                            </p>
                            <p>
                               <label for="wpsl-hide-distance"><?php _e( 'Hide the distance in the search results?', 'wpsl' ); ?></label> 
                               <input type="checkbox" value="" <?php checked( $wpsl_settings['hide_distance'], true ); ?> name="wpsl_ux[hide_distance]" id="wpsl-hide-distance">
                            </p>
                            <p>
                               <label for="wpsl-bounce"><?php _e( 'If a user hovers over the search results the store marker', 'wpsl' ); ?>:<span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'If marker clusters are enabled this option will not work as expected as long as the markers are clustered. %s The bouncing of the marker won\'t be visible at all unless a user zooms in far enough for the marker cluster to change back in to individual markers. %s The info window will open as expected, but it won\'t be clear to which marker it belongs to. ', 'wpsl' ), '<br><br>' , '<br><br>' ); ?></span></span></label> 
                               <?php echo $wpsl_admin->settings_page->create_dropdown( 'marker_effects' ); ?>
                            </p>  
                            <p>
                                <label for="wpsl-address-format"><?php _e( 'Address format', 'wpsl' ); ?>:<span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'You can add custom address formats with the %swpsl_address_formats%s filter.', 'wpsl' ), '<a href="http://wpstorelocator.co/document/wpsl_address_formats/">', '</a>' ); ?></span></span></label> 
                               <?php echo $wpsl_admin->settings_page->create_dropdown( 'address_format' ); ?>
                            </p>
                            <p class="submit">
                                <input type="submit" value="<?php _e( 'Save Changes', 'wpsl' ); ?>" class="button-primary">
                            </p>
                        </div>        
                    </div>   
                </div>  
            </div>

            <div class="postbox-container">
                <div class="metabox-holder">
                    <div id="wpsl-marker-settings" class="postbox">
                        <h3 class="hndle"><span><?php _e( 'Markers', 'wpsl' ); ?></span></h3>
                        <div class="inside">
                            <?php echo $wpsl_admin->settings_page->show_marker_options(); ?>
                            <p>
                               <label for="wpsl-marker-clusters"><?php _e( 'Enable marker clusters?', 'wpsl' ); ?><span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php _e( 'Recommended for maps with a large amount of markers.', 'wpsl' ); ?></span></span></label> 
                               <input type="checkbox" value="" <?php checked( $wpsl_settings['marker_clusters'], true ); ?> name="wpsl_map[marker_clusters]" id="wpsl-marker-clusters" class="wpsl-has-conditional-option">
                            </p>
                            <div class="wpsl-conditional-option" <?php if ( !$wpsl_settings['marker_clusters'] ) { echo 'style="display:none;"'; } ?>>
                                <p>
                                   <label for="wpsl-marker-zoom"><?php _e( 'Max zoom level', 'wpsl' ); ?>:<span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php _e( 'If this zoom level is reached or exceeded, then all markers are moved out of the marker cluster and shown as individual markers.', 'wpsl' ); ?></span></span></label> 
                                   <?php echo $wpsl_admin->settings_page->show_cluster_options( 'cluster_zoom' ); ?>
                                </p>
                                <p>
                                   <label for="wpsl-marker-cluster-size"><?php _e( 'Cluster size', 'wpsl' ); ?>:<span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'The grid size of a cluster in pixels. %s A larger number will result in a lower amount of clusters and also make the algorithm run faster.', 'wpsl' ), '<br><br>' ); ?></span></span></label> 
                                   <?php echo $wpsl_admin->settings_page->show_cluster_options( 'cluster_size' ); ?>
                                </p>
                            </div>
                            <p class="submit">
                                <input type="submit" value="<?php _e( 'Save Changes', 'wpsl' ); ?>" class="button-primary">
                            </p>
                        </div>
                    </div>   
                </div>  
            </div>

            <div class="postbox-container">
                <div class="metabox-holder">
                    <div id="wpsl-store-editor-settings" class="postbox">
                        <h3 class="hndle"><span><?php _e( 'Store Editor', 'wpsl' ); ?></span></h3>
                        <div class="inside">
                            <p>
                                <label for="wpsl-editor-country"><?php _e( 'Default country', 'wpsl' ); ?>:</label> 
                                <input type="text" value="<?php echo esc_attr( $wpsl->i18n->get_translation( 'editor_country', '' ) ); ?>" name="wpsl_editor[default_country]" class="textinput" id="wpsl-editor-country">
                            </p>
                            <p>
                                <label for="wpsl-editor-map-type"><?php _e( 'Map type for the location preview', 'wpsl' ); ?>:</label> 
                                <?php echo $wpsl_admin->settings_page->create_dropdown( 'editor_map_types' ); ?>
                            </p>
                            <p>
                                <label for="wpsl-editor-hide-hours"><?php _e( 'Hide the opening hours?', 'wpsl' ); ?></label> 
                                <input type="checkbox" value="" <?php checked( $wpsl_settings['hide_hours'], true ); ?> name="wpsl_editor[hide_hours]" id="wpsl-editor-hide-hours" class="wpsl-has-conditional-option">
                            </p>
                            <div class="wpsl-conditional-option" <?php if ( $wpsl_settings['hide_hours'] ) { echo 'style="display:none"'; } ?>>
                                <?php if ( get_option( 'wpsl_legacy_support' ) ) { // Is only set for users who upgraded from 1.x ?>
                                <p>
                                    <label for="wpsl-editor-hour-input"><?php _e( 'Opening hours input type', 'wpsl' ); ?>:</label> 
                                    <?php echo $wpsl_admin->settings_page->create_dropdown( 'hour_input' ); ?>
                                </p>
                                <p class="wpsl-hour-notice <?php if ( $wpsl_settings['editor_hour_input'] !== 'dropdown' ) { echo 'style="display:none"'; } ?>">
                                    <em><?php echo sprintf( __( 'Opening hours created in version 1.x %sare not%s automatically converted to the new dropdown format.', 'wpsl' ), '<strong>', '</strong>' ); ?></em>
                                </p>
                                <div class="wpsl-textarea-hours" <?php if ( $wpsl_settings['editor_hour_input'] !== 'textarea' ) { echo 'style="display:none"'; } ?>>
                                    <p class="wpsl-default-hours"><strong><?php _e( 'The default opening hours', 'wpsl' ); ?></strong></p>
                                    <textarea rows="5" cols="5" name="wpsl_editor[textarea]" id="wpsl-textarea-hours"><?php if ( isset( $wpsl_settings['editor_hours']['textarea'] ) ) { echo esc_textarea( stripslashes( $wpsl_settings['editor_hours']['textarea'] ) ); } ?></textarea>
                                </div>
                                <?php } ?>
                                <div class="wpsl-dropdown-hours" <?php if ( $wpsl_settings['editor_hour_input'] !== 'dropdown' ) { echo 'style="display:none"'; } ?>>
                                    <p>
                                        <label for="wpsl-editor-hour-format"><?php _e( 'Opening hours format', 'wpsl' ); ?>:</label> 
                                        <?php echo $wpsl_admin->settings_page->show_opening_hours_format(); ?>
                                    </p>
                                    <p class="wpsl-default-hours"><strong><?php _e( 'The default opening hours', 'wpsl' ); ?></strong></p>
                                    <?php echo $wpsl_admin->metaboxes->opening_hours( 'settings' ); ?>
                                </div>
                            </div>
                            <p><em><?php _e( 'The default country and opening hours are only used when a new store is created. So changing the default values will have no effect on existing store locations.', 'wpsl' ); ?></em></p>

                            <p class="submit">
                                <input type="submit" value="<?php _e( 'Save Changes', 'wpsl' ); ?>" class="button-primary">
                            </p>
                        </div>        
                    </div>   
                </div>  
            </div>

            <div class="postbox-container">
                <div class="metabox-holder">
                    <div id="wpsl-permalink-settings" class="postbox">
                        <h3 class="hndle"><span><?php _e( 'Permalink', 'wpsl' ); ?></span></h3>
                        <div class="inside">
                            <p>
                               <label for="wpsl-permalinks-active"><?php _e( 'Enable permalink?', 'wpsl' ); ?></label> 
                               <input type="checkbox" value="" <?php checked( $wpsl_settings['permalinks'], true ); ?> name="wpsl_permalinks[active]" id="wpsl-permalinks-active" class="wpsl-has-conditional-option">
                            </p>
                            <div class="wpsl-conditional-option" <?php if ( !$wpsl_settings['permalinks'] ) { echo 'style="display:none;"'; } ?>>
                                <p>
                                    <label for="wpsl-permalink-remove-front"><?php _e( 'Remove the front base from the permalink structure?', 'wpsl' ); ?><span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'The front base is set on the %spermalink settings%s page in the "Custom structure" field. %s If a front base is set ( for example /blog/ ), then enabling this option will remove it from the store locator permalinks.', 'wpsl' ), '<a href="https://codex.wordpress.org/Settings_Permalinks_Screen#Customize_Permalink_Structure" target="_blank">', '</a>', '<br><br>' ); ?></span></span></label>
                                    <input type="checkbox" value="" <?php checked( $wpsl_settings['permalink_remove_front'], true ); ?> name="wpsl_permalinks[remove_front]" id="wpsl-permalink-remove-front">
                                </p>
                                <p>
                                    <label for="wpsl-permalinks-slug"><?php _e( 'Store slug', 'wpsl' ); ?>:</label> 
                                    <input type="text" value="<?php echo esc_attr( $wpsl_settings['permalink_slug'] ); ?>" name="wpsl_permalinks[slug]" class="textinput" id="wpsl-permalinks-slug">
                                </p>
                                <p>
                                    <label for="wpsl-category-slug"><?php _e( 'Category slug', 'wpsl' ); ?>:</label> 
                                    <input type="text" value="<?php echo esc_attr( $wpsl_settings['category_slug'] ); ?>" name="wpsl_permalinks[category_slug]" class="textinput" id="wpsl-category-slug">
                                </p>
                                <em><?php echo sprintf( __( 'The permalink slugs %smust be unique%s on your site.', 'wpsl' ), '<strong>', '</strong>' ); ?></em>
                            </div>
                            <p class="submit">
                                <input type="submit" value="<?php _e( 'Save Changes', 'wpsl' ); ?>" class="button-primary">
                            </p>
                        </div>        
                    </div>   
                </div>  
            </div>

            <div class="postbox-container">
                <div class="metabox-holder">
                    <div id="wpsl-label-settings" class="postbox">
                        <h3 class="hndle"><span><?php _e( 'Labels', 'wpsl' ); ?></span></h3>
                        <div class="inside">
                            <?php
                            /*
                             * Show a msg to make sure that when a WPML compatible plugin 
                             * is active users use the 'String Translations' page to change the labels, 
                             * instead of the 'Label' section.
                             */
                            if ( $wpsl->i18n->wpml_exists() ) {
                                echo '<p>' . sprintf( __( '%sWarning!%s %sWPML%s, or a plugin using the WPML API is active.', 'wpsl' ), '<strong>', '</strong>', '<a href="https://wpml.org/">', '</a>' ) . '</p>';
                                echo '<p>' . __( 'Please use the "String Translations" section in the used multilingual plugin to change the labels. Changing them here will have no effect as long as the multilingual plugin remains active.', 'wpsl' ) . '</p>';
                            }
                            ?>
                            <p>
                                <label for="wpsl-search"><?php _e( 'Your location', 'wpsl' ); ?>:</label> 
                                <input type="text" value="<?php echo esc_attr( $wpsl->i18n->get_translation( 'search_label', __( 'Your location', 'wpsl' ) ) ); ?>" name="wpsl_label[search]" class="textinput" id="wpsl-search">
                            </p>
                            <p>
                                <label for="wpsl-search-radius"><?php _e( 'Search radius', 'wpsl' ); ?>:</label> 
                                <input type="text" value="<?php echo esc_attr( $wpsl->i18n->get_translation( 'radius_label', __( 'Search radius', 'wpsl' ) ) ); ?>" name="wpsl_label[radius]" class="textinput" id="wpsl-search-radius">
                            </p>
                            <p>
                                <label for="wpsl-no-results"><?php _e( 'No results found', 'wpsl' ); ?>:</label> 
                                <input type="text" value="<?php echo esc_attr( $wpsl->i18n->get_translation( 'no_results_label', __( 'No results found', 'wpsl' ) ) ); ?>" name="wpsl_label[no_results]" class="textinput" id="wpsl-no-results">
                            </p>
                            <p>
                                <label for="wpsl-search-btn"><?php _e( 'Search', 'wpsl' ); ?>:</label> 
                                <input type="text" value="<?php echo esc_attr( $wpsl->i18n->get_translation( 'search_btn_label', __( 'Search', 'wpsl' ) ) ); ?>" name="wpsl_label[search_btn]" class="textinput" id="wpsl-search-btn">
                            </p>
                            <p>
                                <label for="wpsl-preloader"><?php _e( 'Searching (preloader text)', 'wpsl' ); ?>:</label> 
                                <input type="text" value="<?php echo esc_attr( $wpsl->i18n->get_translation( 'preloader_label', __( 'Searching...', 'wpsl' ) ) ); ?>" name="wpsl_label[preloader]" class="textinput" id="wpsl-preloader">
                            </p>
                            <p>
                                <label for="wpsl-results"><?php _e( 'Results', 'wpsl' ); ?>:</label> 
                                <input type="text" value="<?php echo esc_attr( $wpsl->i18n->get_translation( 'results_label', __( 'Results', 'wpsl' ) ) ); ?>" name="wpsl_label[results]" class="textinput" id="wpsl-results">
                            </p>
                            <p>
                                <label for="wpsl-category"><?php _e( 'Category filter', 'wpsl' ); ?>:</label> 
                                <input type="text" value="<?php echo esc_attr( $wpsl->i18n->get_translation( 'category_label', __( 'Category', 'wpsl' ) ) ); ?>" name="wpsl_label[category]" class="textinput" id="wpsl-category">
                            </p>
                            <p>
                                <label for="wpsl-category-default"><?php _e( 'Category first item', 'wpsl' ); ?>:</label> 
                                <input type="text" value="<?php echo esc_attr( $wpsl->i18n->get_translation( 'category_default_label', __( 'Any', 'wpsl' ) ) ); ?>" name="wpsl_label[category_default]" class="textinput" id="wpsl-category-default">
                            </p>
                            <p>
                                <label for="wpsl-more-info"><?php _e( 'More info', 'wpsl' ); ?>:</label> 
                                <input type="text" value="<?php echo esc_attr( $wpsl->i18n->get_translation( 'more_label', __( 'More info', 'wpsl' ) ) ); ?>" name="wpsl_label[more]" class="textinput" id="wpsl-more-info">
                            </p>
                            <p>
                                <label for="wpsl-phone"><?php _e( 'Phone', 'wpsl' ); ?>:</label> 
                                <input type="text" value="<?php echo esc_attr( $wpsl->i18n->get_translation( 'phone_label', __( 'Phone', 'wpsl' ) ) ); ?>" name="wpsl_label[phone]" class="textinput" id="wpsl-phone">
                            </p>                        
                            <p>
                                <label for="wpsl-fax"><?php _e( 'Fax', 'wpsl' ); ?>:</label> 
                                <input type="text" value="<?php echo esc_attr( $wpsl->i18n->get_translation( 'fax_label', __( 'Fax', 'wpsl' ) ) ); ?>" name="wpsl_label[fax]" class="textinput" id="wpsl-fax">
                            </p>
                            <p>
                                <label for="wpsl-email"><?php _e( 'Email', 'wpsl' ); ?>:</label> 
                                <input type="text" value="<?php echo esc_attr( $wpsl->i18n->get_translation( 'email_label', __( 'Email', 'wpsl' ) ) ); ?>" name="wpsl_label[email]" class="textinput" id="wpsl-email">
                            </p>
                            <p>
                                <label for="wpsl-url"><?php _e( 'Url', 'wpsl' ); ?>:</label> 
                                <input type="text" value="<?php echo esc_attr( $wpsl->i18n->get_translation( 'url_label', __( 'Url', 'wpsl' ) ) ); ?>" name="wpsl_label[url]" class="textinput" id="wpsl-url">
                            </p>
                            <p>
                                <label for="wpsl-hours"><?php _e( 'Hours', 'wpsl' ); ?>:</label> 
                                <input type="text" value="<?php echo esc_attr( $wpsl->i18n->get_translation( 'hours_label', __( 'Hours', 'wpsl' ) ) ); ?>" name="wpsl_label[hours]" class="textinput" id="wpsl-hours">
                            </p>
                            <p>
                                <label for="wpsl-start"><?php _e( 'Start location', 'wpsl' ); ?>:</label> 
                                <input type="text" value="<?php echo esc_attr( $wpsl->i18n->get_translation( 'start_label', __( 'Start location', 'wpsl' ) ) ); ?>" name="wpsl_label[start]" class="textinput" id="wpsl-start">
                            </p>
                            <p>
                                <label for="wpsl-directions"><?php _e( 'Get directions', 'wpsl' ); ?>:</label> 
                                <input type="text" value="<?php echo esc_attr( $wpsl->i18n->get_translation( 'directions_label', __( 'Directions', 'wpsl' ) ) ); ?>" name="wpsl_label[directions]" class="textinput" id="wpsl-directions">
                            </p>
                            <p>
                                <label for="wpsl-no-directions"><?php _e( 'No directions found', 'wpsl' ); ?>:</label> 
                                <input type="text" value="<?php echo esc_attr( $wpsl->i18n->get_translation( 'no_directions_label', __( 'No route could be found between the origin and destination', 'wpsl' ) ) ); ?>" name="wpsl_label[no_directions]" class="textinput" id="wpsl-no-directions">
                            </p>
                            <p>
                                <label for="wpsl-back"><?php _e( 'Back', 'wpsl' ); ?>:</label> 
                                <input type="text" value="<?php echo esc_attr( $wpsl->i18n->get_translation( 'back_label', __( 'Back', 'wpsl' ) ) ); ?>" name="wpsl_label[back]" class="textinput" id="wpsl-back">
                            </p>
                            <p>
                                <label for="wpsl-street-view"><?php _e( 'Street view', 'wpsl' ); ?>:</label> 
                                <input type="text" value="<?php echo esc_attr( $wpsl->i18n->get_translation( 'street_view_label', __( 'Street view', 'wpsl' ) ) ); ?>" name="wpsl_label[street_view]" class="textinput" id="wpsl-street-view">
                            </p> 
                            <p>
                                <label for="wpsl-zoom-here"><?php _e( 'Zoom here', 'wpsl' ); ?>:</label> 
                                <input type="text" value="<?php echo esc_attr( $wpsl->i18n->get_translation( 'zoom_here_label', __( 'Zoom here', 'wpsl' ) ) ); ?>" name="wpsl_label[zoom_here]" class="textinput" id="wpsl-zoom-here">
                            </p>
                            <p>
                                <label for="wpsl-error"><?php _e( 'General error', 'wpsl' ); ?>:</label> 
                                <input type="text" value="<?php echo esc_attr( $wpsl->i18n->get_translation( 'error_label', __( 'Something went wrong, please try again!', 'wpsl' ) ) ); ?>" name="wpsl_label[error]" class="textinput" id="wpsl-error">
                            </p>
                            <p>
                                <label for="wpsl-limit"><?php _e( 'Query limit error', 'wpsl' ); ?>:<span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'You can raise the %susage limit%s by obtaining an API %skey%s, and fill in the "API key" field at the top of this page.', 'wpsl' ), '<a href="https://developers.google.com/maps/documentation/javascript/usage#usage_limits" target="_blank">', '</a>' ,'<a href="https://developers.google.com/maps/documentation/javascript/tutorial#api_key" target="_blank">', '</a>' ); ?></span></span></label> 
                                <input type="text" value="<?php echo esc_attr( $wpsl->i18n->get_translation( 'limit_label', __( 'API usage limit reached', 'wpsl' ) ) ); ?>" name="wpsl_label[limit]" class="textinput" id="wpsl-limit">
                            </p>
                            <p class="submit">
                                <input type="submit" value="<?php _e( 'Save Changes', 'wpsl' ); ?>" class="button-primary">
                            </p>
                        </div>        
                    </div>   
                </div>  
            </div>

            <div class="postbox-container">
                <div class="metabox-holder">
                    <div id="wpsl-tools" class="postbox">
                        <h3 class="hndle"><span><?php _e( 'Tools', 'wpsl' ); ?></span></h3>
                        <div class="inside">
                            <p>
                               <label for="wpsl-debug"><?php _e( 'Enable store locator debug?', 'wpsl' ); ?><span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'This disables the WPSL transient cache. %sThe transient cache is only used if the %sLoad locations on page load%s option is enabled.', 'wpsl' ), '<br><br>', '<em>', '</em>' ); ?></span></span></label> 
                               <input type="checkbox" value="" <?php checked( $wpsl_settings['debug'], true ); ?> name="wpsl_tools[debug]" id="wpsl-debug">
                            </p>
                            <p>
                               <label for="wpsl-deregister-gmaps"><?php _e( 'Enable compatibility mode?', 'wpsl' ); ?><span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'If the %sbrowser console%s shows the error below, then enabling this option should fix it. %s %sYou have included the Google Maps API multiple times on this page. This may cause unexpected errors.%s %s This error can in some situations break the store locator map.', 'wpsl' ), '<a href="https://codex.wordpress.org/Using_Your_Browser_to_Diagnose_JavaScript_Errors#Step_3:_Diagnosis">', '</a>', '<br><br>', '<em>', '</em>', '<br><br>' ); ?></span></span></label>
                               <input type="checkbox" value="" <?php checked( $wpsl_settings['deregister_gmaps'], true ); ?> name="wpsl_tools[deregister_gmaps]" id="wpsl-deregister-gmaps">
                            </p>
                            <p>
                               <label for="wpsl-transient"><?php _e( 'WPSL transients', 'wpsl' ); ?></label> 
                               <a class="button" href="<?php echo wp_nonce_url( admin_url( "edit.php?post_type=wpsl_stores&page=wpsl_settings&action=clear_wpsl_transients" ), 'clear_transients' ); ?>"><?php _e( 'Clear store locator transient cache', 'wpsl' ); ?></a>
                            </p>
                            <?php
                                $borlabs_exists = function_exists( 'BorlabsCookieHelper' );

                                /**
                                 * Make sure the blocked content type for the store locator exists
                                 * in the Borlabs Cookie plugins. If not, then it's created.
                                 */
                                if ( $borlabs_exists ) {
                                    $borlabs = New WPSL_Borlabs_Cookie();
                                    $borlabs->maybe_enable_bct();
                                }
                            ?>
                            <p>
                                <label for="wpsl-delay-loading"><?php _e( 'GDPR - Only load Google Maps after the user agrees to it?', 'wpsl' ); ?>
                                    <span class="wpsl-info <?php if ( !$borlabs_exists ) { echo 'wpsl-warning'; } ?>">
                                        <?php if ( !$borlabs_exists ) { ?>
                                            <span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'This option requires the %sBorlabs Cookie%s plugin.', 'wpsl' ), '<a target="_new" href="https://borlabs.io/borlabs-cookie/">', '</a>' ); ?></span>
                                        <?php } else { ?>
                                            <span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'Make sure to wrap the Borlabs Cookie %sshortcode%s around the WPSL shortcode.', 'wpsl' ), '<a href="https://wpstorelocator.co/document/the-general-data-protection-regulation/#borlabs">', '</a>' ); ?></span>
                                        <?php }?>
                                    </span>
                                </label>
                                <input <?php if ( !$borlabs_exists ) { echo 'disabled="disabled"'; } ?> type="checkbox" value="" <?php checked( $wpsl_settings['delay_loading'], true ); ?> name="wpsl_tools[delay_loading]" id="wpsl-delay-loading">
                            </p>
                            <p>
                                <label for="wpsl-show-geocode-response"><?php _e( 'Show the Geocode API response for a location search', 'wpsl' ); ?></label>
                                <a id="wpsl-show-geocode-response" class="button" href="#"><?php _e( 'Input location details', 'wpsl' ); ?></a>
                            </p>
                            <p class="submit">
                                <input type="submit" value="<?php _e( 'Save Changes', 'wpsl' ); ?>" class="button-primary">
                            </p>
                        </div>
                    </div>
                </div>                    
            </div>

            <?php settings_fields( 'wpsl_settings' ); ?>
        </form>
    </div>
    
    <?php
    } else {
        do_action( 'wpsl_settings_section', $current_tab );
    }
    ?>
</div>
<div id="wpsl-geocode-test" class="wpsl-hide" title="<?php _e( 'Geocode API Response', 'wpsl' ); ?>">
    <div class="wpsl-geocode-warning" style="display: none;">
        <p><strong><?php _e( 'Note', 'wpsl' ); ?>: </strong></p>
    </div>

    <input id="wpsl-geocode-input" type="text" placeholder="<?php _e( 'Location details', 'wpsl' ); ?>" >
    <input id="wpsl-geocode-submit" type="submit" name="<?php _e( 'Search', 'wpsl' ); ?>" />
    <p class="wpsl-geocode-api-notice" style="display: none;">
        <strong><?php _e( 'API Status', 'wpsl' ); ?>: </strong>
        <span></span>
    </p>
    <div id="wpsl-geocode-tabs" style="width: auto;">
        <ul>
            <li><a href="#wpsl-geocode-preview"><?php _e( 'Map Preview', 'wpsl' ); ?></a></li>
            <li><a href="#wpsl-geocode-response"><?php _e( 'API Response', 'wpsl' ); ?></a></li>
        </ul>
        <div id="wpsl-geocode-preview" style="width:auto;height:300px;"></div>
        <div id="wpsl-geocode-response">
            <textarea readonly="readonly" cols="50" rows="25"></textarea>
        </div>
    </div>
</div>admin/templates/add-ons.php000064400000004436151327220640011701 0ustar00<?php
if ( !defined( 'ABSPATH' ) ) exit;

$campaign_params = '?utm_source=wpsl-add-ons&utm_medium=banner&utm_campaign=add-ons';

// Load the add-on data from an existing transient, or grab new data from the remote URL.
if ( false === ( $add_ons = get_transient( 'wpsl_addons' ) ) ) {
    $response = wp_remote_get( 'https://s3.amazonaws.com/wpsl/add-ons.json' );

    if ( !is_wp_error( $response ) ) {
        $add_ons = json_decode( wp_remote_retrieve_body( $response ) );

        if ( $add_ons ) {
            set_transient( 'wpsl_addons', $add_ons, WEEK_IN_SECONDS );
        }
    }
}
?>

<div class="wrap wpsl-add-ons">
    <h2><?php _e( 'WP Store Locator Add-Ons', 'wpsl' ); ?></h2>

    <?php
    if ( $add_ons ) {
        foreach ( $add_ons as $add_on ) {
    ?>
        <div class="wpsl-add-on">
            <?php if ( !empty( $add_on->url ) ) { ?>
            <a title="<?php echo esc_attr( $add_on->name ); ?>" href="<?php echo esc_url( $add_on->url ) . $campaign_params; ?>">
                <img src="<?php echo esc_url( $add_on->img ); ?>"/>
            </a>
            <?php } else { ?>
            <img src="<?php echo esc_url( $add_on->img ); ?>"/>
            <?php } ?>

            <div class="wpsl-add-on-desc">
                <p><?php echo esc_html( $add_on->desc ); ?></p>
                
                <div class="wpsl-add-on-status">
                    <?php if ( !empty( $add_on->class ) && class_exists( $add_on->class ) ) { ?>
                    <p><strong><?php _e( 'Already Installed.', 'wpsl' ); ?></strong></p>
                    <?php } else if ( isset( $add_on->soon ) && $add_on->soon ) { ?>
                    <p><strong><?php _e( 'Coming soon!', 'wpsl' ); ?></strong></p>
                    <?php } else { ?>
                    <a class="button-primary" href="<?php echo esc_url( $add_on->url ) . $campaign_params; ?>">
                        <?php esc_html_e( 'Get This Add-On', 'wpsl' ); ?>
                    </a>
                    <?php } ?>
                </div>
            </div>
        </div>
    <?php 
        }
    } else {
        echo '<p>'. __( 'Failed to load the add-on list from the server.', 'wpsl' ) . '</p>';
        echo '<p>'. __( 'Please try again later!', 'wpsl' ) . '</p>';
    }
    ?>  
</div>admin/class-notices.php000064400000010205151327220640011114 0ustar00<?php
/**
 * Admin Notices
 *
 * @author Tijmen Smit
 * @since  2.0.0
*/

if ( !defined( 'ABSPATH' ) ) exit;

if ( !class_exists( 'WPSL_Notices' ) ) {
    
    /**
     * Handle the meta boxes.
     *
     * @since 2.0.0
     */
	class WPSL_Notices {
        
        /**
         * Holds the notices.
         * @since 2.0.0
         * @var array
         */
        private $notices = array();
                
        public function __construct() {
            
            $this->notices = get_option( 'wpsl_notices' ); 
            
            add_action( 'all_admin_notices', array( $this, 'show' ) );
        }

        /**
         * Show one or more notices.
         * 
         * @since 2.0.0
         * @return void
         */
        public function show() {
            
            if ( !empty( $this->notices ) ) {
                $allowed_html = array(
                    'a' => array(
                        'href'       => array(),
                        'id'         => array(),
                        'class'      => array(),
                        'data-nonce' => array(),
                        'title'      => array(),
                        'target'     => array()
                    ),
                    'p'  => array(),
                    'br' => array(),
                    'em' => array(),
                    'strong' => array(
                        'class' => array()
                    ),
                    'span' => array(
                        'class' => array()
                    ),
                    'ul' => array(
                        'class' => array()
                    ),
                    'li' => array(
                        'class' => array()
                    )
                );
                
                if ( wpsl_is_multi_array( $this->notices ) ) {
                    foreach ( $this->notices as $k => $notice ) {
                        $this->create_notice_content( $notice, $allowed_html );
                    }
                } else {
                    $this->create_notice_content( $this->notices, $allowed_html );
                }

                // Empty the notices.
                $this->notices = array();
                update_option( 'wpsl_notices', $this->notices );
            }
        }
        
        /**
         * Create the content shown in the notice.
         * 
         * @since 2.1.0
         * @param array $notice
         * @param array $allowed_html
         */
        public function create_notice_content( $notice, $allowed_html ) {
            
            $class = ( 'update' == $notice['type'] ) ? 'updated' : 'error';

            if ( isset( $notice['multiline'] ) && $notice['multiline'] ) {
                $notice_msg = wp_kses( $notice['message'], $allowed_html );
            } else {
                $notice_msg = '<p>' . wp_kses( $notice['message'], $allowed_html ) . '</p>';
            }

            echo '<div class="' . esc_attr( $class ) . '">' . $notice_msg . '</div>';
        }
                
        /**
         * Save the notice.
         * 
         * @since 2.0.0
         * @param  string $type      The type of notice, either 'update' or 'error'
         * @param  string $message   The user message
         * @param  bool   $multiline True if the message contains multiple lines ( used with notices created in add-ons ).
         * @return void
         */
        public function save( $type, $message, $multiline = false ) {

            $current_notices = get_option( 'wpsl_notices' );

            $new_notice = array(
                'type'    => $type,
                'message' => $message
            );

            if ( $multiline ) {
                $new_notice['multiline'] = true;
            }

            if ( $current_notices ) {
                if ( !wpsl_is_multi_array( $current_notices ) ) {
                    $current_notices = array( $current_notices );
                }

                array_push( $current_notices, $new_notice );

                update_option( 'wpsl_notices', $current_notices );  
            } else {
                update_option( 'wpsl_notices', $new_notice );    
            }             
        }
    }
}admin/css/style.css000064400000027542151327220640010312 0ustar00@font-face {
  font-family: 'fontello';
  src: url('../font/fontello.eot?54620740');
  src: url('../font/fontello.eot?54620740#iefix') format('embedded-opentype'),
       url('../font/fontello.woff?54620740') format('woff'),
       url('../font/fontello.ttf?54620740') format('truetype'),
       url('../font/fontello.svg?54620740#fontello') format('svg');
  font-weight: normal;
  font-style: normal;
}

#wpsl-store-overview .widefat td,
#wpsl-wrap .widefat td {
    padding: 12px 7px;
}

#wpsl-wrap.wpsl-settings h2 {
    margin-bottom: 15px;
}

#wpsl-wrap .submit {
    padding: 0!important;
    margin-bottom: -10px !important;
}

#wpsl-store-overview .column-action a {
    float: left;
    margin-right: 5px;
}

#wpsl-store-overview p.search-box {
    margin: 0 0 1em 0;
}

.column-action { 
    width:130px;
}

#wpsl-delete-confirmation, 
.wpsl-hide {
    display:none;
}

.wpsl-preloader {
    float:right;
    margin:4px 0 0 4px;
}

.wpsl-api-key-preloader {
    margin-left: 10px;
}

/* Plugin nav */
#wpsl-mainnav {
    border-bottom: 1px solid #CCCCCC;
    float: left;
    margin-bottom: 15px;
    padding-left: 7px;
    width: 99.4%;
}
#wpsl-mainnav li a {
    display: block;
    padding: 9px 12px;
    text-decoration: none;
}

#wpsl-mainnav li {
    float: left;
    margin: 0;
}

#wpsl-wrap.wpsl-add-stores label,
#wpsl-wrap label {
    width:85px;
    margin-top:6px;
}

#wpsl-wrap.wpsl-add-stores label {
    float:left;
}
#wpsl-wrap.wpsl-add-stores p {
    overflow:hidden;
}
#wpsl-wrap.wpsl-add-stores .wpsl-radioboxes label {
    float:none;
    margin-right:10px;
} 

#wpsl-wrap textarea {
    width:489px;
    resize:none;
}

.wpsl-tab #wpsl-hours, #wpsl-wrap textarea  {
    height: 185px;
}

/* Todo uitzoeken voor textarea width */
#wpsl-wrap .wpsl-style-input textarea {
    width: 509px;
    resize: none;
    margin-bottom: 12px;
    height: 165px;
}

#wpsl-style-preview {
    float: left;
    margin-bottom: 12px;
}

.wpsl-style-preview-error {
    float: left; 
    margin: 6px 0 0 10px; 
    color: #b91111;
}

.wpsl-curve {
    float: left;
    border-radius: 3px;
}

#wpsl-geocode-test .wpsl-error,
#wpsl-wrap.wpsl-settings .wpsl-error,
.wpsl-store-meta .wpsl-error {
    border: 1px solid #c01313;
}

#wpsl-lookup-location {
    margin-bottom: 7px;
}

#wpsl-wrap input[type=text],
#wpsl-wrap input[type=email],
#wpsl-wrap input[type=url] {
    width:340px;
}

#wpsl-api-region,
#wpsl-wrap.wpsl-settings input[type=text].textinput {
    width:255px;
}

.wpsl-add-store {
    float:left; 
    width:100%; 
    clear:both; 
}

#wpsl-wrap .metabox-holder {
    float:left; 
    margin-right:20px;
}
#wpsl-wrap .metabox-holder.wpsl-wide {
    width:100%;
    padding-top:0;
}

#wpsl-wrap .wpsl-edit-header {
    margin-bottom:12px;
}

#wpsl-wrap.wpsl-settings .metabox-holder {
    width:100%;
}

#wpsl-wrap.wpsl-settings .metabox-holder h3:hover {
    cursor: auto;
}

#wpsl-gmap-wrap {
    float: left; 
    width: 100%; 
    height: 250px;
    border-radius: 3px;
    margin-top: 0;
    margin-bottom: 20px;
}

#wpsl-map-preview #wpsl-gmap-wrap {
    margin: 6px 0 12px 0;
}

#wpsl-gmap-wrap.wpsl-styles-preview {
    float: none;
    margin: 0;
    border-radius: 0;
    clear: both;
}

#wpsl-style-url {
    display: none;
    margin: 20px 0 0 0;
}

/* Markers */
.wpsl-marker-list {
    overflow: hidden;
}
.wpsl-marker-list li {
    float: left; 
    padding: 10px; 
    margin-right: 5px;
    text-align: center;
}
.wpsl-marker-list li input[type="radio"] {
    margin-right: 0;
}
.wpsl-marker-list img {
    display: block;
    margin-bottom: 7px;
}
.wpsl-marker-list li:hover,
.wpsl-active-marker {
    background: #E4E4E4; 
    border-radius:5px;
    cursor: pointer;
}

/* Settings page */
#wpsl-license-form .postbox-container,
#wpsl-settings-form .postbox-container {
    width: 535px;
    clear: both;
}
#wpsl-wrap .metabox-holder {
    padding-top: 0;
}

/* Tooltip */
.wpsl-info {
    position: relative;
    margin-left: 3px;
}

.wpsl-info:before { 
    content: '\e802'; 
    font-size: 14px;
    font-family: "fontello";
    font-style: normal;
    font-weight: normal;
    speak: none;
    display: inline-block;
    text-decoration: inherit;
    width: 1em;
    margin-right: .2em;
    text-align: center;
    font-variant: normal;
    text-transform: none;
    line-height: 1em;
    margin-left: .2em;
}

.wpsl-info:hover {
    cursor: pointer;
}

.wpsl-warning,
.wpsl-info.wpsl-required-setting:before {
    color: #b91111;
}

.wpsl-info-text {
    position: absolute;
    padding: 10px;
    left: -29px;
    bottom: 28px;
    color: #eee;
    min-width: 200px;
    background: #222;
    border-radius: 3px;
    line-height: 1.4em;
}

#wpsl-map-preview .wpsl-info-text {
    width: 175px;
    min-width: 0;
    left: -88px;
}

#wpsl-map-preview .wpsl-info-text::after {
    left: auto;
    right: 87px;
}

#wpsl-map-preview .wpsl-info {
    position: absolute;
    margin-left: 5px;
    top: 5px;
}

.wpsl-submit-wrap {
    position: relative;
    clear: both;
}

.wpsl-info-text:after {
    position: absolute;
    border-left: 11px solid transparent;
    border-right: 11px solid transparent;
    border-top: 11px solid #222;	
    content: "";	
    left: 27px;
    bottom: -10px;
}

.wpsl-info-text a {
    color: #fff;
}

#wpsl-settings-form label {
    position: relative;
    display: inline-block;
    font-weight: normal;
    margin: 0 10px 0 0;
    width: 220px;
}
	
#wpsl-save-settings {
    float: left; 
    clear: both;
}	
#wpsl-settings-form .wpsl-radioboxes label {
    float: none;
    margin-right: 10px;
    width: auto;
}

#wpsl-faq dt {
    margin-bottom: 4px;
    font-weight: bold;
    font-size: 110%;
}

#wpsl-faq dd {
    margin-left: 0;	
}

#wpsl-faq dl {
    margin-bottom: 25px;	
}

/* Overview page */
.wp-list-table .column-action .button {
    margin: 3px 5px 3px 0;
}

/* Custom post type */
.wpsl-store-meta p {
    overflow: hidden;
}

.wpsl-store-meta label,
.wpsl-store-meta legend {
    float: left;
    width: 95px;
    margin-top: 3px;
}

.wpsl-store-meta fieldset label {
    display: inline-block;
    line-height: 1.4em;
    margin: 0.25em 0 0.5em !important;
}

.wpsl-store-meta textarea,
.wpsl-store-meta input[type="text"], 
.wpsl-store-meta input[type="email"], 
.wpsl-store-meta input[type="url"] {
    width: 340px;
}

.wpsl-store-meta textarea {
    resize: none;
}

#wpsl-map-preview em,
#wpsl-settings-form em,
.wpsl-store-meta em {
    display: block;
}

#wpsl-settings-form .wpsl-info em {
    display: inline;
}

#wpsl-meta-nav {
    margin: 19px 0 6px 0;
}

#wpsl-meta-nav li {
    display:inline;
    margin-right:5px;
}

#wpsl-meta-nav li:hover {
    cursor: pointer;
}

#wpsl-meta-nav li a {
    padding:6px 9px;
    border-radius:3px 3px 0 0;
    border-bottom: none;
    text-decoration: none;
    outline:none;
}

.wpsl-tab {
    padding:5px 15px;
    display:none;
    border: 1px solid #eee;
    border-radius:0px 3px 3px 3px;
}

div.wpsl-active {
    display:block;
    background: #fdfdfd;
}

#wpsl-meta-nav .wpsl-active a {
    border:1px solid #eee;
    border-bottom:1px solid #fdfdfd;
    background: #fdfdfd;
    color:#444;
}

.wpsl-star {
    color:#c01313;
}

/* Opening Hours */
#wpsl-store-hours {
    border-collapse: collapse;
    margin: 5px 0 20px 0;
}

#wpsl-settings-form #wpsl-store-hours {
    width: 100%;
}

#wpsl-store-hours div {
    margin: 0;
    padding: 3px;
    background: #eee;
    border: 1px solid #eee;
    border-radius: 3px;
    white-space: nowrap;
}

#wpsl-store-hours .wpsl-store-closed {
    border: none;
    background: none;
    margin-top: 9px;
    margin-bottom: 0;
}

.wpsl-current-period,
.wpsl-add-period {
    float: left;
}

#wpsl-store-hours .wpsl-multiple-periods {
    float: left;
    clear: both;
    margin-top: 8px;
}

.wpsl-add-period span,
.wpsl-current-period span {
    float:left;
    margin:6px 7px 0;
}

.wpsl-add-period span {
    margin:6px 0 0 7px;
}

#wpsl-store-hours .wpsl-remove-period {
    background:#999;
    border-radius: 9px;
}

.wpsl-add-period {
    border:none;
    background:#eee;
    border-radius: 3px;
    font-size: 13px;
    padding: 3px 10px;
}

.wpsl-default-hours {
    margin-top:25px;
}

#wpsl-store-hours select {
    float:left;
}

#wpsl-store-hours th {
    text-align:left;
    padding:8px 10px 8px 0;
    border-bottom:1px solid #eee;
}

#wpsl-settings-form #wpsl-store-hours th {
    text-align: left;
}

#wpsl-store-hours td {
    border-bottom:1px solid #eee;
    padding:7px 10px 7px 0;
    vertical-align: top;
}

#wpsl-store-hours .wpsl-opening-day {
    min-width:80px;
    padding:17px 17px 0 0;
    text-align:left;
    vertical-align:top;
}

.wpsl-twentyfour-format .wpsl-opening-hours {
    width: 197px;
}

.wpsl-twelve-format .wpsl-opening-hours {
    width: 245px;
}

#wpsl-settings-form #wpsl-store-hours .wpsl-opening-day {
    width: 150px;
}

#wpsl-settings-form #wpsl-store-hours td p  {
    padding: 10px 0 0 0;
    margin: 0;
    text-align: left;
}

#wpsl-store-hours .wpsl-add-period {
    height: 30px;
}

.wpsl-pre-38 .wpsl-add-period {
    height: 27px;    
}

#wpsl-store-hours .dashicons:hover,
.wpsl-add-period:hover {
    cursor:pointer;
}

#wpsl-store-hours .dashicons {
    color: #999;
    margin: 0 3px;
}

#wpsl-store-hours .wpsl-add-period:hover .dashicons,
#wpsl-store-hours .dashicons:hover {
   color: #444; 
}

/* Fix the bottom spacing on the submit buttons */
#wpsl-wrap.wpsl-pre-38 .submit {
    margin-bottom: 0 !important;
}

/* Fontello fonts */
[class^="wpsl-icon-"]:before, [class*=" wpsl-icon-"]:before {
    font-family: "fontello";
    font-style: normal;
    font-weight: normal;
    speak: none;
    display: inline-block;
    text-decoration: inherit;
    width: 1em;
    margin-right: .2em;
    text-align: center;
    font-variant: normal;
    text-transform: none;
    line-height: 1em;
    margin-left: .2em;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

[class^="wpsl-icon-"]:hover, [class*=" wpsl-icon-"]:hover {
    cursor: pointer;
}

.wpsl-icon-location:before { 
    content: '\e801'; 
}

.wpsl-icon-attention-circled:before { 
    content: '\e802'; 
}

.wpsl-icon-cancel-circled:before { 
    content: '\e803'; 
}

.wpsl-icon-plus-circled:before {
    content: '\e805'; 
}

#wpsl-store-hours .wpsl-icon-plus-circled,
#wpsl-store-hours .wpsl-icon-cancel-circled {
    margin-top: 1px;
    font-size: 18px;
    display: inline-block;
    color: #999;
}

#wpsl-store-hours .wpsl-icon-plus-circled:hover,
#wpsl-store-hours .wpsl-icon-cancel-circled:hover {
    color: #444;
}

.wpsl-add-on {
    float: left;
    position: relative;
    width: 300px;
    height: 240px;
    background: #fff;
    margin: 20px 20px 0 0;
    border: 1px solid #e8e8e8;
    border-radius: 3px;
}

.wpsl-add-on p {
    margin-top: 0;
}

.wpsl-add-on img {
    height: auto;
    max-width: 100%;
    vertical-align: bottom;
}

.wpsl-add-on > a {
    width: 300px;
    display: inline-block;
}

.wpsl-add-on a img:hover {
    opacity: 0.95;
}

.wpsl-add-on .wpsl-add-on-desc {
    padding: 20px;    
}

.wpsl-add-on-status {
    position: absolute;
    left: 20px;
    bottom: 20px;
}

.wpsl-add-on-status p {
    margin: 0 0 4px 0;
}

/* Classes to handle the API errors */
.wpsl-api-error {
    margin-top: 13px;
    padding: 10px;
    color: #fff;
    border-radius: 3px;
    background: #c01313;
}

.wpsl-api-error a {
    font-weight: bold;
    color: #fff !important;
}

/* Test API response for any address */
#wpsl-geocode-test {
    overflow: hidden;
}

#wpsl-geocode-tabs {
    margin-top: 10px;
    height: 370px;
}

#wpsl-geocode-tabs .ui-widget-header {
    border: none;
    border-bottom: 1px solid #aaa;
    background: none;
}

#wpsl-geocode-preview {
    margin-top:14px;
    border-radius: 0;
}

#wpsl-geocode-response {
    padding-left: 0;
    padding-right: 0;
}

#wpsl-geocode-response textarea {
    width: 100%;
    height: 328px;
    resize: none;
}

#wpsl-geocode-tabs.ui-widget-content {
    border: none;
}

#wpsl-geocode-tabs.ui-tabs .ui-tabs-nav {
    padding: 0;
}

#wpsl-geocode-tabs {
    width: auto;
}admin/css/style.min.css000064400000022071151327220640011064 0ustar00@font-face{font-family:fontello;src:url(../font/fontello.eot?54620740);src:url(../font/fontello.eot?54620740#iefix) format('embedded-opentype'),url(../font/fontello.woff?54620740) format('woff'),url(../font/fontello.ttf?54620740) format('truetype'),url(../font/fontello.svg?54620740#fontello) format('svg');font-weight:400;font-style:normal}#wpsl-store-overview .widefat td,#wpsl-wrap .widefat td{padding:12px 7px}#wpsl-wrap.wpsl-settings h2{margin-bottom:15px}#wpsl-wrap .submit{padding:0!important;margin-bottom:-10px!important}#wpsl-store-overview .column-action a{float:left;margin-right:5px}#wpsl-store-overview p.search-box{margin:0 0 1em 0}.column-action{width:130px}#wpsl-delete-confirmation,.wpsl-hide{display:none}.wpsl-preloader{float:right;margin:4px 0 0 4px}.wpsl-api-key-preloader{margin-left:10px}#wpsl-mainnav{border-bottom:1px solid #ccc;float:left;margin-bottom:15px;padding-left:7px;width:99.4%}#wpsl-mainnav li a{display:block;padding:9px 12px;text-decoration:none}#wpsl-mainnav li{float:left;margin:0}#wpsl-wrap label,#wpsl-wrap.wpsl-add-stores label{width:85px;margin-top:6px}#wpsl-wrap.wpsl-add-stores label{float:left}#wpsl-wrap.wpsl-add-stores p{overflow:hidden}#wpsl-wrap.wpsl-add-stores .wpsl-radioboxes label{float:none;margin-right:10px}#wpsl-wrap textarea{width:489px;resize:none}#wpsl-wrap textarea,.wpsl-tab #wpsl-hours{height:185px}#wpsl-wrap .wpsl-style-input textarea{width:509px;resize:none;margin-bottom:12px;height:165px}#wpsl-style-preview{float:left;margin-bottom:12px}.wpsl-style-preview-error{float:left;margin:6px 0 0 10px;color:#b91111}.wpsl-curve{float:left;border-radius:3px}#wpsl-geocode-test .wpsl-error,#wpsl-wrap.wpsl-settings .wpsl-error,.wpsl-store-meta .wpsl-error{border:1px solid #c01313}#wpsl-lookup-location{margin-bottom:7px}#wpsl-wrap input[type=email],#wpsl-wrap input[type=text],#wpsl-wrap input[type=url]{width:340px}#wpsl-api-region,#wpsl-wrap.wpsl-settings input[type=text].textinput{width:255px}.wpsl-add-store{float:left;width:100%;clear:both}#wpsl-wrap .metabox-holder{float:left;margin-right:20px}#wpsl-wrap .metabox-holder.wpsl-wide{width:100%;padding-top:0}#wpsl-wrap .wpsl-edit-header{margin-bottom:12px}#wpsl-wrap.wpsl-settings .metabox-holder{width:100%}#wpsl-wrap.wpsl-settings .metabox-holder h3:hover{cursor:auto}#wpsl-gmap-wrap{float:left;width:100%;height:250px;border-radius:3px;margin-top:0;margin-bottom:20px}#wpsl-map-preview #wpsl-gmap-wrap{margin:6px 0 12px 0}#wpsl-gmap-wrap.wpsl-styles-preview{float:none;margin:0;border-radius:0;clear:both}#wpsl-style-url{display:none;margin:20px 0 0 0}.wpsl-marker-list{overflow:hidden}.wpsl-marker-list li{float:left;padding:10px;margin-right:5px;text-align:center}.wpsl-marker-list li input[type=radio]{margin-right:0}.wpsl-marker-list img{display:block;margin-bottom:7px}.wpsl-active-marker,.wpsl-marker-list li:hover{background:#e4e4e4;border-radius:5px;cursor:pointer}#wpsl-license-form .postbox-container,#wpsl-settings-form .postbox-container{width:535px;clear:both}#wpsl-wrap .metabox-holder{padding-top:0}.wpsl-info{position:relative;margin-left:3px}.wpsl-info:before{content:'\e802';font-size:14px;font-family:fontello;font-style:normal;font-weight:400;speak:none;display:inline-block;text-decoration:inherit;width:1em;margin-right:.2em;text-align:center;font-variant:normal;text-transform:none;line-height:1em;margin-left:.2em}.wpsl-info:hover{cursor:pointer}.wpsl-info.wpsl-required-setting:before,.wpsl-warning{color:#b91111}.wpsl-info-text{position:absolute;padding:10px;left:-29px;bottom:28px;color:#eee;min-width:200px;background:#222;border-radius:3px;line-height:1.4em}#wpsl-map-preview .wpsl-info-text{width:175px;min-width:0;left:-88px}#wpsl-map-preview .wpsl-info-text::after{left:auto;right:87px}#wpsl-map-preview .wpsl-info{position:absolute;margin-left:5px;top:5px}.wpsl-submit-wrap{position:relative;clear:both}.wpsl-info-text:after{position:absolute;border-left:11px solid transparent;border-right:11px solid transparent;border-top:11px solid #222;content:"";left:27px;bottom:-10px}.wpsl-info-text a{color:#fff}#wpsl-settings-form label{position:relative;display:inline-block;font-weight:400;margin:0 10px 0 0;width:220px}#wpsl-save-settings{float:left;clear:both}#wpsl-settings-form .wpsl-radioboxes label{float:none;margin-right:10px;width:auto}#wpsl-faq dt{margin-bottom:4px;font-weight:700;font-size:110%}#wpsl-faq dd{margin-left:0}#wpsl-faq dl{margin-bottom:25px}.wp-list-table .column-action .button{margin:3px 5px 3px 0}.wpsl-store-meta p{overflow:hidden}.wpsl-store-meta label,.wpsl-store-meta legend{float:left;width:95px;margin-top:3px}.wpsl-store-meta fieldset label{display:inline-block;line-height:1.4em;margin:.25em 0 .5em!important}.wpsl-store-meta input[type=email],.wpsl-store-meta input[type=text],.wpsl-store-meta input[type=url],.wpsl-store-meta textarea{width:340px}.wpsl-store-meta textarea{resize:none}#wpsl-map-preview em,#wpsl-settings-form em,.wpsl-store-meta em{display:block}#wpsl-settings-form .wpsl-info em{display:inline}#wpsl-meta-nav{margin:19px 0 6px 0}#wpsl-meta-nav li{display:inline;margin-right:5px}#wpsl-meta-nav li:hover{cursor:pointer}#wpsl-meta-nav li a{padding:6px 9px;border-radius:3px 3px 0 0;border-bottom:none;text-decoration:none;outline:0}.wpsl-tab{padding:5px 15px;display:none;border:1px solid #eee;border-radius:0 3px 3px 3px}div.wpsl-active{display:block;background:#fdfdfd}#wpsl-meta-nav .wpsl-active a{border:1px solid #eee;border-bottom:1px solid #fdfdfd;background:#fdfdfd;color:#444}.wpsl-star{color:#c01313}#wpsl-store-hours{border-collapse:collapse;margin:5px 0 20px 0}#wpsl-settings-form #wpsl-store-hours{width:100%}#wpsl-store-hours div{margin:0;padding:3px;background:#eee;border:1px solid #eee;border-radius:3px;white-space:nowrap}#wpsl-store-hours .wpsl-store-closed{border:none;background:0 0;margin-top:9px;margin-bottom:0}.wpsl-add-period,.wpsl-current-period{float:left}#wpsl-store-hours .wpsl-multiple-periods{float:left;clear:both;margin-top:8px}.wpsl-add-period span,.wpsl-current-period span{float:left;margin:6px 7px 0}.wpsl-add-period span{margin:6px 0 0 7px}#wpsl-store-hours .wpsl-remove-period{background:#999;border-radius:9px}.wpsl-add-period{border:none;background:#eee;border-radius:3px;font-size:13px;padding:3px 10px}.wpsl-default-hours{margin-top:25px}#wpsl-store-hours select{float:left}#wpsl-store-hours th{text-align:left;padding:8px 10px 8px 0;border-bottom:1px solid #eee}#wpsl-settings-form #wpsl-store-hours th{text-align:left}#wpsl-store-hours td{border-bottom:1px solid #eee;padding:7px 10px 7px 0;vertical-align:top}#wpsl-store-hours .wpsl-opening-day{min-width:80px;padding:17px 17px 0 0;text-align:left;vertical-align:top}.wpsl-twentyfour-format .wpsl-opening-hours{width:197px}.wpsl-twelve-format .wpsl-opening-hours{width:245px}#wpsl-settings-form #wpsl-store-hours .wpsl-opening-day{width:150px}#wpsl-settings-form #wpsl-store-hours td p{padding:10px 0 0 0;margin:0;text-align:left}#wpsl-store-hours .wpsl-add-period{height:30px}.wpsl-pre-38 .wpsl-add-period{height:27px}#wpsl-store-hours .dashicons:hover,.wpsl-add-period:hover{cursor:pointer}#wpsl-store-hours .dashicons{color:#999;margin:0 3px}#wpsl-store-hours .dashicons:hover,#wpsl-store-hours .wpsl-add-period:hover .dashicons{color:#444}#wpsl-wrap.wpsl-pre-38 .submit{margin-bottom:0!important}[class*=" wpsl-icon-"]:before,[class^=wpsl-icon-]:before{font-family:fontello;font-style:normal;font-weight:400;speak:none;display:inline-block;text-decoration:inherit;width:1em;margin-right:.2em;text-align:center;font-variant:normal;text-transform:none;line-height:1em;margin-left:.2em;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}[class*=" wpsl-icon-"]:hover,[class^=wpsl-icon-]:hover{cursor:pointer}.wpsl-icon-location:before{content:'\e801'}.wpsl-icon-attention-circled:before{content:'\e802'}.wpsl-icon-cancel-circled:before{content:'\e803'}.wpsl-icon-plus-circled:before{content:'\e805'}#wpsl-store-hours .wpsl-icon-cancel-circled,#wpsl-store-hours .wpsl-icon-plus-circled{margin-top:1px;font-size:18px;display:inline-block;color:#999}#wpsl-store-hours .wpsl-icon-cancel-circled:hover,#wpsl-store-hours .wpsl-icon-plus-circled:hover{color:#444}.wpsl-add-on{float:left;position:relative;width:300px;height:240px;background:#fff;margin:20px 20px 0 0;border:1px solid #e8e8e8;border-radius:3px}.wpsl-add-on p{margin-top:0}.wpsl-add-on img{height:auto;max-width:100%;vertical-align:bottom}.wpsl-add-on>a{width:300px;display:inline-block}.wpsl-add-on a img:hover{opacity:.95}.wpsl-add-on .wpsl-add-on-desc{padding:20px}.wpsl-add-on-status{position:absolute;left:20px;bottom:20px}.wpsl-add-on-status p{margin:0 0 4px 0}.wpsl-api-error{margin-top:13px;padding:10px;color:#fff;border-radius:3px;background:#c01313}.wpsl-api-error a{font-weight:700;color:#fff!important}#wpsl-geocode-test{overflow:hidden}#wpsl-geocode-tabs{margin-top:10px;height:370px}#wpsl-geocode-tabs .ui-widget-header{border:none;border-bottom:1px solid #aaa;background:0 0}#wpsl-geocode-preview{margin-top:14px;border-radius:0}#wpsl-geocode-response{padding-left:0;padding-right:0}#wpsl-geocode-response textarea{width:100%;height:328px;resize:none}#wpsl-geocode-tabs.ui-widget-content{border:none}#wpsl-geocode-tabs.ui-tabs .ui-tabs-nav{padding:0}#wpsl-geocode-tabs{width:auto}admin/css/style-3.8.min.css000064400000001502151327220640011366 0ustar00@font-face{font-family:fontello;src:url(../font/fontello.eot?54620740);src:url(../font/fontello.eot?54620740#iefix) format('embedded-opentype'),url(../font/fontello.woff?54620740) format('woff'),url(../font/fontello.ttf?54620740) format('truetype'),url(../font/fontello.svg?54620740#fontello) format('svg');font-weight:400;font-style:normal}#adminmenu #menu-posts-wpsl_stores .wp-menu-image:before,.wpsl-thickbox:before{content:'\e801';display:inline-block;font-family:fontello!important;font-style:normal;font-variant:normal;font-weight:400;font-size:22px;line-height:1em;text-align:center;text-decoration:inherit;text-transform:none;width:1em}.wpsl-thickbox:before{padding-top:1px;font-size:18px;color:#82878c}#adminmenu #menu-posts-wpsl_stores .wp-menu-image img{display:none}#wpsl-store-overview .widefat td.thumb{padding-top:8px}admin/css/style-3.8.css000064400000002107151327220640010606 0ustar00@font-face {
  font-family: 'fontello';
  src: url('../font/fontello.eot?54620740');
  src: url('../font/fontello.eot?54620740#iefix') format('embedded-opentype'),
       url('../font/fontello.woff?54620740') format('woff'),
       url('../font/fontello.ttf?54620740') format('truetype'),
       url('../font/fontello.svg?54620740#fontello') format('svg');
  font-weight: normal;
  font-style: normal;
}

#adminmenu #menu-posts-wpsl_stores .wp-menu-image:before,
.wpsl-thickbox:before {
    content: '\e801';
    display: inline-block;
    font-family: "fontello" !important;
    font-style: normal;
    font-variant: normal;
    font-weight: 400;
    font-size: 22px;
    line-height: 1em;
    text-align: center;
    text-decoration: inherit;
    text-transform: none;
    width: 1em;
}

.wpsl-thickbox:before {
    padding-top: 1px;
    font-size: 18px;
    color: #82878c;
}

/* Hide the pre 3.8 menu icon */
#adminmenu #menu-posts-wpsl_stores .wp-menu-image img {
    display: none;
}

#wpsl-store-overview .widefat td.thumb {
    padding-top: 8px;
}admin/class-license-manager.php000064400000021157151327220640012512 0ustar00<?php
/**
 * Handle the add-on license and updates.
 *
 * @author Tijmen Smit
 * @since  2.1.0
 */

if ( !defined( 'ABSPATH' ) ) exit;

class WPSL_License_Manager {
    
    public $item_name;
    public $item_shortname;
    public $version;
    public $author;
    public $file;
    public $api_url = 'https://wpstorelocator.co/';
    
    /**
	 * Class constructor
	 *
	 * @param string  $item_name
	 * @param string  $version
	 * @param string  $author
	 * @param string  $file
	 */
    function __construct( $item_name, $version, $author, $file  ) {

        $this->item_name      = $item_name;
		$this->item_shortname = 'wpsl_' . preg_replace( '/[^a-zA-Z0-9_\s]/', '', str_replace( ' ', '_', strtolower( $this->item_name ) ) );
		$this->version        = $version;
        $this->author         = $author;
		$this->file           = $file;
        
        $this->includes();

        add_action( 'admin_init',            array( $this, 'auto_updater' ), 0 );
        add_action( 'admin_init',            array( $this, 'license_actions' ) );
        add_filter( 'wpsl_license_settings', array( $this, 'add_license_field' ), 1 );
	}
    
   /**
	 * Include the updater class
	 *
     * @since 2.1.0
	 * @access  private
	 * @return  void
	 */
	private function includes() {
		if ( !class_exists( 'EDD_SL_Plugin_Updater' ) ) {
            require_once 'EDD_SL_Plugin_Updater.php';
        }
	}
    
    /**
     * Handle the add-on updates.
     * 
     * @since 2.1.0
     * @return void
     */
    public function auto_updater() {

        if ( $this->get_license_option( 'status' ) !== 'valid' ) {
			return;
		}

		$args = array(
			'version'   => $this->version,
			'license'   => $this->get_license_option( 'key' ),
			'author'    => $this->author,
            'item_name' => $this->item_name
		);

		// Setup the updater.
		$edd_updater = new EDD_SL_Plugin_Updater(
			$this->api_url,
			$this->file,
			$args
		);    
    }
    
    /**
     * Check which license actions to take.
     * 
     * @since  2.1.0
     * @return void
     */
    public function license_actions() {

    	if ( !isset( $_POST['wpsl_licenses'] ) ) {
            return;
        }

		if ( !isset( $_POST['wpsl_licenses'][ $this->item_shortname ] ) || empty( $_POST['wpsl_licenses'][ $this->item_shortname ] ) ) {
			return;
        }
        
        if ( !check_admin_referer( $this->item_shortname . '_license-nonce', $this->item_shortname . '_license-nonce' ) ) {
            return;
        }

        if ( !current_user_can( 'manage_wpsl_settings' ) ) {
            return;
        }
        
        if ( isset( $_POST[ $this->item_shortname . '_license_key_deactivate' ] ) ) {
            $this->deactivate_license();
        } else {
            $this->activate_license();
        }
    }

    /**
     * Try to activate the license key.
     * 
     * @since  2.1.0
     * @return void
     */
    public function activate_license() {
    
        // Stop if the current license is already active. 
        if ( $this->get_license_option( 'status' ) == 'valid' ) {
			return;
		}

        $license = sanitize_text_field( $_POST['wpsl_licenses'][ $this->item_shortname ] );

		// data to send in our API request.
		$api_params = array(
			'edd_action' => 'activate_license',
			'license' 	 => $license,
			'item_name'  => urlencode( $this->item_name ),
			'url'        => home_url()
		);

        // Get the license data from the API.
		$license_data = $this->call_license_api( $api_params );

        if ( $license_data ) {
            update_option(
                $this->item_shortname . '_license_data',
                array(
                    'key'        => $license,
                    'expiration' => $license_data->expires,
                    'status'     => $license_data->license
                )
            );

            if ( $license_data->success ) {
                $this->set_license_notice( $this->item_name . ' license activated.', 'updated' );
            } else if ( !empty( $license_data->error ) ) {
                $this->handle_activation_errors( $license_data->error );
            }
        }
    }

    /**
     * Deactivate the license key.
     * 
     * @since  2.1.0
     * @return void
     */    
    public function deactivate_license() {

        // Data to send to the API
        $api_params = array(
            'edd_action' => 'deactivate_license',
            'license'    => $this->get_license_option( 'key' ),
            'item_name'  => urlencode( $this->item_name ),
            'url'        => home_url()
        );

        // Get the license data from the API.
		$license_data = $this->call_license_api( $api_params );
        
        if ( $license_data ) {
            if ( $license_data->license == 'deactivated' ) {
                delete_option( $this->item_shortname . '_license_data' );    
                
                $this->set_license_notice( $this->item_name . ' license deactivated.', 'updated' );
            } else {
                $message = sprintf (__( 'The %s license failed to deactivate, please try again later or contact support!', 'wpsl' ), $this->item_name );
                $this->set_license_notice( $message, 'error' );
            }
        }     
    }
    
    /**
     * Access the license API.
     * 
     * @since  2.1.0
     * @params array      $api_params   The used API parameters
     * @return void|array $license_data The returned license data on success
     */     
    public function call_license_api( $api_params ) {
        
        $response = wp_remote_post(
			$this->api_url,
			array(
				'timeout'   => 15,
				'sslverify' => false,
				'body'      => $api_params
			)
		);

		// Make sure the response came back okay.
		if ( is_wp_error( $response ) ) {
            $message = $response->get_error_message() . '. ' . __( 'Please try again later!', 'wpsl' );
            $this->set_license_notice( $message, 'error' );
        } else {
            $license_data = json_decode( wp_remote_retrieve_body( $response ) );        

            return $license_data;
        }
    }    

    /**
     * Get a single license option.
     * 
     * @since 2.1.0
     * @param string        $option Name of the license option.
     * @return void|string          The value for the license option.
     */ 
    public function get_license_option( $option ) {
        
        $license_data = get_option( $this->item_shortname . '_license_data' ); 
        
        if ( isset( $license_data[ $option ] ) ) {
            return $license_data[ $option ];   
        }
    }

    /**
     * Set a notice holding license information.
     *
     * @since 2.1.0
     * @param string $message The license message to display.
     * @param string $type    Either updated or error.
     * @return void
     */
    public function set_license_notice( $message, $type ) {
        add_settings_error( $this->item_shortname . '-license', 'license-notice', $message, $type );
    }

    /**
     * Check the different license activation errors.
     * 
     * @since 2.1.0
     * @param string $activation_errors The activation errors returned by the license API.
     * @return void
     */     
    public function handle_activation_errors( $activation_errors ) {

        switch ( $activation_errors ) {
            case 'item_name_mismatch':
                $error_msg = sprintf( __( 'The %s license key does not belong to this add-on.', 'wpsl' ), $this->item_name );
                break;
            case 'no_activations_left':
                $error_msg = sprintf( __( 'The %s license key does not have any activations left.', 'wpsl' ), $this->item_name );
                break;
            case 'expired':
                $error_msg = sprintf( __( 'The %s license key is expired. Please renew it.', 'wpsl' ), $this->item_name );
                break;
            default:
                $error_msg = sprintf( __( 'There was a problem activating the license key for the %s, please try again or contact support. Error code: %s', 'wpsl' ), $this->item_name, $activation_errors );
                break;
        }

        $this->set_license_notice( $error_msg, 'error' );
    }
        
    /**
     * Add license fields to the settings.
     * 
     * @since  2.1.0
     * @param  array $settings The existing settings.
     * @return array
     */
	public function add_license_field( $settings ) {
        
		$license_setting = array(
			array(
                'name'       => $this->item_name,
				'short_name' => $this->item_shortname,
                'status'     => $this->get_license_option( 'status' ),
                'key'        => $this->get_license_option( 'key' ),
                'expiration' => $this->get_license_option( 'expiration' )
			)
		);

		return array_merge( $settings, $license_setting );
	}
}admin/class-shortcode-generator.php000064400000037661151327220640013445 0ustar00<?php
/**
 * Shortcode Generator class
 *
 * @author Tijmen Smit
 * @since  2.2.10
 */

if ( !defined( 'ABSPATH' ) ) exit;

if ( !class_exists( 'WPSL_Shortcode_Generator' ) ) {

    /**
     * Handle the generation of the WPSL shortcode through the media button
     *
     * @since 2.2.10
     */
    class WPSL_Shortcode_Generator {

        /**
         * Constructor
         */
        public function __construct() {
            add_action( 'media_buttons', array( $this, 'add_wpsl_media_button' ) );
            add_action( 'admin_init',    array( $this, 'show_thickbox_iframe_content' ) );
        }

        /**
         * Add the WPSL media button to the media button row
         *
         * @since 2.2.10
         * @return void
         */
        public function add_wpsl_media_button() {

            global $pagenow, $typenow;

            /* Make sure we're on a post/page or edit screen in the admin area */
            if ( in_array( $pagenow, array( 'post.php', 'page.php', 'post-new.php', 'post-edit.php' ) ) && $typenow != 'wpsl_stores' ) {
                $changelog_link = self_admin_url( '?wpsl_media_action=store_locator&KeepThis=true&TB_iframe=true&width=783&height=800' );

                echo '<a href="' . esc_url( $changelog_link ) . '" class="thickbox button wpsl-thickbox" name="' . __( 'WP Store Locator' ,'wpsl' ) . '">' .  __( 'Insert Store Locator', 'wpsl' ) . '</a>';
            }
        }

        /**
         * Show the shortcode thickbox content
         *
         * @since 2.2.10
         * @return void
         */
        function show_thickbox_iframe_content() {

            global $wpsl_settings, $wpsl_admin;

            if ( empty( $_REQUEST['wpsl_media_action'] ) ) {
                return;
            }

            if ( !current_user_can( 'edit_pages' ) ) {
                wp_die( __( 'You do not have permission to perform this action', 'wpsl' ), __( 'Error', 'wpsl' ), array( 'response' => 403 ) );
            }

            $min = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';

            // Make sure the required JS / CSS files are loaded in the Thickbox iframe
            wp_print_scripts( 'jquery-ui-core' );
            wp_print_scripts( 'jquery-ui-tabs' );
            wp_print_scripts( 'media-upload' );
            ?>
            <script type="text/javascript" src="<?php echo plugins_url( '/js/wpsl-shortcode-generator' . $min . '.js?ver='. WPSL_VERSION_NUM .'', __FILE__ ); ?>"></script>
            <?php
            wp_print_styles('buttons' );
            wp_print_styles('forms' );
            ?>

            <link rel="stylesheet" type="text/css" href="<?php echo plugins_url( '/css/style' . $min . '.css?ver='. WPSL_VERSION_NUM .'', __FILE__ ); ?>" media="all" />
            <style>
                body {
                    color: #444;
                    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
                    font-size: 13px;
                    margin: 0;
                }

                #wpsl-media-tabs .ui-tabs-nav {
                     padding-left: 15px;
                     background: #fff !important;
                     border-bottom: 1px solid #dfdfdf;
                     border-collapse: collapse;
                     padding-top: .2em;
                 }

                #wpsl-media-tabs .ui-tabs-nav::after {
                    clear: both;
                    content: "";
                    display: table;
                    border-collapse: collapse;
                }

                #wpsl-media-tabs .ui-tabs-nav li {
                    list-style: none;
                    float: left;
                    position: relative;
                    top: 0;
                    margin: 1px .2em 0 0;
                    padding: 0;
                    white-space: nowrap;
                    border-bottom-width: 0;
                }

                #wpsl-media-tabs .ui-tabs-anchor {
                    float: left;
                    padding: .5em 1em;
                    text-decoration: none;
                    font-size: 14.3px;
                }

                #wpsl-media-tabs .ui-tabs-active a {
                    color: #212121;
                    cursor: text;
                }

                #wpsl-media-tabs .ui-tabs .ui-tabs-anchor {
                    float: left;
                    padding: .5em 1em;
                    text-decoration: none;
                }

                #wpsl-media-tabs.ui-widget-content {
                    border: none;
                    padding: 10px 0 0 0;
                }

                #wpsl-media-tabs .ui-tabs-anchor {
                    outline: none;
                }

                #wpsl-shortcode-config tr > td {
                    width: 25%;
                }

                #wpsl-markers-tab .wpsl-marker-list {
                    display: block;
                    overflow: hidden;
                    padding: 0;
                    list-style-type: none;
                }

                #wpsl-markers-tab .wpsl-marker-list li input {
                    padding: 0;
                    margin: 0;
                }

                #wpsl-shortcode-config .form-table,
                #wpsl-shortcode-config .form-table td,
                #wpsl-shortcode-config .form-table th,
                #wpsl-shortcode-config .form-table td p {
                    font-size: 13px;
                }

                #wpsl-shortcode-config .ui-tabs .ui-tabs-nav {
                    padding-left: 15px;
                    border-radius: 0;
                    margin: 0;
                }

                .wpsl-shortcode-markers {
                    padding: 0 10px;
                    margin-top: 27px;
                    font-size: 13px;
                }

                #wpsl-insert-shortcode {
                    margin-left: 19px;
                }

                #wpsl-shortcode-config .ui-state-default {
                    border: 1px solid #d3d3d3;
                    border-top-left-radius: 4px;
                    border-top-right-radius: 4px;
                    background: none;
                }

                #wpsl-shortcode-config .ui-state-default a {
                    color: #909090;
                }

                #wpsl-shortcode-config .ui-state-default.ui-tabs-active a {
                    color: #212121;
                }

                #wpsl-shortcode-config .ui-state-hover {
                    border-bottom: none;
                }

                #wpsl-shortcode-config .ui-state-hover a {
                    color: #72777c;
                }

                #wpsl-media-tabs .ui-state-active {
                    border: 1px solid #aaa;
                    border-bottom: 1px solid #fff;
                    padding-bottom: 0;
                }

                #wpsl-shortcode-config li.ui-tabs-active.ui-state-hover,
                #wpsl-shortcode-config li.ui-tabs-active {
                    border-bottom: 1px solid #fff;
                    padding-bottom: 0;
                }

                #wpsl-media-tabs li.ui-tabs-active {
                    margin-bottom: -1px;
                }

                #wpsl-general-tab,
                #wpsl-markers-tab {
                    border: 0;
                    padding: 1em 1.4em;
                    background: none;
                }

                @media ( max-width: 782px ) {
                    #wpsl-shortcode-config tr > td {
                        width: 100%;
                    }
                }
            </style>
            <div id="wpsl-shortcode-config" class="wp-core-ui">
                <div id="wpsl-media-tabs">
                    <ul>
                        <li><a href="#wpsl-general-tab"><?php _e( 'General Options', 'wpsl' ); ?></a></li>
                        <li><a href="#wpsl-markers-tab"><?php _e('Markers', 'wpsl' ); ?></a></li>
                    </ul>
                    <div id="wpsl-general-tab">
                        <table class="form-table wpsl-shortcode-config">
                            <tbody>
                            <tr>
                                <td><label for="wpsl-store-template"><?php _e('Select the used template', 'wpsl' ); ?></label></td>
                                <td><?php echo $wpsl_admin->settings_page->show_template_options(); ?></td>
                            </tr>
                            <tr>
                                <td><label for="wpsl-start-location"><?php _e( 'Start point', 'wpsl' ); ?></label><span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'If nothing it set, then the start point from the %ssettings%s page is used.', '' ), '<a href=' . admin_url( 'edit.php?post_type=wpsl_stores&page=wpsl_settings#wpsl-map-settings' ) . '>', '</a>'  ); ?></span></span></p></td>
                                <td><input type="text" placeholder="Optional" value="" id="wpsl-start-location"></td>
                            </tr>
                            <tr>
                                <td>
                                    <label for="wpsl-auto-locate"><?php _e( 'Attempt to auto-locate the user', 'wpsl' ); ?><span class="wpsl-info"><span class="wpsl-info-text wpsl-hide"><?php echo sprintf( __( 'Most modern browsers %srequire%s a HTTPS connection before the Geolocation feature works.', 'wpsl_csv' ), '<a href="https://wpstorelocator.co/document/html-5-geolocation-not-working/">', '</a>' ); ?></span></span></label>
                                </td>
                                <td><input type="checkbox" value="" <?php checked( $wpsl_settings['auto_locate'], true ); ?> name="wpsl_map[auto_locate]" id="wpsl-auto-locate"></td>
                            </tr>
                            <?php
                            $terms = get_terms( 'wpsl_store_category', 'hide_empty=1' );

                            if ( $terms ) {
                                ?>
                                <tr>
                                    <td><label for="wpsl-cat-filter-types"><?php _e( 'Category filter type', 'wpsl' ); ?></label></p></td>
                                    <td>
                                        <select id="wpsl-cat-filter-types" autocomplete="off">
                                            <option value="" selected="selected"><?php _e( 'None', 'wpsl' ); ?></option>
                                            <option value="dropdown"><?php _e( 'Dropdown', 'wpsl' ); ?></option>
                                            <option value="checkboxes"><?php _e( 'Checkboxes', 'wpsl' ); ?></option>
                                        </select>
                                    </td>
                                </tr>
                                <tr class="wpsl-cat-restriction">
                                    <td style="vertical-align:top;"><label for="wpsl-cat-restriction"><?php _e('Automatically restrict the returned results to one or more categories?', 'wpsl' ); ?></label></td>
                                    <td>
                                        <?php
                                        $cat_restricton = '<select id="wpsl-cat-restriction" multiple="multiple" autocomplete="off">';

                                        foreach ( $terms as $term ) {
                                            $cat_restricton .= '<option value="' . esc_attr( $term->slug ) . '">' . esc_html( $term->name ) . '</option>';
                                        }

                                        $cat_restricton .= '</select>';

                                        echo $cat_restricton;
                                        ?>
                                    </td>
                                </tr>
                                <tr class="wpsl-cat-selection wpsl-hide">
                                    <td style="vertical-align:top;"><label for="wpsl-cat-selection"><?php _e('Set a selected category?', 'wpsl' ); ?></label></td>
                                    <td>
                                        <?php
                                        $cat_selection = '<select id="wpsl-cat-selection" autocomplete="off">';

                                        $cat_selection .= '<option value="" selected="selected">' . __( 'Select category', 'wpsl' ) . '</option>';

                                        foreach ( $terms as $term ) {
                                            $cat_selection .= '<option value="' . esc_attr( $term->slug ) . '">' . esc_html( $term->name ) . '</option>';
                                        }

                                        $cat_selection .= '</select>';

                                        echo $cat_selection;
                                        ?>
                                    </td>
                                </tr>
                                <?php
                            }
                            ?>
                            <tr class="wpsl-checkbox-options wpsl-hide">
                                <td><label for="wpsl-checkbox-columns"><?php _e('Checkbox columns', 'wpsl' ); ?></label></td>
                                <td>
                                    <?php
                                    echo '<select id="wpsl-checkbox-columns">';

                                    $i = 1;

                                    while ( $i <= 4 ) {
                                        $selected = ( $i == 3 ) ? "selected='selected'" : ''; // 3 is the default

                                        echo '<option value="' . $i . '" ' . $selected . '>' . $i . '</option>';
                                        $i++;
                                    }

                                    echo '</select>';
                                    ?>
                                </td>
                            </tr>
                            <tr class="wpsl-checkbox-selection wpsl-hide">
                                <td><label for="wpsl-checkbox-columns"><?php _e('Set selected checkboxes', 'wpsl' ); ?></label></td>
                                <td>
                                    <?php
                                    $checkbox_selection = '<select id="wpsl-checkbox-selection" multiple="multiple" autocomplete="off">';

                                    foreach ( $terms as $term ) {
                                        $checkbox_selection .= '<option value="' . esc_attr( $term->slug ) . '">' . esc_html( $term->name ) . '</option>';
                                    }

                                    $checkbox_selection .= '</select>';

                                    echo $checkbox_selection;
                                    ?>
                                </td>
                            </tr>
                            <tr>
                                <td><label for="wpsl-map-type"><?php _e( 'Map type', 'wpsl' ); ?>:</label></td>
                                <td><?php echo $wpsl_admin->settings_page->create_dropdown( 'map_types' ); ?></td>
                            </tr>
                            </tbody>
                        </table>
                    </div>
                    <div id="wpsl-markers-tab">
                        <div class="wpsl-shortcode-markers">
                            <?php echo $wpsl_admin->settings_page->show_marker_options(); ?>
                        </div>
                    </div>
                </div>

                <p class="submit">
                    <input type="button" id="wpsl-insert-shortcode" class="button-primary" value="<?php echo _e( 'Insert Store Locator', 'wpsl' ); ?>" onclick="WPSL_InsertShortcode();" />
                </p>
            </div>

            <?php

            exit();
        }
    }

    new WPSL_Shortcode_Generator();
}admin/roles.php000064400000006521151327220640007477 0ustar00<?php

/**
 * Add WPSL Roles.
 *
 * @since 2.0.0
 * @return void
 */
function wpsl_add_roles() {
    
    global $wp_roles;

    if ( class_exists( 'WP_Roles' ) ) {
        if ( !isset( $wp_roles ) ) {
            $wp_roles = new WP_Roles();
        }
    }

	if ( is_object( $wp_roles ) ) {
		add_role( 'wpsl_store_locator_manager', __( 'Store Locator Manager', 'wpsl' ), array(
			'read'                   => true,
			'edit_posts'             => true,
			'delete_posts'           => true,
			'unfiltered_html'        => true,
			'upload_files'           => true,
			'delete_others_pages'    => true,
			'delete_others_posts'    => true,
			'delete_pages'           => true,
			'delete_private_pages'   => true,
			'delete_private_posts'   => true,
			'delete_published_pages' => true,
			'delete_published_posts' => true,
			'edit_others_pages'      => true,
			'edit_others_posts'      => true,
			'edit_pages'             => true,
			'edit_private_pages'     => true,
			'edit_private_posts'     => true,
			'edit_published_pages'   => true,
			'edit_published_posts'   => true,
			'moderate_comments'      => true,
			'publish_pages'          => true,
			'publish_posts'          => true,
			'read_private_pages'     => true,
			'read_private_posts'     => true
		) );
    }
}

/**
 * Add WPSL user capabilities.
 *
 * @since 2.0.0
 * @return void
 */
function wpsl_add_caps() {
    
    global $wp_roles;

    if ( class_exists( 'WP_Roles' ) ) {
        if ( !isset( $wp_roles ) ) {
            $wp_roles = new WP_Roles();
        }
    }

    if ( is_object( $wp_roles ) ) {
        $wp_roles->add_cap( 'administrator', 'manage_wpsl_settings' );
        
        $capabilities = wpsl_get_post_caps();
        
        foreach ( $capabilities as $cap ) {
            $wp_roles->add_cap( 'wpsl_store_locator_manager', $cap );
            $wp_roles->add_cap( 'administrator',              $cap );
        }
    } 
}

/** 
 * Get the WPSL post type capabilities.
 * 
 * @since 2.0.0
 * @return array $capabilities The post type capabilities
 */
function wpsl_get_post_caps() {

    $capabilities = array(
        'edit_store',
        'read_store',
        'delete_store',
        'edit_stores',
        'edit_others_stores',
        'publish_stores',
        'read_private_stores',
        'delete_stores',
        'delete_private_stores',
        'delete_published_stores',
        'delete_others_stores',
        'edit_private_stores',
        'edit_published_stores'
    );
    
    return $capabilities;
}

/**
 * Remove the WPSL caps and roles.
 * 
 * Only called from uninstall.php
 *
 * @since 2.0.0
 * @return void
 */
function wpsl_remove_caps_and_roles() {
      
    global $wp_roles;

    if ( class_exists( 'WP_Roles' ) ) {
        if ( !isset( $wp_roles ) ) {
            $wp_roles = new WP_Roles();
        }
    }
    
    if ( is_object( $wp_roles ) ) {
        $wp_roles->remove_cap( 'administrator', 'manage_wpsl_settings' );
        
        $capabilities = wpsl_get_post_caps();
        
        foreach ( $capabilities as $cap ) {
            $wp_roles->remove_cap( 'wpsl_store_locator_manager', $cap );
            $wp_roles->remove_cap( 'administrator',              $cap );
        }
    } 
    
    remove_role( 'wpsl_store_locator_manager' ); 
}admin/class-settings.php000064400000166366151327220640011334 0ustar00<?php
/**
 * Handle the plugin settings.
 *
 * @author Tijmen Smit
 * @since  2.0.0
 */

if ( !defined( 'ABSPATH' ) ) exit;

if ( !class_exists( 'WPSL_Settings' ) ) {
    
	class WPSL_Settings {
                        
        public function __construct() {
            
            $this->manually_clear_transient();

            add_action( 'wp_ajax_validate_server_key',        array( $this, 'ajax_validate_server_key' ) );
            add_action( 'wp_ajax_nopriv_validate_server_key', array( $this, 'ajax_validate_server_key' ) );
            add_action( 'admin_init',                         array( $this, 'register_settings' ) );
            add_action( 'admin_init',                         array( $this, 'maybe_flush_rewrite_and_transient' ) );
        }

        /**
         * Determine if we need to clear the autoload transient.
         * 
         * User can do this manually from the 'Tools' section on the settings page. 
         * 
         * @since 2.0.0
         * @return void
         */
        public function manually_clear_transient() {
            
            global $wpsl_admin;
            
            if ( isset( $_GET['action'] ) && $_GET['action'] == 'clear_wpsl_transients' && isset( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( $_REQUEST['_wpnonce'], 'clear_transients' ) ) {
                $wpsl_admin->delete_autoload_transient();
                
                $msg = __( 'WP Store Locator Transients Cleared', 'wpsl' );
                $wpsl_admin->notices->save( 'update', $msg );
                
                /* 
                 * Make sure the &action=clear_wpsl_transients param is removed from the url.
                 * 
                 * Otherwise if the user later clicks the 'Save Changes' button, 
                 * and the &action=clear_wpsl_transients param is still there it 
                 * will show two notices 'WP Store Locator Transients Cleared' and 'Settings Saved'.
                 */
                wp_redirect( admin_url( 'edit.php?post_type=wpsl_stores&page=wpsl_settings' ) );
                exit;
            }
        }

        /**
         * Register the settings.
         * 
         * @since 2.0.0
         * @return void
         */
        public function register_settings() {
            register_setting( 'wpsl_settings', 'wpsl_settings', array( $this, 'sanitize_settings' ) );
        }       
            
        /**
         * Sanitize the submitted plugin settings.
         * 
         * @since 1.0.0
         * @return array $output The setting values
         */
		public function sanitize_settings() {

            global $wpsl_settings, $wpsl_admin;

            $ux_absints = array(
                'height',
                'infowindow_width',
                'search_width',
                'label_width'
            );
            
            $marker_effects = array(
                'bounce',
                'info_window',
                'ignore'
            );
            
            $ux_checkboxes = array(
                'new_window',
                'reset_map',
                'listing_below_no_scroll',
                'direction_redirect',
                'more_info',
                'store_url',
                'phone_url',
                'marker_streetview',
                'marker_zoom_to',
                'mouse_focus',
                'reset_map',
                'show_contact_details',
                'clickable_contact_details',
                'hide_country',
                'hide_distance'
            );

            /*
             * If the provided server key is different then the existing value,
             * then we test if it's valid by making a call to the Geocode API.
             */
            if ( $_POST['wpsl_api']['server_key'] && $wpsl_settings['api_server_key'] != $_POST['wpsl_api']['server_key'] || !get_option( 'wpsl_valid_server_key' ) ) {
                $server_key = sanitize_text_field( $_POST['wpsl_api']['server_key'] );

                $this->validate_server_key( $server_key );
            }

			$output['api_server_key']        = sanitize_text_field( $_POST['wpsl_api']['server_key'] );
            $output['api_browser_key']       = sanitize_text_field( $_POST['wpsl_api']['browser_key'] );
			$output['api_language']          = wp_filter_nohtml_kses( $_POST['wpsl_api']['language'] );
			$output['api_region']            = wp_filter_nohtml_kses( $_POST['wpsl_api']['region'] );
            $output['api_geocode_component'] = isset( $_POST['wpsl_api']['geocode_component'] ) ? 1 : 0;
                        
            // Check the search filter.
            $output['autocomplete']         = isset( $_POST['wpsl_search']['autocomplete'] ) ? 1 : 0;
            $output['results_dropdown']     = isset( $_POST['wpsl_search']['results_dropdown'] ) ? 1 : 0;
            $output['radius_dropdown']      = isset( $_POST['wpsl_search']['radius_dropdown'] ) ? 1 : 0;
            $output['category_filter']      = isset( $_POST['wpsl_search']['category_filter'] ) ? 1 : 0;
            $output['category_filter_type'] = ( $_POST['wpsl_search']['category_filter_type'] == 'dropdown' ) ? 'dropdown' : 'checkboxes';
            
            $output['distance_unit'] = ( $_POST['wpsl_search']['distance_unit'] == 'km' ) ? 'km' : 'mi';
			
			// Check for a valid max results value, otherwise we use the default.
			if ( !empty( $_POST['wpsl_search']['max_results'] ) ) {
				$output['max_results'] = sanitize_text_field( $_POST['wpsl_search']['max_results'] );
			} else {
				$this->settings_error( 'max_results' );
				$output['max_results'] = wpsl_get_default_setting( 'max_results' );
			}
			
			// See if a search radius value exist, otherwise we use the default.
			if ( !empty( $_POST['wpsl_search']['radius'] ) ) {
				$output['search_radius'] = sanitize_text_field( $_POST['wpsl_search']['radius'] );
			} else {
				$this->settings_error( 'search_radius' );
				$output['search_radius'] = wpsl_get_default_setting( 'search_radius' );
			}

            $output['force_postalcode'] = isset( $_POST['wpsl_search']['force_postalcode'] ) ? 1 : 0;

			// Check if we have a valid zoom level, it has to be between 1 or 12. If not set it to the default of 3.
			$output['zoom_level'] = wpsl_valid_zoom_level( $_POST['wpsl_map']['zoom_level'] );	
            
            // Check for a valid max auto zoom level.
            $max_zoom_levels = wpsl_get_max_zoom_levels();
            
            if ( in_array( absint( $_POST['wpsl_map']['max_auto_zoom'] ), $max_zoom_levels ) ) {
                $output['auto_zoom_level'] = $_POST['wpsl_map']['max_auto_zoom'];
            } else {
                $output['auto_zoom_level'] = wpsl_get_default_setting( 'auto_zoom_level' );
            }

            if ( isset( $_POST['wpsl_map']['start_name'] ) ) {
                $output['start_name'] = sanitize_text_field( $_POST['wpsl_map']['start_name'] );
            } else {
                $output['start_name'] = '';
            }

			// If no location name is then we also empty the latlng values from the hidden input field.
			if ( empty( $output['start_name'] ) ) {
				$this->settings_error( 'start_point' );
                $output['start_latlng'] = '';
			} else {

                /*
                 * If the start latlng is empty, but a start location name is provided, 
                 * then make a request to the Geocode API to get it.
                 * 
                 * This can only happen if there is a JS error in the admin area that breaks the
                 * Google Maps Autocomplete. So this code is only used as fallback to make sure
                 * the provided start location is always geocoded.
                 */
                if ( $wpsl_settings['start_name'] != $_POST['wpsl_map']['start_name']
                  && $wpsl_settings['start_latlng'] == $_POST['wpsl_map']['start_latlng']
                  || empty( $_POST['wpsl_map']['start_latlng'] ) ) {
                    $start_latlng = wpsl_get_address_latlng( $_POST['wpsl_map']['start_name'] );
                } else {
                    $start_latlng = sanitize_text_field( $_POST['wpsl_map']['start_latlng'] );
                }
                
				$output['start_latlng'] = $start_latlng;
			}

			// Do we need to run the fitBounds function make the markers fit in the viewport?
            $output['run_fitbounds'] = isset( $_POST['wpsl_map']['run_fitbounds'] ) ? 1 : 0;

			// Check if we have a valid map type.
			$output['map_type']    = wpsl_valid_map_type( $_POST['wpsl_map']['type'] );
            $output['auto_locate'] = isset( $_POST['wpsl_map']['auto_locate'] ) ? 1 : 0; 
            $output['autoload']    = isset( $_POST['wpsl_map']['autoload'] ) ? 1 : 0; 

            // Make sure the auto load limit is either empty or an int.
            if ( empty( $_POST['wpsl_map']['autoload_limit'] ) ) {
                $output['autoload_limit'] = '';
            } else {
                $output['autoload_limit'] = absint( $_POST['wpsl_map']['autoload_limit'] );
            }
     
			$output['streetview'] 		= isset( $_POST['wpsl_map']['streetview'] ) ? 1 : 0;
            $output['type_control']     = isset( $_POST['wpsl_map']['type_control'] ) ? 1 : 0;
            $output['scrollwheel']      = isset( $_POST['wpsl_map']['scrollwheel'] ) ? 1 : 0;	
			$output['control_position'] = ( $_POST['wpsl_map']['control_position'] == 'left' ) ? 'left' : 'right';	
            
            $output['map_style'] = json_encode( strip_tags( trim( $_POST['wpsl_map']['map_style'] ) ) );
                    
            // Make sure we have a valid template ID.
            if ( isset( $_POST['wpsl_ux']['template_id'] ) && ( $_POST['wpsl_ux']['template_id'] ) ) {
				$output['template_id'] = sanitize_text_field( $_POST['wpsl_ux']['template_id'] );
			} else {
				$output['template_id'] = wpsl_get_default_setting( 'template_id' );
			}
            
            $output['marker_clusters'] = isset( $_POST['wpsl_map']['marker_clusters'] ) ? 1 : 0;	
                        
            // Check for a valid cluster zoom value.
            if ( in_array( $_POST['wpsl_map']['cluster_zoom'], $this->get_default_cluster_option( 'cluster_zoom' ) ) ) {
                $output['cluster_zoom'] = $_POST['wpsl_map']['cluster_zoom'];
            } else {
                $output['cluster_zoom'] = wpsl_get_default_setting( 'cluster_zoom' );
            }
            
            // Check for a valid cluster size value.
            if ( in_array( $_POST['wpsl_map']['cluster_size'], $this->get_default_cluster_option( 'cluster_size' ) ) ) {
                $output['cluster_size'] = $_POST['wpsl_map']['cluster_size'];
            } else {
                $output['cluster_size'] = wpsl_get_default_setting( 'cluster_size' );
            }
                        
            /* 
             * Make sure all the ux related fields that should contain an int, actually are an int.
             * Otherwise we use the default value. 
             */
            foreach ( $ux_absints as $ux_key ) {
                if ( absint( $_POST['wpsl_ux'][$ux_key] ) ) {
                    $output[$ux_key] = $_POST['wpsl_ux'][$ux_key];
                } else {
                    $output[$ux_key] = wpsl_get_default_setting( $ux_key );
                }
            }
            
            // Check if the ux checkboxes are checked.
            foreach ( $ux_checkboxes as $ux_key ) {
                $output[$ux_key] = isset( $_POST['wpsl_ux'][$ux_key] ) ? 1 : 0; 
            }
            
            // Check if we have a valid marker effect.
            if ( in_array( $_POST['wpsl_ux']['marker_effect'], $marker_effects ) ) {
                $output['marker_effect'] = $_POST['wpsl_ux']['marker_effect'];
            } else {
				$output['marker_effect'] = wpsl_get_default_setting( 'marker_effect' );
			}
            
            // Check if we have a valid address format.  
            if ( array_key_exists( $_POST['wpsl_ux']['address_format'], wpsl_get_address_formats() ) ) {
                $output['address_format'] = $_POST['wpsl_ux']['address_format'];
            } else {
				$output['address_format'] = wpsl_get_default_setting( 'address_format' );
			}
            
            $output['more_info_location'] = ( $_POST['wpsl_ux']['more_info_location'] == 'store listings' ) ? 'store listings' : 'info window';	
            $output['infowindow_style']   = isset( $_POST['wpsl_ux']['infowindow_style'] ) ? 'default' : 'infobox';
            $output['start_marker']       = wp_filter_nohtml_kses( $_POST['wpsl_map']['start_marker'] );
            $output['store_marker']       = wp_filter_nohtml_kses( $_POST['wpsl_map']['store_marker'] );
			$output['editor_country']     = sanitize_text_field( $_POST['wpsl_editor']['default_country'] );
            $output['editor_map_type']    = wpsl_valid_map_type( $_POST['wpsl_editor']['map_type'] );
            $output['hide_hours']         = isset( $_POST['wpsl_editor']['hide_hours'] ) ? 1 : 0; 
            
            if ( isset( $_POST['wpsl_editor']['hour_input'] ) ) {
				$output['editor_hour_input'] = ( $_POST['wpsl_editor']['hour_input'] == 'textarea' ) ? 'textarea' : 'dropdown';	
			} else {
				$output['editor_hour_input'] = 'dropdown';
			}
            
            $output['editor_hour_format'] = ( $_POST['wpsl_editor']['hour_format'] == 12 ) ? 12 : 24;
            
            // The default opening hours.
            if ( isset( $_POST['wpsl_editor']['textarea'] ) ) {
                $output['editor_hours']['textarea'] = wp_kses_post( trim( stripslashes( $_POST['wpsl_editor']['textarea'] ) ) );
            }
            
            $output['editor_hours']['dropdown'] = $wpsl_admin->metaboxes->format_opening_hours();
            array_walk_recursive( $output['editor_hours']['dropdown'], 'wpsl_sanitize_multi_array' );  
            
            // Permalink and taxonomy slug.
            $output['permalinks'] = isset( $_POST['wpsl_permalinks']['active'] ) ? 1 : 0;
            $output['permalink_remove_front'] = isset( $_POST['wpsl_permalinks']['remove_front'] ) ? 1 : 0;
            
            if ( !empty( $_POST['wpsl_permalinks']['slug'] ) ) {
				$output['permalink_slug'] = sanitize_text_field( $_POST['wpsl_permalinks']['slug'] );
			} else {
				$output['permalink_slug'] = wpsl_get_default_setting( 'permalink_slug' );
			}
            
            if ( !empty( $_POST['wpsl_permalinks']['category_slug'] ) ) {
				$output['category_slug'] = sanitize_text_field( $_POST['wpsl_permalinks']['category_slug'] );
			} else {
				$output['category_slug'] = wpsl_get_default_setting( 'category_slug' );
			}
                                    
			$required_labels = wpsl_labels();
            
			// Sanitize the labels.
			foreach ( $required_labels as $label ) {
                $output[$label.'_label'] = sanitize_text_field( $_POST['wpsl_label'][$label] );
			}

            $output['show_credits']     = isset( $_POST['wpsl_credits'] ) ? 1 : 0;
            $output['debug']            = isset( $_POST['wpsl_tools']['debug'] ) ? 1 : 0;
            $output['deregister_gmaps'] = isset( $_POST['wpsl_tools']['deregister_gmaps'] ) ? 1 : 0;
            $output['delay_loading']    = isset( $_POST['wpsl_tools']['delay_loading'] ) ? 1 : 0;

            // Check if we need to flush the permalinks.
            $this->set_flush_rewrite_option( $output );           
  
            // Check if there is a reason to delete the autoload transient.
            if ( $wpsl_settings['autoload'] ) {
                $this->set_delete_transient_option( $output );
            }
            
			return $output;
		}

        /**
         * Handle the AJAX call to validate the provided
         * server key for the Google Maps API.
         *
         * @since 2.2.10
         * @return void
         */
        public function ajax_validate_server_key() {

            if ( ( current_user_can( 'manage_wpsl_settings' ) ) && is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX  ) {
                $server_key = sanitize_text_field( $_GET['server_key'] );

                if ( $server_key ) {
                    $this->validate_server_key( $server_key );
                }
            }
        }

        /**
         * Check if the provided server key for
         * the Google Maps API is valid.
         *
         * @since 2.2.10
         * @param string $server_key The server key to validate
         * @return json|void If the validation failed and AJAX is used, then json
         */
        public function validate_server_key( $server_key ) {

            global $wpsl_admin;

            // Test the server key by making a request to the Geocode API.
            $address  = 'Manhattan, NY 10036, USA';
            $url      = 'https://maps.googleapis.com/maps/api/geocode/json?address=' . urlencode( $address ) .'&key=' . $server_key;
            $response = wp_remote_get( $url );

            if ( !is_wp_error( $response ) ) {
                $response = json_decode( $response['body'], true );

                // If the state is not OK, then there's a problem with the key.
                if ( $response['status'] !== 'OK' ) {
                    $geocode_errors = $wpsl_admin->geocode->check_geocode_error_msg( $response, true );

                    $error_msg = sprintf( __( 'There\'s a problem with the provided %sserver key%s. %s' ), '<a href="https://wpstorelocator.co/document/create-google-api-keys/#server-key">', '</a>', $geocode_errors );

                    update_option( 'wpsl_valid_server_key', 0 );

                    // If the server key input field has 'wpsl-validate-me' class on it, then it's validated with AJAX in the background.
                    if ( defined('DOING_AJAX' ) && DOING_AJAX ) {
                        $key_status = array(
                            'valid' => 0,
                            'msg'   => $error_msg
                        );

                        wp_send_json( $key_status );

                        exit();
                    } else {
                        add_settings_error( 'setting-errors', esc_attr( 'server-key' ), $error_msg, 'error' );
                    }
                } else {
                    update_option( 'wpsl_valid_server_key', 1 );

                    if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
                        $key_status = array(
                            'valid' => 1,
                            'msg'   => __( 'No problems found with the server key.', 'wpsl' )
                        );

                        wp_send_json( $key_status );

                        exit();
                    }
                }
            }
        }

        /**
         * Check if we need set the option that will be used to determine 
         * if we need to flush the permalinks once the setting page reloads.
         * 
         * @since 2.0.0
         * @param array $new_settings The submitted plugin settings
         * @return void
         */
        public function set_flush_rewrite_option( $new_settings ) {
            
            global $wpsl_settings;
            
            // The settings fields to check.
            $fields = array( 'permalinks', 'permalink_slug', 'permalink_remove_front', 'category_slug' );

            foreach ( $fields as $k => $field ) {
                if ( $wpsl_settings[$field] != $new_settings[$field] ) {
                update_option( 'wpsl_flush_rewrite', 1 );

                    break;
                }
            }
        }
        
        /**
         * Check if we need set the option that is used to determine 
         * if we need to delete the autoload transient once the settings page reloads.
         * 
         * @since 2.0.0
         * @param array $new_settings The submitted plugin settings
         * @return void
         */
        public function set_delete_transient_option( $new_settings ) {

            global $wpsl_settings;

            // The options we need to check for changes.
            $options = array(
                'start_name',
                'debug',
                'autoload', 
                'autoload_limit', 
                'more_info', 
                'more_info_location', 
                'hide_hours',
                'hide_distance',
                'hide_country',
                'show_contact_details'
            );

            foreach ( $options as $option_name ) {
                if ( $wpsl_settings[$option_name] != $new_settings[$option_name] ) {
                    update_option( 'wpsl_delete_transient', 1 );
                    break;
                }
            }
        }

        /**
         * Check if the permalinks settings changed.
         * 
         * @since 2.0.0
         * @return void
         */
        public function maybe_flush_rewrite_and_transient() {

            global $wpsl_admin;
            
            if ( isset( $_GET['page'] ) && ( $_GET['page'] == 'wpsl_settings' ) ) {
                $flush_rewrite    = get_option( 'wpsl_flush_rewrite' );
                $delete_transient = get_option( 'wpsl_delete_transient' );
                
                if ( $flush_rewrite ) {
                    flush_rewrite_rules();
                    update_option( 'wpsl_flush_rewrite', 0 );
                }
                
                if ( $delete_transient ) {
                    update_option( 'wpsl_delete_transient', 0 );
                }
                
                if ( $flush_rewrite || $delete_transient ) {
                    $wpsl_admin->delete_autoload_transient();     
                }
            }
        }

        /**
         * Handle the different validation errors for the plugin settings.
         * 
         * @since 1.0.0
         * @param string $error_type Contains the type of validation error that occured
         * @return void
         */
		private function settings_error( $error_type ) {
            
			switch ( $error_type ) {
				case 'max_results':
					$error_msg = __( 'The max results field cannot be empty, the default value has been restored.', 'wpsl' );	
					break;
				case 'search_radius':
					$error_msg = __( 'The search radius field cannot be empty, the default value has been restored.', 'wpsl' );	
					break;	
                case 'start_point':
					$error_msg = sprintf( __( 'Please provide the name of a city or country that can be used as a starting point under "Map Settings". %s This will only be used if auto-locating the user fails, or the option itself is disabled.', 'wpsl' ), '<br><br>' );
					break;
			}
			
			add_settings_error( 'setting-errors', esc_attr( 'settings_fail' ), $error_msg, 'error' );
		}
        
        /**
         * Options for the language and region list.
         *
         * @since 1.0.0
         * @param  string      $list        The request list type
         * @return string|void $option_list The html for the selected list, or nothing if the $list contains invalud values
         */
		public function get_api_option_list( $list ) {
            
            global $wpsl_settings;
            
			switch ( $list ) {
				case 'language':	
					$api_option_list = array ( 	
						__('Select your language', 'wpsl')    => '',
						__('English', 'wpsl')                 => 'en',
						__('Arabic', 'wpsl')                  => 'ar',
						__('Basque', 'wpsl')                  => 'eu',
						__('Bulgarian', 'wpsl')               => 'bg',
						__('Bengali', 'wpsl')                 => 'bn',
						__('Catalan', 'wpsl')                 => 'ca',
						__('Czech', 'wpsl')                   => 'cs',
						__('Danish', 'wpsl')                  => 'da',
						__('German', 'wpsl')                  => 'de',
						__('Greek', 'wpsl')                   => 'el',
						__('English (Australian)', 'wpsl')    => 'en-AU',
						__('English (Great Britain)', 'wpsl') => 'en-GB',
						__('Spanish', 'wpsl')                 => 'es',
						__('Farsi', 'wpsl')                   => 'fa',
						__('Finnish', 'wpsl')                 => 'fi',
						__('Filipino', 'wpsl')                => 'fil',
						__('French', 'wpsl')                  => 'fr',
						__('Galician', 'wpsl')                => 'gl',
						__('Gujarati', 'wpsl')                => 'gu',
						__('Hindi', 'wpsl')                   => 'hi',
						__('Croatian', 'wpsl')                => 'hr',
						__('Hungarian', 'wpsl')               => 'hu',
						__('Indonesian', 'wpsl')              => 'id',
						__('Italian', 'wpsl')                 => 'it',
						__('Hebrew', 'wpsl')                  => 'iw',
						__('Japanese', 'wpsl')                => 'ja',
						__('Kannada', 'wpsl')                 => 'kn',
						__('Korean', 'wpsl')                  => 'ko',
						__('Lithuanian', 'wpsl')              => 'lt',
						__('Latvian', 'wpsl')                 => 'lv',
						__('Malayalam', 'wpsl')               => 'ml',
						__('Marathi', 'wpsl')                 => 'mr',
						__('Dutch', 'wpsl')                   => 'nl',
						__('Norwegian', 'wpsl')               => 'no',
						__('Norwegian Nynorsk', 'wpsl')       => 'nn',
						__('Polish', 'wpsl')                  => 'pl',
						__('Portuguese', 'wpsl')              => 'pt',
						__('Portuguese (Brazil)', 'wpsl')     => 'pt-BR',
						__('Portuguese (Portugal)', 'wpsl')   => 'pt-PT',
						__('Romanian', 'wpsl')                => 'ro',
						__('Russian', 'wpsl')                 => 'ru',
						__('Slovak', 'wpsl')                  => 'sk',
						__('Slovenian', 'wpsl')               => 'sl',
						__('Serbian', 'wpsl')                 => 'sr',
						__('Swedish', 'wpsl')                 => 'sv',
						__('Tagalog', 'wpsl')                 => 'tl',
						__('Tamil', 'wpsl')                   => 'ta',
						__('Telugu', 'wpsl')                  => 'te',
						__('Thai', 'wpsl')                    => 'th',
						__('Turkish', 'wpsl')                 => 'tr',
						__('Ukrainian', 'wpsl')               => 'uk',
						__('Vietnamese', 'wpsl')              => 'vi',
						__('Chinese (Simplified)', 'wpsl')    => 'zh-CN',
						__('Chinese (Traditional)' ,'wpsl')   => 'zh-TW'
				);	
					break;			
				case 'region':
                    $api_option_list = array (
                        __('Select your region', 'wpsl')               => '',
                        __('Afghanistan', 'wpsl')                      => 'af',
                        __('Albania', 'wpsl')                          => 'al',
                        __('Algeria', 'wpsl')                          => 'dz',
                        __('American Samoa', 'wpsl')                   => 'as',
                        __('Andorra', 'wpsl')                          => 'ad',
                        __('Angola', 'wpsl')                           => 'ao',
                        __('Anguilla', 'wpsl')                         => 'ai',
                        __('Antarctica', 'wpsl')                       => 'aq',
                        __('Antigua and Barbuda', 'wpsl')              => 'ag',
                        __('Argentina', 'wpsl')                        => 'ar',
                        __('Armenia', 'wpsl')                          => 'am',
                        __('Aruba', 'wpsl')                            => 'aw',
                        __('Ascension Island', 'wpsl')                 => 'ac',
                        __('Australia', 'wpsl')                        => 'au',
                        __('Austria', 'wpsl')                          => 'at',
                        __('Azerbaijan', 'wpsl')                       => 'az',
                        __('Bahamas', 'wpsl')                          => 'bs',
                        __('Bahrain', 'wpsl')                          => 'bh',
                        __('Bangladesh', 'wpsl')                       => 'bd',
                        __('Barbados', 'wpsl')                         => 'bb',
                        __('Belarus', 'wpsl')                          => 'by',
                        __('Belgium', 'wpsl')                          => 'be',
                        __('Belize', 'wpsl')                           => 'bz',
                        __('Benin', 'wpsl')                            => 'bj',
                        __('Bermuda', 'wpsl')                          => 'bm',
                        __('Bhutan', 'wpsl')                           => 'bt',
                        __('Bolivia', 'wpsl')                          => 'bo',
                        __('Bosnia and Herzegovina', 'wpsl')           => 'ba',
                        __('Botswana', 'wpsl')                         => 'bw',
                        __('Bouvet Island', 'wpsl')                    => 'bv',
                        __('Brazil', 'wpsl')                           => 'br',
                        __('British Indian Ocean Territory', 'wpsl')   => 'io',
                        __('British Virgin Islands', 'wpsl')           => 'vg',
                        __('Brunei', 'wpsl')                           => 'bn',
                        __('Bulgaria', 'wpsl')                         => 'bg',
                        __('Burkina Faso', 'wpsl')                     => 'bf',
                        __('Burundi', 'wpsl')                          => 'bi',
                        __('Cambodia', 'wpsl')                         => 'kh',
                        __('Cameroon', 'wpsl')                         => 'cm',
                        __('Canada', 'wpsl')                           => 'ca',
                        __('Canary Islands', 'wpsl')                   => 'ic',
                        __('Cape Verde', 'wpsl')                       => 'cv',
                        __('Caribbean Netherlands', 'wpsl')            => 'bq',
                        __('Cayman Islands', 'wpsl')                   => 'ky',
                        __('Central African Republic', 'wpsl')         => 'cf',
                        __('Ceuta and Melilla', 'wpsl')                => 'ea',
                        __('Chad', 'wpsl')                             => 'td',
                        __('Chile', 'wpsl')                            => 'cl',
                        __('China', 'wpsl')                            => 'cn',
                        __('Christmas Island', 'wpsl')                 => 'cx',
                        __('Clipperton Island', 'wpsl')                => 'cp',
                        __('Cocos (Keeling) Islands', 'wpsl')          => 'cc',
                        __('Colombia', 'wpsl')                         => 'co',
                        __('Comoros', 'wpsl')                          => 'km',
                        __('Congo (DRC)', 'wpsl')                       => 'cd',
                        __('Congo (Republic)', 'wpsl')                 => 'cg',
                        __('Cook Islands', 'wpsl')                     => 'ck',
                        __('Costa Rica', 'wpsl')                       => 'cr',
                        __('Croatia', 'wpsl')                          => 'hr',
                        __('Cuba', 'wpsl')                             => 'cu',
                        __('Curaçao', 'wpsl')                          => 'cw',
                        __('Cyprus', 'wpsl')                           => 'cy',
                        __('Czech Republic', 'wpsl')                   => 'cz',
                        __('Côte d\'Ivoire', 'wpsl')                   => 'ci',
                        __('Denmark', 'wpsl')                          => 'dk',
                        __('Djibouti', 'wpsl')                         => 'dj',
                        __('Democratic Republic of the Congo', 'wpsl') => 'cd',
                        __('Dominica', 'wpsl')                         => 'dm',
                        __('Dominican Republic', 'wpsl')               => 'do',
                        __('Ecuador', 'wpsl')                          => 'ec',
                        __('Egypt', 'wpsl')                            => 'eg',
                        __('El Salvador', 'wpsl')                      => 'sv',
                        __('Equatorial Guinea', 'wpsl')                => 'gq',
                        __('Eritrea', 'wpsl')                          => 'er',
                        __('Estonia', 'wpsl')                          => 'ee',
                        __('Ethiopia', 'wpsl')                         => 'et',
                        __('Falkland Islands(Islas Malvinas)', 'wpsl') => 'fk',
                        __('Faroe Islands', 'wpsl')                    => 'fo',
                        __('Fiji', 'wpsl')                             => 'fj',
                        __('Finland', 'wpsl')                          => 'fi',
                        __('France', 'wpsl')                           => 'fr',
                        __('French Guiana', 'wpsl')                    => 'gf',
                        __('French Polynesia', 'wpsl')                 => 'pf',
                        __('French Southern Territories', 'wpsl')      => 'tf',
                        __('Gabon', 'wpsl')                            => 'ga',
                        __('Gambia', 'wpsl')                           => 'gm',
                        __('Georgia', 'wpsl')                          => 'ge',
                        __('Germany', 'wpsl')                          => 'de',
                        __('Ghana', 'wpsl')                            => 'gh',
                        __('Gibraltar', 'wpsl')                        => 'gi',
                        __('Greece', 'wpsl')                           => 'gr',
                        __('Greenland', 'wpsl')                        => 'gl',
                        __('Grenada', 'wpsl')                          => 'gd',
                        __('Guam', 'wpsl')                             => 'gu',
                        __('Guadeloupe', 'wpsl')                       => 'gp',
                        __('Guam', 'wpsl')                             => 'gu',
                        __('Guatemala', 'wpsl')                        => 'gt',
                        __('Guernsey', 'wpsl')                         => 'gg',
                        __('Guinea', 'wpsl')                           => 'gn',
                        __('Guinea-Bissau', 'wpsl')                    => 'gw',
                        __('Guyana', 'wpsl')                           => 'gy',
                        __('Haiti', 'wpsl')                            => 'ht',
                        __('Heard and McDonald Islands', 'wpsl')       => 'hm',
                        __('Honduras', 'wpsl')                         => 'hn',
                        __('Hong Kong', 'wpsl')                        => 'hk',
                        __('Hungary', 'wpsl')                          => 'hu',
                        __('Iceland', 'wpsl')                          => 'is',
                        __('India', 'wpsl')                            => 'in',
                        __('Indonesia', 'wpsl')                        => 'id',
                        __('Iran', 'wpsl')                             => 'ir',
                        __('Iraq', 'wpsl')                             => 'iq',
                        __('Ireland', 'wpsl')                          => 'ie',
                        __('Isle of Man', 'wpsl')                      => 'im',
                        __('Israel', 'wpsl')                           => 'il',
                        __('Italy', 'wpsl')                            => 'it',
                        __('Jamaica', 'wpsl')                          => 'jm',
                        __('Japan', 'wpsl')                            => 'jp',
                        __('Jersey', 'wpsl')                           => 'je',
                        __('Jordan', 'wpsl')                           => 'jo',
                        __('Kazakhstan', 'wpsl')                       => 'kz',
                        __('Kenya', 'wpsl')                            => 'ke',
                        __('Kiribati', 'wpsl')                         => 'ki',
                        __('Kosovo', 'wpsl')                           => 'xk',
                        __('Kuwait', 'wpsl')                           => 'kw',
                        __('Kyrgyzstan', 'wpsl')                       => 'kg',
                        __('Laos', 'wpsl')                             => 'la',
                        __('Latvia', 'wpsl')                           => 'lv',
                        __('Lebanon', 'wpsl')                          => 'lb',
                        __('Lesotho', 'wpsl')                          => 'ls',
                        __('Liberia', 'wpsl')                          => 'lr',
                        __('Libya', 'wpsl')                            => 'ly',
                        __('Liechtenstein', 'wpsl')                    => 'li',
                        __('Lithuania', 'wpsl')                        => 'lt',
                        __('Luxembourg', 'wpsl')                       => 'lu',
                        __('Macau', 'wpsl')                            => 'mo',
                        __('Macedonia (FYROM)', 'wpsl')                => 'mk',
                        __('Madagascar', 'wpsl')                       => 'mg',
                        __('Malawi', 'wpsl')                           => 'mw',
                        __('Malaysia ', 'wpsl')                        => 'my',
                        __('Maldives ', 'wpsl')                        => 'mv',
                        __('Mali', 'wpsl')                             => 'ml',
                        __('Malta', 'wpsl')                            => 'mt',
                        __('Marshall Islands', 'wpsl')                 => 'mh',
                        __('Martinique', 'wpsl')                       => 'mq',
                        __('Mauritania', 'wpsl')                       => 'mr',
                        __('Mauritius', 'wpsl')                        => 'mu',
                        __('Mayotte', 'wpsl')                          => 'yt',
                        __('Mexico', 'wpsl')                           => 'mx',
                        __('Micronesia', 'wpsl')                       => 'fm',
                        __('Moldova', 'wpsl')                          => 'md',
                        __('Monaco' ,'wpsl')                           => 'mc',
                        __('Mongolia', 'wpsl')                         => 'mn',
                        __('Montenegro', 'wpsl')                       => 'me',
                        __('Montserrat', 'wpsl')                       => 'ms',
                        __('Morocco', 'wpsl')                          => 'ma',
                        __('Mozambique', 'wpsl')                       => 'mz',
                        __('Myanmar (Burma)', 'wpsl')                  => 'mm',
                        __('Namibia', 'wpsl')                          => 'na',
                        __('Nauru', 'wpsl')                            => 'nr',
                        __('Nepal', 'wpsl')                            => 'np',
                        __('Netherlands', 'wpsl')                      => 'nl',
                        __('Netherlands Antilles', 'wpsl')             => 'an',
                        __('New Caledonia', 'wpsl')                    => 'nc',
                        __('New Zealand', 'wpsl')                      => 'nz',
                        __('Nicaragua', 'wpsl')                        => 'ni',
                        __('Niger', 'wpsl')                            => 'ne',
                        __('Nigeria', 'wpsl')                          => 'ng',
                        __('Niue', 'wpsl')                             => 'nu',
                        __('Norfolk Island', 'wpsl')                   => 'nf',
                        __('North Korea', 'wpsl')                      => 'kp',
                        __('Northern Mariana Islands', 'wpsl')         => 'mp',
                        __('Norway', 'wpsl')                           => 'no',
                        __('Oman', 'wpsl')                             => 'om',
                        __('Pakistan', 'wpsl')                         => 'pk',
                        __('Palau', 'wpsl')                            => 'pw',
                        __('Palestine', 'wpsl')                        => 'ps',
                        __('Panama' ,'wpsl')                           => 'pa',
                        __('Papua New Guinea', 'wpsl')                 => 'pg',
                        __('Paraguay' ,'wpsl')                         => 'py',
                        __('Peru', 'wpsl')                             => 'pe',
                        __('Philippines', 'wpsl')                      => 'ph',
                        __('Pitcairn Islands', 'wpsl')                 => 'pn',
                        __('Poland', 'wpsl')                           => 'pl',
                        __('Portugal', 'wpsl')                         => 'pt',
                        __('Puerto Rico', 'wpsl')                      => 'pr',
                        __('Qatar', 'wpsl')                            => 'qa',
                        __('Reunion', 'wpsl')                          => 're',
                        __('Romania', 'wpsl')                          => 'ro',
                        __('Russia', 'wpsl')                           => 'ru',
                        __('Rwanda', 'wpsl')                           => 'rw',
                        __('Saint Helena', 'wpsl')                     => 'sh',
                        __('Saint Kitts and Nevis', 'wpsl')            => 'kn',
                        __('Saint Vincent and the Grenadines', 'wpsl') => 'vc',
                        __('Saint Lucia', 'wpsl')                      => 'lc',
                        __('Samoa', 'wpsl')                            => 'ws',
                        __('San Marino', 'wpsl')                       => 'sm',
                        __('São Tomé and Príncipe', 'wpsl')            => 'st',
                        __('Saudi Arabia', 'wpsl')                     => 'sa',
                        __('Senegal', 'wpsl')                          => 'sn',
                        __('Serbia', 'wpsl')                           => 'rs',
                        __('Seychelles', 'wpsl')                       => 'sc',
                        __('Sierra Leone', 'wpsl')                     => 'sl',
                        __('Singapore', 'wpsl')                        => 'sg',
                        __('Sint Maarten', 'wpsl')                     => 'sx',
                        __('Slovakia', 'wpsl')                         => 'sk',
                        __('Slovenia', 'wpsl')                         => 'si',
                        __('Solomon Islands', 'wpsl')                  => 'sb',
                        __('Somalia', 'wpsl')                          => 'so',
                        __('South Africa', 'wpsl')                     => 'za',
                        __('South Georgia and South Sandwich Islands', 'wpsl') => 'gs',
                        __('South Korea', 'wpsl')                      => 'kr',
                        __('South Sudan', 'wpsl')                      => 'ss',
                        __('Spain', 'wpsl')                            => 'es',
                        __('Sri Lanka', 'wpsl')                        => 'lk',
                        __('Sudan', 'wpsl')                            => 'sd',
                        __('Swaziland', 'wpsl')                        => 'sz',
                        __('Sweden', 'wpsl')                           => 'se',
                        __('Switzerland', 'wpsl')                      => 'ch',
                        __('Syria', 'wpsl')                            => 'sy',
                        __('São Tomé & Príncipe', 'wpsl')              => 'st',
                        __('Taiwan', 'wpsl')                           => 'tw',
                        __('Tajikistan', 'wpsl')                       => 'tj',
                        __('Tanzania', 'wpsl')                         => 'tz',
                        __('Thailand', 'wpsl')                         => 'th',
                        __('Timor-Leste', 'wpsl')                      => 'tl',
                        __('Tokelau' ,'wpsl')                          => 'tk',
                        __('Togo', 'wpsl')                             => 'tg',
                        __('Tokelau' ,'wpsl')                          => 'tk',
                        __('Tonga', 'wpsl')                            => 'to',
                        __('Trinidad and Tobago', 'wpsl')              => 'tt',
                        __('Tristan da Cunha', 'wpsl')                 => 'ta',
                        __('Tunisia', 'wpsl')                          => 'tn',
                        __('Turkey', 'wpsl')                           => 'tr',
                        __('Turkmenistan', 'wpsl')                     => 'tm',
                        __('Turks and Caicos Islands', 'wpsl')         => 'tc',
                        __('Tuvalu', 'wpsl')                           => 'tv',
                        __('Uganda', 'wpsl')                           => 'ug',
                        __('Ukraine', 'wpsl')                          => 'ua',
                        __('United Arab Emirates', 'wpsl')             => 'ae',
                        __('United Kingdom', 'wpsl')                   => 'gb',
                        __('United States', 'wpsl')                    => 'us',
                        __('Uruguay', 'wpsl')                          => 'uy',
                        __('Uzbekistan', 'wpsl')                       => 'uz',
                        __('Vanuatu', 'wpsl')                          => 'vu',
                        __('Vatican City', 'wpsl')                     => 'va',
                        __('Venezuela', 'wpsl')                        => 've',
                        __('Vietnam', 'wpsl')                          => 'vn',
                        __('Wallis Futuna', 'wpsl')                    => 'wf',
                        __('Western Sahara', 'wpsl')                   => 'eh',
                        __('Yemen', 'wpsl')                            => 'ye',
                        __('Zambia' ,'wpsl')                           => 'zm',
                        __('Zimbabwe', 'wpsl')                         => 'zw',
                        __('Åland Islands', 'wpsl')                    => 'ax'
                    );
			}
			
			// Make sure we have an array with a value.
			if ( !empty( $api_option_list ) && ( is_array( $api_option_list ) ) ) {
                $option_list = '';
				$i = 0;
				
				foreach ( $api_option_list as $api_option_key => $api_option_value ) {  
				
					// If no option value exist, set the first one as selected.
					if ( ( $i == 0 ) && ( empty( $wpsl_settings['api_'.$list] ) ) ) {
						$selected = 'selected="selected"';
					} else {
						$selected = ( $wpsl_settings['api_'.$list] == $api_option_value ) ? 'selected="selected"' : '';
					}
					
					$option_list .= '<option value="' . esc_attr( $api_option_value ) . '" ' . $selected . '>' . esc_html( $api_option_key ) . '</option>';
					$i++;
				}
												
				return $option_list;				
			}
		}
        
        /**
         * Create the dropdown to select the zoom level.
         *
         * @since 1.0.0
         * @return string $dropdown The html for the zoom level list
         */
		public function show_zoom_levels() {
            
            global $wpsl_settings;
                        
			$dropdown = '<select id="wpsl-zoom-level" name="wpsl_map[zoom_level]" autocomplete="off">';
			
			for ( $i = 1; $i < 13; $i++ ) {
				$selected = ( $wpsl_settings['zoom_level'] == $i ) ? 'selected="selected"' : '';
				
				switch ( $i ) {
					case 1:
						$zoom_desc = ' - ' . __( 'World view', 'wpsl' );
						break;
					case 3:
						$zoom_desc = ' - ' . __( 'Default', 'wpsl' );
						break;
					case 12:
						$zoom_desc = ' - ' . __( 'Roadmap', 'wpsl' );
						break;	
					default:
						$zoom_desc = '';		
				}
		
				$dropdown .= "<option value='$i' $selected>". $i . esc_html( $zoom_desc ) . "</option>";	
			}
				
			$dropdown .= "</select>";
				
			return $dropdown;
		}
        
        /**
         * Create the html output for the marker list that is shown on the settings page.
         * 
         * There are two markers lists, one were the user can set the marker for the start point 
         * and one were a marker can be set for the store. We also check if the marker img is identical
         * to the name in the option field. If so we set it to checked.
         *
         * @since 1.0.0
         * @param  string $marker_img  The filename of the marker
         * @param  string $location    Either contains "start" or "store"
         * @return string $marker_list A list of all the available markers
         */
        public function create_marker_html( $marker_img, $location ) {

            global $wpsl_settings;

            $marker_path = ( defined( 'WPSL_MARKER_URI' ) ) ? WPSL_MARKER_URI : WPSL_URL . 'img/markers/';
            $marker_list = '';

            if ( $wpsl_settings[$location.'_marker'] == $marker_img ) {
                $checked   = 'checked="checked"';
                $css_class = 'class="wpsl-active-marker"';
            } else {
                $checked   = '';
                $css_class = '';
            }
            
            $marker_list .= '<li ' . $css_class . '>';
            $marker_list .= '<img src="' . $marker_path . $marker_img . '" />';
            $marker_list .= '<input ' . $checked . ' type="radio" name="wpsl_map[' . $location . '_marker]"  value="' . $marker_img . '" />';
            $marker_list .= '</li>';

            return $marker_list;
        }
        
        /**
         * Get the default values for the marker clusters dropdown options.
         *
         * @since 1.2.20
         * @param  string $type           The cluster option type
         * @return string $cluster_values The default cluster options
         */
		public function get_default_cluster_option( $type ) {
            
            $cluster_values = array(
                'cluster_zoom' => array(
                    '7',
                    '8',
                    '9',
                    '10',
                    '11',
                    '12',
                    '13'
                ),
                'cluster_size' => array(
                    '40',
                    '50',
                    '60',
                    '70',
                    '80'
                ), 
            );
            
            return $cluster_values[$type];
        }
        
        /**
         * Create a dropdown for the marker cluster options.
         *
         * @since 1.2.20
         * @param  string $type     The cluster option type
         * @return string $dropdown The html for the distance option list
         */
		public function show_cluster_options( $type ) {
            
            global $wpsl_settings;
            
			$cluster_options = array(
                'cluster_zoom' => array(
                    'id'      => 'wpsl-marker-zoom',
                    'name'    => 'cluster_zoom',
                    'options' => $this->get_default_cluster_option( $type )
                 ),
                'cluster_size' => array(
                    'id'      => 'wpsl-marker-cluster-size',
                    'name'    => 'cluster_size',
                    'options' => $this->get_default_cluster_option( $type )
                ),
			);
            
			$dropdown = '<select id="' . esc_attr( $cluster_options[$type]['id'] ) . '" name="wpsl_map[' . esc_attr( $cluster_options[$type]['name'] ) . ']" autocomplete="off">';
			
            $i = 0;
			foreach ( $cluster_options[$type]['options'] as $item => $value ) {
				$selected = ( $wpsl_settings[$type] == $value ) ? 'selected="selected"' : '';
                
                if ( $i == 0 ) {
                    $dropdown .= "<option value='0' $selected>" . __( 'Default', 'wpsl' ) . "</option>";
                } else {
                    $dropdown .= "<option value=". absint( $value ) . " $selected>" . absint( $value ) . "</option>";
                }
                    
                $i++;
			}
			
			$dropdown .= "</select>";
			
			return $dropdown;			
		}
        
        /**
         * Show the options of the start and store markers.
         *
         * @since 1.0.0
         * @return string $marker_list The complete list of available and selected markers
         */
        public function show_marker_options() {

            $marker_list      = '';
            $marker_images    = $this->get_available_markers();
            $marker_locations = array( 
                'start', 
                'store' 
            );

            foreach ( $marker_locations as $location ) {
                if ( $location == 'start' ) {
                    $marker_list .= __( 'Start location marker', 'wpsl' ) . ':';
                } else  {
                    $marker_list .= __( 'Store location marker', 'wpsl' ) . ':'; 
                }

                if ( !empty( $marker_images ) ) {
                    $marker_list .= '<ul class="wpsl-marker-list">';

                    foreach ( $marker_images as $marker_img ) {
                        $marker_list .= $this->create_marker_html( $marker_img, $location );
                    }

                    $marker_list .= '</ul>';
                }
            }

            return $marker_list;
        }

        /**
         * Load the markers that are used on the map.
         *
         * @since 1.0.0
         * @return array $marker_images A list of all the available markers.
         */
        public function get_available_markers() {
            
            $marker_images = array();
            $dir           = apply_filters( 'wpsl_admin_marker_dir', WPSL_PLUGIN_DIR . 'img/markers/' );
            
            if ( is_dir( $dir ) ) {
                if ( $dh = opendir( $dir ) ) {
                    while ( false !== ( $file = readdir( $dh ) ) ) {
                        if ( $file == '.' || $file == '..' || ( strpos( $file, '@2x' ) !== false ) ) continue;
                        $marker_images[] = $file;
                    }

                    closedir( $dh );
                }
            }
            
            return $marker_images;
        }
        
        /**
         * Show a list of available templates.
         *
         * @since 1.2.20
         * @return string $dropdown The html for the template option list
         */
        public function show_template_options() {
            
            global $wpsl_settings;
            
			$dropdown = '<select id="wpsl-store-template" name="wpsl_ux[template_id]" autocomplete="off">';

            foreach ( wpsl_get_templates() as $template ) {
                $template_id = ( isset( $template['id'] ) ) ? $template['id'] : '';
                
				$selected = ( $wpsl_settings['template_id'] == $template_id ) ? ' selected="selected"' : '';
				$dropdown .= "<option value='" . esc_attr( $template_id ) . "' $selected>" . esc_html( $template['name'] ) . "</option>";
            }
			
			$dropdown .= '</select>';
			
			return $dropdown;            
        }
        
        /**
         * Create dropdown lists.
         * 
         * @since 2.0.0
         * @param  string $type     The type of dropdown
         * @return string $dropdown The html output for the dropdown
         */
        public function create_dropdown( $type ) {
            
            global $wpsl_settings;
            
			$dropdown_lists = apply_filters( 'wpsl_setting_dropdowns', array(
                'hour_input' => array(
                    'values' => array(
                        'textarea' => __( 'Textarea', 'wpsl' ), 
                        'dropdown' => __( 'Dropdowns (recommended)', 'wpsl' )
                     ),
                    'id'       => 'wpsl-editor-hour-input',
                    'name'     => 'wpsl_editor[hour_input]',
                    'selected' => $wpsl_settings['editor_hour_input']
                ),
                'marker_effects' => array(
                    'values' => array(
                        'bounce'      => __( 'Bounces up and down', 'wpsl' ),
                        'info_window' => __( 'Will open the info window', 'wpsl' ),
                        'ignore'      => __( 'Does not respond', 'wpsl' )
                    ),
                    'id'       => 'wpsl-marker-effect',
                    'name'     => 'wpsl_ux[marker_effect]',
                    'selected' => $wpsl_settings['marker_effect']
                ),
                'more_info' => array(
                    'values' => array(
                        'store listings' => __( 'In the store listings', 'wpsl' ),
                        'info window'    => __( 'In the info window on the map', 'wpsl' )
                    ),
                    'id'       => 'wpsl-more-info-list',
                    'name'     => 'wpsl_ux[more_info_location]',
                    'selected' => $wpsl_settings['more_info_location']
                ),
                'map_types' => array(
                    'values'   => wpsl_get_map_types(),
                    'id'       => 'wpsl-map-type',
                    'name'     => 'wpsl_map[type]',
                    'selected' => $wpsl_settings['map_type']
                ),
                'editor_map_types' => array(
                    'values'   => wpsl_get_map_types(),
                    'id'       => 'wpsl-editor-map-type',
                    'name'     => 'wpsl_editor[map_type]',
                    'selected' => $wpsl_settings['editor_map_type']
                ),
                'max_zoom_level' => array(
                    'values'   => wpsl_get_max_zoom_levels(),
                    'id'       => 'wpsl-max-auto-zoom',
                    'name'     => 'wpsl_map[max_auto_zoom]',
                    'selected' => $wpsl_settings['auto_zoom_level']
                ),
                'address_format' => array(
                    'values'   => wpsl_get_address_formats(),
                    'id'       => 'wpsl-address-format',
                    'name'     => 'wpsl_ux[address_format]',
                    'selected' => $wpsl_settings['address_format']
                ),
                'filter_types' => array(
                    'values' => array(
                        'dropdown'   => __( 'Dropdown', 'wpsl' ), 
                        'checkboxes' => __( 'Checkboxes', 'wpsl' )
                     ),
                    'id'       => 'wpsl-cat-filter-types',
                    'name'     => 'wpsl_search[category_filter_type]',
                    'selected' => $wpsl_settings['category_filter_type']
                )
            ) );
                        
			$dropdown = '<select id="' . esc_attr( $dropdown_lists[$type]['id'] ) . '" name="' . esc_attr( $dropdown_lists[$type]['name'] ) . '" autocomplete="off">';
			
			foreach ( $dropdown_lists[$type]['values'] as $key => $value ) {
				$selected = ( $key == $dropdown_lists[$type]['selected'] ) ? 'selected="selected"' : '';
				$dropdown .= "<option value='" . esc_attr( $key ) . "' $selected>" . esc_html( $value ) . "</option>";
			}
			
			$dropdown .= '</select>';
			
			return $dropdown;			
		}
        
        /**
         * Create a dropdown for the 12/24 opening hours format.
         * 
         * @since 2.0.0
         * @param  string $hour_format The hour format that should be set to selected
         * @return string $dropdown    The html for the dropdown
         */
        public function show_opening_hours_format( $hour_format = '' ) {
            
            global $wpsl_settings;
            
			$items = array( 
                '12' => __( '12 Hours', 'wpsl' ),
                '24' => __( '24 Hours', 'wpsl' )
            );
            
            if ( !absint( $hour_format ) ) {
                $hour_format = $wpsl_settings['editor_hour_format'];
            } 
            
			$dropdown = '<select id="wpsl-editor-hour-format" name="wpsl_editor[hour_format]" autocomplete="off">';
			
			foreach ( $items as $key => $value ) {
				$selected = ( $hour_format == $key ) ? 'selected="selected"' : '';
				$dropdown .= "<option value='$key' $selected>" . esc_html( $value ) . "</option>";
			}
			
			$dropdown .= '</select>';
			
			return $dropdown;			
		}
    }
}admin/js/retina.min.js000064400000005030151327220640010652 0ustar00/*!
 * Retina.js v1.3.0
 *
 * Copyright 2014 Imulus, LLC
 * Released under the MIT license
 *
 * Retina.js is an open source script that makes it easy to serve
 * high-resolution images to devices with retina displays.
 */
!function(){function a(){}function b(a){return f.retinaImageSuffix+a}function c(a,c){if(this.path=a||"","undefined"!=typeof c&&null!==c)this.at_2x_path=c,this.perform_check=!1;else{if(void 0!==document.createElement){var d=document.createElement("a");d.href=this.path,d.pathname=d.pathname.replace(g,b),this.at_2x_path=d.href}else{var e=this.path.split("?");e[0]=e[0].replace(g,b),this.at_2x_path=e.join("?")}this.perform_check=!0}}function d(a){this.el=a,this.path=new c(this.el.getAttribute("src"),this.el.getAttribute("data-at2x"));var b=this;this.path.check_2x_variant(function(a){a&&b.swap()})}var e="undefined"==typeof exports?window:exports,f={retinaImageSuffix:"@2x",check_mime_type:!0,force_original_dimensions:!0};e.Retina=a,a.configure=function(a){null===a&&(a={});for(var b in a)a.hasOwnProperty(b)&&(f[b]=a[b])},a.init=function(a){null===a&&(a=e);var b=a.onload||function(){};a.onload=function(){var a,c,e=document.getElementsByTagName("img"),f=[];for(a=0;a<e.length;a+=1)c=e[a],c.getAttributeNode("data-no-retina")||f.push(new d(c));b()}},a.isRetina=function(){var a="(-webkit-min-device-pixel-ratio: 1.5), (min--moz-device-pixel-ratio: 1.5), (-o-min-device-pixel-ratio: 3/2), (min-resolution: 1.5dppx)";return e.devicePixelRatio>1?!0:e.matchMedia&&e.matchMedia(a).matches?!0:!1};var g=/\.\w+$/;e.RetinaImagePath=c,c.confirmed_paths=[],c.prototype.is_external=function(){return!(!this.path.match(/^https?\:/i)||this.path.match("//"+document.domain))},c.prototype.check_2x_variant=function(a){var b,d=this;return this.is_external()?a(!1):this.perform_check||"undefined"==typeof this.at_2x_path||null===this.at_2x_path?this.at_2x_path in c.confirmed_paths?a(!0):(b=new XMLHttpRequest,b.open("HEAD",this.at_2x_path),b.onreadystatechange=function(){if(4!==b.readyState)return a(!1);if(b.status>=200&&b.status<=399){if(f.check_mime_type){var e=b.getResponseHeader("Content-Type");if(null===e||!e.match(/^image/i))return a(!1)}return c.confirmed_paths.push(d.at_2x_path),a(!0)}return a(!1)},b.send(),void 0):a(!0)},e.RetinaImage=d,d.prototype.swap=function(a){function b(){c.el.complete?(f.force_original_dimensions&&(c.el.setAttribute("width",c.el.offsetWidth),c.el.setAttribute("height",c.el.offsetHeight)),c.el.setAttribute("src",a)):setTimeout(b,5)}"undefined"==typeof a&&(a=this.path.at_2x_path);var c=this;b()},a.isRetina()&&a.init(e)}();admin/js/retina.js000064400000013350151327220640010074 0ustar00/*!
 * Retina.js v1.3.0
 *
 * Copyright 2014 Imulus, LLC
 * Released under the MIT license
 *
 * Retina.js is an open source script that makes it easy to serve
 * high-resolution images to devices with retina displays.
 */

(function() {
    var root = (typeof exports === 'undefined' ? window : exports);
    var config = {
        // An option to choose a suffix for 2x images
        retinaImageSuffix : '@2x',

        // Ensure Content-Type is an image before trying to load @2x image
        // https://github.com/imulus/retinajs/pull/45)
        check_mime_type: true,

        // Resize high-resolution images to original image's pixel dimensions
        // https://github.com/imulus/retinajs/issues/8
        force_original_dimensions: true
    };

    function Retina() {}

    root.Retina = Retina;

    Retina.configure = function(options) {
        if (options === null) {
            options = {};
        }

        for (var prop in options) {
            if (options.hasOwnProperty(prop)) {
                config[prop] = options[prop];
            }
        }
    };

    Retina.init = function(context) {
        if (context === null) {
            context = root;
        }

        var existing_onload = context.onload || function(){};

        context.onload = function() {
            var images = document.getElementsByTagName('img'), retinaImages = [], i, image;
            for (i = 0; i < images.length; i += 1) {
                image = images[i];
                if (!!!image.getAttributeNode('data-no-retina')) {
                    retinaImages.push(new RetinaImage(image));
                }
            }
            existing_onload();
        };
    };

    Retina.isRetina = function(){
        var mediaQuery = '(-webkit-min-device-pixel-ratio: 1.5), (min--moz-device-pixel-ratio: 1.5), (-o-min-device-pixel-ratio: 3/2), (min-resolution: 1.5dppx)';

        if (root.devicePixelRatio > 1) {
            return true;
        }

        if (root.matchMedia && root.matchMedia(mediaQuery).matches) {
            return true;
        }

        return false;
    };


    var regexMatch = /\.\w+$/;
    function suffixReplace (match) {
        return config.retinaImageSuffix + match;
    }

    function RetinaImagePath(path, at_2x_path) {
        this.path = path || '';
        if (typeof at_2x_path !== 'undefined' && at_2x_path !== null) {
            this.at_2x_path = at_2x_path;
            this.perform_check = false;
        } else {
            if (undefined !== document.createElement) {
                var locationObject = document.createElement('a');
                locationObject.href = this.path;
                locationObject.pathname = locationObject.pathname.replace(regexMatch, suffixReplace);
                this.at_2x_path = locationObject.href;
            } else {
                var parts = this.path.split('?');
                parts[0] = parts[0].replace(regexMatch, suffixReplace);
                this.at_2x_path = parts.join('?');
            }
            this.perform_check = true;
        }
    }

    root.RetinaImagePath = RetinaImagePath;

    RetinaImagePath.confirmed_paths = [];

    RetinaImagePath.prototype.is_external = function() {
        return !!(this.path.match(/^https?\:/i) && !this.path.match('//' + document.domain) );
    };

    RetinaImagePath.prototype.check_2x_variant = function(callback) {
        var http, that = this;
        if (this.is_external()) {
            return callback(false);
        } else if (!this.perform_check && typeof this.at_2x_path !== 'undefined' && this.at_2x_path !== null) {
            return callback(true);
        } else if (this.at_2x_path in RetinaImagePath.confirmed_paths) {
            return callback(true);
        } else {
            http = new XMLHttpRequest();
            http.open('HEAD', this.at_2x_path);
            http.onreadystatechange = function() {
                if (http.readyState !== 4) {
                    return callback(false);
                }

                if (http.status >= 200 && http.status <= 399) {
                    if (config.check_mime_type) {
                        var type = http.getResponseHeader('Content-Type');
                        if (type === null || !type.match(/^image/i)) {
                            return callback(false);
                        }
                    }

                    RetinaImagePath.confirmed_paths.push(that.at_2x_path);
                    return callback(true);
                } else {
                    return callback(false);
                }
            };
            http.send();
        }
    };


    function RetinaImage(el) {
        this.el = el;
        this.path = new RetinaImagePath(this.el.getAttribute('src'), this.el.getAttribute('data-at2x'));
        var that = this;
        this.path.check_2x_variant(function(hasVariant) {
            if (hasVariant) {
                that.swap();
            }
        });
    }

    root.RetinaImage = RetinaImage;

    RetinaImage.prototype.swap = function(path) {
        if (typeof path === 'undefined') {
            path = this.path.at_2x_path;
        }

        var that = this;
        function load() {
            if (! that.el.complete) {
                setTimeout(load, 5);
            } else {
                if (config.force_original_dimensions) {
                    that.el.setAttribute('width', that.el.offsetWidth);
                    that.el.setAttribute('height', that.el.offsetHeight);
                }

                that.el.setAttribute('src', path);
            }
        }
        load();
    };


    if (Retina.isRetina()) {
        Retina.init(root);
    }
})();
admin/js/wpsl-cpt-upgrade.js000064400000006211151327220640012006 0ustar00jQuery( document ).ready( function( $ ) { 
var updateInterval;

$( "#wpsl-cpt-dialog" ).on( "click", function() {	
	$( "#wpsl-cpt-lightbox, #wpsl-cpt-overlay" ).show();
});

$( "#wpsl-cpt-overlay, #wpsl-cpt-lightbox .tb-close-icon" ).on( "click", function() {
	$( "#wpsl-cpt-lightbox, #wpsl-cpt-overlay" ).hide();
});

/* Start converting the locations to custom post types once the button is clicked */
$( "#wpsl-start-cpt-conversion" ).on( "click", function() {
	var ajaxData = {
		action: "convert_cpt",
		_ajax_nonce: $( this ).parents( "#wpsl-cpt-lightbox" ).find( "input[name='wpsl-cpt-fix-nonce']" ).val()
	};

	$( "#wpsl-cpt-lightbox .wpsl-preloader" ).show();
	$( ".wpsl-cpt-timeout" ).remove();	
	
	/* Make the ajax request to start the cpt conversion */ 
	$.get( ajaxurl, ajaxData, function( response ) {
		 if ( response == -1 ) {
			alert( wpslCptConversion.securityFail );
			stopConvertingCpt();
		}
	});
	
	/* Get the latest amount of locations that still need to be converted */
	updateInterval = setInterval( function() { convertCptCount(); }, 10000 );
	
	return false;
});

/**
 * Cancel the conversion count updates and hide the preloader.
 * 
 * @since 2.0
 * @return {void}
 */
function stopConvertingCpt() {
	clearInterval( updateInterval );
	$( ".wpsl-preloader" ).hide();	
}

/**
 * When the script that converts the locations to custom post types timed out, we show this msg.
 * 
 * @since 2.0
 * @return {void}
 */
function convertCptTimeoutMsg() {
	$( ".wslp-cpt-fix-wrap" ).after( "<p class='wpsl-cpt-timeout'>" + wpslCptConversion.timeout + "</p>" );	
}

/**
 * Make the ajax request to update the count of the
 * remaining locations that need to be converted.
 * 
 * @since 2.0
 * @return {void}
 */
function convertCptCount() { 
	var convertCount, ajaxData = {
		action: "convert_cpt_count",
		_ajax_nonce: $( "#wpsl-cpt-lightbox" ).find( "input[name='wpsl-cpt-conversion-count']" ).val()
	};
	
	$.ajaxQueue({
		url: ajaxurl,
		data: ajaxData,
		type: "GET"
	}).done( function( response ) {
		
		if ( response == -1 ) {
			stopConvertingCpt();
			alert( wpslCptConversion.securityFail );
		} else if ( typeof response.count !== "undefined" ) {
			convertCount = $( "#wpsl-cpt-lightbox p span" ).text();
			
			/* Check if the convert count still changes, if so the script is still running and we update the correct value. 
			 * If not then the convert script timed out and we show a different message. 
			 */
			if ( response.count != convertCount ) {
				$( ".wpsl-cpt-remaining span").html( response.count );	
			} else if ( response.count > 0 ) {
				stopConvertingCpt();
				convertCptTimeoutMsg();				
			}
		} else if ( typeof response.url !== "undefined" ) {
			$( ".wpsl-cpt-remaining" ).html( response.url ).parents( ".error" ).remove();
			$( ".wslp-cpt-fix-wrap" ).remove();
			stopConvertingCpt();	
		}
	});
}

/* Copy the remaining number of locations that need to be 
 * converted to custom post types to the thickbox field.
 */
if ( $( ".error .wpsl-cpt-remaining" ).length ) {
	var cptCount = parseInt( $( ".error .wpsl-cpt-remaining" ).text() );
	
	if ( isNaN( cptCount ) ) {
		cptCount = '-';	
	}
		
	$( ".wpsl-cpt-remaining span" ).html( cptCount );
}

});admin/js/wpsl-shortcode-generator.min.js000064400000004466151327220640014345 0ustar00function WPSL_InsertShortcode(){var e,t,s,o,l,i=window.dialogArguments||opener||parent||top,r=jQuery("#wpsl-start-location").val(),c=jQuery("#wpsl-cat-filter-types").val(),n=jQuery("#wpsl-cat-restriction").val(),a=jQuery("#wpsl-auto-locate").is(":checked")?!0:!1;t='template="'+jQuery("#wpsl-store-template").val()+'" map_type="'+jQuery("#wpsl-map-type").val()+'" auto_locate="'+a+'"',e=WPSL_Selected_Markers(),"undefined"!=typeof e.start&&(t+=' start_marker="'+e.start+'"'),"undefined"!=typeof e.store&&(t+=' store_marker="'+e.store+'"'),r&&(t+=' start_location="'+r+'"'),"undefined"==typeof n||null===n||c||(t+=' category="'+n+'"'),o="dropdown"==c?"wpsl-cat-selection":"wpsl-checkbox-selection",l=jQuery("#"+o).val(),l&&(t+=' category_selection="'+l+'"'),c&&(t+=' category_filter_type="'+c+'"'),"checkboxes"==c&&(s=parseInt(jQuery("#wpsl-checkbox-columns").val()),"number"==typeof s&&(t+=' checkbox_columns="'+s+'"')),i.send_to_editor("[wpsl "+t+"]")}function WPSL_Selected_Markers(){var e,t,s=[],o={};return jQuery(".wpsl-marker-list ").each(function(e){s.push(jQuery(".wpsl-marker-list:eq("+e+" ) .wpsl-active-marker input").val())}),2==s.length&&(e=s[0].split("."),t=s[1].split("."),"undefined"!=typeof e[0]&&(o.start=e[0]),"undefined"!=typeof t[0]&&(o.store=t[0])),o}jQuery(document).ready(function(e){e("#wpsl-media-tabs").tabs(),e(".wpsl-info").on("mouseover",function(){e(this).find(".wpsl-info-text").show()}),e(".wpsl-info").on("mouseout",function(){e(this).find(".wpsl-info-text").hide()}),e(".wpsl-marker-list input[type=radio]").click(function(){e(this).parents(".wpsl-marker-list").find("li").removeClass(),e(this).parent("li").addClass("wpsl-active-marker")}),e(".wpsl-marker-list li").click(function(){e(this).parents(".wpsl-marker-list").find("input").prop("checked",!1),e(this).find("input").prop("checked",!0),e(this).siblings().removeClass(),e(this).addClass("wpsl-active-marker")}),e("#wpsl-cat-filter-types").change(function(){var t=e(this).val();"dropdown"==t?(e(".wpsl-cat-selection").show(),e(".wpsl-checkbox-options, .wpsl-cat-restriction, .wpsl-checkbox-selection").hide()):"checkboxes"==t?(e(".wpsl-cat-selection, .wpsl-cat-restriction").hide(),e(".wpsl-checkbox-options, .wpsl-checkbox-selection").show()):(e(".wpsl-cat-restriction").show(),e(".wpsl-checkbox-options, .wpsl-cat-selection, .wpsl-checkbox-selection").hide())})});admin/js/wpsl-admin.js000064400000133271151327220640010672 0ustar00jQuery( document ).ready( function( $ ) {
    var map, geocoder, startLatLng, markersArray = [],
        wpslAdmin = wpslAdmin || {};

    /**
     * Verify the provided API keys
     *
     * @since 2.2.22
     */
    wpslAdmin.verifyKeys = {
        init: function() {
            var self       = this,
                $btn       = $( "#wpsl-verify-keys" ),
                preloader  = wpslSettings.url + "img/ajax-loader.gif",
                mapService = ( typeof wpslSettings.mapService !== "undefined" ) ? wpslSettings.mapService : "gmaps";

            $btn.on( "click", function() {
                $( "#wpsl-wrap .notice" ).remove();

                self[mapService].check();

                $btn.after( '<img src="' + preloader + '" class="wpsl-api-key-preloader" />' );

                return false;
            });
        },
        /**
         * Show the status of the API keys.
         *
         * @since 2.2.22
         * @param {string} response   The API response
         * @param {string} keyType 	   The type of API key we need to show the notice for
         * @param {string} noticeType Show either an error or success notice.
         * @returns {void}
         */
        showStatus: function( response, keyType, noticeType = "error" ) {

            this.createNotice( response, keyType, noticeType );

            // After the browser check has finished we remove the preloader.
            if ( keyType == "browser" ) {
                $( ".wpsl-api-key-preloader" ).remove();
            }
        },
        /**
         * Create the error notice.
         *
         * @since 2.2.10
         * @param {string} response   The API response to show
         * @param {string} keyType 	   The type of API key we need to show the notice for
         * @param {string} noticeType Show either an error or success notice.
         * @returns void
         */
        createNotice: function( response, keyType, noticeType ) {
            var notice, noticeLocation, cssClass;

            cssClass = ( noticeType == "error" ) ? "error" : "updated";

            notice = '<div class="' + cssClass + ' notice is-dismissible">';
            notice += '<p><strong>' + response + '</strong></p>';
            notice += '<button type="button" class="notice-dismiss"><span class="screen-reader-text">' + wpslL10n.dismissNotice + '</span></button>';
            notice += '</div>';

            noticeLocation = ( $( "#wpsl-tabs" ).length ) ? "wpsl-tabs" : "wpsl-settings-form";

            $( "#" + noticeLocation + "" ).before( notice );

            if ( noticeType == "error" ) {
                $( "#wpsl-api-" + keyType + "-key" ).addClass( "wpsl-error" );
            } else {
                $( "#wpsl-api-" + keyType + "-key" ).removeClass( "wpsl-error" );
            }
        },
        gmaps: {
            /**
             * Check for any issues with the used API keys.
             *
             * @since   2.2.22
             * @returns {void}
             */
            check: function() {
                this.server(function() {
                    wpslAdmin.verifyKeys.gmaps.browser();
                });
            },
            /**
             * Make a request to the Google Geocode API to
             * check if the server key is valid or not.
             *
             * @since   2.2.22
             * @returns {void}
             */
            server: function( callback ) {
                var status,
                    ajaxData = {
                        action: "validate_server_key",
                        server_key: $( "#wpsl-api-server-key" ).val()
                    };

                if ( ajaxData.server_key ) {
                    $.get( wpslSettings.ajaxurl, ajaxData, function( response ) {
                        status = ( response.valid ) ? "updated" : "error";

                        wpslAdmin.verifyKeys.showStatus( response.msg, "server", status );

                        callback();
                    });
                } else {
                    wpslAdmin.verifyKeys.showStatus( wpslL10n.serverKeyMissing, "server" );

                    callback();
                }
            },
            /**
             * Make a request to the Google JavaScript API to
             * check if the browser key is valid or not.
             *
             * @since   2.2.22
             * @returns {void}
             */
            browser: function() {
                var browserAPICheck,
                    browserKey = $( "#wpsl-api-browser-key" ).val();

                if ( browserKey ) {

                    /**
                     * Wait 3 seconds before checking if the
                     * Geocode API returned data.
                     *
                     * If this hasn't happened, then there has to
                     * be a problem with the API keys.
                     */
                    browserAPICheck = setInterval(function() {
                        wpslAdmin.verifyKeys.showStatus( wpslL10n.browserKeyError, "browser" );

                        clearInterval( browserAPICheck );
                    }, 3000 );

                    /**
                     * This will only complete if there are no issues
                     * with the API key, otherwise it won't even make a request.
                     *
                     * To check this we use the setInterval in the above section.
                     */
                    geocoder.geocode( { 'address': 'Manhattan, NY 10036, USA' }, function( response, status ) {
                        if ( status == google.maps.GeocoderStatus.OK ) {
                            wpslAdmin.verifyKeys.showStatus( wpslL10n.browserKeySuccess, "browser", "success" );
                        } else {
                            wpslAdmin.verifyKeys.showStatus( wpslL10n.browserKeyError, "browser" );
                        }

                        clearInterval( browserAPICheck );
                    });
                } else {
                    wpslAdmin.verifyKeys.showStatus( wpslL10n.browserKeyMissing, "browser" );
                }
            }
        }
    };

    /**
     * Handle the Geocode requests made from
     * the Tools section on the settings page.
     *
     * This can be used to check the API response
     * for any input the user provides, and see if
     * it's in the expected location.
     *
     * Will show error messages if there are any
     * issues with the used browser API keys.
     *
     * @since 2.2.22
     */
    wpslAdmin.showApiResponse = {
        init: function() {
            var $geocodeInput = $( "#wpsl-geocode-input" ),
                self          = this,
                mapLoaded     = false;

            $( "#wpsl-show-geocode-response" ).on( "click", function( e ) {
                self.createDialog();

                initializeGmap("wpsl-geocode-preview" );

                // Make sure we don't add the same message twice.
                if ( !$( ".wpsl-geocode-warning span" ).length ) {
                    self.createRestrictionsMsg();
                }

                // Check for map errors after it finished loading.
                google.maps.event.addListenerOnce( map, "tilesloaded", function() {
                    mapLoaded = true;
                    self.checkQuotaError();
                });

                // Check if the map was load succesfully, if not show an error message explaining it.
                setTimeout(function() {
                    if ( !mapLoaded ) {
                        $(".wpsl-geocode-warning, #wpsl-geocode-test input, #wpsl-geocode-tabs").remove();
                        $(".wpsl-geocode-api-notice").show().html( wpslL10n.loadingFailed );
                    }
                }, 1000 );

                return false;
            });

            // Submit the geocode request.
            $( "#wpsl-geocode-submit" ).on( "click", function( e ) {
                $geocodeInput.removeClass( "wpsl-error" );

                if ( !$geocodeInput.val() ) {
                    $geocodeInput.addClass( "wpsl-error" );
                    $( ".wpsl-geocode-api-notice" ).hide();
                } else {
                    self.geocoding.makeRequest();
                }
            });

            // Handle users using the enter key in the dialog box.
            $( "#wpsl-geocode-test" ).keydown( function( event ) {
                var keyCode = ( event.keyCode ? event.keyCode : event.which );

                if ( keyCode == 13 ) {
                    $( "#wpsl-geocode-submit" ).trigger( "click" );
                }
            });
        },
        /**
         * Create the dialog box
         *
         * @since   2.2.22
         * @returns {void}
         */
        createDialog: function() {
            $( "#wpsl-geocode-test" ).dialog({
                resizable: false,
                height: "auto",
                width: 550,
                modal: true,
                open: function() {

                    // Move it closer to the top then it normally would
                    $( this ).parent().css({ "top": window.pageYOffset + 50 });

                    $( "#wpsl-geocode-tabs" ).tabs();
                    $( "#wpsl-geocode-input" ).focus();
                    $( ".wpsl-geocode-api-notice" ).hide();

                    // Make sure the first tab is always selected after the dialog is opened a second time
                    $( "#wpsl-geocode-tabs" ).tabs( "option", "active", $( "li" ).index( $( "li:visible:eq(0)" ) ) );

                    // Make sure to remove any previous input
                    $( "#wpsl-geocode-input, #wpsl-geocode-response textarea" ).val( "" );

                    $( ".ui-widget-overlay" ).bind( "click", function() {
                        $( "#wpsl-geocode-test" ).dialog( "close" );
                    });
                },
                buttons: {
                    Cancel: function() {
                        $( this ).dialog( "close" );
                    }
                }
            });
        },
        /**
         * If there's a problem with the billing account,
         * then a 'dismissButton' class will exist in the map itself.
         *
         * If this is the case, then we remove everything and
         * show an error explaining the problem.
         *
         * @since   2.2.22
         * @returns {void}
         */
        checkQuotaError: function() {

            setTimeout(function() {
                if ( $( "#wpsl-geocode-preview .dismissButton" ).length > 0 ) {
                    $( ".wpsl-geocode-warning, #wpsl-geocode-test input" ).remove();

                    $( ".wpsl-geocode-api-notice" ).show();
                    $( ".wpsl-geocode-api-notice span" ).html( wpslL10n.loadingError );
                }

            }, 1000 );
        },
        /**
         * Create a message explaning the user that the
         * results are restricted to the selected map region,
         * and possibly only work for zip codes.
         *
         * @since   2.2.22
         * @returns {void}
         */
        createRestrictionsMsg: function() {
            var countryName, zipcodeOnly,
                $warningElem = $( ".wpsl-geocode-warning" ).show().find( "strong" );

            if ( $( "#wpsl-api-region" ).val() ) {
                countryName = $( "#wpsl-api-region option:selected" ).text();
                zipcodeOnly = ( $( "#wpsl-force-postalcode" ).is( ":checked" ) ) ? wpslL10n.restrictedZipCode : '';

                $warningElem.after( "<span>" + wpslL10n.resultsWarning + ' ' + countryName + ' ' + zipcodeOnly + "</span>" );
            } else {
                $warningElem.after( "<span>" + wpslL10n.noRestriction + "</span>" );

                $( ".wpsl-region-href" ).on( "click", function() {
                    $( ".ui-widget-overlay" ).trigger( "click" );
                });
            }
        },
        geocoding: {
            /**
             * Geocode the provided user input
             *
             * @since   2.2.22
             * @returns {void}
             */
            makeRequest: function() {
                var request = this.createParams();

                geocoder.geocode( request, function( response, status ) {

                    // Show an error message if there is a problem with the browser API key.
                    if ( status == "OK" || status == "ZERO_RESULTS" ) {

                        // Make sure to remove the marker from the map if one exists.
                        if ( typeof markersArray[0] !== "undefined" ) {
                            markersArray[0].setMap( null );
                            markersArray.length = 0;
                        }

                        if ( status == "OK" ) {
                            addMarker( response[0].geometry.location, false );

                            map.setZoom( 12 );
                            map.setCenter( response[0].geometry.location );
                        } else {
                            map.setZoom( parseInt( wpslSettings.defaultZoom ) );
                            map.setCenter( startLatLng );
                        }
                    } else {
                        status = wpslL10n.browserKeyError;

                        $( "#wpsl-geocode-preview, #wpsl-geocode-response textarea" ).remove();
                    }

                    $( ".wpsl-geocode-api-notice" ).show();
                    $( ".wpsl-geocode-api-notice span" ).html( status );
                    $( "#wpsl-geocode-response textarea" ).val( JSON.stringify( response, null, 4 ) );
                });
            },
            /**
             * Create the params used in the geocode request
             * made through the test tool in the tools section.
             *
             * @since  2.2.22
             * @return {object} request The parameters included in the geocode API request
             */
            createParams: function() {
                var request = {};

                // Check if we need to set the geocode component restrictions.
                if ( typeof wpslSettings.geocodeComponents !== "undefined" && !$.isEmptyObject( wpslSettings.geocodeComponents ) ) {
                    request.componentRestrictions = wpslSettings.geocodeComponents;

                    if ( typeof request.componentRestrictions.postalCode !== "undefined" ) {
                        request.componentRestrictions.postalCode = $( "#wpsl-geocode-input" ).val();
                    } else {
                        request.address = $( "#wpsl-geocode-input" ).val();
                    }
                } else {
                    request.address = $( "#wpsl-geocode-input" ).val();
                }

                return request;
            },
        },
    };

    if ( $( "#wpsl-gmap-wrap" ).length ) {
        initializeGmap();
    }

    /**
     * If we are on the settings page, then init the API tools.
     */
    if ( $( "#wpsl-map-settings").length ) {
        wpslAdmin.verifyKeys.init();
        wpslAdmin.showApiResponse.init();
    }

    /**
     * Initialize the map with the correct settings.
     *
     * @since	1.0.0
     * @param   string mapId The ID of the element to render the map in
     * @returns {void}
     */
    function initializeGmap( mapId = "wpsl-gmap-wrap" ) {
        var defaultLatLng = wpslSettings.defaultLatLng.split( "," ),
            mapOptions;

        startLatLng = new google.maps.LatLng( defaultLatLng[0], defaultLatLng[1] );
        mapOptions  = {
            zoom: parseInt( wpslSettings.defaultZoom ),
            center: startLatLng,
            mapTypeId: google.maps.MapTypeId[ wpslSettings.mapType.toUpperCase() ],
            mapTypeControl: false,
            streetViewControl: false,
            zoomControlOptions: {
                position: google.maps.ControlPosition.RIGHT_TOP
            }
        };

        geocoder = new google.maps.Geocoder();
        map		  = new google.maps.Map( document.getElementById( mapId ), mapOptions );

        checkEditStoreMarker();
    }

    /**
     * Check if we have an existing latlng value.
     *
     * If there is an latlng value, then we add a marker to the map.
     * This can only happen on the edit store page.
     *
     * @since	1.0.0
     * @returns {void}
     */
    function checkEditStoreMarker() {
        var location,
            lat = $( "#wpsl-lat" ).val(),
            lng = $( "#wpsl-lng" ).val();

        if ( ( lat ) && ( lng ) ) {
            location = new google.maps.LatLng( lat, lng );

            map.setCenter( location );
            map.setZoom( 16 );
            addMarker( location );
        }
    }

    // If we have a city/country input field enable the autocomplete.
    if ( $( "#wpsl-start-name" ).length ) {
        activateAutoComplete();
    }

    /**
     * Activate the autocomplete function for the city/country field.
     *
     * @since	1.0.0
     * @returns {void}
     */
    function activateAutoComplete() {
        var latlng,
            input = document.getElementById( "wpsl-start-name" ),
            options = {
                types: ['geocode']
            },
            autocomplete = new google.maps.places.Autocomplete( input, options );

        google.maps.event.addListener( autocomplete, "place_changed", function() {
            latlng = autocomplete.getPlace().geometry.location;
            setLatlng( latlng, "zoom" );
        });
    }

    /**
     * Add a new marker to the map based on the provided location (latlng).
     *
     * @since	1.0.0
     * @param   {object}  location   The latlng value
     * @param   {boolean} draggable Whether the marker should be draggable or not
     * @returns {void}
     */
    function addMarker( location, draggable = true ) {
        var marker = new google.maps.Marker({
            position: location,
            map: map,
            draggable: draggable
        });

        markersArray.push( marker );

        // If the marker is dragged on the map, make sure the latlng values are updated.
        google.maps.event.addListener( marker, "dragend", function() {
            setLatlng( marker.getPosition(), "store" );
        });
    }

    // Lookup the provided location with the Google Maps API.
    $( "#wpsl-lookup-location" ).on( "click", function( e ) {
        e.preventDefault();
        codeAddress();
    });

    /**
     * Update the hidden input field with the current latlng values.
     *
     * @since	1.0.0
     * @param   {object} latLng The latLng values
     * @param   {string} target The location where we need to set the latLng
     * @returns {void}
     */
    function setLatlng( latLng, target ) {
        var coordinates = stripCoordinates( latLng ),
            lat			= roundCoordinate( coordinates[0] ),
            lng			= roundCoordinate( coordinates[1] );

        if ( target == "store" ) {
            $( "#wpsl-lat" ).val( lat );
            $( "#wpsl-lng" ).val( lng );
        } else if ( target == "zoom" ) {
            $( "#wpsl-latlng" ).val( lat + ',' + lng );
        }
    }

    /**
     * Geocode the user input.
     *
     * @since	1.0.0
     * @returns {void}
     */
    function codeAddress() {
        var filteredResponse, geocodeAddress;

        // Check if we have all the required data before attempting to geocode the address.
        if ( !validatePreviewFields() ) {
            geocodeAddress = createGeocodeAddress();

            geocoder.geocode( { 'address': geocodeAddress }, function( response, status ) {
                if ( status === google.maps.GeocoderStatus.OK ) {

                    // If we have a previous marker on the map we remove it.
                    if ( typeof( markersArray[0] ) !== "undefined" ) {
                        if ( markersArray[0].draggable ) {
                            markersArray[0].setMap( null );
                            markersArray.splice(0, 1);
                        }
                    }

                    // Center and zoom to the searched location.
                    map.setCenter( response[0].geometry.location );
                    map.setZoom( 16 );

                    addMarker( response[0].geometry.location );
                    setLatlng( response[0].geometry.location, "store" );

                    filteredResponse = filterApiResponse( response );

                    $( "#wpsl-country" ).val( filteredResponse.country.long_name );
                    $( "#wpsl-country_iso" ).val( filteredResponse.country.short_name );
                } else {
                    alert( wpslL10n.geocodeFail + ": " + status );
                }
            });

            return false;
        } else {
            activateStoreTab( "first" );

            alert( wpslL10n.missingGeoData );

            return true;
        }
    }

    /**
     * Check that all required fields for the map preview are there.
     *
     * @since	1.0.0
     * @returns {boolean} error  Whether all the required fields contained data.
     */
    function validatePreviewFields() {
        var i, fieldData, requiredFields,
            error = false;

        $( ".wpsl-store-meta input" ).removeClass( "wpsl-error" );

        // Check which fields are required.
        if ( typeof wpslSettings.requiredFields !== "undefined" && _.isArray( wpslSettings.requiredFields ) ) {
            requiredFields = wpslSettings.requiredFields;

            // Check if all the required fields contain data.
            for ( i = 0; i < requiredFields.length; i++ ) {
                fieldData = $.trim( $( "#wpsl-" + requiredFields[i] ).val() );

                if ( !fieldData ) {
                    $( "#wpsl-" + requiredFields[i] ).addClass( "wpsl-error" );
                    error = true;
                }

                fieldData = '';
            }
        }

        return error;
    }

    /**
     * Build the address that's send to the Geocode API.
     *
     * @since	2.1.0
     * @returns {string} geocodeAddress The address separated by , that's send to the Geocoder.
     */
    function createGeocodeAddress() {
        var i, part,
            address      = [],
            addressParts = [ "address", "city", "state", "zip", "country" ];

        for ( i = 0; i < addressParts.length; i++ ) {
            part = $.trim( $( "#wpsl-" + addressParts[i] ).val() );

            /*
             * At this point we already know the address, city and country fields contain data.
             * But no need to include the zip and state if they are empty.
             */
            if ( part ) {
                address.push( part );
            }

            part = "";
        }

        return address.join();
    }

    /**
     * Filter out the country name from the API response.
     *
     * @since	1.0.0
     * @param   {object} response	   The response of the geocode API
     * @returns {object} collectedData The short and long country name
     */
    function filterApiResponse( response ) {
        var i, responseType, collectedData,
            country		  = {},
            addressLength = response[0].address_components.length;

        // Loop over the API response.
        for ( i = 0; i < addressLength; i++ ) {
            responseType = response[0].address_components[i].types;

            // Filter out the country name.
            if ( /^country,political$/.test( responseType ) ) {
                country = {
                    long_name: response[0].address_components[i].long_name,
                    short_name: response[0].address_components[i].short_name
                };
            }
        }

        collectedData = {
            country: country
        };

        return collectedData;
    }

    /**
     * Round the coordinate to 6 digits after the comma.
     *
     * @since	1.0.0
     * @param   {string} coordinate   The coordinate
     * @returns {number} roundedCoord The rounded coordinate
     */
    function roundCoordinate( coordinate ) {
        var roundedCoord, decimals = 6;

        roundedCoord = Math.round( coordinate * Math.pow( 10, decimals ) ) / Math.pow( 10, decimals );

        return roundedCoord;
    }

    /**
     * Strip the '(' and ')' from the captured coordinates and split them.
     *
     * @since	1.0.0
     * @param   {string} coordinates The coordinates
     * @returns {object} latLng      The latlng coordinates
     */
    function stripCoordinates( coordinates ) {
        var latLng    = [],
            selected  = coordinates.toString(),
            latLngStr = selected.split( ",", 2 );

        latLng[0] = latLngStr[0].replace( "(", "" );
        latLng[1] = latLngStr[1].replace( ")", "" );

        return latLng;
    }

    $( ".wpsl-marker-list input[type=radio]" ).click( function() {
        $( this ).parents( ".wpsl-marker-list" ).find( "li" ).removeClass();
        $( this ).parent( "li" ).addClass( "wpsl-active-marker" );
    });

    $( ".wpsl-marker-list li" ).click( function() {
        $( this ).parents( ".wpsl-marker-list" ).find( "input" ).prop( "checked", false );
        $( this ).find( "input" ).prop( "checked", true );
        $( this ).siblings().removeClass();
        $( this ).addClass( "wpsl-active-marker" );
    });

    // Detect changes in checkboxes that have a conditional option.
    $( ".wpsl-has-conditional-option" ).on( "change", function() {
        $( this ).parent().next( ".wpsl-conditional-option" ).toggle();
    });

    /*
     * Detect changes to the store template dropdown. If the template is selected to
     * show the store list under the map then we show the option to hide the scrollbar.
     */
    $( "#wpsl-store-template" ).on( "change", function() {
        var $scrollOption = $( "#wpsl-listing-below-no-scroll" );

        if ( $( this ).val() == "below_map" ) {
            $scrollOption.show();
        } else {
            $scrollOption.hide();
        }
    });

    $( "#wpsl-api-region" ).on( "change", function() {
        var $geocodeComponent = $( "#wpsl-geocode-component" );

        if ( $( this ).val() ) {
            $geocodeComponent.show();
        } else {
            $geocodeComponent.hide();
        }
    });

    // Make sure the correct hour input format is visible.
    $( "#wpsl-editor-hour-input" ).on( "change", function() {
        $( ".wpsl-" + $( this ).val() + "-hours" ).show().siblings( "div" ).hide();
        $( ".wpsl-hour-notice" ).toggle();
    });

    // Set the correct tab to active and show the correct content block.
    $( "#wpsl-meta-nav li" ).on( "click", function( e ) {
        var activeClass = $( this ).attr( "class" );
        activeClass = activeClass.split( "-tab" );

        e.stopPropagation();

        // Set the correct tab and metabox to active.
        $( this ).addClass( "wpsl-active" ).siblings().removeClass( "wpsl-active" );
        $( ".wpsl-store-meta ." + activeClass[0] + "" ).show().addClass( "wpsl-active" ).siblings( "div" ).hide().removeClass( "wpsl-active" );
    });

    // Make sure the required store fields contain data.
    if ( $( "#wpsl-store-details" ).length ) {
        $( "#publish" ).click( function() {
            var firstErrorElem, currentTabClass, elemClass,
                errorMsg	= '<div id="message" class="error"><p>' + wpslL10n.requiredFields + '</p></div>',
                missingData = false;

            // Remove error messages and css classes from previous submissions.
            $( "#wpbody-content .wrap #message" ).remove();
            $( ".wpsl-required" ).removeClass( "wpsl-error" );

            // Loop over the required fields and check for a value.
            $( ".wpsl-required" ).each( function() {
                if ( $( this ).val() == "" ) {
                    $( this ).addClass( "wpsl-error" );

                    if ( typeof firstErrorElem === "undefined" ) {
                        firstErrorElem = getFirstErrorElemAttr( $( this ) );
                    }

                    missingData = true;
                }
            });

            // If one of the required fields are empty, then show the error msg and make sure the correct tab is visible.
            if ( missingData ) {
                $( "#wpbody-content .wrap > h2" ).after( errorMsg );

                if ( typeof firstErrorElem.val !== "undefined" ) {
                    if ( firstErrorElem.type == "id" ) {
                        currentTabClass = $( "#" + firstErrorElem.val + "" ).parents( ".wpsl-tab" ).attr( "class" );
                        $( "html, body" ).scrollTop( Math.round( $( "#" + firstErrorElem.val + "" ).offset().top - 100 ) );
                    } else if ( firstErrorElem.type == "class" ) {
                        elemClass		= firstErrorElem.val.replace( /wpsl-required|wpsl-error/g, "" );
                        currentTabClass = $( "." + elemClass + "" ).parents( ".wpsl-tab" ).attr( "class" );
                        $( "html, body" ).scrollTop( Math.round( $( "." + elemClass + "" ).offset().top - 100 ) );
                    }

                    currentTabClass = $.trim( currentTabClass.replace( /wpsl-tab|wpsl-active/g, "" ) );
                }

                // If we don't have a class of the tab that should be set to visible, we just show the first one.
                if ( !currentTabClass ) {
                    activateStoreTab( 'first' );
                } else {
                    activateStoreTab( currentTabClass );
                }

                /*
                 * If not all required fields contains data, and the user has
                 * clicked the submit button. Then an extra css class is added to the
                 * button that will disabled it. This only happens in WP 3.8 or earlier.
                 *
                 * We need to make sure this css class doesn't exist otherwise
                 * the user can never resubmit the page.
                 */
                $( "#publish" ).removeClass( "button-primary-disabled" );
                $( ".spinner" ).hide();

                return false;
            } else {
                return true;
            }
        });
    }

    /**
     * Set the correct tab to visible, and hide all other metaboxes
     *
     * @since	2.0.0
     * @param   {string} $target The name of the tab to show
     * @returns {void}
     */
    function activateStoreTab( $target ) {
        if ( $target == 'first' ) {
            $target = ':first-child';
        } else {
            $target = '.' + $target;
        }

        if ( !$( "#wpsl-meta-nav li" + $target + "-tab" ).hasClass( "wpsl-active" ) ) {
            $( "#wpsl-meta-nav li" + $target + "-tab" ).addClass( "wpsl-active" ).siblings().removeClass( "wpsl-active" );
            $( ".wpsl-store-meta > div" + $target + "" ).show().addClass( "wpsl-active" ).siblings( "div" ).hide().removeClass( "wpsl-active" );
        }
    }

    /**
     * Get the id or class of the first element that's an required field, but is empty.
     *
     * We need this to determine which tab we need to set active,
     * which will be the tab were the first error occured.
     *
     * @since	2.0.0
     * @param   {object} elem			The element the error occured on
     * @returns {object} firstErrorElem The id/class set on the first elem that an error occured on and the attr value
     */
    function getFirstErrorElemAttr( elem ) {
        var firstErrorElem = { "type": "id", "val" : elem.attr( "id" ) };

        // If no ID value exists, then check if we can get the class name.
        if ( typeof firstErrorElem.val === "undefined" ) {
            firstErrorElem = { "type": "class", "val" : elem.attr( "class" ) };
        }

        return firstErrorElem;
    }

    // If we have a store hours dropdown, init the event handler.
    if ( $( "#wpsl-store-hours" ).length ) {
        initHourEvents();
    }

    /**
     * Assign an event handler to the button that enables
     * users to remove an opening hour period.
     *
     * @since	2.0.0
     * @returns {void}
     */
    function initHourEvents() {
        $( "#wpsl-store-hours .wpsl-icon-cancel-circled" ).off();
        $( "#wpsl-store-hours .wpsl-icon-cancel-circled" ).on( "click", function() {
            removePeriod( $( this ) );
        });
    }

    // Add new openings period to the openings hours table.
    $( ".wpsl-add-period" ).on( "click", function( e ) {
        var newPeriod,
            hours		= {},
            returnList  = true,
            $tr			= $( this ).parents( "tr" ),
            periodCount = currentPeriodCount( $( this ) ),
            periodCss   = ( periodCount >= 1 ) ? "wpsl-current-period wpsl-multiple-periods" : "wpsl-current-period",
            day 	    = $tr.find( ".wpsl-opening-hours" ).attr( "data-day" ),
            selectName  = ( $( "#wpsl-settings-form" ).length ) ? "wpsl_editor[dropdown]" : "wpsl[hours]";

        newPeriod = '<div class="' + periodCss +'">';
        newPeriod += '<select autocomplete="off" name="' + selectName + '[' + day + '_open][]" class="wpsl-open-hour">' + createHourOptionList( returnList ) + '</select>';
        newPeriod += '<span> - </span>';
        newPeriod += '<select autocomplete="off" name="' + selectName + '[' + day + '_close][]" class="wpsl-close-hour">' + createHourOptionList( returnList ) + '</select>';
        newPeriod += '<div class="wpsl-icon-cancel-circled"></div>';
        newPeriod += '</div>';

        $tr.find( ".wpsl-store-closed" ).remove();
        $( "#wpsl-hours-" + day + "" ).append( newPeriod ).end();

        initHourEvents();

        if ( $( "#wpsl-editor-hour-format" ).val() == 24 ) {
            hours = {
                "open": "09:00",
                "close": "17:00"
            };
        } else {
            hours = {
                "open": "9:00 AM",
                "close": "5:00 PM"
            };
        }

        $tr.find( ".wpsl-open-hour:last option[value='" + hours.open + "']" ).attr( "selected", "selected" );
        $tr.find( ".wpsl-close-hour:last option[value='" + hours.close + "']" ).attr( "selected", "selected" );

        e.preventDefault();
    });

    /**
     * Remove an openings period
     *
     * @since  2.0.0
     * @param  {object} elem The clicked element
     * @return {void}
     */
    function removePeriod( elem ) {
        var periodsLeft	= currentPeriodCount( elem ),
            $tr			= elem.parents( "tr" ),
            day 	    = $tr.find( ".wpsl-opening-hours" ).attr( "data-day" );

        // If there was 1 opening hour left then we add the 'Closed' text.
        if ( periodsLeft == 1 ) {
            $tr.find( ".wpsl-opening-hours" ).html( "<p class='wpsl-store-closed'>" + wpslL10n.closedDate + "<input type='hidden' name='wpsl[hours][" + day + "_open]' value='' /></p>" );
        }

        // Remove the selected openings period.
        elem.parent().closest( ".wpsl-current-period" ).remove();

        // If the first element has the multiple class, then we need to remove it.
        if ( $tr.find( ".wpsl-opening-hours div:first-child" ).hasClass( "wpsl-multiple-periods" ) ) {
            $tr.find( ".wpsl-opening-hours div:first-child" ).removeClass( "wpsl-multiple-periods" );
        }
    }

    /**
     * Count the current opening periods in a day block
     *
     * @since  2.0.0
     * @param  {object} elem		   The clicked element
     * @return {string} currentPeriods The ammount of period divs found
     */
    function currentPeriodCount( elem ) {
        var currentPeriods = elem.parents( "tr" ).find( ".wpsl-current-period" ).length;

        return currentPeriods;
    }

    /**
     * Create an option list with the correct opening hour format and interval
     *
     * @since  2.0.0
     * @param  {string} returnList Whether to return the option list or call the setSelectedOpeningHours function
     * @return {mixed}  optionList The html for the option list of or void
     */
    function createHourOptionList( returnList ) {
        var openingHours, openingHourInterval, hour, hrFormat,
            pm   			   = false,
            twelveHrsAfternoon = false,
            pmOrAm			   = "",
            optionList		   = "",
            openingTimes 	   = [],
            openingHourOptions = {
                "hours": {
                    "hr12": [ 12, 1, 2, 3 ,4 ,5 ,6, 7, 8, 9, 10, 11, 12, 1, 2, 3 , 4, 5, 6, 7, 8, 9, 10, 11 ],
                    "hr24": [ 0, 1, 2, 3 ,4 ,5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ,16, 17, 18, 19, 20, 21, 22, 23 ]
                },
                "interval": [ '00', '15', '30', '45' ]
            };

        if ( $( "#wpsl-editor-hour-format" ).length ) {
            hrFormat = $( "#wpsl-editor-hour-format" ).val();
        } else {
            hrFormat = wpslSettings.hourFormat;
        }

        $( "#wpsl-store-hours td" ).removeAttr( "style" );

        if ( hrFormat == 12 ) {
            $( "#wpsl-store-hours" ).removeClass().addClass( "wpsl-twelve-format" );
            openingHours = openingHourOptions.hours.hr12;
        } else {
            $( "#wpsl-store-hours" ).removeClass().addClass( "wpsl-twentyfour-format" );
            openingHours = openingHourOptions.hours.hr24;
        }

        openingHourInterval = openingHourOptions.interval;

        for ( var i = 0; i < openingHours.length; i++ ) {
            hour = openingHours[i];

            /*
             * If the 12hr format is selected, then check if we need to show AM or PM.
             *
             * If the 24hr format is selected and the hour is a single digit
             * then we add a 0 to the start so 5:00 becomes 05:00.
             */
            if ( hrFormat == 12 ) {
                if ( hour >= 12 ) {
                    pm = ( twelveHrsAfternoon ) ? true : false;

                    twelveHrsAfternoon = true;
                }

                pmOrAm = ( pm ) ? "PM" : "AM";
            } else if ( ( hrFormat == 24 ) && ( hour.toString().length == 1 ) ) {
                hour = "0" + hour;
            }

            // Collect the new opening hour format and interval.
            for ( var j = 0; j < openingHourInterval.length; j++ ) {
                openingTimes.push( hour + ":" + openingHourInterval[j] + " " + pmOrAm );
            }
        }

        // Create the <option> list.
        for ( var i = 0; i < openingTimes.length; i++ ) {
            optionList = optionList + '<option value="' + $.trim( openingTimes[i] ) + '">' + $.trim( openingTimes[i] ) + '</option>';
        }

        if ( returnList ) {
            return optionList;
        } else {
            setSelectedOpeningHours( optionList, hrFormat );
        }
    }

    /**
     * Set the correct selected opening hour in the dropdown
     *
     * @since  2.0.0
     * @param  {string} optionList The html for the option list
     * @param  {string} hrFormat   The html for the option list
     * @return {void}
     */
    function setSelectedOpeningHours( optionList, hrFormat ) {
        var splitHour, hourType, periodBlock,
            hours = {};

        /*
         * Loop over each open/close block and make sure the selected
         * value is still set as selected after changing the hr format.
         */
        $( ".wpsl-current-period" ).each( function() {
            periodBlock = $( this ),
                hours 		= {
                    "open": $( this ).find( ".wpsl-open-hour" ).val(),
                    "close": $( this ).find( ".wpsl-close-hour" ).val()
                };

            // Set the new hour format for both dropdowns.
            $( this ).find( "select" ).html( optionList ).promise().done( function() {

                // Select the correct start/end hours as selected.
                for ( var key in hours ) {
                    if ( hours.hasOwnProperty( key ) ) {

                        // Breakup the hour, so we can check the part before and after the : separately.
                        splitHour = hours[key].split( ":" );

                        if ( hrFormat == 12 ) {
                            hourType = "";

                            // Change the hours to a 12hr format and add the correct AM or PM.
                            if ( hours[key].charAt( 0 ) == 0 ) {
                                hours[key] = hours[key].substr( 1 );
                                hourType   = " AM";
                            } else if ( ( splitHour[0].length == 2 ) && ( splitHour[0] > 12 ) ) {
                                hours[key] = ( splitHour[0] - 12 ) + ":" + splitHour[1];
                                hourType   = " PM";
                            } else if ( splitHour[0] < 12 ) {
                                hours[key] = splitHour[0] + ":" + splitHour[1];
                                hourType   = " AM";
                            } else if ( splitHour[0] == 12 ) {
                                hours[key] = splitHour[0] + ":" + splitHour[1];
                                hourType   = " PM";
                            }

                            // Add either AM or PM behind the time.
                            if ( ( splitHour[1].indexOf( "PM" ) == -1 ) && ( splitHour[1].indexOf( "AM" ) == -1 ) ) {
                                hours[key] = hours[key] + hourType;
                            }

                        } else if ( hrFormat == 24 ) {

                            // Change the hours to a 24hr format and remove the AM or PM.
                            if ( splitHour[1].indexOf( "PM" ) != -1 ) {
                                if ( splitHour[0] == 12 ) {
                                    hours[key] = "12:" + splitHour[1].replace( " PM", "" );
                                } else {
                                    hours[key] = ( + splitHour[0] + 12 ) + ":" + splitHour[1].replace( " PM", "" );
                                }
                            } else if ( splitHour[1].indexOf( "AM" ) != -1 ) {
                                if ( splitHour[0].toString().length == 1 ) {
                                    hours[key] = "0" + splitHour[0] + ":" + splitHour[1].replace( " AM", "" );
                                } else {
                                    hours[key] = splitHour[0] + ":" + splitHour[1].replace( " AM", "" );
                                }
                            } else {
                                hours[key] = splitHour[0] + ":" + splitHour[1]; // When the interval is changed
                            }
                        }

                        // Set the correct value as the selected one.
                        periodBlock.find( ".wpsl-" + key + "-hour option[value='" + $.trim( hours[key] ) + "']" ).attr( "selected", "selected" );
                    }
                }

            });
        });
    }

    // Update the opening hours format if one of the dropdown values change.
    $( "#wpsl-editor-hour-format, #wpsl-editor-hour-interval" ).on( "change", function() {
        createHourOptionList();
    });

    // Show the tooltips.
    $( ".wpsl-info" ).on( "mouseover", function() {
        $( this ).find( ".wpsl-info-text" ).show();
    });

    $( ".wpsl-info" ).on( "mouseout", function() {
        $( this ).find( ".wpsl-info-text" ).hide();
    });

    // If the start location is empty, then we color the info icon red instead of black.
    if ( $( "#wpsl-latlng" ).length && !$( "#wpsl-latlng" ).val() ) {
        $( "#wpsl-latlng" ).siblings( "label" ).find( ".wpsl-info" ).addClass( "wpsl-required-setting" );
    }

    /**
     * Try to apply the custom style data to the map.
     *
     * If the style data is invalid json we show an error.
     *
     * @since  2.0.0
     * @return {void}
     */
    function tryCustomMapStyle() {
        var validStyle = "",
            mapStyle   = $.trim( $( "#wpsl-map-style" ).val() );

        $( ".wpsl-style-preview-error" ).remove();

        if ( mapStyle ) {

            // Make sure the data is valid json.
            validStyle = tryParseJSON( mapStyle );

            if ( !validStyle ) {
                $( "#wpsl-style-preview" ).after( "<div class='wpsl-style-preview-error'>" + wpslL10n.styleError + "</div>" );
            }
        }

        map.setOptions({ styles: validStyle });
    }

    // Handle the map style changes on the settings page.
    if ( $( "#wpsl-map-style" ).val() ) {
        tryCustomMapStyle();
    }

    // Handle clicks on the map style preview button.
    $( "#wpsl-style-preview" ).on( "click", function() {
        tryCustomMapStyle();

        return false;
    });

    /**
     * Make sure the JSON is valid.
     *
     * @link   http://stackoverflow.com/a/20392392/1065294
     * @since  2.0.0
     * @param  {string} jsonString The JSON data
     * @return {object|boolean}	   The JSON string or false if it's invalid json.
     */
    function tryParseJSON( jsonString ) {

        try {
            var o = JSON.parse( jsonString );

            /*
             * Handle non-exception-throwing cases:
             * Neither JSON.parse(false) or JSON.parse(1234) throw errors, hence the type-checking,
             * but... JSON.parse(null) returns 'null', and typeof null === "object",
             * so we must check for that, too.
             */
            if ( o && typeof o === "object" && o !== null ) {
                return o;
            }
        }
        catch ( e ) { }

        return false;
    }

    // Make sure the custom error notices can be removed
    $( "#wpsl-wrap" ).on( "click", "button.notice-dismiss", function() {
        $( this ).closest( 'div.notice' ).remove();
    });

    /**
     * Handle the red warning that's shown next to the
     * force zipcode search option if the autocomplete
     * value is changed.
     *
     * The autocomplete option itself doesn't support
     * zip only searches, so having both of them enabled
     * gives the user the wrong expectation.
     */
    $( "#wpsl-search-autocomplete, #wpsl-force-postalcode" ).change( function() {
        var $info = $( "#wpsl-force-postalcode" ).parent( "p" ).find( ".wpsl-info-zip-only" );

        if ( $( "#wpsl-search-autocomplete" ).is( ":checked" ) && $( "#wpsl-force-postalcode" ).is( ":checked" ) ) {
            $info.show();
        } else {
            $info.hide();
        }
    });

    $( "#wpsl-delay-loading" ).change( function() {
        if ( $( this ).is( ":checked" ) ) {
            $( this ).parent( "p" ).find( ".wpsl-info" ).trigger( "mouseover" );
        } else {
            $( this ).parent( "p" ).find( ".wpsl-info" ).trigger( "mouseout" );
        }
    });

    $( "#wpsl-wrap" ).on( "click", function( e ) {
        $( ".wpsl-info-text" ).hide();
    });
});admin/js/wpsl-shortcode-generator.js000064400000010643151327220640013555 0ustar00/**
 * Insert the WPSL shortcode
 *
 * Grab the values from the thickbox form
 * and use them to set the wpsl shortcode attributes.
 *
 * @since 2.2.10
 */
function WPSL_InsertShortcode() {
    var markers, shortcodeAtts, checkboxColumns, catSelectionID, catSelection,
        win            = window.dialogArguments || opener || parent || top,
        startLocation  = jQuery( "#wpsl-start-location" ).val(),
        catFilterType  = jQuery( "#wpsl-cat-filter-types" ).val(),
        catRestriction = jQuery( "#wpsl-cat-restriction" ).val(),
        locateUser     = ( jQuery( "#wpsl-auto-locate" ).is( ":checked" ) ) ? true : false;

    shortcodeAtts = 'template="' + jQuery( "#wpsl-store-template" ).val() + '" map_type="' + jQuery( "#wpsl-map-type" ).val() + '" auto_locate="' + locateUser + '"';

    // Grab the values for the selected markers
    markers = WPSL_Selected_Markers();

    if ( typeof markers.start !== "undefined" ) {
        shortcodeAtts += ' start_marker="' + markers.start + '"';
    }

    if ( typeof markers.store !== "undefined" ) {
        shortcodeAtts += ' store_marker="' + markers.store + '"';
    }

    if ( startLocation ) {
        shortcodeAtts += ' start_location="' + startLocation + '"';
    }

    if ( typeof catRestriction !== "undefined" && catRestriction !== null && !catFilterType ) {
        shortcodeAtts += ' category="' + catRestriction + '"';
    }

    // Make sure we target the correct ID based on the filter type selection.
    if ( catFilterType == "dropdown" ) {
        catSelectionID = "wpsl-cat-selection";
    } else {
        catSelectionID = "wpsl-checkbox-selection";
    }

    catSelection = jQuery( '#' + catSelectionID + '' ).val();

    if ( catSelection ) {
        shortcodeAtts += ' category_selection="' + catSelection + '"';
    }

    if ( catFilterType ) {
        shortcodeAtts += ' category_filter_type="' + catFilterType + '"';
    }

    if ( catFilterType == "checkboxes" ) {
        checkboxColumns = parseInt( jQuery( "#wpsl-checkbox-columns" ).val() );

        if ( typeof checkboxColumns === 'number' ) {
            shortcodeAtts += ' checkbox_columns="' + checkboxColumns + '"';
        }
    }

    // Send the collected shortcode attributes to the editor
    win.send_to_editor("[wpsl " + shortcodeAtts + "]");
}

function WPSL_Selected_Markers() {
    var startMarker, storeMarker,
        markers = [],
        selectedMarkers = {};

    jQuery( ".wpsl-marker-list ").each( function( i ) {
        markers.push( jQuery( ".wpsl-marker-list:eq(" + i + " ) .wpsl-active-marker input" ).val());
    });

    if ( markers.length == 2 ) {
        startMarker = markers[0].split( "." );
        storeMarker = markers[1].split( "." );

        if ( typeof startMarker[0] !== "undefined" ) {
            selectedMarkers.start = startMarker[0];
        }

        if ( typeof storeMarker[0] !== "undefined" ) {
            selectedMarkers.store = storeMarker[0];
        }
    }

    return selectedMarkers;
}

jQuery( document ).ready( function( $ ) {
    $( "#wpsl-media-tabs" ).tabs();

    // Show the tooltips.
    $( ".wpsl-info" ).on( "mouseover", function() {
        $(this).find(".wpsl-info-text").show();
    });

    $( ".wpsl-info" ).on( "mouseout", function() {
        $(this).find( ".wpsl-info-text" ).hide();
    });

    $( ".wpsl-marker-list input[type=radio]" ).click( function() {
        $( this ).parents( ".wpsl-marker-list" ).find( "li" ).removeClass();
        $( this ).parent( "li" ).addClass( "wpsl-active-marker" );
    });

    $( ".wpsl-marker-list li" ).click( function() {
        $( this ).parents( ".wpsl-marker-list" ).find( "input" ).prop( "checked", false );
        $( this ).find( "input" ).prop( "checked", true );
        $( this ).siblings().removeClass();
        $( this ).addClass( "wpsl-active-marker" );
    });

    $( "#wpsl-cat-filter-types" ).change( function() {
        var filterType = $( this ).val();

        if ( filterType == 'dropdown' ) {
            $( ".wpsl-cat-selection" ).show();
            $( ".wpsl-checkbox-options, .wpsl-cat-restriction, .wpsl-checkbox-selection" ).hide();
        } else if ( filterType == 'checkboxes' ) {
            $( ".wpsl-cat-selection, .wpsl-cat-restriction" ).hide();
            $( ".wpsl-checkbox-options, .wpsl-checkbox-selection" ).show();
        } else {
            $( ".wpsl-cat-restriction" ).show();
            $( ".wpsl-checkbox-options, .wpsl-cat-selection, .wpsl-checkbox-selection" ).hide();
        }
    });
});admin/js/ajax-queue.js000064400000002401151327220640010652 0ustar00/*
* jQuery.ajaxQueue - A queue for ajax requests
*
* (c) 2011 Corey Frang
* Dual licensed under the MIT and GPL licenses.
*
* Requires jQuery 1.5+
*/ 
(function($) {

// jQuery on an empty object, we are going to use this as our Queue
var ajaxQueue = $({});

$.ajaxQueue = function( ajaxOpts ) {
    var jqXHR,
        dfd = $.Deferred(),
        promise = dfd.promise();

    // run the actual query
    function doRequest( next ) {
        jqXHR = $.ajax( ajaxOpts );
        jqXHR.done( dfd.resolve )
            .fail( dfd.reject )
            .then( next, next );
    }

    // queue our ajax request
    ajaxQueue.queue( doRequest );

    // add the abort method
    promise.abort = function( statusText ) {

        // proxy abort to the jqXHR if it is active
        if ( jqXHR ) {
            return jqXHR.abort( statusText );
        }

        // if there wasn't already a jqXHR we need to remove from queue
        var queue = ajaxQueue.queue(),
            index = $.inArray( doRequest, queue );

        if ( index > -1 ) {
            queue.splice( index, 1 );
        }

        // and then reject the deferred
        dfd.rejectWith( ajaxOpts.context || ajaxOpts, [ promise, statusText, "" ] );
        return promise;
    };

    return promise;
};

})(jQuery);
admin/js/ajax-queue.min.js000064400000001016151327220640011435 0ustar00(function($){var ajaxQueue=$({});$.ajaxQueue=function(ajaxOpts){var jqXHR,dfd=$.Deferred(),promise=dfd.promise();function doRequest(next){jqXHR=$.ajax(ajaxOpts);jqXHR.done(dfd.resolve).fail(dfd.reject).then(next,next)}ajaxQueue.queue(doRequest);promise.abort=function(statusText){if(jqXHR){return jqXHR.abort(statusText)}var queue=ajaxQueue.queue(),index=$.inArray(doRequest,queue);if(index>-1){queue.splice(index,1)}dfd.rejectWith(ajaxOpts.context||ajaxOpts,[promise,statusText,""]);return promise};return promise}})(jQuery);admin/js/wpsl-admin.min.js000064400000035043151327220640011452 0ustar00jQuery(document).ready(function(e){var s,o,t,n,l,r=[],i=i||{};function a(n="wpsl-gmap-wrap"){var l,r,i,a,c=wpslSettings.defaultLatLng.split(",");t=new google.maps.LatLng(c[0],c[1]),l={zoom:parseInt(wpslSettings.defaultZoom),center:t,mapTypeId:google.maps.MapTypeId[wpslSettings.mapType.toUpperCase()],mapTypeControl:!1,streetViewControl:!1,zoomControlOptions:{position:google.maps.ControlPosition.RIGHT_TOP}},o=new google.maps.Geocoder,s=new google.maps.Map(document.getElementById(n),l),i=e("#wpsl-lat").val(),a=e("#wpsl-lng").val(),i&&a&&(r=new google.maps.LatLng(i,a),s.setCenter(r),s.setZoom(16),p(r))}function p(e,o=!0){var t=new google.maps.Marker({position:e,map:s,draggable:o});r.push(t),google.maps.event.addListener(t,"dragend",function(){c(t.getPosition(),"store")})}function c(s,o){var t=function(e){var s=[],o=e.toString().split(",",2);return s[0]=o[0].replace("(",""),s[1]=o[1].replace(")",""),s}(s),n=d(t[0]),l=d(t[1]);"store"==o?(e("#wpsl-lat").val(n),e("#wpsl-lng").val(l)):"zoom"==o&&e("#wpsl-latlng").val(n+","+l)}function d(e){return Math.round(e*Math.pow(10,6))/Math.pow(10,6)}function w(s){e("#wpsl-meta-nav li"+(s="first"==s?":first-child":"."+s)+"-tab").hasClass("wpsl-active")||(e("#wpsl-meta-nav li"+s+"-tab").addClass("wpsl-active").siblings().removeClass("wpsl-active"),e(".wpsl-store-meta > div"+s).show().addClass("wpsl-active").siblings("div").hide().removeClass("wpsl-active"))}function u(){e("#wpsl-store-hours .wpsl-icon-cancel-circled").off(),e("#wpsl-store-hours .wpsl-icon-cancel-circled").on("click",function(){!function(e){var s=g(e),o=e.parents("tr"),t=o.find(".wpsl-opening-hours").attr("data-day");1==s&&o.find(".wpsl-opening-hours").html("<p class='wpsl-store-closed'>"+wpslL10n.closedDate+"<input type='hidden' name='wpsl[hours]["+t+"_open]' value='' /></p>");e.parent().closest(".wpsl-current-period").remove(),o.find(".wpsl-opening-hours div:first-child").hasClass("wpsl-multiple-periods")&&o.find(".wpsl-opening-hours div:first-child").removeClass("wpsl-multiple-periods")}(e(this))})}function g(e){return e.parents("tr").find(".wpsl-current-period").length}function v(s){var o,t,n,l,r=!1,i=!1,a="",p="",c=[],d={hr12:[12,1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11],hr24:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]},w=["00","15","30","45"];l=e("#wpsl-editor-hour-format").length?e("#wpsl-editor-hour-format").val():wpslSettings.hourFormat,e("#wpsl-store-hours td").removeAttr("style"),12==l?(e("#wpsl-store-hours").removeClass().addClass("wpsl-twelve-format"),o=d.hr12):(e("#wpsl-store-hours").removeClass().addClass("wpsl-twentyfour-format"),o=d.hr24),t=w;for(var u=0;u<o.length;u++){n=o[u],12==l?(n>=12&&(r=!!i,i=!0),a=r?"PM":"AM"):24==l&&1==n.toString().length&&(n="0"+n);for(var g=0;g<t.length;g++)c.push(n+":"+t[g]+" "+a)}for(u=0;u<c.length;u++)p=p+'<option value="'+e.trim(c[u])+'">'+e.trim(c[u])+"</option>";if(s)return p;!function(s,o){var t,n,l,r={};e(".wpsl-current-period").each(function(){l=e(this),r={open:e(this).find(".wpsl-open-hour").val(),close:e(this).find(".wpsl-close-hour").val()},e(this).find("select").html(s).promise().done(function(){for(var s in r)r.hasOwnProperty(s)&&(t=r[s].split(":"),12==o?(n="",0==r[s].charAt(0)?(r[s]=r[s].substr(1),n=" AM"):2==t[0].length&&t[0]>12?(r[s]=t[0]-12+":"+t[1],n=" PM"):t[0]<12?(r[s]=t[0]+":"+t[1],n=" AM"):12==t[0]&&(r[s]=t[0]+":"+t[1],n=" PM"),-1==t[1].indexOf("PM")&&-1==t[1].indexOf("AM")&&(r[s]=r[s]+n)):24==o&&(-1!=t[1].indexOf("PM")?12==t[0]?r[s]="12:"+t[1].replace(" PM",""):r[s]=+t[0]+12+":"+t[1].replace(" PM",""):-1!=t[1].indexOf("AM")?1==t[0].toString().length?r[s]="0"+t[0]+":"+t[1].replace(" AM",""):r[s]=t[0]+":"+t[1].replace(" AM",""):r[s]=t[0]+":"+t[1]),l.find(".wpsl-"+s+"-hour option[value='"+e.trim(r[s])+"']").attr("selected","selected"))})})}(p,l)}function h(){var o="",t=e.trim(e("#wpsl-map-style").val());e(".wpsl-style-preview-error").remove(),t&&((o=function(e){try{var s=JSON.parse(e);if(s&&"object"==typeof s&&null!==s)return s}catch(e){}return!1}(t))||e("#wpsl-style-preview").after("<div class='wpsl-style-preview-error'>"+wpslL10n.styleError+"</div>")),s.setOptions({styles:o})}i.verifyKeys={init:function(){var s=this,o=e("#wpsl-verify-keys"),t=wpslSettings.url+"img/ajax-loader.gif",n=void 0!==wpslSettings.mapService?wpslSettings.mapService:"gmaps";o.on("click",function(){return e("#wpsl-wrap .notice").remove(),s[n].check(),o.after('<img src="'+t+'" class="wpsl-api-key-preloader" />'),!1})},showStatus:function(s,o,t="error"){this.createNotice(s,o,t),"browser"==o&&e(".wpsl-api-key-preloader").remove()},createNotice:function(s,o,t){var n,l;n='<div class="'+("error"==t?"error":"updated")+' notice is-dismissible">',n+="<p><strong>"+s+"</strong></p>",n+='<button type="button" class="notice-dismiss"><span class="screen-reader-text">'+wpslL10n.dismissNotice+"</span></button>",n+="</div>",l=e("#wpsl-tabs").length?"wpsl-tabs":"wpsl-settings-form",e("#"+l).before(n),"error"==t?e("#wpsl-api-"+o+"-key").addClass("wpsl-error"):e("#wpsl-api-"+o+"-key").removeClass("wpsl-error")},gmaps:{check:function(){this.server(function(){i.verifyKeys.gmaps.browser()})},server:function(s){var o,t={action:"validate_server_key",server_key:e("#wpsl-api-server-key").val()};t.server_key?e.get(wpslSettings.ajaxurl,t,function(e){o=e.valid?"updated":"error",i.verifyKeys.showStatus(e.msg,"server",o),s()}):(i.verifyKeys.showStatus(wpslL10n.serverKeyMissing,"server"),s())},browser:function(){var s;e("#wpsl-api-browser-key").val()?(s=setInterval(function(){i.verifyKeys.showStatus(wpslL10n.browserKeyError,"browser"),clearInterval(s)},3e3),o.geocode({address:"Manhattan, NY 10036, USA"},function(e,o){o==google.maps.GeocoderStatus.OK?i.verifyKeys.showStatus(wpslL10n.browserKeySuccess,"browser","success"):i.verifyKeys.showStatus(wpslL10n.browserKeyError,"browser"),clearInterval(s)})):i.verifyKeys.showStatus(wpslL10n.browserKeyMissing,"browser")}}},i.showApiResponse={init:function(){var o=e("#wpsl-geocode-input"),t=this,n=!1;e("#wpsl-show-geocode-response").on("click",function(o){return t.createDialog(),a("wpsl-geocode-preview"),e(".wpsl-geocode-warning span").length||t.createRestrictionsMsg(),google.maps.event.addListenerOnce(s,"tilesloaded",function(){n=!0,t.checkQuotaError()}),setTimeout(function(){n||(e(".wpsl-geocode-warning, #wpsl-geocode-test input, #wpsl-geocode-tabs").remove(),e(".wpsl-geocode-api-notice").show().html(wpslL10n.loadingFailed))},1e3),!1}),e("#wpsl-geocode-submit").on("click",function(s){o.removeClass("wpsl-error"),o.val()?t.geocoding.makeRequest():(o.addClass("wpsl-error"),e(".wpsl-geocode-api-notice").hide())}),e("#wpsl-geocode-test").keydown(function(s){13==(s.keyCode?s.keyCode:s.which)&&e("#wpsl-geocode-submit").trigger("click")})},createDialog:function(){e("#wpsl-geocode-test").dialog({resizable:!1,height:"auto",width:550,modal:!0,open:function(){e(this).parent().css({top:window.pageYOffset+50}),e("#wpsl-geocode-tabs").tabs(),e("#wpsl-geocode-input").focus(),e(".wpsl-geocode-api-notice").hide(),e("#wpsl-geocode-tabs").tabs("option","active",e("li").index(e("li:visible:eq(0)"))),e("#wpsl-geocode-input, #wpsl-geocode-response textarea").val(""),e(".ui-widget-overlay").bind("click",function(){e("#wpsl-geocode-test").dialog("close")})},buttons:{Cancel:function(){e(this).dialog("close")}}})},checkQuotaError:function(){setTimeout(function(){e("#wpsl-geocode-preview .dismissButton").length>0&&(e(".wpsl-geocode-warning, #wpsl-geocode-test input").remove(),e(".wpsl-geocode-api-notice").show(),e(".wpsl-geocode-api-notice span").html(wpslL10n.loadingError))},1e3)},createRestrictionsMsg:function(){var s,o,t=e(".wpsl-geocode-warning").show().find("strong");e("#wpsl-api-region").val()?(s=e("#wpsl-api-region option:selected").text(),o=e("#wpsl-force-postalcode").is(":checked")?wpslL10n.restrictedZipCode:"",t.after("<span>"+wpslL10n.resultsWarning+" "+s+" "+o+"</span>")):(t.after("<span>"+wpslL10n.noRestriction+"</span>"),e(".wpsl-region-href").on("click",function(){e(".ui-widget-overlay").trigger("click")}))},geocoding:{makeRequest:function(){var n=this.createParams();o.geocode(n,function(o,n){"OK"==n||"ZERO_RESULTS"==n?(void 0!==r[0]&&(r[0].setMap(null),r.length=0),"OK"==n?(p(o[0].geometry.location,!1),s.setZoom(12),s.setCenter(o[0].geometry.location)):(s.setZoom(parseInt(wpslSettings.defaultZoom)),s.setCenter(t))):(n=wpslL10n.browserKeyError,e("#wpsl-geocode-preview, #wpsl-geocode-response textarea").remove()),e(".wpsl-geocode-api-notice").show(),e(".wpsl-geocode-api-notice span").html(n),e("#wpsl-geocode-response textarea").val(JSON.stringify(o,null,4))})},createParams:function(){var s={};return void 0===wpslSettings.geocodeComponents||e.isEmptyObject(wpslSettings.geocodeComponents)?s.address=e("#wpsl-geocode-input").val():(s.componentRestrictions=wpslSettings.geocodeComponents,void 0!==s.componentRestrictions.postalCode?s.componentRestrictions.postalCode=e("#wpsl-geocode-input").val():s.address=e("#wpsl-geocode-input").val()),s}}},e("#wpsl-gmap-wrap").length&&a(),e("#wpsl-map-settings").length&&(i.verifyKeys.init(),i.showApiResponse.init()),e("#wpsl-start-name").length&&(n=document.getElementById("wpsl-start-name"),l=new google.maps.places.Autocomplete(n,{types:["geocode"]}),google.maps.event.addListener(l,"place_changed",function(){c(l.getPlace().geometry.location,"zoom")})),e("#wpsl-lookup-location").on("click",function(t){var n,l;t.preventDefault(),!function(){var s,o,t=!1;if(e(".wpsl-store-meta input").removeClass("wpsl-error"),void 0!==wpslSettings.requiredFields&&_.isArray(wpslSettings.requiredFields))for(o=wpslSettings.requiredFields,s=0;s<o.length;s++)e.trim(e("#wpsl-"+o[s]).val())||(e("#wpsl-"+o[s]).addClass("wpsl-error"),t=!0);return t}()?(l=function(){var s,o,t=[],n=["address","city","state","zip","country"];for(s=0;s<n.length;s++)(o=e.trim(e("#wpsl-"+n[s]).val()))&&t.push(o),o="";return t.join()}(),o.geocode({address:l},function(o,t){t===google.maps.GeocoderStatus.OK?(void 0!==r[0]&&r[0].draggable&&(r[0].setMap(null),r.splice(0,1)),s.setCenter(o[0].geometry.location),s.setZoom(16),p(o[0].geometry.location),c(o[0].geometry.location,"store"),n=function(e){var s,o,t={},n=e[0].address_components.length;for(s=0;s<n;s++)o=e[0].address_components[s].types,/^country,political$/.test(o)&&(t={long_name:e[0].address_components[s].long_name,short_name:e[0].address_components[s].short_name});return{country:t}}(o),e("#wpsl-country").val(n.country.long_name),e("#wpsl-country_iso").val(n.country.short_name)):alert(wpslL10n.geocodeFail+": "+t)})):(w("first"),alert(wpslL10n.missingGeoData))}),e(".wpsl-marker-list input[type=radio]").click(function(){e(this).parents(".wpsl-marker-list").find("li").removeClass(),e(this).parent("li").addClass("wpsl-active-marker")}),e(".wpsl-marker-list li").click(function(){e(this).parents(".wpsl-marker-list").find("input").prop("checked",!1),e(this).find("input").prop("checked",!0),e(this).siblings().removeClass(),e(this).addClass("wpsl-active-marker")}),e(".wpsl-has-conditional-option").on("change",function(){e(this).parent().next(".wpsl-conditional-option").toggle()}),e("#wpsl-store-template").on("change",function(){var s=e("#wpsl-listing-below-no-scroll");"below_map"==e(this).val()?s.show():s.hide()}),e("#wpsl-api-region").on("change",function(){var s=e("#wpsl-geocode-component");e(this).val()?s.show():s.hide()}),e("#wpsl-editor-hour-input").on("change",function(){e(".wpsl-"+e(this).val()+"-hours").show().siblings("div").hide(),e(".wpsl-hour-notice").toggle()}),e("#wpsl-meta-nav li").on("click",function(s){var o=e(this).attr("class");o=o.split("-tab"),s.stopPropagation(),e(this).addClass("wpsl-active").siblings().removeClass("wpsl-active"),e(".wpsl-store-meta ."+o[0]).show().addClass("wpsl-active").siblings("div").hide().removeClass("wpsl-active")}),e("#wpsl-store-details").length&&e("#publish").click(function(){var s,o,t,n='<div id="message" class="error"><p>'+wpslL10n.requiredFields+"</p></div>",l=!1;return e("#wpbody-content .wrap #message").remove(),e(".wpsl-required").removeClass("wpsl-error"),e(".wpsl-required").each(function(){""==e(this).val()&&(e(this).addClass("wpsl-error"),void 0===s&&(s=function(e){var s={type:"id",val:e.attr("id")};void 0===s.val&&(s={type:"class",val:e.attr("class")});return s}(e(this))),l=!0)}),!l||(e("#wpbody-content .wrap > h2").after(n),void 0!==s.val&&("id"==s.type?(o=e("#"+s.val).parents(".wpsl-tab").attr("class"),e("html, body").scrollTop(Math.round(e("#"+s.val).offset().top-100))):"class"==s.type&&(t=s.val.replace(/wpsl-required|wpsl-error/g,""),o=e("."+t).parents(".wpsl-tab").attr("class"),e("html, body").scrollTop(Math.round(e("."+t).offset().top-100))),o=e.trim(o.replace(/wpsl-tab|wpsl-active/g,""))),w(o||"first"),e("#publish").removeClass("button-primary-disabled"),e(".spinner").hide(),!1)}),e("#wpsl-store-hours").length&&u(),e(".wpsl-add-period").on("click",function(s){var o,t={},n=e(this).parents("tr"),l=g(e(this))>=1?"wpsl-current-period wpsl-multiple-periods":"wpsl-current-period",r=n.find(".wpsl-opening-hours").attr("data-day"),i=e("#wpsl-settings-form").length?"wpsl_editor[dropdown]":"wpsl[hours]";o='<div class="'+l+'">',o+='<select autocomplete="off" name="'+i+"["+r+'_open][]" class="wpsl-open-hour">'+v(!0)+"</select>",o+="<span> - </span>",o+='<select autocomplete="off" name="'+i+"["+r+'_close][]" class="wpsl-close-hour">'+v(!0)+"</select>",o+='<div class="wpsl-icon-cancel-circled"></div>',o+="</div>",n.find(".wpsl-store-closed").remove(),e("#wpsl-hours-"+r).append(o).end(),u(),t=24==e("#wpsl-editor-hour-format").val()?{open:"09:00",close:"17:00"}:{open:"9:00 AM",close:"5:00 PM"},n.find(".wpsl-open-hour:last option[value='"+t.open+"']").attr("selected","selected"),n.find(".wpsl-close-hour:last option[value='"+t.close+"']").attr("selected","selected"),s.preventDefault()}),e("#wpsl-editor-hour-format, #wpsl-editor-hour-interval").on("change",function(){v()}),e(".wpsl-info").on("mouseover",function(){e(this).find(".wpsl-info-text").show()}),e(".wpsl-info").on("mouseout",function(){e(this).find(".wpsl-info-text").hide()}),e("#wpsl-latlng").length&&!e("#wpsl-latlng").val()&&e("#wpsl-latlng").siblings("label").find(".wpsl-info").addClass("wpsl-required-setting"),e("#wpsl-map-style").val()&&h(),e("#wpsl-style-preview").on("click",function(){return h(),!1}),e("#wpsl-wrap").on("click","button.notice-dismiss",function(){e(this).closest("div.notice").remove()}),e("#wpsl-search-autocomplete, #wpsl-force-postalcode").change(function(){var s=e("#wpsl-force-postalcode").parent("p").find(".wpsl-info-zip-only");e("#wpsl-search-autocomplete").is(":checked")&&e("#wpsl-force-postalcode").is(":checked")?s.show():s.hide()}),e("#wpsl-delay-loading").change(function(){e(this).is(":checked")?e(this).parent("p").find(".wpsl-info").trigger("mouseover"):e(this).parent("p").find(".wpsl-info").trigger("mouseout")}),e("#wpsl-wrap").on("click",function(s){e(".wpsl-info-text").hide()})});admin/EDD_SL_Plugin_Updater.php000064400000044030151327220640012344 0ustar00<?php

// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) exit;

/**
 * Allows plugins to use their own update API.
 *
 * @author Easy Digital Downloads
 * @version 1.6.19
 */
class EDD_SL_Plugin_Updater {

	private $api_url     = '';
	private $api_data    = array();
	private $name        = '';
	private $slug        = '';
	private $version     = '';
	private $wp_override = false;
	private $cache_key   = '';

	private $health_check_timeout = 5;

	/**
	 * Class constructor.
	 *
	 * @uses plugin_basename()
	 * @uses hook()
	 *
	 * @param string  $_api_url     The URL pointing to the custom API endpoint.
	 * @param string  $_plugin_file Path to the plugin file.
	 * @param array   $_api_data    Optional data to send with API calls.
	 */
	public function __construct( $_api_url, $_plugin_file, $_api_data = null ) {

		global $edd_plugin_data;

		$this->api_url     = trailingslashit( $_api_url );
		$this->api_data    = $_api_data;
		$this->name        = plugin_basename( $_plugin_file );
		$this->slug        = basename( $_plugin_file, '.php' );
		$this->version     = $_api_data['version'];
		$this->wp_override = isset( $_api_data['wp_override'] ) ? (bool) $_api_data['wp_override'] : false;
		$this->beta        = ! empty( $this->api_data['beta'] ) ? true : false;
		$this->cache_key   = 'edd_sl_' . md5( serialize( $this->slug . $this->api_data['license'] . $this->beta ) );

		$edd_plugin_data[ $this->slug ] = $this->api_data;

		/**
		 * Fires after the $edd_plugin_data is setup.
		 *
		 * @since x.x.x
		 *
		 * @param array $edd_plugin_data Array of EDD SL plugin data.
		 */
		do_action( 'post_edd_sl_plugin_updater_setup', $edd_plugin_data );

		// Set up hooks.
		$this->init();

	}

	/**
	 * Set up WordPress filters to hook into WP's update process.
	 *
	 * @uses add_filter()
	 *
	 * @return void
	 */
	public function init() {

		add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) );
		add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
		remove_action( 'after_plugin_row_' . $this->name, 'wp_plugin_update_row', 10 );
		add_action( 'after_plugin_row_' . $this->name, array( $this, 'show_update_notification' ), 10, 2 );
		add_action( 'admin_init', array( $this, 'show_changelog' ) );

	}

	/**
	 * Check for Updates at the defined API endpoint and modify the update array.
	 *
	 * This function dives into the update API just when WordPress creates its update array,
	 * then adds a custom API call and injects the custom plugin data retrieved from the API.
	 * It is reassembled from parts of the native WordPress plugin update code.
	 * See wp-includes/update.php line 121 for the original wp_update_plugins() function.
	 *
	 * @uses api_request()
	 *
	 * @param array   $_transient_data Update array build by WordPress.
	 * @return array Modified update array with custom plugin data.
	 */
	public function check_update( $_transient_data ) {

		global $pagenow;

		if ( ! is_object( $_transient_data ) ) {
			$_transient_data = new stdClass;
		}

		if ( 'plugins.php' == $pagenow && is_multisite() ) {
			return $_transient_data;
		}

		if ( ! empty( $_transient_data->response ) && ! empty( $_transient_data->response[ $this->name ] ) && false === $this->wp_override ) {
			return $_transient_data;
		}

		$version_info = $this->get_cached_version_info();

		if ( false === $version_info ) {
			$version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug, 'beta' => $this->beta ) );

			$this->set_version_info_cache( $version_info );

		}

		if ( false !== $version_info && is_object( $version_info ) && isset( $version_info->new_version ) ) {

			if ( version_compare( $this->version, $version_info->new_version, '<' ) ) {

				$_transient_data->response[ $this->name ] = $version_info;

				// Make sure the plugin property is set to the plugin's name/location. See issue 1463 on Software Licensing's GitHub repo.
				$_transient_data->response[ $this->name ]->plugin = $this->name;

			}

			$_transient_data->last_checked           = time();
			$_transient_data->checked[ $this->name ] = $this->version;

		}

		return $_transient_data;
	}

	/**
	 * show update nofication row -- needed for multisite subsites, because WP won't tell you otherwise!
	 *
	 * @param string  $file
	 * @param array   $plugin
	 */
	public function show_update_notification( $file, $plugin ) {

		if ( is_network_admin() ) {
			return;
		}

		if( ! current_user_can( 'update_plugins' ) ) {
			return;
		}

		if( ! is_multisite() ) {
			return;
		}

		if ( $this->name != $file ) {
			return;
		}

		// Remove our filter on the site transient
		remove_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ), 10 );

		$update_cache = get_site_transient( 'update_plugins' );

		$update_cache = is_object( $update_cache ) ? $update_cache : new stdClass();

		if ( empty( $update_cache->response ) || empty( $update_cache->response[ $this->name ] ) ) {

			$version_info = $this->get_cached_version_info();

			if ( false === $version_info ) {
				$version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug, 'beta' => $this->beta ) );

				// Since we disabled our filter for the transient, we aren't running our object conversion on banners, sections, or icons. Do this now:
				if ( isset( $version_info->banners ) && ! is_array( $version_info->banners ) ) {
					$version_info->banners = $this->convert_object_to_array( $version_info->banners );
				}

				if ( isset( $version_info->sections ) && ! is_array( $version_info->sections ) ) {
					$version_info->sections = $this->convert_object_to_array( $version_info->sections );
				}

				if ( isset( $version_info->icons ) && ! is_array( $version_info->icons ) ) {
					$version_info->icons = $this->convert_object_to_array( $version_info->icons );
				}

				if ( isset( $version_info->icons ) && ! is_array( $version_info->icons ) ) {
					$version_info->icons = $this->convert_object_to_array( $version_info->icons );
				}

				if ( isset( $version_info->contributors ) && ! is_array( $version_info->contributors ) ) {
					$version_info->contributors = $this->convert_object_to_array( $version_info->contributors );
				}

				$this->set_version_info_cache( $version_info );
			}

			if ( ! is_object( $version_info ) ) {
				return;
			}

			if ( version_compare( $this->version, $version_info->new_version, '<' ) ) {

				$update_cache->response[ $this->name ] = $version_info;

			}

			$update_cache->last_checked = time();
			$update_cache->checked[ $this->name ] = $this->version;

			set_site_transient( 'update_plugins', $update_cache );

		} else {

			$version_info = $update_cache->response[ $this->name ];

		}

		// Restore our filter
		add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) );

		if ( ! empty( $update_cache->response[ $this->name ] ) && version_compare( $this->version, $version_info->new_version, '<' ) ) {

			// build a plugin list row, with update notification
			$wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
			# <tr class="plugin-update-tr"><td colspan="' . $wp_list_table->get_column_count() . '" class="plugin-update colspanchange">
			echo '<tr class="plugin-update-tr" id="' . $this->slug . '-update" data-slug="' . $this->slug . '" data-plugin="' . $this->slug . '/' . $file . '">';
			echo '<td colspan="3" class="plugin-update colspanchange">';
			echo '<div class="update-message notice inline notice-warning notice-alt">';

			$changelog_link = self_admin_url( 'index.php?edd_sl_action=view_plugin_changelog&plugin=' . $this->name . '&slug=' . $this->slug . '&TB_iframe=true&width=772&height=911' );

			if ( empty( $version_info->download_link ) ) {
				printf(
					__( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s.', 'easy-digital-downloads' ),
					esc_html( $version_info->name ),
					'<a target="_blank" class="thickbox" href="' . esc_url( $changelog_link ) . '">',
					esc_html( $version_info->new_version ),
					'</a>'
				);
			} else {
				printf(
					__( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s or %5$supdate now%6$s.', 'easy-digital-downloads' ),
					esc_html( $version_info->name ),
					'<a target="_blank" class="thickbox" href="' . esc_url( $changelog_link ) . '">',
					esc_html( $version_info->new_version ),
					'</a>',
					'<a href="' . esc_url( wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $this->name, 'upgrade-plugin_' . $this->name ) ) .'">',
					'</a>'
				);
			}

			do_action( "in_plugin_update_message-{$file}", $plugin, $version_info );

			echo '</div></td></tr>';
		}
	}

	/**
	 * Updates information on the "View version x.x details" page with custom data.
	 *
	 * @uses api_request()
	 *
	 * @param mixed   $_data
	 * @param string  $_action
	 * @param object  $_args
	 * @return object $_data
	 */
	public function plugins_api_filter( $_data, $_action = '', $_args = null ) {

		if ( $_action != 'plugin_information' ) {

			return $_data;

		}

		if ( ! isset( $_args->slug ) || ( $_args->slug != $this->slug ) ) {

			return $_data;

		}

		$to_send = array(
			'slug'   => $this->slug,
			'is_ssl' => is_ssl(),
			'fields' => array(
				'banners' => array(),
				'reviews' => false,
				'icons'   => array(),
			)
		);

		$cache_key = 'edd_api_request_' . md5( serialize( $this->slug . $this->api_data['license'] . $this->beta ) );

		// Get the transient where we store the api request for this plugin for 24 hours
		$edd_api_request_transient = $this->get_cached_version_info( $cache_key );

		//If we have no transient-saved value, run the API, set a fresh transient with the API value, and return that value too right now.
		if ( empty( $edd_api_request_transient ) ) {

			$api_response = $this->api_request( 'plugin_information', $to_send );

			// Expires in 3 hours
			$this->set_version_info_cache( $api_response, $cache_key );

			if ( false !== $api_response ) {
				$_data = $api_response;
			}

		} else {
			$_data = $edd_api_request_transient;
		}

		// Convert sections into an associative array, since we're getting an object, but Core expects an array.
		if ( isset( $_data->sections ) && ! is_array( $_data->sections ) ) {
			$_data->sections = $this->convert_object_to_array( $_data->sections );
		}

		// Convert banners into an associative array, since we're getting an object, but Core expects an array.
		if ( isset( $_data->banners ) && ! is_array( $_data->banners ) ) {
			$_data->banners = $this->convert_object_to_array( $_data->banners );
		}

		// Convert icons into an associative array, since we're getting an object, but Core expects an array.
		if ( isset( $_data->icons ) && ! is_array( $_data->icons ) ) {
			$_data->icons = $this->convert_object_to_array( $_data->icons );
		}

		// Convert contributors into an associative array, since we're getting an object, but Core expects an array.
		if ( isset( $_data->contributors ) && ! is_array( $_data->contributors ) ) {
			$_data->contributors = $this->convert_object_to_array( $_data->contributors );
		}

		if( ! isset( $_data->plugin ) ) {
			$_data->plugin = $this->name;
		}

		return $_data;
	}

	/**
	 * Convert some objects to arrays when injecting data into the update API
	 *
	 * Some data like sections, banners, and icons are expected to be an associative array, however due to the JSON
	 * decoding, they are objects. This method allows us to pass in the object and return an associative array.
	 *
	 * @since 3.6.5
	 *
	 * @param stdClass $data
	 *
	 * @return array
	 */
	private function convert_object_to_array( $data ) {
		$new_data = array();
		foreach ( $data as $key => $value ) {
			$new_data[ $key ] = is_object( $value ) ? $this->convert_object_to_array( $value ) : $value;
		}

		return $new_data;
	}

	/**
	 * Disable SSL verification in order to prevent download update failures
	 *
	 * @param array   $args
	 * @param string  $url
	 * @return object $array
	 */
	public function http_request_args( $args, $url ) {

		$verify_ssl = $this->verify_ssl();
		if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
			$args['sslverify'] = $verify_ssl;
		}
		return $args;

	}

	/**
	 * Calls the API and, if successfull, returns the object delivered by the API.
	 *
	 * @uses get_bloginfo()
	 * @uses wp_remote_post()
	 * @uses is_wp_error()
	 *
	 * @param string  $_action The requested action.
	 * @param array   $_data   Parameters for the API action.
	 * @return false|object
	 */
	private function api_request( $_action, $_data ) {

		global $wp_version, $edd_plugin_url_available;

		$verify_ssl = $this->verify_ssl();

		// Do a quick status check on this domain if we haven't already checked it.
		$store_hash = md5( $this->api_url );
		if ( ! is_array( $edd_plugin_url_available ) || ! isset( $edd_plugin_url_available[ $store_hash ] ) ) {
			$test_url_parts = parse_url( $this->api_url );

			$scheme = ! empty( $test_url_parts['scheme'] ) ? $test_url_parts['scheme']     : 'http';
			$host   = ! empty( $test_url_parts['host'] )   ? $test_url_parts['host']       : '';
			$port   = ! empty( $test_url_parts['port'] )   ? ':' . $test_url_parts['port'] : '';

			if ( empty( $host ) ) {
				$edd_plugin_url_available[ $store_hash ] = false;
			} else {
				$test_url = $scheme . '://' . $host . $port;
				$response = wp_remote_get( $test_url, array( 'timeout' => $this->health_check_timeout, 'sslverify' => $verify_ssl ) );
				$edd_plugin_url_available[ $store_hash ] = is_wp_error( $response ) ? false : true;
			}
		}

		if ( false === $edd_plugin_url_available[ $store_hash ] ) {
			return;
		}

		$data = array_merge( $this->api_data, $_data );

		if ( $data['slug'] != $this->slug ) {
			return;
		}

		if( $this->api_url == trailingslashit ( home_url() ) ) {
			return false; // Don't allow a plugin to ping itself
		}

		$api_params = array(
			'edd_action' => 'get_version',
			'license'    => ! empty( $data['license'] ) ? $data['license'] : '',
			'item_name'  => isset( $data['item_name'] ) ? $data['item_name'] : false,
			'item_id'    => isset( $data['item_id'] ) ? $data['item_id'] : false,
			'version'    => isset( $data['version'] ) ? $data['version'] : false,
			'slug'       => $data['slug'],
			'author'     => $data['author'],
			'url'        => home_url(),
			'beta'       => ! empty( $data['beta'] ),
		);

		$request    = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => $verify_ssl, 'body' => $api_params ) );

		if ( ! is_wp_error( $request ) ) {
			$request = json_decode( wp_remote_retrieve_body( $request ) );
		}

		if ( $request && isset( $request->sections ) ) {
			$request->sections = maybe_unserialize( $request->sections );
		} else {
			$request = false;
		}

		if ( $request && isset( $request->banners ) ) {
			$request->banners = maybe_unserialize( $request->banners );
		}

		if ( $request && isset( $request->icons ) ) {
			$request->icons = maybe_unserialize( $request->icons );
		}

		if( ! empty( $request->sections ) ) {
			foreach( $request->sections as $key => $section ) {
				$request->$key = (array) $section;
			}
		}

		return $request;
	}

	public function show_changelog() {

		global $edd_plugin_data;

		if( empty( $_REQUEST['edd_sl_action'] ) || 'view_plugin_changelog' != $_REQUEST['edd_sl_action'] ) {
			return;
		}

		if( empty( $_REQUEST['plugin'] ) ) {
			return;
		}

		if( empty( $_REQUEST['slug'] ) ) {
			return;
		}

		if( ! current_user_can( 'update_plugins' ) ) {
			wp_die( __( 'You do not have permission to install plugin updates', 'easy-digital-downloads' ), __( 'Error', 'easy-digital-downloads' ), array( 'response' => 403 ) );
		}

		$data         = $edd_plugin_data[ $_REQUEST['slug'] ];
		$beta         = ! empty( $data['beta'] ) ? true : false;
		$cache_key    = md5( 'edd_plugin_' . sanitize_key( $_REQUEST['plugin'] ) . '_' . $beta . '_version_info' );
		$version_info = $this->get_cached_version_info( $cache_key );

		if( false === $version_info ) {

			$api_params = array(
				'edd_action' => 'get_version',
				'item_name'  => isset( $data['item_name'] ) ? $data['item_name'] : false,
				'item_id'    => isset( $data['item_id'] ) ? $data['item_id'] : false,
				'slug'       => $_REQUEST['slug'],
				'author'     => $data['author'],
				'url'        => home_url(),
				'beta'       => ! empty( $data['beta'] )
			);

			$verify_ssl = $this->verify_ssl();
			$request    = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => $verify_ssl, 'body' => $api_params ) );

			if ( ! is_wp_error( $request ) ) {
				$version_info = json_decode( wp_remote_retrieve_body( $request ) );
			}


			if ( ! empty( $version_info ) && isset( $version_info->sections ) ) {
				$version_info->sections = maybe_unserialize( $version_info->sections );
			} else {
				$version_info = false;
			}

			if( ! empty( $version_info ) ) {
				foreach( $version_info->sections as $key => $section ) {
					$version_info->$key = (array) $section;
				}
			}

			$this->set_version_info_cache( $version_info, $cache_key );

		}

		if( ! empty( $version_info ) && isset( $version_info->sections['changelog'] ) ) {
			echo '<div style="background:#fff;padding:10px;">' . $version_info->sections['changelog'] . '</div>';
		}

		exit;
	}

	public function get_cached_version_info( $cache_key = '' ) {

		if( empty( $cache_key ) ) {
			$cache_key = $this->cache_key;
		}

		$cache = get_option( $cache_key );

		if( empty( $cache['timeout'] ) || time() > $cache['timeout'] ) {
			return false; // Cache is expired
		}

		// We need to turn the icons into an array, thanks to WP Core forcing these into an object at some point.
		$cache['value'] = json_decode( $cache['value'] );
		if ( ! empty( $cache['value']->icons ) ) {
			$cache['value']->icons = (array) $cache['value']->icons;
		}

		return $cache['value'];

	}

	public function set_version_info_cache( $value = '', $cache_key = '' ) {

		if( empty( $cache_key ) ) {
			$cache_key = $this->cache_key;
		}

		$data = array(
			'timeout' => strtotime( '+3 hours', time() ),
			'value'   => json_encode( $value )
		);

		update_option( $cache_key, $data, 'no' );

	}

	/**
	 * Returns if the SSL of the store should be verified.
	 *
	 * @since  1.6.13
	 * @return bool
	 */
	private function verify_ssl() {
		return (bool) apply_filters( 'edd_sl_api_request_verify_ssl', true, $this );
	}

}readme.txt000064400000133352151327220640006553 0ustar00=== WP Store Locator ===
Plugin URI: https://wpstorelocator.co
Contributors: tijmensmit
Donate link: https://www.paypal.me/tijmensmit
Tags: google maps, store locator, business locations, geocoding, stores, geo, zipcode locator, dealer locater, geocode, gmaps, google map, google map plugin, location finder, map tools, shop locator, wp google map
Requires at least: 3.7
Tested up to: 5.8.1
Stable tag: 2.2.234
License: GPLv3
License URI: http://www.gnu.org/licenses/gpl.html

An easy to use location management system that enables users to search for nearby physical stores.

== Description ==

WP Store Locator is a powerful and easy to use location management system. 
You can customize the appearance of the map, and provide custom labels for entry fields. 
Users can filter the results by radius, and see driving directions to the nearby stores in 
the language that is set in the admin panel. 

= Features include: =

* Manage an unlimited numbers of stores.
* Provide extra details for stores like the phone, fax, email, url, description and opening hours. There are filters available that allow you add [custom](http://wpstorelocator.co/document/add-custom-meta-data-to-store-locations/) meta data.
* Support for custom [map styles](https://snazzymaps.com/).
* Choose from nine retina ready marker icons.
* Show the driving distances in either km or miles.
* Shortcodes that enable you to add individual opening hours, addresses or just a map with a single marker to any page.
* Compatible with multilingual plugins like [WPML](https://wpml.org/plugin/wp-store-locator/) and qTranslate X.
* You can drag the marker in the editor to the exact location on the map.
* Show the search results either underneath the map, or next to it.
* Show Google Maps in different languages, this also influences the language for the driving directions.
* Show the driving directions to the stores.
* Customize the max results and search radius values that users can select.
* Users can filter the returned results by radius, max results or category.
* Supports [marker clusters](https://developers.google.com/maps/articles/toomanymarkers?hl=en#markerclusterer).
* Customize map settings like the terrain type, location of the map controls and the default zoom level.
* Use the Geolocation API to find the current location of the user and show nearby stores.
* Developer friendly code. It uses custom post types and includes almost 50 different [filters](https://wpstorelocator.co/documentation/filters/) that help you change the look and feel of the store locator.
* GDPR - Load Google Maps only after the user agrees to it ( requires the [Borlabs Cookie](https://borlabs.io/borlabs-cookie/) plugin ).

> <strong>Documentation</strong><br>
> Please take a look at the store locator [documentation](https://wpstorelocator.co/documentation/) before making a support request.

* [Getting Started](https://wpstorelocator.co/documentation/getting-started/)
* [Troubleshooting](https://wpstorelocator.co/documentation/troubleshooting/)
* [Customisations](https://wpstorelocator.co/documentation/customisations/)
* [Filters](https://wpstorelocator.co/documentation/filters/)

= Premium Add-ons =
 
**CSV Manager**

The [CSV Manager](https://wpstorelocator.co/add-ons/csv-manager/) allows you to bulk import, export and update your locations using a CSV file.

**Search Widget**

The [Search Widget](https://wpstorelocator.co/add-ons/search-widget/) enables users to search from any of the widgetized areas in your theme for nearby store locations, and show the results on the store locator page.

**Statistics**

The [Statistics](https://wpstorelocator.co/add-ons/statistics/) add-on enables you to keep track of the locations users are searching for and see where there is demand for a new store.

**Extenders**

The [Extenders](https://www.de-baat.nl/wp-store-locator/wp-store-locator-extenders/) add-on adds the features needed by power users such as managing location based events, social media information and locations managed by other logged in users.

== Installation ==

1. Upload the `wp-store-locator` folder to the `/wp-content/plugins/` directory
1. Activate the plugin through the 'Plugins' menu in WordPress
1. Create a [Google API Key](https://wpstorelocator.co/document/create-google-api-keys/) and set them on the [settings](https://wpstorelocator.co/document/configure-wp-store-locator/#google-maps-api) page.
1. Set the start point on the [settings](https://wpstorelocator.co/document/configure-wp-store-locator/#map).
1. Add your stores under 'Store Locator' -> Add Store
1. Add the map to a page with this shortcode: [wpsl]

== Frequently Asked Questions ==

= How do I add the store locator to a page? =

Add this [shortcode](https://wpstorelocator.co/document/shortcodes/) [wpsl] to the page where you want to display the store locator.

= Oops! Something went wrong =

You can fix this by setting the [browser](https://wpstorelocator.co/document/configure-wp-store-locator/#google-maps-api) key on the settings page.

= There are weird characters in the search results, how do I remove them? =

This is most likely caused by a plugin like W3 Total Cache that tried to minify the HTML output on the store locator page. You can fix this by excluding the store locator from being minified on the settings page of the caching plugin you're using. In W3 Total Cache this is done by going to Minify -> Advanced -> Never minify the following pages, and fill in the page you don't want to have minified. So if your store locator is used on mydomain.com/store-locator, then fill in 'store-locator'.

= Can I use different markers for category or individual store locations? =

How to use custom markers is described [here](https://wpstorelocator.co/document/use-custom-markers/), you can also only use [different markers](https://wpstorelocator.co/document/use-custom-markers/) for a few locations, or just for the [categories](https://wpstorelocator.co/document/set-unique-category-markers/).

= The map doesn't display properly. It's either broken in half or doesn't load at all. =

Make sure you have defined a start point for the map under settings -> Map Settings.

= The map doesn't work anymore after installing the latest update =

If you use a caching plugin, or a service like Cloudflare, then make sure to flush the cache.

= I can't dismiss the pop up asking me to join the mailing list, how do I fix this? =

There is probably a JS error in the WP Admin area that prevents the pop up from being dismissed. Try for a second to switch back to a default WP theme, disable all other plugins, and then try to dismiss the newsletter pop up again.

= Why does it show the location I searched for in the wrong country? =

Some location names exist in more then one country, and Google will guess which one you mean. This can be fixed by setting the correct 'Map Region' on the settings page -> API Settings.

= The store locator doesn't load, it only shows the number 1? =

This is most likely caused by your theme using ajax navigation ( the loading of content without reloading the page ), or a conflict with another plugin. Try to disable the ajax navigation in the theme settings, or deactivate the plugin that enables it to see if that solves the problem.

If you don't use ajax navigation, but do see the number 1 it's probably a conflict with another plugin. Try to disable the plugins one by one to see if one of them is causing a conflict.

If you find a plugin or theme that causes a conflict, please report it on the [support page](http://wordpress.org/support/plugin/wp-store-locator).

> You can find the full documentation [here](https://wpstorelocator.co/documentation/).

== Screenshots ==

1. Front-end of the plugin
2. The driving directions from the user location to the selected store
3. The 'Store Details' section
4. The plugin settings

== Changelog ==

= 2.2.234, 23 January, 2021 =
* Fixed: PHP 8 Compatiblity
* Fixed: Polylang Compatiblity

= 2.2.233, July 10, 2020 =
* Fixed: A problem with the [Borlabs Cookie](https://borlabs.io/borlabs-cookie/) plugin where Google Maps wasn't blocked correctly.
* Changed: Set the loaded Google Maps JavaScript [version](https://developers.google.com/maps/documentation/javascript/versions) to quarterly. So every quarter it will automatically load the latest version.

= 2.2.232, Nov 27, 2019 =
* Fixed: The opening hours triggering an error on some server configurations.
* Fixed: Restored the [wpsl_skip_cpt_template](https://wpstorelocator.co/document/wpsl_skip_cpt_template/) filter which was accidently removed in a previous update.
* Changed: Set the loaded Google Maps JavaScript [version](https://developers.google.com/maps/documentation/javascript/versions) to 3.39 instead of 3.36.

= 2.2.231, Sept 18, 2019 =
* Fixed: Bug that in some cases broken the Borlabs Cookie plugin from working correctly together with the store locator plugin.

= 2.2.23, May 6, 2019 =
* Fixed: The export data function on the single location pages in the admin area not working.
* Fixed: The map and location data not showing up in the TwentyNineteen theme on individual location pages.
* Changed: Updated the included EDD_SL_Plugin_Updater class that handles updates / license key checks for add-ons.

= 2.2.22, March 24, 2019 =
* Added: Support for the [Borlabs Cookie](https://borlabs.io/borlabs-cookie/) plugin. This allows you to [block the loading](https://wpstorelocator.co/document/the-general-data-protection-regulation/#borlabs) of Google Maps until the user agrees to it.
* Added: A 'Validate API Keys' tool that will provided feedback for any issues with the used API keys.
* Added: A tool that will show you the raw Google Geocode API response for any address you provide based on the current configuration together with a preview map.
* Changed: Made sure that links included in error messages from the Google Geocode API are always clickable.
* Changed: If no zip code is included in the returned location data after the users location is automatically determined, then it will now show the city / town name in the search field instead of leaving it empty.

= 2.2.21, March 7, 2019 =
* Changed: Set the loaded Google Maps JavaScript [version](https://developers.google.com/maps/documentation/javascript/versions) to 3.36 instead of 3.33.

= 2.2.20, December 26, 2018 =
* New: Added an option to the permalinks section to optionally remove the front base ( for example /blog/ ) from the store locator permalinks.
* New: Added an option to the search section to force the Google Geocode API to assume the search input is a zip code. So searching for town / city names won't work if this option is enabled.
* New: Included a [wpsl_autocomplete_options](https://wpstorelocator.co/document/wpsl_autocomplete_options/) filter to customize the included data in requests made to the places API ( used with autocomplete ).
* Changed: Limited the requested data for the places API ( used with autocomplete ) to only 'geometry.location', which should reduce the cost on high traffic websites.
* Removed: Unused CSS rules from the admin CSS.
* Fixed: Using keyboard input to select a location after the first search with the autocomplete option enabled now returns the correct location.

= 2.2.19, December 6, 2018 =
* Fixed: Not being able to assign locations to a category when [Gutenberg](https://wordpress.org/gutenberg/) is used.

= 2.2.18, December 2, 2018 =
* New: Added role="presentation" to the hours table.
* New: Added a [wpsl_strip_content_shortcode](https://wpstorelocator.co/document/wpsl_strip_content_shortcode/) filter to optionally prevent strip_shortcodes from running on the post content data shown in the search results.
* New: Included the 'show_in_rest' param when the wpsl_stores post type is registered for WP 5.x to enable the [Gutenberg editor](https://wordpress.org/gutenberg/). You can read how to disable this [here](https://wpstorelocator.co/document/wpsl_post_type_args/#disable-rest).
* Note: Setting '[show_in_rest](https://developer.wordpress.org/rest-api/extending-the-rest-api/adding-rest-api-support-for-custom-content-types/)' to true will make the store locator data partially available through the [REST API](https://developer.wordpress.org/rest-api/). If you don't want this, then you can use a plugin like [this](https://wordpress.org/plugins/disable-json-api/) to disable access to it for anonymous users. Full REST API support will come in the 3.0 update.
* Fixed: Added CSS rules that target the Twenty Nineteen theme from WP 5.x to fix a few alignment issues.
* Fixed: Prevented duplicate content from showing up on single stores pages when the Twenty Nineteen theme is used.
* Fixed: Disable the scrollWheel option in the JS code if the Google Maps gestureHandling is set to cooperative, otherwise the cooperative value is ignored.
* Fixed: Make the [wpsl_hours] shortcode respect the setting to hide the hours from the settings page. Via [@agbruce](https://wordpress.org/support/users/agbruce/).
* Changed: Removed the unused 'no-results' class from being targeted in the JS code.
* Changed: Reversed the order of the API key fields on the settings page to make it match with how it's described in the documentation.
* Changed: Disable the 'On page load move the mouse cursor to the search field?' option by default on new installations.
* Changed: Improved the code that filters the city / state / country data from the returned API data for the statistics add-on.

= 2.2.17, September 16, 2018 =
* Changed: Truncated the used coordinates to 5 decimals in the JS script to workaround this [reverse geocoding bug](https://issuetracker.google.com/issues/115484101#comment3). This bug resulted in a 'No results found' error ( based on the used WPSL settings ) if you searched for major cities like Los Angeles.

= 2.2.16, August 14, 2018 =
* Changed: Set the Google Maps API version to 3.33 to prevent [weekly API updates](https://developers.google.com/maps/documentation/javascript/versions) from suddenly breaking the map. You can overwrite the version number with the wpsl_gmap_api_version filter.

= 2.2.15, May 24, 2018 =
* Added: Included a 'Export Location Data' button in the admin editor to make it easier to handle possible GDPR data access requests. If you want to, then you can hide it with [this](https://wpstorelocator.co/document/wpsl_enable_export_option/) filter.

= 2.2.14, March 27, 2018 =
* Added: Included a wpsl_setting_dropdowns filter that enables the creation of additional dropdowns on the settings page.
* Added: A wpsl_get_location_fields() function that returns an array of the used meta fields.
* Changed: Made it easier for add-ons to access the WPSL_Frontend class.
* Fixed: Made sure the search results are visible when a RTL language is used.
* Fixed: Removed a CSS rule that prevented the markers and the links in the info window from responding to mouse clicks in IE 11.

= 2.2.13, February 28, 2018 =
* Added: Included support for 'directions' and 'clickable_contact_details' to the [wpsl_address](https://wpstorelocator.co/document/shortcodes/#store-address) shortcode.
* Added: An option to the User Experience section on the settings page to make the contact details ( phone / email ) always clickable.
* Added: A 'wpsl_skip_cpt_template' filter that you can use to prevent the code in the 'cpt_template' function from running.
* Changed: When the statistics add-on is active, then the complete response from the Geocode API is included in the AJAX data.
* Changed: Added a check in the makeAjaxRequest function to prevent it from processing data from AJAX request made by add-ons.
* Changed: Included a CSS rule to hide duplicate dropdowns generated by the [Select2](https://select2.org/) library used by some themes.
* Changed: Replaced the usage of findFormattedAddress with the reverseGeocode function in the wpsl-gmap.js.
* Changed: Fixed a typo in the geoLocationTim(e)out var.
* Changed: Updated the wpsl.pot file.
* Fixed: A ICL_LANGUAGE_CODE notice when Polylang is active.
* Fixed: On some installations a call to undefined function pll__() showed up when Polylang was used.

= 2.2.12, February 16, 2018 =
* Fixed: The zoom level automatically going down to streetlevel with the wpsl_map shortcode, and ignoring the set zoom level in the shortcode options.
* Fixed: The zipcode not always being correctly filtered out of the geocode API response when the user location is automatically detected.
* Changed: Removed unused customCheckboxValue variable.

= 2.2.11, January 14, 2018 =
* Added: A WPSL_Templates class that handles the different templates in the store locator and in the upcoming directory and nearby locations add-ons.
* Added: A 'wpsl_settings_tab' filter that makes it possible to add custom tabs on the settings page.
* Added: A 'wpsl_settings_section' action so you can add custom fields to the settings page.
* Changed: The find_nearby_locations(), check_store_filter() and the check_allowed_filter_value() now accepts an $args param.
* Changed: Increased the timeout for the geolocation request.

= 2.2.10, December 12, 2017 =
* Added: The [wpsl_map_tab_anchor](https://wpstorelocator.co/document/wpsl_map_tab_anchor) filter now also accepts an array, so you can show multiple maps ( with the wpsl_map shortcode ) next to eachother in different tabs.
* Added: A store locator media button in the editor that enables you to generate the shortcode attributes for the wpsl shortcode.
* Added: A check on the settings page that validates the provided Google Maps API keys in the background when they are saved.
* Added: Support to the [wpsl](https://wpstorelocator.co/document/shortcodes/) shortcode for 'auto_locate', 'category_selection', 'category_filter_type', 'checkbox_columns', 'map_type', 'start_marker' and 'store_marker'.
* Added: A requiredFields value to the js_settings function that allows you to customize/remove the required fields check when the 'Preview Location' button is used in the admin area.
* Added: A wpsl_save_post action.
* Added: Placed a 'wpsl-no-results' class on the outer div when no results are returned.
* Changed: Removed unused $i counter from the settings class.
* Changed: Improved the handling of errors returned by the Geocode API and clarified the meaning of them.
* Changed: Firefox now also [requires](https://www.mozilla.org/en-US/firefox/55.0/releasenotes/) SSL to access the Geolocation API, so updated the notice text on the settings page.
* Changed: Included the latest version of the EDD_SL_Plugin_Updater class ( 1.6.14 ).
* Changed: Replaced $wpsl_settings['category_filter'] with $this->use_category_filter() in the templates to make it compatible with the new category shortcode attributes. So if you're using a custom template, then make the same change.
* Changed: Renamed the 'no-results' class to 'wpsl-no-results-msg' to prevent conflicts with CSS rules from other themes / plugins.
* Changed: Included a missing ) in the country name list on the settings page.
* Changed: Updated the .pot file, and the Dutch and Spanish ( via [Jaime Smeke](http://untaljai.me/) ) translations.
* Changed: Set the display mode for the wpsl-directions class to table instead of block to prevent some themes from showing a wide underline.
* Changed: Moved get_ajax_url to the wpsl-functions.php and named it wpsl_get_ajax_url().
* Fixed: Include the used [travel mode](https://wpstorelocator.co/document/wpsl_direction_travel_mode/) in the generated URL that shows the user the directions on Google Maps itself.
* Fixed: A notice triggered by Polylang for ICL_SITEPRESS_VERSION.

= 2.2.9, July 9, 2017 =
* Added: The possibility to load [custom images](https://wpstorelocator.co/document/change-marker-cluster-images/) for the marker clusters.
* Added: An option to the map section to disable the zoom level from being automatically adjusted after a search is complete. If it's disabled then it will focus on the start point, and use the zoom level from the 'Initial zoom level' field.
* Added: A check that prevents the search radius / max results value used in the SQL query from being bigger then the max value set on the settings page.
* Fixed: The get_default_filter_value func not returning the default value for the search radius field ( see next item ).
* Changed: Had to rename the param for the search radius in the AJAX call from radius to search_radius to make it match with the settings page value.
* Note: If you're using custom code that relies on the returned paramater being radius, then rename it to search_radius.
* Changed: Updated the .pot file.

= 2.2.8, April 30, 2017 =
* Added: Support for [Polylang](https://wordpress.org/plugins/polylang/).
* Added: A [wpsl_direction_travel_mode](https://wpstorelocator.co/document/wpsl_direction_travel_mode/) filter that enabled you to change the used [travel mode](https://developers.google.com/maps/documentation/javascript/directions#TravelModes) for the directions.
* Added: A [wpsl_distance_unit](https://wpstorelocator.co/document/wpsl_distance_unit/) filter.
* Added: A [wpsl_disable_welcome_pointer](https://wpstorelocator.co/document/wpsl_disable_welcome_pointer/) filter that enables you disable the newsletter signup on a multisite network.
* Added: Support for custom alternateMarkerUrl and categoryMarkerUrl data in the JS file, this allows you to set a custom marker for [individual locations](https://wpstorelocator.co/document/use-different-marker-for-each-location/) and for [categories](https://wpstorelocator.co/document/set-unique-category-markers/).
* Changed: Deprecated the [wpsl_draggable_map](https://wpstorelocator.co/document/wpsl_draggable_map/) filter and [replaced](https://wpstorelocator.co/document/wpsl_gesture_handling/) it with support for Google Maps [gestureHandling](https://developers.google.com/maps/documentation/javascript/interaction).
* Changed: Made sure the supported map regions on the settings page match with the list of supported regions from [Google](https://developers.google.com/maps/coverage).
* Changed: Included the latest version of the EDD_SL_Plugin_Updater class ( 1.6.12 ).
* Fixed: A fatal call to undefined function error when the plugin is activated through WP-CLI.
* Fixed: The controls in street view mode not having a background color, so the back button wasn't visible.
* Fixed: Prevented two consecutive underscores from showing up in the generated transient names if no autoload limit is set.

= 2.2.7, December 31, 2016 =
* Changed: Included the latest version of the EDD_SL_Plugin_Updater class ( 1.6.8 ).
* Changed: Reverted a change in the CSS file that ended up breaking the map for some users.

= 2.2.6, December 24, 2016 =
* Fixed: The opening hours not working correctly for Saturday / Sunday in the admin area. The 12:00 AM field was missing.
* Fixed: A PHP notice showing up when an invalid value was set for the radius / max results dropdown.
* Fixed: The zoom attribute now works correctly for the wpsl_map shortcode.
* Changed: Included the latest version of the EDD_SL_Plugin_Updater class ( 1.6.7 ).
* Changed: Removed unused locationCount var from wpsl-gmap.js.
* Changed: Added a CSS rule that makes it harder for themes to scaled images on the map.

= 2.2.5, December 11, 2016 =
* Fixed: Made it work with the latest WPML version.
* Fixed: Remove the WPSL caps and Store Locator Manager role on uninstall. The code was always there to do so, but was never called.
* Fixed: A PHP notice that showed up when the settings page was saved with an empty start location field.
* Changed: Adjusted the structure of the post type labels so you can correctly translate them in singular / plural forms based on the used language. Via [deshack](https://wordpress.org/support/users/deshack/).
* Changed: Added a tooltip to the 'Attempt to auto-locate the user' field explaining that HTTPS is now [required](https://wpstorelocator.co/document/html-5-geolocation-not-working-chrome-safari/) in Chrome and Safari.
* Changed: The coordinates from the start location are now used to center the map in the map section on the settings page instead of it always defaulting to Holland.
* Changed: Renamed the existing option that prevents two Google Maps libraries from loading at the same time to "Enable compatibility mode" on the settings page ( Tools section ).
* Changed: Updated the wpsl.pot file.
* Changed: No longer use the deprecated icl_object_id() function when the WPML version is newer then 3.2.

= 2.2.4, Augustus 6, 2016 =
* New: Added an option to the tools section to prevent other scripts from including the Google Maps API a second time on the store locator page. This sometimes breaks the map.
* Fixed: Assigned the correct country code to Martinique on the settings page.
* Fixed: The code that calls [wp_editor](https://codex.wordpress.org/Function_Reference/wp_editor) now includes a random ID after 'wpsleditor' to make sure you can use it multiple times on the same page.
* Fixed: The inline [qTranslate X](https://wordpress.org/plugins/qtranslate-x/) syntax ( [:en]English Text[:de]Deutsch[:] ) now works for the label fields.
* Fixed: Added a workaround for [this](https://bugzilla.mozilla.org/show_bug.cgi?id=1283563) bug with the Geolocation API in Firefox.
* Changed: Automatically adjust the language Google Maps uses when WMPL or qTranslate X is active.
* Changed: Improved the handling of error codes returned by the Google Geocode API.
* Changed: Removed the '_' prefix from the returned language code in check_multilingual_code().
* Changed: Updated the wpsl.pot file.

= 2.2.3, June 27, 2016 =
* Fixed: Included the browser key in requests made to the Google Maps JavaScript API in the admin area. This is now [required](http://googlegeodevelopers.blogspot.nl/2016/06/building-for-scale-updates-to-google.html).
* Changed: Include the language code in the AJAX request if WPML is active.
* New: Spanish translations (es_ES). Via [Jaime Smeke](http://untaljai.me/).
* New: Added support for the upcoming statistics add-on.

= 2.2.2, May 18, 2016 =
* Fixed: Corrected the [path](https://github.com/googlemaps/js-marker-clusterer/pull/61) for the cluster marker images.

= 2.2.1, March 24, 2016 =
* Fixed: A JS bug that sometimes resulted in duplicate results showing up in the search results.

= 2.2, March 20, 2016 =
* New: The option to show the categories with checkboxes instead of a dropdown.
* Note: If you're showing the categories with checkboxes, then you can change the amount of used columns by setting the "checkbox_columns" ( between 1 and 4 ) on the [wpsl] shortcode.
* New: A [wpsl_no_results](https://wpstorelocator.co/document/wpsl_no_results) filter that allows you to create a custom HTML block that replaces the 'No results found' text.
* New: The option to enable [autocomplete](https://developers.google.com/maps/documentation/javascript/examples/places-autocomplete) for location searches.
* Note: Read [this](https://wpstorelocator.co/version-2-2-released/#autocomplete) if you're using a custom template and want to use the autocomplete option.
* New: A [wpsl_enable_styled_dropdowns](https://wpstorelocator.co/document/wpsl_enable_styled_dropdowns/) filter that allows you to disable the current JS styling for all the dropdowns.
* New: You can now change the "Any" text used in the category dropdown in the labels section on the settings page.
* New: The option to hide the country name in the search results / marker pop-up.
* New: The option to show the contact details below the address.
* New: A [wpsl_hide_closed_hours](https://wpstorelocator.co/document/wpsl_hide_closed_hours/) filter that enables you to hide the days that the location is closed from the opening hours list.
* New: Values from [custom dropdowns](https://wpstorelocator.co/version-2-2-released/#custom-dropdown) that have a "wpsl-custom-dropdown" class set are automatically included in the AJAX data.
* New: Added a Add-Ons page to the "Store Locator" menu.
* New: A [wpsl_map_tab_anchor_return](https://wpstorelocator.co/document/wpsl_map_tab_anchor_return/) filter that allows you to choose between return true or false if the tab anchor is clicked.
* New: Added the "aria-required" attribute to the search field.
* Changed: The category dropdown is now created with [wp_dropdown_categories](https://codex.wordpress.org/Function_Reference/wp_dropdown_categories) and correctly indents sub categories.
* Changed: If a search returns no results, then the map will now focus on the searched location instead of only showing the "No results found" msg. 
* Changed: Instead of a single "API key" [field](https://wpstorelocator.co/document/configure-wp-store-locator/#google-maps-api) there are now separate [server](https://developers.google.com/maps/documentation/geocoding/get-api-key#get-an-api-key) and [browser](https://developers.google.com/maps/documentation/javascript/get-api-key#get-an-api-key) key fields. If an API key existed, then it's assumed to be a server key.
* Changed: A scrollbar is shown inside the styled dropdown filters if they are heigher then 300px. You can change the maximum height with the [wpsl_max_dropdown_height](https://wpstorelocator.co/document/wpsl_max_dropdown_height/) filter.
* Changed: Removed the text wrap on the category filter items. If a category name is too long, then it will now go over two lines instead of being cut off.
* Changed: Updated the wpml-config.xml and wpsl.pot.
* Changed: If the autocomplete for the start location on the settings page fails ( JS error ), then the set start location is geocoded in the background when the settings are saved.
* Changed: A single JS function now handles all the conditional options on the settings page instead of several smaller ones.
* Changed: The "zoom_name" and "zoom_latlng" setting is renamed to "start_name" and "start_latlng".
* Changed: Renamed the "category_dropdown" setting to "category_filter" to better reflect the value that it holds ( either checkbox or dropdown ). So if you're using a custom template, then make sure to change "category_dropdown" to "category_filter" in your code.
* Fixed: If you click on one of the styled dropdowns when it's already open, then it will now close.

= 2.1.2, March 4, 2016 =
* Fixed: Invalid HTML in the category dropdown.
* Fixed: Clicking on the marker on a single store / [wpsl_map] page triggered a JS error if the location permalinks are enabled.
* Fixed: The wpsl_map_tab_anchor filter not working with the [wpsl_map] shortcode.
* Fixed: Compatibility [issue](https://make.wordpress.org/core/2016/02/17/backbone-and-underscore-updated-to-latest-versions/) with Underscore 1.8.3.

= 2.1.1, January 13, 2016 =
* New: Restrict the search results to one or more categories by using the "category" attribute on the [wpsl] [shortcode](https://wpstorelocator.co/document/shortcodes/#store-locator).
* New: A "start_location" attribute for the [wpsl] [shortcode](https://wpstorelocator.co/document/shortcodes/#store-locator).
* New: Included a link to the add-ons page in the plugin meta row.
* New: Support for the "wp_editor" type with the [wpsl_meta_box_fields](https://wpstorelocator.co/document/wpsl_meta_box_fields/) filter, this will render the default WP Editor. Via [Richard](http://ampersandstudio.uk/).
* Changed: Moved the documentation link from the plugin actions row to the plugin meta row.
* Changed: If you use the "category" attribute on the [wpsl_map] shortcode, then the store names in the marker info window will automatically link to the store page or custom url.

= 2.1.0, December 23, 2015 =
* New: You can now use the "category" attribute ( use the category slugs as values ) on the [wpsl_map] shortcode to show locations that belong to one or more categories.
* New: Support to load the marker images from a [different folder](https://wpstorelocator.co/document/use-custom-markers/).
* New: A [wpsl_marker_props](https://wpstorelocator.co/document/wpsl_marker_props) filter that enables you to change the default "anchor", "scaledSize" and "origin" for the [marker image](https://developers.google.com/maps/documentation/javascript/3.exp/reference#Icon).
* New: A [wpsl_geocode_components](https://wpstorelocator.co/document/wpsl_geocode_components) filter that enables you to restrict the returned geocode results by administrativeArea, country, locality, postalCode and route.
* New: A [wpsl_draggable](https://wpstorelocator.co/document/wpsl_draggable_map) filter that enables you to enable/disable the dragging of the map.
* New: Support for the upcoming add-ons.
* Note: Read [this](https://wpstorelocator.co/version-2-1-released/#widget-support) if you're using a custom template!
* Changed: If you need to geocode the full address ( new store ), and a value for 'state' is provided it's now included in the geocode request.
* Changed: If the Geocode API returns a REQUEST_DENIED status, then the returned error message is shown explaining why it failed. 
* Fixed: In rare cases the SQL query returned duplicate locations with the same post id. To prevent this from happening the results are now by default grouped by post id.

= 2.0.4, November 23, 2015 =
* Fixed: HTML entity encoding issue in the marker tooltip, via [momo-fr](https://wordpress.org/support/profile/momo-fr) and [js-enigma](https://wordpress.org/support/profile/js-enigma).
* Fixed: Missing tooltip text for the start marker, and the info window for the start marker breaking when the Geolocation API successfully determined the users location.
* Fixed: Multiple shortcode attributes ignoring the "false" value, via [dynamitepets](https://wordpress.org/support/profile/dynamitepets) and [drfoxg](https://profiles.wordpress.org/drfoxg/).
* Changed: If a WPML compatible plugin is detected, a notice is shown above the label section explaining that the "String Translations" section in the used multilingual plugin should be used to change the labels.
* Changed: Removed the "sensor" parameter from the Google Maps JavaScript API. It triggered a 'SensorNotRequired' [warning](https://developers.google.com/maps/documentation/javascript/error-messages).
* Changed: Updated translation files.

= 2.0.3, October 27, 2015 =
* Fixed: The default search radius is no longer ignored if the Geolocation API is used. Via [xeyefex](https://wordpress.org/support/profile/xeyefex).
* Changed: Replaced get_page ( deprecated ) with get_post.
* Changed: Adjusted the position, and size of the reset map / current location icon to make them match with the new [control styles](http://googlegeodevelopers.blogspot.com/2015/09/new-controls-style-for-google-maps.html) introduced in v3.22 of the Google Maps API.
* Changed: Made it harder for themes to overwrite the icon font that is used to show the reset map / current location icon.
* Changed: Removed support for the map's pan control and zoom control style from the settings page and [wpsl_map] shortcode attributes. They are both [deprecated](https://developers.google.com/maps/articles/v322-controls-diff) in v3.22 of the Google Maps API.

= 2.0.2, September 19, 2015 =
* Fixed: Not all users always seeing the notice to convert the 1.x locations to custom post types.
* Fixed: Prevented empty search results from ending up in the autoload transient.
* Fixed: The autoload transient not being cleared after changing the start location on the settings page.
* Changed: Added extra CSS to make it harder for themes to turn the map completely grey, and set the default opening hours alignment to left.
* Changed: If you use the store locator in a tab, then it no longer requires the tab anchor to be 'wpsl-map-tab'. You can use whatever you want with the 'wpsl_map_tab_anchor' filter.

= 2.0.1, September 10, 2015 =
* Fixed: Prevented other plugins that use [underscore](http://underscorejs.org/) or [backbone](http://backbonejs.org/) from breaking the JavaScript templates, via [fatman49](https://profiles.wordpress.org/fatman49/) and [zurf](https://profiles.wordpress.org/zurf/).
* Fixed: Street view not showing the correct location after using it more then once, via [marijke_25](https://profiles.wordpress.org/marijke_25/).

= 2.0, September 7, 2015 =
* New: Moved away from a custom db table, the store locations are now registered as custom post types. 
* Note: The upgrade procedure will ask you to convert the current store locations to custom post types. This takes around 1 minute for every 1000 store locations.
* New: The option to enable/disable permalinks for the stores, and set a custom slug from the settings page.
* New: Three new [shortcodes](http://wpstorelocator.co/document/shortcodes/): [wpsl_map], [wpsl_hours] and [wpsl_address].
* New: A template attribute for the [wpsl](http://wpstorelocator.co/document/shortcodes/#store-locator) shortcode, via [Damien Carbery](http://www.damiencarbery.com).
* New: Supports [WPML](https://wpml.org/) and [qTranslate X](https://wordpress.org/plugins/qtranslate-x/).
* New: A textarea on the settings page where you can paste JSON code to create a [custom map style](https://developers.google.com/maps/documentation/javascript/styling).
* New: The option to hide the search radius dropdown on the frontend.
* New: A [wpsl_geolocation_timeout](http://wpstorelocator.co/document/wpsl_geolocation_timeout/) filter.
* New: The option to choose between different address formats, and a [filter](http://wpstorelocator.co/document/wpsl_address_formats/) to add custom ones.
* New: The option to use the [InfoBox](http://google-maps-utility-library-v3.googlecode.com/svn/trunk/infobox/docs/reference.html) library to style the info window.
* New: The option to choose between two different effects when a user hovers over the result list.
* New: Set the opening hours through dropdowns instead of a textarea.
* New: Filters that make it possible to add custom store data, and change the HTML structure of the info window and store listing template.
* New: The option to define a max location load if the auto loading of locations is enabled.
* New: The option to enable/disable scroll wheel zooming and the map type control on the map.
* New: Added 'Email' and 'Url' to the labels on the settings page.
* New: Added a general settings and documentation link to the plugin action links.
* New: The option to set a max auto zoom level to prevent the auto zoom from zooming to far.
* New: The option to set a different map type for the location preview.
* New: A check to see if the [SCRIPT_DEBUG](https://codex.wordpress.org/Debugging_in_WordPress#SCRIPT_DEBUG) constant is set, if this is the case the full scripts are loaded, otherwise the minified scripts are used.
* New: A [wpsl_thumb_size](http://wpstorelocator.co/document/wpsl_thumb_size/) filter that enables you to set the thumb size on the frontend without editing CSS files.
* New: The option to hide the distance in the store listing.
* New: Added JS code that prevents a grey map when the store locator is placed in a tab. This does require the use of a #wpsl-map-tab anchor.
* New: Portuguese translation via [Rúben Martins](http://www.rubenmartins.pt/).
* Changed: Better error handling for the Geolocation API.
* Changed: Regardless of the selected template, the store map is always placed before the store list on smaller screens.
* Changed: The wp-content/languages folder is checked for translations before using the translations in the plugin folder.
* Changed: The 'reset map' button now uses an icon font, and is placed in right bottom corner together with a new 'current location' icon.
* Changed: The cluster marker image will use HTTPS when available.
* Changed: Increased the default Geolocation timeout from 3000 to 5000 ms.
* Changed: The geocode requests to the Google Maps API will always use HTTPS.
* Changed: Instead of curl or file_get_contents the Google Maps API request will now use [wp_remote_get](https://codex.wordpress.org/Function_Reference/wp_remote_get).
* Changed: Replaced the 'wpsl_capability' filter with a 'Store Locator Manager' [role](http://wpstorelocator.co/document/roles/).
* Changed: Added an extra check in JS to prevent the search radius or max results value being set to NaN.
* Changed: The [wpsl_templates](http://wpstorelocator.co/document/wpsl_templates/) filter now expects an id field to be present in the array.
* Changed: Renamed the 'wpsl_gmap_api_attributes' filter to [wpsl_gmap_api_params](http://wpstorelocator.co/document/wpsl_gmap_api_params/).
* Changed: Added the 'enableHighAccuracy' parameter to the Geolocation request to make it more accurate on mobile devices.
* Fixed: An issue that prevented the settings page from saving the changes on servers that used the mod_security module.
* Fixed: The pan control option not working on the frontend if it was enabled on the settings page.
* Fixed: Prevented an empty comma from appearing in the direction URL if the zip code didn't exist.
* Fixed: Modified the CSS to prevent themes hiding the map images.
* Fixed: Dragging the store location marker in the store editor would sometimes return the incorrect coordinates.
* Fixed: The 'Back' button appeared multiple times after the user clicked on the 'Directions' link from different info windows.
* Fixed: The dropdown fields not being restored to the default values after the 'reset map' button was clicked.
* Note: Requires at least WP 3.7 instead of WP 3.5.

= 1.2.25 =
* Fixed: The store search breaking after the reset button was clicked, via [Drew75](https://wordpress.org/support/profile/drew75)
* Fixed: Two PHP notices.

= 1.2.24 =
* Fixed: Clicking the marker would no longer open the info window after a Google Maps API update. This only happened if street view was enabled.
* Fixed: A fatal error on some installations caused by the usage of mysql_real_escape_string, it is replaced with esc_sql.
* Fixed: A problem where some themes would just show "1" instead of the shortcode output.
* Fixed: The "dismiss" link not working in the notice that reminds users to define a start point.
* Fixed: A missing html tag that broken the store listing in IE7/8.
* Changed: Replaced the non-GPL compatible dropdown script.

= 1.2.23 =
* Fixed the geocoding request for the map preview on the add/edit page not including the zipcode when it's present, which can misplace the marker

= 1.2.22 =
* Fixed compatibility issues with the Google Maps field in the Advanced Custom Fields plugin
* Fixed the store urls in the store listings sometimes breaking
* Removed the requirement for a zipcode on the add/edit store page
* Improved the documentation in the js files

= 1.2.21 =
* Fixed an js error breaking the store locator

= 1.2.20 =
* Fixed the directions url sometimes showing an incomplete address due to an encoding issue
* Fixed the 'items' count on the store overview page showing the incorrect number after deleting a store
* Fixed the autocomplete for the 'start point' field sometimes not working on the settings page
* Fixed php notices breaking the store search when wp_debug is set to true
* Fixed the bulk actions when set to 'Bulk Actions' showing the full store list without paging
* Fixed small css alignment issues in the admin area
* Fixed the js script still trying to load store data when autoload was disabled
* Fixed the clickable area around the marker being to big
* Improved: After a user clicks on 'directions' and then clicks 'back', the map view is returned to the original location
* Removed: the 'Preview location on the map' button no longer updates the zip code value it receives from the Google Maps API
* Changed the way the dropdown filters are handled on mobile devices. They are now styled and behave according to the default UI of the device
* Added support for WP Multisite
* Added 'Screen Options' for the 'Current Stores' page, so you can define the amount of stores that are visible on a single page
* Added the option to make phone numbers clickable on mobile devices by adding a link around them with 'tel:'
* Added the option to make store names automatically clickable if the store url exists
* Added the option to show a 'zoom here' and 'street view' (when available) into the infowindow
* Added a second address field to the store fields
* Added the option to enable marker clusters
* Added the option to set a default country for the "Add Store" page
* Added Dutch (nl_NL) translations
* Added a .pot file to the languages folder for translators
* Added error handling for the driving directions
* Added several filters for developers: 
'wpsl_templates' for loading a custom template from another directory
'wpsl_menu_position' for adjusting the position of the store locator menu in the admin panel
'wpsl_capability' to manually set the required user capability for adding/editing stores
'wpsl_gmap_api_attributes' to modify the Google maps parameters ( change the map language dynamically )

= 1.2.13 =
* Fixed the store search not returning any results when the limit results dropdown is hidden

= 1.2.12 =
* Added an option to choose where the 'More info' details is shown, either in the store listings or on the map
* Added the 'back' and 'reset' text to the label fields on the settings page
* Added the option to remove the scrollbar when the store listings are shown below the map
* Improved the position of the reset button when the map controls are right aligned
* Fixed the 'More info' translation not working
* Fixed the start position marker disappearing when dragged

= 1.2.11 =
* Fixed the distance format always using km when you click the 'directions' text in the marker
* Fixed an issue where a CSS rule in some themes would place a background image on the active item in the dropdown list
* Added an option to disable the mouse cursor on pageload focusing on the location input field 
* Added an option to add a 'More info' link to the store listings, which when clicked will open the info window in the marker on the map

= 1.2.1 =
* Added an option to show the store listings below the map instead of next to it
* Added an option to open the directions in a new window on maps.google.com itself
* Fixed a 'too much recursion' js error that showed up when no start location was defined
* Fixed the auto loading of stores not being ordered by distance
* Fixed a problem with the input fields not always aligning in Chrome
* Improved the handling of thumbnails. If the thumbnail format is disabled in the theme, it will look for the medium or full format instead
* Several other small code improvements

= 1.1 =
* Added the option to open a link in a new window
* Added the option to show a reset button that will reset the map back to how it was on page load
* Added the option to load all stores on page load
* Fixed a problem with the shortcode output

= 1.0.1 =
* Fixed the styling for the store locator dropdowns being applied site wide
* Fixed a problem with slashes in store titles

= 1.0 =
* Initial release

Youez - 2016 - github.com/yon3zu
LinuXploit