/ Scripts & jquery / Посты — метки на карте

Посты — метки на карте

HIT

11.08.2018

2180

Пытаясь реализовать удобный функционал по созданию меток на интерактивной карте я пришел к следующей системе. Заводим произвольный тип записи и таксономии чтобы структурировать и удобно манипулировать городами и точками.

Основа

В основе решения находиться плагин Oi Yandex.Maps for WordPress (хотя я использую его только частично), который в свою очередь основан на Яндекс Api. т.е. плагин необходимо установить.

Создаем пользовательский тип записи city (название не вполне соответствует, т.к. это будут точки. конкретное место в городе):

// Добавляем произвольный тип записей
add_action( 'init', 'register_post_type_city' ); // Использовать функцию только внутри хука init
function register_post_type_city() {
    $labels = array(
        'name' => 'Где купить',
        'singular_name' => 'City', // админ панель Добавить->Функцию
        'add_new' => 'Добавить точку',
        'add_new_item' => 'Добавить новую точку', // заголовок тега <title>
        'edit_item' => 'Редактировать точку',
        'new_item' => 'Новая точка',
        'all_items' => 'Все точки',
        'view_item' => 'Просмотр страницы точки на сайте',
        'search_items' => 'Искать точку',
        'not_found' =>  'Точка не найдена.',
        'not_found_in_trash' => 'В корзине нет точки.',
        'menu_name' => 'Где купить' // ссылка в меню в админке
    );
    $args = array(
        'labels' => $labels,
        'public' => true,
        'show_ui' => true, // показывать интерфейс в админке
        'has_archive' => true, // показывать страницу архива данного типа записей
        'menu_icon' => 'dashicons-location-alt', // иконка dashicons в меню
        'menu_position' => 20, // порядок в меню
        'supports' => array( 'title', 'editor', 'comments', 'author', 'thumbnail'),
        //'taxonomies' => array('cities') // добавляем поддержку стандартных таксономий 'post_tag', 'category', либо пользовательскую 'album' (через запятую)
    );
    register_post_type('city', $args);
}


// Тексты уведомлений для типа постов
add_filter( 'post_updated_messages', 'true_post_type_messages_city' );
function true_post_type_messages_city( $messages ) {
    global $post, $post_ID;
    $messages['city'] = array( // city - название созданного нами типа записей
        0 => '', // Данный индекс не используется.
        1 => sprintf( 'Точка обновлена. Просмотр', esc_url( get_permalink($post_ID) ) ),
        2 => 'Точка обновлёна.',
        3 => 'Точка удалёна.',
        4 => 'Точка обновлена.',
        5 => isset($_GET['revision']) ? sprintf( 'Точка восстановлена из редакции: %s', wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
        6 => sprintf( 'Точка опубликована на сайте. Просмотр', esc_url( get_permalink($post_ID) ) ),
        7 => 'Точка сохранена.',
        8 => sprintf( 'Отправлена на проверку. Просмотр', esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ),
        9 => sprintf( 'Запланирована на публикацию: %1$s. Просмотр', date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ), esc_url( get_permalink($post_ID) ) ),
        10 => sprintf( 'Черновик обновлён. Просмотр', esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ),
    );
    return $messages;
}

// Произвольные поля для пользовательского типа записей
function true_custom_fields_city() {
    add_post_type_support( 'city', 'custom-fields'); // в качестве первого параметра укажите название типа поста
}
add_action('init', 'true_custom_fields_city');


//Создаем пользовательскую таксономию (элементами этой таксономии будут города)

// Пользовательская таксономия Город
function add_new_taxonomies() {
    register_taxonomy('cities', // создаем функцию с произвольным именем и вставляем в неё register_taxonomy()
    array('city'),
    array(
        'hierarchical' => false, // true - по типу рубрик, false - по типу меток, по умолчанию - false 
        'labels' => array(
            /* ярлыки, нужные при создании UI, можете не писать ничего, тогда будут использованы ярлыки по умолчанию */
            'name' => 'Город',
            'singular_name' => 'City',
            'search_items' => 'Найти город',
            'popular_items' => 'Популярные города',
            'all_items' => 'Все города',
            'parent_item' => null,
            'parent_item_colon' => null,
            'edit_item' => 'Редактировать город',
            'update_item' => 'Обновить город',
            'add_new_item' => 'Добавить новый город',
            'new_item_name' => 'Название нового города',
            'separate_items_with_commas' => 'Разделяйте города запятыми',
            'add_or_remove_items' => 'Добавить или удалить город',
            'choose_from_most_used' => 'Выбрать из наиболее часто используемых городов',
            'menu_name' => 'Города'
        ),
        'public' => true, // каждый может использовать таксономию, либо только администраторы, по умолчанию - true
        'show_in_nav_menus' => true, // добавить на страницу создания меню
        'show_ui' => true, // добавить интерфейс создания и редактирования
        'show_tagcloud' => true, // нужно ли разрешить облако тегов для этой таксономии
        'update_count_callback' => '_update_post_term_count', // callback-функция для обновления счетчика $object_type
        'query_var' => true, // разрешено ли использование query_var, также можно указать строку, которая будет использоваться в качестве него, по умолчанию - имя таксономии
        'rewrite' => array( // настройки URL пермалинков
        'slug' => 'cities', // ярлык
        'hierarchical' => false // разрешить вложенность
        ),
    )
    );
}
add_action( 'init', 'add_new_taxonomies', 0 );

Города точкам назначать будем как метки.

Произвольные поля

Задаем для записей типа city поля Координаты точки, Название точки, Контакты точки:

// Поле Координаты точки
add_action('add_meta_boxes', 'coordinati_tochka_box');
function coordinati_tochka_box() { add_meta_box('material_box', 'Координаты', 'coordinati_tochka_box_func', 'city', 'normal'); }
function coordinati_tochka_box_func($post){
    $coordinati_tochka = get_post_meta($post->ID, 'coordinati_tochka', 1);
    ?>
    <label><input style="width:100%;" type="text" name="extra[coordinati_tochka]" value="<?php if($coordinati_tochka){echo $coordinati_tochka;}?>" /></label>
    <input type="hidden" name="atb_nonce" value="<?php echo wp_create_nonce(__FILE__); ?>" />
    <?php
}

add_action('save_post', 'coordinati_tochka_box_update');
function coordinati_tochka_box_update($post_id){
    if (!wp_verify_nonce($_POST['atb_nonce'], __FILE__)) return false; // Проверка, что сохраняется именно нужная нам страница.
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return false; // Проверка, что это не автосохранение
    if (!current_user_can('edit_post', $post_id)) return false; // Проверка, что пользователь может изменять этот пост
    if(!isset($_POST['extra']) ) return false;    // Проверка, что нам пришли все поля
    foreach($_POST['extra'] as $key=>$value){ // Циклом добавляем поля. Можно и в ручную это делать... Но так проще добавить новое поле
        if(empty($value) AND $value != 0){ // Если значение пустое и не равно 0
            delete_post_meta($post_id, $key); // Удаляем это поле из мета-данных
            continue; // Продолжаем
        }
        update_post_meta($post_id, $key, $value); // Обновляем или добавляем мета-данные
    }
    return $post_id;
}



// Поле Название точки
add_action('add_meta_boxes', 'name_tochka_box');
function name_tochka_box() { add_meta_box('material_box_2', 'Название точки', 'name_tochka_box_func', 'city', 'normal'); }
function name_tochka_box_func($post){
    $name_tochka = get_post_meta($post->ID, 'name_tochka', 1);
    ?>
    <label><input style="width:100%;" type="text" name="extra[name_tochka]" value="<?php if($name_tochka){echo $name_tochka;}?>" /></label>
    <input type="hidden" name="atb_nonce" value="<?php echo wp_create_nonce(__FILE__); ?>" />
    <?php
}

add_action('save_post', 'name_tochka_box_update');
function name_tochka_box_update($post_id){
    if (!wp_verify_nonce($_POST['atb_nonce'], __FILE__)) return false; // Проверка, что сохраняется именно нужная нам страница.
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return false; // Проверка, что это не автосохранение
    if (!current_user_can('edit_post', $post_id)) return false; // Проверка, что пользователь может изменять этот пост
    if(!isset($_POST['extra']) ) return false;    // Проверка, что нам пришли все поля
    foreach($_POST['extra'] as $key=>$value){ // Циклом добавляем поля. Можно и в ручную это делать... Но так проще добавить новое поле
        if(empty($value) AND $value != 0){ // Если значение пустое и не равно 0
            delete_post_meta($post_id, $key); // Удаляем это поле из мета-данных
            continue; // Продолжаем
        }
        update_post_meta($post_id, $key, $value); // Обновляем или добавляем мета-данные
    }
    return $post_id;
}



// Поле Контакты точки
add_action('add_meta_boxes', 'contacts_tochka_box');
function contacts_tochka_box() { add_meta_box('material_box_3', 'Контакты точки', 'contacts_tochka_box_func', 'city', 'normal'); }
function contacts_tochka_box_func($post){
    $contacts_tochka = get_post_meta($post->ID, 'contacts_tochka', 1);
    ?>
    <label><input style="width:100%;" type="text" name="extra[contacts_tochka]" value="<?php if($contacts_tochka){echo $contacts_tochka;}?>" /></label>
    <input type="hidden" name="atb_nonce" value="<?php echo wp_create_nonce(__FILE__); ?>" />
    <?php
}

add_action('save_post', 'contacts_tochka_box_update');
function contacts_tochka_box_update($post_id){
    if (!wp_verify_nonce($_POST['atb_nonce'], __FILE__)) return false; // Проверка, что сохраняется именно нужная нам страница.
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return false; // Проверка, что это не автосохранение
    if (!current_user_can('edit_post', $post_id)) return false; // Проверка, что пользователь может изменять этот пост
    if(!isset($_POST['extra']) ) return false;    // Проверка, что нам пришли все поля
    foreach($_POST['extra'] as $key=>$value){ // Циклом добавляем поля. Можно и в ручную это делать... Но так проще добавить новое поле
        if(empty($value) AND $value != 0){ // Если значение пустое и не равно 0
            delete_post_meta($post_id, $key); // Удаляем это поле из мета-данных
            continue; // Продолжаем
        }
        update_post_meta($post_id, $key, $value); // Обновляем или добавляем мета-данные
    }
    return $post_id;
}

В последствии в поле Координаты точки мы будем прописывать реальные координаты точки, беря их из карт Яндекс. Поля Название точки и Контакты точки нужны для сопроводительного текста при нажатии на точку, или если точки выводить в виде списка.

Зададим произвольное поле и для таксономии с городами:

// Создание метаполя Координаты для города
function pippin_taxonomy_add_new_meta_field() { // this will add the custom meta field to the add new term page
    ?>
    <div class="form-field">
    <label for="term_meta[custom_term_meta]"><?php _e( 'Example meta field', 'pippin' ); ?></label>
    <input type="text" name="term_meta[custom_term_meta]" id="term_meta[custom_term_meta]" value="">
    <p class="description"><?php _e( 'Enter a value for this field','pippin' ); ?></p>
    </div>
    <?php
}
add_action( 'cities_add_form_fields', 'pippin_taxonomy_add_new_meta_field', 10, 2 );


// Редактирование мета поля
function pippin_taxonomy_edit_meta_field($term) {
    $t_id = $term->term_id;  // put the term ID into a variable
    $term_meta = get_option( "taxonomy_$t_id" ); // retrieve the existing value(s) for this meta field. This returns an array
    ?> 
    <tr class="form-field">
    <th scope="row" valign="top"><label for="term_meta[custom_term_meta]"><?php _e( 'Example meta field', 'pippin' ); ?></label></th>
    <td>
    <input type="text" name="term_meta[custom_term_meta]" id="term_meta[custom_term_meta]" value="<?php echo esc_attr( $term_meta['custom_term_meta'] ) ? esc_attr( $term_meta['custom_term_meta'] ) : ''; ?>">
    <p class="description"><?php _e( 'Enter a value for this field','pippin' ); ?></p>
    </td>
    </tr>
    <?php
}
add_action( 'cities_edit_form_fields', 'pippin_taxonomy_edit_meta_field', 10, 2 );


// Сохранение метаполя
function save_taxonomy_custom_meta( $term_id ) {
    if ( isset( $_POST['term_meta'] ) ) {
        $t_id = $term_id;
        $term_meta = get_option( "taxonomy_$t_id" );
        $cat_keys = array_keys( $_POST['term_meta'] );
        foreach ( $cat_keys as $key ) {
            if ( isset ( $_POST['term_meta'][$key] ) ) { $term_meta[$key] = $_POST['term_meta'][$key]; }
        }
        update_option( "taxonomy_$t_id", $term_meta ); // Save the option array.
    }
}
add_action( 'edited_cities', 'save_taxonomy_custom_meta', 10, 2 );
add_action( 'create_cities', 'save_taxonomy_custom_meta', 10, 2 );

Это поле нужно чтобы вписывать координаты городов, которые придется предварительно уточнять в Яндекс картах.

Найти способ генерации координатов налету по адресу точки или города

Шаблоны вывода

Шаблон archive-city.php — здесь будем выводить список всех городов, причем размечая их по алфавиту. Для меню шаблон доступен по ссылке /city/

<?php $terms = get_terms( 'cities'); ?>

<script type="text/javascript" src="https://api-maps.yandex.ru/2.1/?lang=ru_RU"></script>

<style>.YMaps {position: relative; height: 400px; width:100%;}</style>

<div id="YMaps_0" class="YMaps"></div>

<script type="text/javascript">
ymaps.ready(init);

function init () {
    var myMap = new ymaps.Map("YMaps_0", {
        center: [47.413167,40.532044],
        zoom: 7
    });
    myMap.controls.add("routeEditor");
    
    <?php foreach( $terms as $term ): ?>
        <?php $term_meta = get_option( "taxonomy_$term->term_id" ); 
        $term_link = get_term_link($term->term_id, 'cities'); ?>
        myPlacemark_1 = new ymaps.Placemark([<?php echo esc_attr( $term_meta['custom_term_meta'] ) ? esc_attr( $term_meta['custom_term_meta'] ) : ''; ?>], 
        {balloonContentHeader: "<a href='<?php echo $term_link; ?>'><?php echo $term->name; ?></a>",},
        {preset: "islands#redDotIcon"}
        );
        myMap.geoObjects.add(myPlacemark_1);
    <?php endforeach; ?>
}

</script>

<h1 id="title"><i class="fa fa-map-marker" aria-hidden="true"></i> Где купить</h1> 

<div id="all-city">

<?php global $query_string;
parse_str($query_string, $args);  // добавляем базовые параметры в массив $args
$args['posts_per_page'] = -1;  // добавляем/заменяем параметр в массиве
query_posts( $args ); ?>  

<?php echo '<div class="city-letter">'; 
foreach( $terms as $k => $term ){
    $fl = get_first_letter( $term->name );  // первая буква
    $prev_fl = isset( $terms[ ($k-1) ] ) ? get_first_letter( $terms[ ($k-1) ]->name ) : '';
    if( $prev_fl !== $fl ) 
    echo '</div><div class="city-letter"><h3>'.$fl.'</h3>'; // Буква
    printf ( '<a href="%s">%s</a><br>' , get_term_link($term->term_id, 'cities'), $term->name ); // Выводим название записи в виде ссылки на неё
}
echo '</div>';
wp_reset_postdata(); ?>

<?php // Функция возвращает первую букву переданного в неё слова
function get_first_letter( $str ){ return mb_substr($str, 0, 1, 'utf-8'); } ?> 

</div>

Выглядеть это должно примерно так:

Шаблон taxonomy-cities.php будет выводить элементы пользовательской таксономии (отдельный город с точками)

<?php $term_slug = get_query_var( 'cities' ); 
$term = get_term_by('slug', $term_slug, 'cities'); 
$term_meta = get_option( "taxonomy_$term->term_id" ); ?>

<script type="text/javascript" src="https://api-maps.yandex.ru/2.1/?lang=ru_RU"></script>

<style>.YMaps {position: relative; width:100%; height:650px;}}</style>

<div id="YMaps_0" class="YMaps"></div>

<script type="text/javascript">
ymaps.ready(init);
function init () {
    var myMap = new ymaps.Map("YMaps_0", {
        center: [<?php echo esc_attr( $term_meta['custom_term_meta'] ) ? esc_attr( $term_meta['custom_term_meta'] ) : ''; ?>], //найти какая функция отвечает за определение центра, а пока сделать полем
        zoom: 11
    });
    myMap.controls.add("routeEditor");

    <?php if ( have_posts() ) : ?>
    <?php while ( have_posts() ) : the_post(); ?> 
        myPlacemark_1 = new ymaps.Placemark([<?php echo get_post_meta($post->ID, 'coordinati_tochka', 1); ?>], //научиться налету конвертировать координаты
        {balloonContentHeader: "<?php echo get_post_meta($post->ID, 'name_tochka', 1); ?>",
        balloonContentBody: "<?php echo get_post_meta($post->ID, 'contacts_tochka', 1); ?>"},
        {preset: "islands#redDotIcon"}
        );
        myMap.geoObjects.add(myPlacemark_1);
    <?php endwhile; ?>
    <?php endif; ?>
}
</script>

<h1 id="title"><?php echo $term->name; ?></h1>

<?php if ( have_posts() ) : ?><ul> 
<?php while ( have_posts() ) : the_post(); ?>

    <li><strong><?php echo get_post_meta($post->ID, 'name_tochka', 1); ?></strong> <?php the_title(); ?> <?php echo get_post_meta($post->ID, 'contacts_tochka', 1); ?></li>

<?php endwhile; ?></ul>
<?php endif; ?>

В этом шаблоне мне пришлось оказаться от хлебных крошек от Kama (получалась несуразица) и прописать свои:

<div id="path"><div class="kama_breadcrumbs" itemscope="" itemtype="http://schema.org/BreadcrumbList">
    <span itemprop="itemListElement" itemscope="" itemtype="http://schema.org/ListItem"><a href="https://site.ru" itemprop="item"><span itemprop="name">Главная</span></a></span> / 
    <a href="/city/" itemprop="item"><span itemprop="name">Где купить</span></a> / <span class="current"><?php echo $term->name; ?></span></div>
</div>

В итоге должно получиться примерно так:

Информация в balloonContentBody

В всплывающий блок balloonContentBody можно вставлять любую верстку html и контент. Пример:

balloonContentBody: "<img src='/wp-content/uploads/2019/09/image.jpg'><br><p>г. Ростов-на-Дону, пр. Космонавтов, 39</p>"
[site-socialshare]
  • Похожие записи
  • Комментарии
  • Вложения
API Яндекс.Карт

API Яндекс.Карт

Если нам нужно кастомизировать карту Яндекс, то будет не достаточно подключить ее через iframe, т.к. в нем не будет никаких настроек. Необходимо подключить API Яндекс.Карт Подключаем API Яндекс.Карт На данный Читать далее »

Записи-метки на картах

Записи-метки на картах

Сделаем функционал привязки записи (любого типа) к картам Google или Yandex. Это может быть востребовано для контактов дилерских центров, филиалов и т.п. Это статья является как бы вступительной теоретической. Более Читать далее »

Изменить стиль карты Google Map

Изменить стиль карты Google Map

Изменяем стили оформления карты Google Map. Также можно настроить отображение маркера, скрыть либо добавить объекты на карту. Подключение скрипта Google Maps API Подключаем скрипт добавляющий функционал добавления и редактирования карт Читать далее »

Добавить комментарий

Пока нет комментариев. Будь первым!

Посты — метки на карте Посты — метки на карте Посты — метки на карте
Адаптация woocommerce под свой шаблон
Рекомендации для васАдаптация woocommerce под свой шаблонOpttour.ru
Спасибо! Наш менеджер свяжется с Вами в течении 5 минут.