На одном из сайтов был установлен плагин CookieYes | GDPR Cookie Consent. Нужно было сделать так, чтобы он появлялся, а внизу у него пробегала полоса загрузки и он исчезал и больше не появлялся на этом устройстве.
Поступил очень просто, в настройках плагина указал, чтобы он скрывался автоматически через 20 секунд.
А затем прописал код в сниппете, в котором скрипт отвечающий за анимацию полосы загрузки, которая длится тоже 20 сек, а также стили для самого окошка.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
add_action( 'wp_footer', function () { ?> <style> #cookie-law-info-bar span { padding: 5px 20px 5px 20px; margin:0 auto; border-radius: 25px; font-size: 13px; line-height: 1.3; align-items: center; width: fit-content; box-shadow: 0 1px 8px 0 rgba(0, 0, 0, 0.15); background:#ffffff; position:relative; display:block; overflow:hidden; } #cookie-law-info-bar { background:transparent !important; box-shadow: none; } #cookie-law-info-bar span .scroll-time { content:""; position: absolute; left: 0; bottom: 0; height: 5px; background: #38d646; z-index: 1; } #cookie-law-info-bar span a.cli-plugin-button { border-radius:20px; } } </style> <div class="bar-footer"></div> <script type="text/javascript"> jQuery('#cookie-law-info-bar span').append('<div class="scroll-time"></div>') var cookieIndicator = jQuery('.scroll-time'); cookieIndicator.stop().animate({ width: '100%' }, 20000); // ставим задержку как в настройках плагина GDPR Cookie Consent -> Auto-hide(Accept) cookie bar after delay </script> <?php } ); |
В итоге получилось такое окошко с текстом о куках, которое автоматически скрывается, а по индикатору загрузки видно, сколько ему осталось.
На одном из сайтов необходимо было сделать, чтобы во время нерабочего времени писалось, что офис закрыт, а в рабочее отрыт. Для этого был написан небольшой сниппет, выкладываю его тут, там куски кода отвечающие за разные стили в разное время суток и разные надписи. А также кусок кода который умеет склонять в зависимости от количества. В данном случае это врямя: 1 час, 2 часа, . . . 5 часов.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
// функция склонения function num_decline( $number, $titles, $show_number = true ){ if( is_string( $titles ) ){ $titles = preg_split( '/, */', $titles ); } // когда указано 2 элемента if( empty( $titles[2] ) ){ $titles[2] = $titles[1]; } $cases = [ 2, 0, 1, 1, 1, 2 ]; $intnum = abs( (int) strip_tags( $number ) ); $title_index = ( $intnum % 100 > 4 && $intnum % 100 < 20 ) ? 2 : $cases[ min( $intnum % 10, 5 ) ]; return ( $show_number ? "$number " : '' ) . $titles[ $title_index ]; } // // это изменение стиля блоков в зависимости от времени суток add_action( 'wp_footer', function () { date_default_timezone_set('Asia/Vladivostok'); // текущий час $time=date('H'); // текущий день недели // День недели возвращается в виде числа (0=Воскресенье, 1=Понедельник и т.д.) $day = date("w", mktime(0,0,0,date("m"),date("d"),date("Y"))); if ($day==0 || $day==6) { ?> <style> div#div_block-37-357 { background: url(/wp-content/uploads/2023/08/night.webp); background-color: #353535; background-repeat:no-repeat; background-size: 50px; background-position: 99% 10px; padding: 30px 70px 30px 30px; color: #fff; border-radius: 30px; } </style> <?php } else { if($time>=9 && $time<18) { ?> <style> div#div_block-37-357 { background: url(/wp-content/uploads/2023/08/sun.webp); background-repeat:no-repeat; background-size: 50px; background-position: 100% 0px; padding: 0 60px 0 0; } </style> <?php } else { ?> <style> div#div_block-37-357 { background: url(/wp-content/uploads/2023/08/night.webp); background-color: #353535; background-repeat:no-repeat; background-size: 50px; background-position: 99% 10px; padding: 30px 70px 30px 30px; color: #fff; border-radius: 30px; } </style> <?php } } }); // шорткод с текстом, что офис закрыт add_shortcode( 'close-office', function () { date_default_timezone_set('Asia/Vladivostok'); // текущий час $time=date('H'); // текущий день недели // День недели возвращается в виде числа (0=Воскресенье, 1=Понедельник и т.д.) $day = date("w", mktime(0,0,0,date("m"),date("d"),date("Y"))); if ($day==0 || $day==6) { $close_open = '<span>Закрыто</span>'; } else { if($time>=9 && $time<18) { $close_open = 'Открыто'; } else { if($time>9) { $ostatok_time = 24-$time+9; } else { $ostatok_time = 9-$time; } $close_open = '<span>Откроется через '.num_decline( $ostatok_time, 'час, часа, часов' ).'</span>'; } } $timer=date("H:i"); echo '<div class="close_time">'.$timer.'</div>'; echo '<div class="close_mes">'.$close_open.'</div>'; } ); add_action( 'wp_footer', function () { ?> <style> div.close_time { font-size: 24px; font-weight: 600; } div.close_mes { margin: 10px 30px 0 0; text-wrap: nowrap; } div.close_mes span { color:#ffaeae; } </style> <?php }); |
Нужно быстро сделать какое-нибудь действие на сайте, чтобы записать его в куки и запомнить на этом устройстве. Это допустим всплывающее окошко, которое предупреждает о чём-то и после его закрытия не появляется еще долго.
На выручку пришел сайт https://codernote.ru/jquery/rabota-s-cookies-na-jquery/ на нем подробно описано как это реализовать.
Я же реализовал так:
Скачал файл с github.com
Подключил его, при условии, что библиотека jQuery подключена.
1 |
<script type="text/javascript" src="https://elmagaz.ru/js/jquery.cookie.js"></script> |
На странице, где мне нужна была появляющаяся подсказка добавил код с блоком:
1 2 3 4 5 6 7 |
<div class="mobile_hand_scrolle_table"> <div class="popup_hand"> <img src="/img/hand_scrolle.png"> <p>двигайте таблицу чтобы увидеть целиком</p> <span>понятно</span> </div> </div> |
Прописал скрипт, который проверяет определена ли кука и если нет, до добавляет класс к блоку «mobile_hand_scrolle_table» .show_popup при нажатии на это окно, класс .show_popup удаляется, и в куки записывается переменная show_scroll_table=yes и в последствии это окно будет скрыто по истечении 365 дней.
1 |
mobile_hand_scrolle_table |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<script type="text/javascript"> if ( jQuery.cookie('show_scroll_table') == null ) { jQuery('.mobile_hand_scrolle_table').addClass('show_popup'); } else { jQuery('.mobile_hand_scrolle_table').removeClass('show_popup'); } jQuery('.mobile_hand_scrolle_table .popup_hand').on('click', function(e){ e.preventDefault(); jQuery('.mobile_hand_scrolle_table').removeClass('show_popup'); jQuery.cookie('show_scroll_table', 'yes', { expires: 365, path: '/' }); }); </script> |
Где expires: 365 - это количество дней жизни переменной,
path: '/' — это для всех страниц сайта установлена кука, можно прописывать конкретный адрес.
А также прописываю стили для блока, чтобы он по умолчанию появлялся, а когда мы по нему кликнули, то скрывался. Конкретно в этом варианте, он появляется один раз только на мобильных устройствах.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
.mobile_hand_scrolle_table { display:none; position: absolute; top: 0; bottom: 0; left: 0; right: 0; background: rgba(2, 2, 2, 0.55); justify-content: center; align-items: flex-start; } .mobile_hand_scrolle_table .popup_hand { display: inline-flex; padding: 20px; flex-direction: column; justify-content: center; align-items: center; gap: 12px; margin:105px 0 0 0; border-radius: 9px; background: rgba(255, 255, 255, 0.82); width: 190px; } .mobile_hand_scrolle_table .popup_hand img { width: 53px; height: 53px; } .mobile_hand_scrolle_table .popup_hand p { color: #000; text-align: center; font-size: 12px; font-style: normal; font-weight: 400; line-height: normal; } .mobile_hand_scrolle_table .popup_hand span { display: flex; padding: 10px 30px; align-items: flex-start; gap: 10px; border-radius: 8px; background: #FFF; color: #000; text-align: center; font-size: 12px; font-style: normal; font-weight: 400; line-height: normal; } @media only screen and (max-width: 768px) { .mobile_hand_scrolle_table.show_popup { display: flex; } } |
После обновления Woocommerce до версии 7.8, перестала пересчитывается общая сумма заказа, когда меняем количество товаров на странице - Корзина. Общая сумма выведена через блок Oxygen oxy-cart-total. Так же не пересчитывается общее количество товаров выведенные через свой код. Так же не работает пересчет в плагине Side Cart WooCommerce если мы на странице Корзины или Оформлении заказа.
РЕШЕНИЕ: помогло решение с форума поддержки плагина Woocommerce.
На сайте добавил следующий код в сниппет, и сумма стала пересчитывается при обновлении количества товаров.
1 2 3 4 |
add_action( 'wp_enqueue_scripts', 'custom_enqueue_wc_cart_fragments' ); function custom_enqueue_wc_cart_fragments() { wp_enqueue_script( 'wc-cart-fragments' ); } |
Задача: Есть страница, у неё дочерние страницы. На этих страницах необходимо выводить список PDF файлов, но их много и добавлять вручную лень. Поэтому для простоты, файлы называют русскими буквами и закидываю по FTP на сервер в определенные папки, а там раскидывают по папкам по годам. Нужно вывести список этих файлов и разложить по годам.
Решение: С помощью искусственного интеллекта эта задача решилась за час. Был написан код, который выводит список файлов, а с помощью библиотеки Isotope, которая уже подключена в этом проекте сделан фильтр по годам.
Вот код для сниппета, CSS же выведен отдельно, здесь его не прикладываю.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
// Название шорткода который необходимо вставить на страницу, для вывода файлов из соответствующих папок на FTP add_shortcode( 'vivod_materials', function () { // Возмем SLUG текущей страницы global $post; $slug_obj = $post->post_name; // Пробежимся по подпапкам в основной папке $dir = $_SERVER['DOCUMENT_ROOT'].'/wp-content/uploads/building/'. $slug_obj .'/materials'; $folders = array_filter(scandir($dir), function($item) use ($dir) { return is_dir($dir . '/' . $item) && !in_array($item, array('.', '..')); }); // Переворачиваем сортировку, чтобы последние года были наверху $folders = array_reverse($folders); // выводи наверху список годов echo '<div class="obj_file_filter_materials button-group filter-button-group">'; foreach($folders as $folder) { //Проверка текущего года $yaer_now = date('Y'); if ($folder == $yaer_now){ $css_is_checked = 'is-checked'; } else { $css_is_checked = 'none'; } echo '<button class="' . $css_is_checked . '" data-filter=".block_file_materials_' .$folder. '">' . $folder . '</button>'; } echo '</div>'; // добавляем блок для фильтрации echo '<div class="obj-file-all_materials">'; // Выводим файлы по годам foreach($folders as $folder) { echo '<div class="block_file_item block_file_materials_' .$folder. '">'; echo '<h3>' . $folder . '</h3>'; // Указываем путь к папке, в которой будем искать файлы $path = $dir . '/' . $folder . '/'; // Получаем список файлов и папок в указанной директории $files = scandir($path); // Проходим по всем файлам в указанной папке и выводим их имена foreach ($files as $filename) { if (is_file($path . '/' . $filename)) { $name = pathinfo($filename, PATHINFO_FILENAME); $extension = pathinfo($filename, PATHINFO_EXTENSION); echo '<a target="_blank" class="file_' . $extension . ' year_' . $folder . '" href="/wp-content/uploads/building/' . $slug_obj . '/materials/'.$folder.'/' . $filename . '">' . $name . '</a>'; } } echo '</div>'; } echo '</div>'; // скрипт фильтра изотоп add_action( 'wp_footer', function () { ?> <script type="text/javascript"> // Инициализация Isotope var $grid_m = jQuery('.obj-file-all_materials').isotope({ // Опции itemSelector: '.block_file_item', layoutMode: 'fitRows', filter: '.block_file_materials_<?php echo date('Y');?>' }); // Фильтруем по нажатию кнопок var filters = {}; jQuery('.obj_file_filter_materials').on( 'click', 'button', function() { var $this = jQuery(this); // get group key var $buttonGroup = $this.parents('.button-group'); var filterGroup = $buttonGroup.attr('data-filter-group'); // set filter for group filters[ filterGroup ] = $this.attr('data-filter'); // combine filters var filterValue = concatValues( filters ); $grid_m.isotope({ filter: filterValue }); }); // flatten object by concatting values function concatValues( obj ) { var value = ''; for ( var prop in obj ) { value += obj[ prop ]; } return value; } // Добавляем и убираем класс is-checked для активных кнопок jQuery('.button-group').each( function( i, buttonGroup ) { var $buttonGroup = jQuery( buttonGroup ); $buttonGroup.on( 'click', 'button', function( event ) { $buttonGroup.find('.is-checked').removeClass('is-checked'); var $button = jQuery( event.currentTarget ); $button.addClass('is-checked'); }); }); jQuery('.filter-foto-button').click(function(){ jQuery('.filter-button-group .filter-foto-button:not(.is-checked)').toggleClass("default"); }); </script> <?php }); }); |
Вот так это выглядит на фронте
https://symbl.cc/ru/202F/ особенно полезен когда нужно вставить перед знаком рубль, после цены.
Нужно было на сайте поменять title на свой, чтобы в нем брались данные с переменных в ссылке вида мой.сайт/page/?hash=suvorov-naprimer_1_1_1876_63d51d8a170de
Для этого в сниппете пишем код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
// берем значение из гет строки $hash = isset($_GET['hash']) ? strtolower(trim($_GET['hash'])) : ''; // если переменная не пустая if ($hash) { // вычленяем отдельные параметры $parts = explode('_', $hash); global $name_user; $name_user = $parts[0]; $day = ltrim($parts[1], '0'); $month = ltrim($parts[2], '0'); $year = $parts[3]; $dbhash = $parts[4]; global $data_user; $data_user = $day.'.'.$month.'.'.$year; } else { echo 'Нет данных для отображения'; } function get_myname() { global $name_user; return $name_user; // выводим имя } function get_mydate() { global $data_user; return $data_user; } // регистрация своих переменных для Yoast SEO function register_custom_yoast_variables() { wpseo_register_var_replacement( '%%nameuser%%', 'get_myname', 'advanced', 'текст подсказки' ); wpseo_register_var_replacement( '%%dateuser%%', 'get_mydate', 'advanced', 'текст подсказки' ); } add_action('wpseo_register_extra_replacements', 'register_custom_yoast_variables'); |
В настройках блока Yoast SEO вставляем свои переменные %%nameuser%% и %%dateuser%%
Иногда место на хостинге заканчивается, и тогда встает вопрос, как посмотреть кто виновник. Особенно это актуально, когда проектов много, и некоторые уже забыты, а место они занимают.
Я поступаю так:
По команде DU можно поискать в интернете, для себя сохранил именно эту. Ключи:
Так находятся файлы о которых или забыли, всякие архивы, дампы и многое другое.
На одном из сайтов потребовалось менять номер телефона если переход идет с Яндекс Директа, и есть ссылка с UTM параметром. Попробовал несколько скриптов, но остановился на этом, так как он не критичен к тому если один из селекторов не находит. Поэтому можно прописать кучу селекторов, которые есть на сайте. И он будет работать. Вставляя его в сниппет:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
<script> // Добавьте UTM-метку utm_medium к ссылке в рекламной кампании, например //site.ru/?utm_source=yadirect&utm_medium=cpc (function( $ ) { $.fn.changeData = function(options) { var settings = { urlParam: null, nameCookie: null, paramList: null, newData: null }; return this.each(function() { if (options) { $.extend(settings, options); } function getCookie(name) { var cookie = " " + document.cookie; var search = " " + name + "="; var setStr = null; var offset = 0; var end = 0; if (cookie.length > 0) { offset = cookie.indexOf(search); if (offset != -1) { offset += search.length; end = cookie.indexOf(";", offset); if (end == -1) { end = cookie.length; } setStr = unescape(cookie.substring(offset, end)); } } return(setStr); } // записывает utm в cookie на 30 дней function setCookie(name, valCookie) { document.cookie = name+"=; expires=; path=/"; expires = new Date(); expires.setTime(expires.getTime() + (30*24*60*60*1000)); document.cookie = name+"=" + valCookie + "; expires=" + expires.toGMTString() + "; path=/" } function parseGetParams(peremennya) { var getURl = window.location.search.substring(1); var peremennii = getURl.split("&"); for (var i=0; i<peremennii.length; i++) { var pair = peremennii[i].split("="); if (pair[0] == peremennya) { return pair[1]; } } return(false); } var param = parseGetParams(settings.urlParam); if (settings.paramList.indexOf(param)!=-1) { setCookie(settings.nameCookie, param); } var param_cookie = getCookie(settings.nameCookie); for(var i=0; i<settings.paramList.length; i++){ if ((param_cookie == settings.paramList[i]) || (param == settings.paramList[i])) { $(this).html(settings.newData[i]); } } }) }; })(jQuery); jQuery(function() { // в шапке jQuery('#shortcode-172-6350').changeData({ urlParam: 'utm_medium', nameCookie: 'utm_medium_change', paramList: [ 'cpc' ], newData: [ '<a href="tel:+74230000000">8 (423) 000-00-00</a>' ] }); // на главной jQuery('#shortcode-1411-7215').changeData({ urlParam: 'utm_medium', nameCookie: 'utm_medium_change', paramList: [ 'cpc' ], newData: [ '<a href="tel:+74230000000">8 (423) 000-00-00</a>' ] }); // в футере jQuery('#tel_footer').changeData({ urlParam: 'utm_medium', nameCookie: 'utm_medium_change', paramList: [ 'cpc' ], newData: [ '<a href="tel:+74230000000">8 (423) 000-00-00</a>' ] }); // в контактах jQuery('#shortcode-59-416').changeData({ urlParam: 'utm_medium', nameCookie: 'utm_medium_change', paramList: [ 'cpc' ], newData: [ '<a href="tel:+74230000000">8 (423) 000-00-00</a>' ] }); // в материалах jQuery('#div_block-368-7014').changeData({ urlParam: 'utm_medium', nameCookie: 'utm_medium_change', paramList: [ 'cpc' ], newData: [ '<a id="link_text-370-7014" class="ct-link-text" href="tel:+74230000000">+7 (423) 000-00-00</a>' ] }); }); </script> |
Решение взял с этого сайта https://brandmaker.ru/base/change-data
Понадобилось на одном проекте сделать галерею с превьюшками.
Так как это были кастомные записи, и их было много то, решил эту галерею вывести с помощью кастомных полей ACF и слайдера на основе Slick.
Для этого создал дополнительное поле для записи как Редактор WordPress
В поле добавлял обычную галерею которая есть в редакторе WordPress, а выводил её в шаблоне вывода записи, с помощью PHP-кода или через Oxygen, причем в двух местах, одна за другой (дубль). Только первому присваивал дополнительный стиль: slider-for-jq, а второму: slider-nav-jq.
И через сниппет подключил модуль Slick и прописал стили.
Вот код сниппета с готовым кодом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
// Подключаем библиотеку Slick add_action( 'wp_footer', function () { ?> <style> .slider-for-jq div.gallery, .slider-nav-jq div.gallery { display:flex; flex-direction: row; width:100%; } .slider-for-jq div.gallery { height: max-content; flex-wrap: wrap; } .slider-for-jq div.gallery figure.gallery-item, .slider-nav-jq div.gallery figure.gallery-item { margin:0 5px; } .slider-for-jq div.gallery figure { width:100%; height: max-content; } .slider-for-jq div.gallery.slick-slider figure img { height: 400px; object-fit: cover; width: 100%; } .slider-nav-jq div.gallery figure img { width:100px; height: 100px; object-fit: cover; opacity: .5; transition:all 0.3s; } .slider-nav-jq div.gallery.slick-slider figure img { width:100%; } .slider-nav-jq div.gallery figure.slick-active.slick-current img { opacity: .95; } @media only screen and (max-width: 768px) { .slider-nav-jq div.gallery figure img { height: 50px; } .slider-for-jq div.gallery.slick-slider figure img { height:auto; } } </style> <link rel="stylesheet" type="text/css" href="/wp-content/themes/for_oxygen/plugins/slick/slick.css"/> <link rel="stylesheet" type="text/css" href="/wp-content/themes/for_oxygen/plugins/slick/slick-theme.css"/> <script type="text/javascript" src="/wp-content/themes/for_oxygen/plugins/slick/slick.min.js"></script> <script> jQuery(document).ready(function(){ // добавляем стили для галереи, чтобы она заработала jQuery('span.slider-for-jq div.gallery').addClass( 'slider-for' ); jQuery('span.slider-nav-jq div.gallery').addClass( 'slider-nav' ); //слайдр в проектах jQuery('.slider-for').slick({ slidesToShow: 1, slidesToScroll: 1, arrows: false, fade: true, asNavFor: '.slider-nav' }); jQuery('.slider-nav').slick({ slidesToShow: 4, slidesToScroll: 1, asNavFor: '.slider-for', arrows: false, dots: false, centerMode: true, focusOnSelect: true }); }); // отключение ссылок на иконках галереи jQuery('.slider-nav-jq div.gallery figure.gallery-item a').on('click', function (e) { e.preventDefault(); // этот код предотвращает стандартное поведение браузера по клику // остальной код //alert("Мы не перешли по ссылке, а вывели своё сообщение!"); }); </script> <?php } ); |
И еще один момент, для того чтобы по клику на изображение открывалось большое изображение в модальном окне - установил плагин Easy FancyBox. А для навигационных слайдов отключил автоматическое определение ссылок как фансибокс, для этого добавил стиль .slider-nav-jq .gallery-icon a в исключения:
Необходимо было сделать, чтобы модальное окно открывалось на смартфоне во всю ширину экрана. Поэтому пользователи чтобы закрыть его использовали кнопку НАЗАД, на своем смартфоне. Но это приводило к переходу на одну страницу назад.
Шаблон сверстан в Oxygen, такой функции по умолчанию нет, поэтому прописал в сниппете следующий код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
//По нажатию на кнопку вызова модального окна, добавляет хэш и изменяет историю браузера. jQuery("a.cast-button-butt").on("click", function() { var urlReplace = "#" + jQuery(this).attr('id'); history.pushState(null, null, urlReplace); }); jQuery("a.button-xs").on("click", function() { var urlReplace = "#" + jQuery(this).attr('id'); history.pushState(null, null, urlReplace); }); // По нажатию на кнопку назад, закрывает модальное окно Oxy jQuery(window).on('popstate', function() { jQuery(document).ready(function() { oxyCloseModal(); }); }); |
Этот код делает следующие действия, когда нажимаю на кнопку, чтобы открыть модальное окошко, добавляется новое состояние истории в виде нового хэша в урл. Затем событие popstate закрывает открытое модальное окно.
Пример взят тут, за что им очень благодарен.
Необходимо было сделать чтобы переключалки слайдера были внизу и показывалось количество слайдов и номер слайда.
Для этого добавляем вот такой код в сниппет, и всё работает.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
add_action( 'wp_head', function () { ?> <script type="text/javascript"> window.onload=function(){ jQuery('nav.unslider-nav').each(function() { var text = jQuery(this).find('li:last-child').text(); // находим выбранную опцию и берем из нее текст jQuery(this).append('/ '+text); }); } </script> <style> nav.unslider-nav { position: absolute; bottom: 0; left: calc(50% - 80px); color: #fff; background: rgb(45,176,2); background: -moz-linear-gradient(left, rgba(45,176,2,1) 0%, rgba(56,215,73,1) 100%); background: -webkit-linear-gradient(left, rgba(45,176,2,1) 0%,rgba(56,215,73,1) 100%); background: linear-gradient(to right, rgba(45,176,2,1) 0%,rgba(56,215,73,1) 100%); filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#2db002', endColorstr='#38d749',GradientType=1 ); padding: 20px 60px 10px 60px; display: flex; flex-direction: row; align-items: center; justify-content: center; font-size:22px; } body nav.unslider-nav ol li { text-indent:0; width:auto; height: auto; margin: 0 4px; background: transparent; border-radius: 0px; overflow: hidden; border: none; cursor: pointer; box-shadow:none; display: none; font-size:22px; } body nav.unslider-nav ol li.unslider-active { border: none !important; background:transparent !important; box-shadow:none !important; display:block; } body .unslider-arrow.prev { top: calc(100% - 31px); left: calc(50% - 75px) !important; background:transparent; } body .unslider-arrow.next { top: calc(100% - 23px); right: calc(50% - 85px) !important; background:transparent; } body .unslider-arrow:before { content: "\e902"; color:#ffffff; font-family: 'intersite' !important; line-height: 1; font-size: 25px; position: absolute; top: 0; left: 0; text-indent: 0; } </style> <?php } ); |
Столкнулся с такой проблемой, что созданные атрибуты в Woocommerce не выводятся в карточке товаров которая сверстана в Oxygen. Вернее если применен стандартный вывод информации товара. Так же атрибуты не выводятся в модальном окне через плагин yith-woocommerce-quick-view.
С помощью хуков вывел атрибуты и в большой карточке товаров и в модальном окне. Так же можно выводить в мини-карточках на странице архивов.
1 2 3 4 5 6 7 8 9 |
// Функция вывода атрибутов function atrb_productShoes() { global $product; $product->list_attributes(); } // Хук для вывода в большой карточке товара add_action( 'woocommerce_single_product_summary', 'atrb_productShoes' ); // Хук для вывода в карточке товара в YITH окне add_action( 'yith_wcqv_product_summary', 'atrb_productShoes', 16 ); |
Чтобы посмотреть порядок вывода для модального окна YITH, можно заглянуть в файл:
/wp-content/plugins/yith-woocommerce-quick-view/includes/class.yith-wcqv-frontend.php
Сам код я взял на сайте https://wpcraft.top/woocommerce-kak-vyvesti-atributy-tovarov-v-kataloge/ Там есть еще пару вариантов, я их не проверял. Но размещу тут, вдруг пригодятся.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
function atrb_productShoes2() { global $product; global $post; $attributes = $product->get_attributes(); if ( ! $attributes ) { return; } foreach ( $attributes as $attribute ) { // Получение таксаномии $terms = wp_get_post_terms( $product->id, $attribute[ 'name' ], 'all' ); $taxonomy = $terms[ 0 ]->taxonomy; // Получение объекта таксаномии $taxonomy_object = get_taxonomy( $taxonomy ); // Получение меток атрибутов $attribute_label = $taxonomy_object->labels->name; $attribute_label = str_replace('Товар', '', $attribute_label); // Отображение метки с кликабельным списком терминов echo get_the_term_list( $post->ID, $attribute[ 'name' ] , '<div class="attributes">' . $attribute_label . ': ' , ', ', '</div>' ); } } // Хук для вывода после заголовка товаров в категории add_action( 'woocommerce_after_shop_loop_item_title', 'atrb_productShoes2' ); |
И вывод не всех атрибутов, а только первых двух:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
function atrb_productShoes2() { global $product; global $post; $attributes = $product->get_attributes(); if ( ! $attributes ) { return; } $counter = 0; // задаем счетчик foreach ( $attributes as $attribute ) { $counter++; // Считаем количество итераций и выходим из цикла при условии if($counter > 2) { break; }; // Получение таксаномии $terms = wp_get_post_terms( $product->id, $attribute[ 'name' ], 'all' ); $taxonomy = $terms[ 0 ]->taxonomy; // Получение объекта таксаномии $taxonomy_object = get_taxonomy( $taxonomy ); // Получение меток атрибутов $attribute_label = $taxonomy_object->labels->name; $attribute_label = str_replace('Товар', '', $attribute_label); // Отображение метки с кликабельным списком терминов echo get_the_term_list( $post->ID, $attribute[ 'name' ] , '<div class="attributes">' . $attribute_label . ': ' , ', ', '</div>' ); } } // Хук для вывода после заголовка товаров в категории add_action( 'woocommerce_after_shop_loop_item_title', 'atrb_productShoes2' ); |
На одном проекте было необходимо по ссылке сохранять переменные в файл CSV. Реализовал это средствами PHP, через сниппеты в WordPress.
Для этого завел сниппет, как шорткод. Сам шорткод [save_csv] вставил на страницу, на которую ссылается форма с перемеными передаваемые GET запросом.
URL имеет вот такой вид:
1 |
/result2/?d2=29&m2=09&y2=1989&prof_name=Имя&email=mail%40mail.ru&checkbox-1=Даю-согласие-на-обработку-своих-персональных-данных-в-соответствии-с-Условиями |
Код самого сниппета вот:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
add_shortcode( 'save_csv', function () { // начало шорткода if ( $_GET['checkbox-1']='Даю-согласие-на-обработку-своих-персональных-данных-в-соответствии-с-Условиями' ) { function saveRow($list) { $file = fopen($_SERVER['DOCUMENT_ROOT'].'/wp-content/uploads/base.csv','a'); foreach ($list as $line) { // перекодеровка в cp1251, что открывалось в Excel $line = iconv( "UTF-8", "cp1251", $line ); fputcsv($file,explode(',',$line)); } fclose($file); } // Массив с GET-переменными saveRow( Array( $_GET['d2'].';'.$_GET['m2'].';'.$_GET['y2'].';'.$_GET['prof_name'].';'.$_GET['email'].';'.'checkbox-1=true' )); } // конец шорткода // } ); |
Файл сохраняется по адресу /wp-content/uploads/base.csv и имеет правильную кодировку cp1251, для открытия его через Excel без лишних манипуляций.
Чтобы разрешить хеш-ссылки (hash links) для открытия вкладок (tabs) в Oxygen нужно проделать следующее. Так как по умолчанию это не работает.
Нужно для таба прописать JS код, это делается так:
1 2 3 4 5 6 7 8 9 10 11 12 |
var hash = window.location.hash.substr(1); if (hash == '%%ELEMENT_ID%%') { setTimeout(function(){ jQuery([document.documentElement, document.body]).animate({ scrollTop: jQuery('#' + '%%ELEMENT_ID%%').offset().top - 100 }, 1000); jQuery('#' + '%%ELEMENT_ID%%').trigger('click'); },1000); } |
Решение взято тут: https://gist.github.com/wplit/0cc261359e17e7cb9140fb56b2412e47#file-tab-element-js
Чтобы на сайте сделать современный, красивый скроллбар (он же scrollbar) необходимо минимум кода CSS. Меняя цвета на своё усмотрение можно на своем сайте показывать красивый скролл.
И не нужно его прятать и избегать, так как он вписывается в общий дизайн сайта.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
div.scrollbar_castom::-webkit-scrollbar { width: 15px; border-radius: 10px; background-color: transparent; } div.scrollbar_castom::-webkit-scrollbar-thumb { border-radius: 15px; background-color: #eeefc8; border-right: 4px solid #fdfdf7; border-left: 4px solid #fdfdf7; } div.scrollbar_castom::-webkit-scrollbar-track { border-radius: 10px; background-color: transparent; } div.scrollbar_castom::-webkit-scrollbar-thumb:hover { background-color: #a8bbbf; } |
На одном из проектов стояла задача разместить камеры наблюдения на сайте. Чтобы посетители могли наблюдать за объектом. Камеры были подключены и выданы ссылки с протоколом RTSP, с помощью VLC плеера можно было к ним подключится. Но чтобы их разместить на сайте — нужен сервер который поток RTSP преобразует в другой формат и который можно транслировать на сайте.
После поисков, было найдено простое и рабочее решение, благодаря программисту, который написал программу для сервера. Вот ссылка на описание этой программы.
И за объектом стало возможно наблюдать прямо на сайте.
Код программы на Гитхабе: https://github.com/carpediem-av/rtsp2hls
Столкнулся с такой задачей. Для пункта в Max Mega Menu нужно было повесить своё событие через JQuery. Но оно не хотело работать. Причина оказалось в том, что maxmegamenu.js выводится в самом конце страницы. Поэтому чтобы запустить свое событие, его нужно инициализировать после запуска всех скриптов. Я поступил так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// запуск скрипта после загрузки всей страницы window.onload=function(){ jQuery(function(){ // по клику пункта меню убрать переход по ссылке jQuery('#mega-menu-wrap-max_mega_menu_1 #mega-menu-max_mega_menu_1 > li.mega-menu-megamenu > ul.mega-sub-menu li.mega-menu-column > ul.mega-sub-menu ul.mega-sub-menu li.mega-menu-item-has-children>a').click(function(e){ e.preventDefault(); }); // по клику добавлять стиль active для отображения меню 3-его уровня jQuery('#mega-menu-wrap-max_mega_menu_1 #mega-menu-max_mega_menu_1 > li.mega-menu-megamenu > ul.mega-sub-menu li.mega-menu-column > ul.mega-sub-menu ul.mega-sub-menu li.mega-menu-item-has-children').click(function(){ jQuery(this).toggleClass('active'); jQuery(this).find('ul.mega-sub-menu').toggleClass('active'); }); }); } |
Данный код по клику открывает меню 3-его уровня если он есть. Для этого необходимо еще прописать стиль:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
/* меню 3-его уровня */ #mega-menu-wrap-max_mega_menu_1 #mega-menu-max_mega_menu_1 > li.mega-menu-megamenu > ul.mega-sub-menu li.mega-menu-column > ul.mega-sub-menu ul.mega-sub-menu ul.mega-sub-menu { max-height: 0; opacity: 0; line-height:0; margin: 0em .8em 0em; overflow: hidden; transition: all 500ms cubic-bezier(1.000, -0.415, 0.055, 1.355); transition-timing-function: cubic-bezier(1.000, -0.415, 0.055, 1.355); } #mega-menu-wrap-max_mega_menu_1 #mega-menu-max_mega_menu_1 > li.mega-menu-megamenu > ul.mega-sub-menu li.mega-menu-column > ul.mega-sub-menu ul.mega-sub-menu li ul.mega-sub-menu.active { max-height: 999em; opacity: 1; line-height:inherit; margin: .8em; } #mega-menu-wrap-max_mega_menu_1 #mega-menu-max_mega_menu_1 > li.mega-menu-megamenu > ul.mega-sub-menu li.mega-menu-column > ul.mega-sub-menu ul.mega-sub-menu li.mega-menu-item-has-children>a:after { content: '' ; display: inline-block; width: 7px; height: 7px; border-top: 2px solid #666; border-right: 2px solid #666; transform: rotate(45deg); position: absolute; margin-left: 5px; margin-top: 8px; transition: all 500ms cubic-bezier(1.000, -0.415, 0.055, 1.355); transition-timing-function: cubic-bezier(1.000, -0.415, 0.055, 1.355); } #mega-menu-wrap-max_mega_menu_1 #mega-menu-max_mega_menu_1 > li.mega-menu-megamenu > ul.mega-sub-menu li.mega-menu-column > ul.mega-sub-menu ul.mega-sub-menu li.mega-menu-item-has-children.active>a:after { transform: rotate(135deg); } |
Сегодня, в мае 2022 года я для себя открыл супер инструмент. Ранее которого мне не хватало. А именно как изменить цвет SVG иконке не вставляя её как код? А вот как.
Вставляем картинку СВГ (чёрно-белую иконку) как обычную картинку через тег IMG SRC
1 |
<img src="/work.svg" class="chm__icon_svg"> |
И присваиваем ей стиль через CSS:
1 2 3 4 5 6 7 |
img.chm__icon_svg { filter: invert(42%) sepia(66%) saturate(1328%) hue-rotate(93deg) brightness(100%) contrast(103%); -webkit-filter: invert(42%) sepia(66%) saturate(1328%) hue-rotate(93deg) brightness(100%) contrast(103%); -moz-filter: invert(42%) sepia(66%) saturate(1328%) hue-rotate(93deg) brightness(100%) contrast(103%); -ms-filter: invert(42%) sepia(66%) saturate(1328%) hue-rotate(93deg) brightness(100%) contrast(103%); -o-filter: invert(42%) sepia(66%) saturate(1328%) hue-rotate(93deg) brightness(100%) contrast(103%); } |
Получится из черного цвета, зеленый цвет. Вот этот код
invert(42%) sepia(66%) saturate(1328%) hue-rotate(93deg) brightness(100%) contrast(103%);
генерируется в этом сервисе. Указываем там какой нам нужен цвет в формате #00bb12 и получаем код фильтра.
Как-то на одном проекте возникла необходимость стилизовать тег <select> и его пункты. Как известно с помощью простого CSS он не стилизуется так, как бы этого хотелось. В сети нашел решение. Решение реализовано на CSS и jQuery, взял его на этом сайте. Здесь выложу уже рабочий код, который применил для своих нужд, для плагина Contact Form, отличается он немного скриптом, так как я реализовал, чтобы в описание поля попадало первое значение из выпадающего списка. Так как само поле с выпадающим списком формируется через плагин Contact Form7 и его нельзя поправить.
1. В Contact Form7 я создал поле с выпадающим списком.
2. В сниппете прописал следующий код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
// стилизация SELECT jQuery('.wpcf7-select').each(function() { const _this = jQuery(this), selectOption = _this.find('option'), selectOptionLength = selectOption.length, selectedOption = selectOption.filter(':selected'), duration = 450; // длительность анимации _this.hide(); _this.wrap('<div class="select"></div>'); jQuery('<div>', { class: 'new-select', text: _this.children('option:first').text() }).insertAfter(_this); const selectHead = _this.next('.new-select'); jQuery('<div>', { class: 'new-select__list' }).insertAfter(selectHead); const selectList = selectHead.next('.new-select__list'); for (let i = 1; i < selectOptionLength; i++) { jQuery('<div>', { class: 'new-select__item', html: jQuery('<span>', { text: selectOption.eq(i).text() }) }) .attr('data-value', selectOption.eq(i).val()) .appendTo(selectList); } const selectItem = selectList.find('.new-select__item'); selectList.slideUp(0); selectHead.on('click', function() { if ( !jQuery(this).hasClass('on') ) { jQuery(this).addClass('on'); selectList.slideDown(duration); selectItem.on('click', function() { let chooseItem = jQuery(this).data('value'); jQuery('select').val(chooseItem).attr('selected', 'selected'); selectHead.text( jQuery(this).find('span').text() ); selectList.slideUp(duration); selectHead.removeClass('on'); }); } else { jQuery(this).removeClass('on'); selectList.slideUp(duration); } }); }); |
3. И прописал стили для этого селекта,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
.chm_modal_uslugi .form-contact .select { display: block; width: 100%; position: relative; margin: 0 0 10px 0; } .chm_modal_uslugi .form-contact .new-select { position: relative; border: none; background-color: #f4f6fb; padding: 10px 10px; cursor: pointer; user-select: none; border-radius:8px; font-size: 14px; font-family: Roboto; line-height: 1.15; } .chm_modal_uslugi .form-contact .new-select__list { position: absolute; top: 35px; left: 0; border: none; cursor: pointer; width: 100%; z-index: 2; background: #f4f6fb; user-select: none; } .chm_modal_uslugi .form-contact .new-select__list.on { display: block; } .chm_modal_uslugi .form-contact .new-select__item span { display: block; padding: 10px 15px; border-bottom: 1px solid #ccc; font-size: 14px; font-weight: 600; } .chm_modal_uslugi .form-contact .new-select__item span:hover { background: #ecf0f8; } .chm_modal_uslugi .form-contact .new-select:after { content: ''; display: block; width: 25px; height: 25px; position: absolute; right: 9px; top: 5px; background: url('/wp-content/themes/for_oxygen/img/icn-r-chevron-selectel.svg') no-repeat right center / cover; opacity: 0.6; -webkit-transition: all .27s ease-in-out; -o-transition: all .27s ease-in-out; transition: all .27s ease-in-out; -webkit-transform: rotate(0deg); -ms-transform: rotate(0deg); -o-transform: rotate(0deg); transform: rotate(0deg); } .chm_modal_uslugi .form-contact .new-select.on:after { -webkit-transform: rotate(180deg); -ms-transform: rotate(180deg); -o-transform: rotate(180deg); transform: rotate(180deg); } |
Получилось очень симпатично, а главное просто.
Открыл для себя плагин WP Grid Builder. Попробовал его в Oxygen применить для EasyPosts и Repeater element, результат огонь. Можно выводить список записей в Oxygen, через EasyPosts или Repeater, или Woocomerce и применять к нему Facet (фильтр).
Для этого я использую такие настройки:
А также установил плагин-дополнение WP Grid Builder - Oxygen для удобства, чтобы не вставлять фильтры через шорткод, а добавлять их через соответствующие элементы.
Там задается фильтр который создается отдельно и для какого блока записей он применяется.
В настройках EasyPosts появляется соответствующее меню. Где можно указать сообщение о том, если результаты не найдены (No Results Message) и добавить анимацию, при фильтрации записей.
Но эта анимация представляет из себя плавное появление записей, поэтому я нашел решение которое эту анимацию кастомизирует и добавляет плавную прокрутку в начало записей при выборе фильтра.
В редакторе Oxygen нужно добавить блок Code Block, и добавить в него Javascript код:
Код следующий, пробовал его добавить через сниппет, не заработал, работает только через Code Block:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
window.WP_Grid_Builder && WP_Grid_Builder.on( 'init', onInit ); function onInit( wpgb ) { wpgb.facets.on( 'appended', onAppended ); } function onAppended( posts ) { posts.forEach( animate ); } function animate( post, index ) { post.style.opacity = 0; setTimeout( function() { requestAnimationFrame( function() { post.style.opacity = 1; post.classList.add( 'post-animation' ); } ); // это прокрутка вверх страницы по выбору фильтра до блока с ID const el = document.getElementById('div_block-69-1641'); el.scrollIntoView({behavior: "smooth"}); }, index * 60 ); } |
А затем нужно добавит CSS в любом удобном месте. Я добавляю через сниппеты следующий код CSS:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@keyframes post-animation { from { opacity: 0; transform: translateY(50px); } to { opacity: 1; transform: translatey(0); } } .post-animation { animation: post-animation 0.9s ease; } |
Данное решение я взял с этого сайта, но выбрал для себя CSS с простой анимацией, так как при применении более сложной анимации, у меня зависал редактор. Можно написать и свой CSS для фильтрации записей. Главное? что добавляется стиль при применении фильтра.
Если не нужна анимация каждой записи, то можно обойтись вообще просто CSS, так как при применении фильтра для блока с записями добавляется класс .wpgb-loading примерно на 1 секунду. Вот для этого класса можно прописать свой стиль появления блоков. Тем самым не будет надобности использовать Javascript, но тогда нужно будет что-то придумывать с плавной прокруткой до начала, а так это все реализовано в одном коде.
Проблемы: При активированном плагине Autoptimize данный скрипт не работает. Не помогло даже убирание всех галочек в настройках плагина оптимизации. Только его деактивация.
Довольно часто необходимо скачать сразу много файлов по списку. Есть несколько способов, первоначально я это делал через Download master, но потом я попробовал это сделать через консольную утилиту Wget. Мне очень понравилось, так как нечего лишнего, и список может быть довольно большой.
Для начала я подготавливаю список с URL. И сохраняю его в текстовый файл url.txt. На сайте https://eternallybored.org/misc/wget/ скачиваю для своей версии операционной системы утилиту wget. Распаковываю программу в папку на диске C:\wget\. Туда же ложу файл url.txt для удобства. Создаю папку downloads_file на диске C:. И через командную строку запускаю команду:
c:\wget\wget.exe -i c:\wget\url.txt --secure-protocol=auto -nc -c -P c:\downloads_file\
На экране появится ЛОГ операций. Дожидаемся окончания и проверяем в папке закачанные изображения или файлы.
Нашел плагин Advanced Product Fields (Product Addons) for WooCommerce но еще не пробовал. Думаю, это альтернатива подобному-платному плагину. Чтобы не забыть.
Для того, что бы вывести Re-usable part в любом месте на сайте через шорткод, нужно в сниппете, через Code Snippets добавить код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
add_shortcode( 'oxygen-template', 'func_oxygen_template' ); /** * Add a custom shortcode for displaying a Oxygen template/reusable part. * * Sample usage: [oxygen-template id="478"] * * @param array $atts Shortcode attributes. * @return string HTML output of the specified Oxygen template/reusable part. */ function func_oxygen_template( $atts ) { return do_shortcode( get_post_meta( $atts['id'], 'ct_builder_shortcodes', true ) ); } |
Для этого в нужно в Code Snippets выбрать: Запускать только на публичной части сайта
Затем нужно в том месте, где необходимо вывести этот шаблон вставить шорткод:
1 |
[oxygen-template id="627"] |
Где 627 это ID шаблона Oxygen.
Только стили в шаблоне Oxygen нужно прописывать для стилей, а не для ID, так как таблица стилей для идентификаторов не будет подгружаться.
Информация взята с сайта: https://wpdevdesign.com/shortcode-for-displaying-oxygen-templates-and-reusable-parts/
Нужно было с помощью Repeater создать рандомный вывод статей через Oxygen. Это делается через advanced
Но нужно было вывести всего 5 постов и убрать пагинацию в конце постов. Это делается следующим методом. Заходим в настройки и добавляем параметры.
Параетры:
Взято решение с этого сайта: https://wpdevdesign.com/how-to-remove-pagination-for-repeater-queries-in-oxygen/
При установке плагина Плагин расчёта стоимости доставки СДЭК для WooCommerce от WooDev. И если стоит плагин редактирования полей оформления заказа, такой как Checkout Fields Manager for WooCommerce или от Saphali. То при оформлении заказа вылетает ошибка: «Невозможно создать заказ, так как город получатель не определён.»
Для устранения этой ошибки, нужно добавить скрытое поле в платежный адрес с ID billing_state_id. Это можно сделать следующим кодом.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/** * Добавляем поле billing_state_id на страницу оформления заказа **/ add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' ); // Our hooked in function – $fields is passed via the filter! function custom_override_checkout_fields( $fields ) { $fields['billing']['billing_state_id'] = array( 'type' => 'hidden', 'required' => false, 'clear' => true ); return $fields; } |
Для добавления Google Tag Manager я использовал раньше на сайтах плагин Head, Footer and Post Injections. Так как нужно было разместить код сразу за тегом <body>. В WordPress версии 5.2 и выше появился хук для этого wp_body_open() . Но я использую билдер Oxygen и для него тоже есть решение, вот оно. Нужно в сниппетах прописать следующий код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
add_action( 'wp_head', 'sk_google_tag_manager1', 1 ); /** * Код между тегами <head> */ function sk_google_tag_manager1() { ?> <!-- Google Tag Manager --> <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-xxxxxxx');</script> <!-- End Google Tag Manager --> <?php } add_action( 'ct_before_builder', 'sk_google_tag_manager2' ); /** * Код сразу за тегом <body>. */ function sk_google_tag_manager2() { ?> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-xxxxxxx" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <?php } |
Теперь одним плагином меньше.
В этой статье я расскажу о том как я создал интернет-магазин по доставке еды. Сайт был настроен и запущен одним человеком. Дизайн рисовал дизайнер, синхронизацию сайта с программой кафе делал программист. Опустим расходы на дизайнера и программиста. Так как в большинстве случаев для маленького кафе достаточно настроить сайт, и чтобы заказы с него прилетали на почту или телефон оператора, а он бы уже в ручную забивал их в программе, как если бы он принимал заказ по телефону.
И так начнем.
Мне понадобилось почти 100 часов, wordpress, woocommerce и несколько платных плагинов. Стоимость готового сайта для клиента сложилась из моих потраченных часов, стоимости плагинов, и стоимость дизайнера и программиста. Но как я уже писал выше программиста и дизайнера не будем учитывать, так как не всем нужна та или иная функциональность.
Тем что я создал новый интернет-магазин на основе старого. Т.е. если у вас уже есть готовый, наполненный магазин, то при минимум затрат и времени его можно доработать. Старый сайт по доставке пиццы был сделан в 2013 году тоже на основе woocommerce. Но для функциональности на нем было куча «костылей» прям в коде woocommerce, из-за которых не могли провести очередное обновления плагинов. Поэтому при переделке сайта, а точнее сказать создании. Правок напрямую в коде плагинов не производилось. Только хуки и дополнительные функции созданные через сниппеты.
Конечно же это woocommerce, и ряд разных плагинов для нужной функциональности. Некоторые конечно можно заменить, но я не заменил их по причине того, что они уже стояли и перенастраивать их заново заняло бы больше времени. Из бесплатных это:
И платные плагины:
Это плагины, которые нужны для самого интернет магазина. Также помимо этих, на сайте используются и другие. Которые необходимы для правильной работы сайта в целом.
И теперь кратко о плагинах и для чего они нужны.
Это бильдер, он заменяет тему в wordpress. В нем собраны все шаблоны. Эти шаблоны можно легко экспортировать и импортировать на другой сайт через стандартный Экспорт-Импорт WordPress.
Это дополнение для Oxygen, установка этого плагина добавляет блоки от woocommerce/
Это плагин дополнений. В нем настраиваются дополнения или опции для товаров, при выборе которых в карточке товара добавляется стоимость дополнения к основной стоимости товара. В этом случае это были дополнения для блюд.
Это плагин экспорта и импорта любых записей, товаров, кастомных записей. С этими плагинами производится массовое редактирование описаний, цен товаров и многое другое. В ручную редактировать товары, когда их много, да еще у каждого есть вариации - очень затруднительно. А благодаря этим плагинам это происходить существенно быстрее.
Это плагин для кастомных полей, с его помощью создаются дополнительные поля с необходимой информацией о товаре. Которую необходимо разместить в описании товара отдельным блоком.
Это меню для сайта, использую его, потому что оно мне нравится. Можно использовать и другой. Но в этом можно настроить красивое мобильное меню. А главное при минимуме затрат. А так же у него есть функция экспорта-импорта. Что сокращает время настройки при переносе его на другой проект.
Это плагин сниппетов, заменяет стандартный файл functions.php в теме. Можно создавать свои функции и через хуки менять woocommerce и всё это правится прям в админке. Без этого плагина работа с Oxygen очень затруднительна.
Это собственно плагин самого интернет-магазина, о нем уж столько расписано, что нет смысла говорит какую функцию он выполняет.
Это плагин добавления товара в корзину с карточки товара без перезагрузки страницы.
Это плагин для редактирования полей при оформлении заказов. Вместо него можно использовать Checkout Manager for WooCommerce мне он даже нравится больше, но в данном проекте стоял уже Saphali.
Это плагин который переключения вариаций превращает в кнопки вместо выпадашек.
Это плагин для быстрого просмотра товара через модальное окно, работает как через аякс. В каталоге с большим количеством товаров не грузит сильно страницу, так как не создает для каждого товара отдельную карточку, как некоторые плагины.
Это плагин от сбербанка, платежный шлюз. Через который осуществляются он-лайн платежи на сайте.
Изначально планировалось, просто уйти от «костылей» в коде. Чтобы WP и все плагины работали как есть от разработчика, и обновление не затрагивало функциональности, а сайт работал без перебоев в работе. Для этого была сделана копия сайта, обновил WP и плагины, установили Oxygen, чтобы дизайн собирать в нем. Но когда клиент увидел скорость работы нового сайта, он захотел сразу вложить в него больше денег и переделать дизайн.
Для себя я выбрал такой подход, что все изменения я делал в шаблонах Oxygen и все новые функции прописывал в сниппетах. Чтобы потом, просто обновить старый сайт и через экспорт-импорт перенести шаблоны и сниппеты. Но от этого в последствии отказались, просто заменили местами сайты. Хотя из-за этого подхода я теперь могу для другого проекта перенести все свои наработки на другой сайт и потратить на него в пределах 10-20 часов рабочего времени и иметь готовый интернет-магазин доработанный, чтобы было удобно покупателям.
К таким удобствам относятся:
Конечно эти пункты обычные, но в стандартном woocommerce этого нет, приходится через хуки делать изменения. И сейчас у меня готовые наработки которые за 4 клика можно применить к другому сайту.
Готовый набор своих наработок я могу продать или установить сам на ваш сайт. Кому интересно, обращайтесь через форму обратной связи.
Что бы запустить сайт и начать с ним работать. Я делаю следующие шаги. У каждого эти шаги свои и разные. Но мне удобно так, поэтому я расскажу о своем опыте. Коротко о шагах которых я придерживаюсь, чтобы не упустить деталей.
Регистрирую доменное имя. Если есть уже, то прошу доступы или прописать NS-сервера от хостинга на котором будет сайт.
Выбираю хостинг. Мой выбор сейчас остановился на ТаймВеб. Я его рекомендую всем клиентам, так как с ними работать удобно. И цена у них соответствует услугам.
На хостинг устанавливаю свежий архив https://ru.wordpress.org/download/#download-install Так как процесс установки полностью контролирую сам. Создаю базу с понятным именем. Меню прификс базы с стандартного WP_ на другой (для надежности). Создаю администратора с нестандартным именем. Захожу в админ панель и начинаю настраивать.
Для удобной работы с CMS ставлю основные плагины. Все бесплатные плагины устанавливаю через админку, через поиск. Но если нужно запускать сразу много сайтов. То можно все эти плагины скачать в архив, и потом распаковывать это архив на хостинге, а в админке только активировать и обновлять если потребуется. Так существенно экономится время.
Дополнительно ставлю, если нужно будет:
Если требуется интернет магазин или каталог то ставлю:
Также я ставлю платные плагины, которые облегчают работу и без которых уже трудно представить работу на сайте и его обслуживание.
Пробегаюсь по настройкам, устанавливаю
Если настраиваю интернет магазин, то захожу в настройки Woocommerce и настраиваю там первоначальные данные.
Так как в работе я использую Oxygen, то в нем создаю основные шаблоны.
Для чего? Так удобнее переносить потом дизайн через стандартный экспорт-импрот средствами самого WordPress. Если будет необходимо перенести на другой, уже рабочий и наполненный сайт.
Завожу основные страницы, которые будут в меню. Если на сайте будут новости или блог, то завожу 3-4 записи. Для интернета-магазина, добавляю несколько товаров. Это для того, чтобы сразу выстроить структуру сайта и добавить меню на сайт.
Создаю пользователей, для того чтобы разграничить доступ. Чтобы у меня всегда оставался свой пользователь, так как иногда когда сайт начинает работать, просят что-то поправить через год. А доступы все утеряны, даже от хостинга. А отдельная своя учетная запись иногда выручает, если её не удалили. Также это помогает разбираться, кто накосячил, для этого ставится плагин, который ведет историю по пользователям — кто и когда правил записи и страницы.
Далее настраиваю:
И начинаю тонкую и глубокую работу с сайтом по ТЗ, верстку по макету, доделки и пожелания клиента. Процесс этот долгий, для каждого сайта индивидуальный. Поэтому некоторые части этого процесса будут описаны отдельными записями.
Чтобы на странице оформления заказа убрать итоговую таблицу, это иногда надо, когда совмещается корзина и оформление заказа на одной странице. Нужно вставить следующий код.
(далее…)На одном из проектов, необходимо было реализовать фотогалерею по разделам. Она была реализована с помощью кастомных записей и плагина Search & Filter. Но при переводе проекта на Oxygen, плагин Search & Filter отказался работать. Поэтому переделали фильтр на основе кастомных записей и библиотеки Isotope.
(далее…)При оформлении заказа, часто нужно вставить свои поля, но по умолчанию они не попадают в шаблон письма. Есть решение, добавляем код, который добавит нужные нам поля в письмо.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
// Выводим значения полей в шаблоне письма с заказом add_filter('woocommerce_email_order_meta_fields', 'add_cust_fields_email_order_meta_fields', 10, 3 ); function add_cust_fields_email_order_meta_fields( $fields, $sent_to_admin, $order_obj ) { //получаем номер заказа $o_n = $order_obj->get_order_number(); //получаем поля через get_post_meta на вывод их в письме $fields['dostavka_tovara'] = array( 'label' => 'Способ доставки', 'value' => get_post_meta( $o_n, '_billing_wooccm11', true ) ); $fields['dostavka_upakovka1'] = array( 'label' => 'Имя поля 1', 'value' => get_post_meta( $o_n, '_additional_wooccm1', true ) ); $fields['dostavka_upakovka2'] = array( 'label' => 'Имя поля 2', 'value' => get_post_meta( $o_n, '_additional_wooccm2', true ) ); return $fields; } |
Хочу рассказать, почему именно WordPress я выбираю для сайтов. Всё просто, это движок мне нравится больше остальных, я с ним работаю с 2010 года. За это время было много сайтов созданых другими инструментами, но WordPress по сравнению с ними на порядок выше, он гораздо удобнее.
В работе с командой я выполняю роль верстальщика. Задачи по программированию лежат на программисте. Но если я собираю сайт на WordPress-е, то большинство задач я выполняю сам, не прибегая к помощи программиста. Так простые сайты, одностраничники, Landing page и простые интернет-магазины я собираю сам от начала и до конца. Если же требуется реализовать не стандартную схему работы на сайте, то тут помагает программист.
Так работая над одним проектом в bitrix, мы постоянно были привязаны к программисту, из-за чего сроки поджимали. Делая сайт на вордпрессе, такого бы не было. Но и в конце с битриксом ждала проблема, при его интеграции с 1C (а именно из-за этого его выбрал клиент), настройки постояно «ломались», каждое обновление приносило головную боль. В итоге мы поняли, что если бы сразу начали собирать сайт на WordPress+Woocommerce, такого бы не произошло. Так как для интеграции 1C с Woocommerce есть готовые плагины.
А если собирать простые интернет-магазины на WordPress+Woocommerce, так это вообще сказка, за неделю удается начать с нуля и полностью отдать клиенту готовый и рабочий магазин. С корзиной, экварингом и массовым редактированием товаров через Excel, CSV или XML.
Поэтому цикл статей по cозданию сайтов я буду посвещать только WordPress и его плагинам. По нему в сети есть куча полезной информации, которая помогает создавать очень интересные проекты.
Те кто говорит, что WP это не лучший выбор для создания сайта, что он тормозной, что он тупит. Пускай остаются при своем мнении, я же на нем создал не мало сайтов и понимаю, что сибестоимость готового проекта на WordPress в разы обходится дешевле клиенту, чем разработка подобного проекта на других «движках».
Понадобилось на одном сайте, на WordPress сделать переключение городов и разный контент для каждого города. Реализовал просто, установил плагин WT GeoTargeting — https://wordpress.org/plugins/wt-geotargeting/ В настройках прописал только город по умолчанию, в шапке сайта поставил шорткод:
1 |
[wt_geotargeting get="city"] |
Который выводил город, на этот блок повесил событие по клику, которое выводило модальное окно с выбором городов, в нем просто поставил ссылки:
1 2 3 4 5 |
<a href="?wt_city_by_default=Владивосток">Владивосток</a>,<br> <a href="?wt_city_by_default=Спасск-Дальний">Спасск-Дальний</a>,<br> <a href="?wt_city_by_default=Лесозаводск">Лесозаводск</a>,<br> <a href="?wt_city_by_default=Дальнереченск">Дальнереченск</a><br><br> <a href="?wt_geo_clean=1">Отменить выбор</a> |
А в том месте где нужен разный контент для разных городов, вставил шорткоды:
1 2 3 4 5 6 7 |
<?php echo do_shortcode('[wt_geotargeting type="title" city_show="Владивосток"]<a class="but-head-oplata" href="#1">ОПЛАТИТЬ</a>[/wt_geotargeting]'); echo do_shortcode('[wt_geotargeting type="title" city_show="Спасск-Дальний"]<a class="but-head-oplata" href="#2">ОПЛАТИТЬ</a>[/wt_geotargeting]'); ?> |
Описание шорткодов можно смотреть на сайте разработчиков плагина: https://web-technology.biz/cms-wordpress/plugin-wt-geotargeting-for-cms-wordpress/shortkod-wt_geotargeting/
Для товаров без указанной цены выводим сообщение «Цена по запросу»
1 2 3 4 |
add_filter('woocommerce_empty_price_html', 'empty_price_message'); function empty_price_message() { return 'Цена по запросу'; } |
Для товаров с нулевой ценой выводим «Цена по запросу» вместо «Бесплатно»
1 2 3 4 5 |
function my_price_replace($price, $product) { if ($price == 0) return __( 'Цена по запросу' ); return $price; } add_filter( 'woocommerce_get_price_html', 'my_price_replace', 1, 2 ); |
И отключаем возможность покупки товара с нулевой ценой
1 2 3 4 5 6 |
function make_not_purchasable( $purchasable, $product ){ if( $product->get_price() == 0 ) $purchasable = false; return $purchasable; } add_filter( 'woocommerce_is_purchasable', 'make_not_purchasable', 10, |
Взято тут: https://conotes.ru/sajtostroj/wordpress/woocommerce/woocommerce-tsena-po-zaprosu.html
Столкнулся с такой проблемой. Woocommerce не сортирует товары у которого стоит статус "в наличии" или "нет в наличии". Он только сортирует по остаткам на складе. Поэтому вышел из положения так. На странице вывел все товары и те у кого статус "нет в наличии" скриптом перекинул вниз.
1 2 3 4 5 6 7 8 9 10 11 12 |
add_action( 'wp_footer', function () { ?> <?php if (is_woocommerce() && is_product_category()) : ?> <script> jQuery(document).ready(function() { jQuery('.outofstock').each(function(index, item) { var $this = jQuery(item); $this.appendTo($this.parent()); }); }); </script> <?php endif; ?> <?php } ); |
Если заменить на $this.prependTo($this.parent()); то все товары не в наличии попадут наверх.
Этот же скрипт помог в случае когда нужно было "прилипающие" сообщения вывести наверх списка. Для этого в шаблоне вывода постов Oxygen я добавил в класс следующий код
1 |
<div class='oxy-post <?php if (in_array( get_the_ID(), get_option( 'sticky_posts' ) )) {echo "sticky";} ?>'> |
А в сниппете подключил скрипт, который посты с классом sticky перекидывает наверх:
1 2 3 4 5 6 7 8 9 10 11 12 |
add_action( 'wp_footer', function () { ?> <script> jQuery(document).ready(function() { jQuery('.sticky').each(function(index, item) { var $this = jQuery(item); $this.prependTo($this.parent()); }); }); </script> <?php } ); |
Записываем в functions.php следующий код
1 2 3 4 5 6 7 |
// Удаляем URL из формы отправки комментариев add_filter('comment_form_default_fields', 'sheens_unset_url_field'); function sheens_unset_url_field ( $fields ) { if ( isset($fields['url'] )) unset ( $fields['url'] ); return $fields; } |
Если не сработает, то, скорее всего, в теме есть файл шаблонов комментариев — comments.php. Тогда нужно в нем править. Закомментировать это поле с name="url".
Иногда нужно создать копию сайта, и когда размер папки с сайтом занимает большой объем, то возникают трудности с работой по ФТП через панель управления хостингом — не всё копируется. А работать через ФТП-клиент тоже не удобно, так как большой объем файлов.
Поэтому гораздо проще и быстрее это сделать через SSH-консоль командой рекурсивного копирования всего содержимого папки:
cp -r * /home/r/папка_назначения/public_html/
Эта команда скопирует содержимое папки в которой мы находимся в папку /home/r/папка_назначения/public_html/
Восстановить базу данных из дампа можно несколькими способами, это и через панель хостинга, и через MyPhpAdmin. Но иногда импорт через MyPhpAdmin завершается ошибкой, особенно когда база большого объема. Поэтому гораздо проще и быстрее развернуть дамп базы через консоль SSH.
Это можно сделать с помощью следующей команды:
mysql -h имя_хоста_DB -u имя_пользователя_DB -pпароль_DB имя_DB < путь_к_файлу_дампа_базы
Внимание: между параметром «-p» и паролем к базе данных не должно быть пробела.
Пример:
mysql -h localhost -u user -pBzzZw nameDB < dump-DB-full-05.03.2020.sql
Если дамп запакован в архив, перед разворачиванием его нужно разархивировать, это также можно сделать одной командой:
zcat dump-DB-full-05.03.2020.gz | mysql -h localhost -u user -pBzzZw nameDB
Иногда создать дамп через панель управления хостингом не получается, тогда его можно создать через SSH консоль.
Для этого выбираем директорию с требуемым сайтом и вводим в командную строку следующее:
mysqldump -ulogin -p dbname >dump_file.sql
login - логин для доступа к базе данных,
dbname - имя базы данных
dump_file.sql - имя создаваемого файла дампа)
Нажимаем Enter, система запросит пароль для доступа к базе данных. Если введённые данные верны, то начнётся создание дампа. По его окончании увидим строку для ввода команд. Дамп готов. Файл дампа будет расположен в текущей директории, имя файла dump_file.sql.
Ultimate Member — плагин для создания сообществ и пользовательских профилей в WordPress. https://ultimatemember.com/ и https://wordpress.org/plugins/ultimate-member/. Альтернатива: плагин WP-Recall https://wordpress.org/plugins/wp-recall/ (Ultimate Member проще и понятнее)
Search & Filter — плагин для организации своего поиска на сайте и фильтра рубрик и кастомных записей. https://ru.wordpress.org/plugins/search-filter/
WPC Variations Radio Buttons for WooCommerce — плагин для удобного выбора вариативных товаров. https://ru.wordpress.org/plugins/wpc-variations-radio-buttons/
Чтобы изменить URL адрес WordPress, Вы должны прописать этот код в файл wp-config.php:
1 2 |
define('WP_HOME','http://example.com'); define('WP_SITEURL','http://example.com'); |
В файле functions.php прописываем следующий код:
1 2 3 4 5 6 7 8 9 |
// отключим Гутенберг if( 'disable_gutenberg' ){ add_filter( 'use_block_editor_for_post_type', '__return_false', 100 ); remove_action( 'wp_enqueue_scripts', 'wp_common_block_scripts_and_styles' ); add_action( 'admin_init', function(){ remove_action( 'admin_notices', [ 'WP_Privacy_Policy_Content', 'notice' ] ); add_action( 'edit_form_after_title', [ 'WP_Privacy_Policy_Content', 'notice' ] ); } ); } |
При работе с плагином Woocommerce на сайте часто требуется изменять вид отображения карточек товара, корзины и многое другое.
Для этих целей можно править шаблоны, применять плагины и использовать хуки. В этом посте я буду собирать полезные хуки для вукомерц.
На сайте часто нужно вывести информацию в шапке о режиме работы или контактах. Чтобы не нагромождать информацию, её можно разместить во всплавающем окне, которое выводится по клику на какой нибудь элемент.
Простое всплывающее окошко можно сделать с помощью CSS и jQuery.
Для это добавляем код html на сайт:
1 2 3 4 5 6 |
<div class="wrap"> <div class="modal"></div> <div class="header"> <a href="#">режим работы</a> </div> </div> |
Скрипт вставляем в шапку или футер:
1 2 3 4 |
$('a').on('click', function(e){ e.preventDefault(); $('.modal').toggleClass('active'); }); |
И прописываем стиль для появления этого окошка.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
.wrap { width:500px; margin: 0 auto; height:400px; background:red; position:relative; } .header { background:green; height:50px; } .modal { background:blue; height:200px; width:180px; position:absolute; right:10px; top:-210px; -webkit-transition: top 0.5s; -moz-transition: top 0.5s; -o-transition: top 0.5s; transition: top 0.5s } .modal.active { top:10px; } |
Источник кода взят тут: http://jsfiddle.net/iiil/7Ly6y/3/
Если с сайта нужно выгрузить фид для Яндекса или для другого сервиса. То есть два способа. Первый это всевозможные плагины, но они почти все работаю с Woocommerce. Второй вариант, написать выгрузку вручную.
С такой проблемой я столкнулся на сайте застройщика, квартиры были выполнены кастомными записями. А нужно было несколько фидов в XML-формате для разных сервисов. И вот как я поступил, покажу на примере одного фида. Я же по подобию делал их несколько.
В файл functions.php вставляю следующий код:
1 2 3 4 5 6 7 8 |
// Yandex.Realty RSS add_action('init', 'AddYandexRSS'); function AddYandexRSS(){ add_feed('yandex-realty.xml', 'ProceedYandexRealtyRSS'); } function ProceedYandexRealtyRSS() { get_template_part('rss-realty'); } |
Описание: yandex-realty.xml это адрес фида https://название_сайта/yandex-realty.xml/ и rss-realty — это название шаблона который нужно положить в папку с темой сайта (rss-realty.php).
В файле rss-realty.php вставляем цикл WP_Query который берет из кастомных записей, кастомные поля. Для примера приведу готовый код Яндекс.Недвижимость.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
<?php header('Content-Type: '.feed_content_type('rss-http').'; charset='.get_option('blog_charset'), true); echo '<?xml version="1.0" encoding="'.get_option('blog_charset').'"?>'; ?> <realty-feed xmlns="http://webmaster.yandex.ru/schemas/feed/realty/2010-06"> <generation-date><?= date('c'); ?></generation-date> <?php // задаем нужные нам критерии выборки данных из БД $args = array( 'post_type' => 'flat', 'posts_per_page' => -1, 'meta_query' => array( array( 'key' => 'flat_reservation', 'value' => 1, 'compare' => '!=', ), ), ); $query = new WP_Query( $args ); // Цикл if ( $query->have_posts() ) { while ( $query->have_posts() ) { $query->the_post(); ?> <offer internal-id="<? the_ID(); ?>"> <type>продажа</type> <property-type>жилая</property-type> <category>квартира</category> <creation-date><?= date('c'); ?></creation-date> <location> <country>Россия</country> <locality-name>Город</locality-name> <address>Улица ул., д. номер</address> <apartment><? echo get_field( 'flat_number', get_the_ID() ); ?></apartment> </location> <sales-agent> <category>agency</category> <phone>+71111111111</phone> </sales-agent> <price> <value><? echo get_field( 'flat_price', get_the_ID() ); ?></value> <currency>RUR</currency> </price> <area> <value><? echo get_field( 'flat_area', get_the_ID() ); ?></value> <unit>кв. м</unit> </area> <? if ( get_field( 'flat_rooms', get_the_ID() ) == 'студия' ) { ?> <studio>да</studio> <? } else { ?> <rooms><? echo preg_replace("/[^0-9]/", '', get_field( 'flat_rooms', get_the_ID() )); ?></rooms> <rooms-offered><? echo preg_replace("/[^0-9]/", '', get_field( 'flat_rooms', get_the_ID() )); ?></rooms-offered> <? } ?> <floor><? echo get_field( 'flat_level', get_the_ID() ); ?></floor> </offer> <?php } } else { // Постов не найдено } // Возвращаем оригинальные данные поста. Сбрасываем $post. wp_reset_postdata(); ?> </realty-feed> |
Для WordPress плагин Elementor выполняет большинство задач не прибегая к ковырянию в коде. Но всё же есть моменты, которые Elementor не выполняет без Хуков.
Так виджет AE Post Blocks от плагина AnyWhere Elementor Pro выводит записи именно те которые прописываются в фильтре
И если этот виджет применить для шаблона архива в Elementor, то при переходе по таксономиям (рубрики, теги) записи не фильтруются. Чтобы это исправить есть один хук.
В виджете, в поле Query Filter прописываем название пользовательского фильтра: my_super_filter (можно название любое).
В файл funtions.php для активной темы прописываем следующий код:
1 2 3 4 5 6 7 8 9 |
function my_super_filer_function($query_args){ $queried_object = get_queried_object(); // Получаем ID тега $term_id = $queried_object->term_id; // Получаем ID тега $term = get_term($term_id); // Получаем ID тега $query_args[$queried_object->taxonomy] = $term->slug; // фильтруем по таксономии и тегу через SLUG return $query_args; } add_filter('my_super_filter', 'my_super_filer_function'); |
И после этого записи фильтруются по рубрикам. Так же можно и фильтровать по тегам. Этот же хук можно применить для виджета — Записи, который входит в плагин Elementor Pro. Для этого во вкладке Запрос, есть поле ID запроса.
О работе этого хука я узнал из документации к AnyWhere Elementor Pro.
Чтобы блок с меню (или шапка сайта целиком) при прокрутке страницы вниз — скрывался, а потом прилипал сверху сайта, нужно присвоив блоку стиль и задать ему свойство position: fixed;.
1 2 3 4 |
.menu.fixed { position: fixed; top: 0px; } |
И прописать, код который при прокрутке на несколько пикселей вниз (в нашем случае на 135px) будет блоку со стилем .menu присваивать стиль .fixed.
1 2 3 4 5 6 7 8 9 10 11 |
<script type="text/javascript"> jQuery(window).scroll(function() { var the_top = jQuery(document).scrollTop(); if (the_top > 135) { jQuery('.menu').addClass('fixed'); } else { jQuery('.menu').removeClass('fixed'); } }); </script> |
Так можно создавать дополнительный блок со свойством display: none; а при достижении прокрутки до определенного расстояния появляться. Таким образом можно создать разные шапки, основную и дополнительную (минимальную), которая будет прилипать при скролле сайта вниз.
В Oxygen есть настройка для хедера, чтобы он показывался при прокрутке вниз. Но у него нет функции, чтобы на мобильных устройствах при прокрутке вниз он не показывался, а когда мы листаем вверх, то он появлялся. Для это я в настройках хедера в редакторе Oxy выставляю для него skicky всегда, и добавляю в сниппет код JS и CSS. Где при прокрутке вниз добавляется стиль, который скрывается, а при прокрутке вверх он удаляется, соответственно header появляется.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<script> // добавляем класс при прокрутке вниз, а вверх он не добовляется var headerVisible = true; var scrollPos = jQuery(document).scrollTop(); jQuery(window).scroll(function() { var scrollTop = jQuery(document).scrollTop(); if(headerVisible && scrollTop > scrollPos) { headerVisible = false; jQuery('.oxy-sticky-header').addClass('chm-sticky-header-hidden'); } else if(!headerVisible && scrollTop < scrollPos) { headerVisible = true; jQuery('.oxy-sticky-header').removeClass('chm-sticky-header-hidden'); } scrollPos = scrollTop; }); </script> <style> @media only screen and (max-width: 769px) { .oxy-sticky-header-active.oxy-sticky-header-fade-in.chm-sticky-header-hidden { display:none; } } </style> |
Если необходимо на сайте в div подгрузить какой нибудь html контент, это можно сделать следующим образом. Положить html файл на сервер, через FTP-клиент. И прописать скрипт.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$(document).ready(function(){ $.get('/readme.html',function(data){ //указываешь урл от корня папки $('#content_file_html').html(data); //тут после # пишешь ID слоя куда подгрузить текст }); }); Для WordPress если вставлять код через админку, то этот код: jQuery(document).ready(function(){ jQuery.get('/readme.html',function(data){ //указываешь урл от корня папки jQuery('#content_file_html').html(data); //тут после # пишешь ID слоя куда подгрузить текст }); }); |
Когда нужно сделать простой слайдер фотографий или слайдер текста. То можно применить bxslider.
При вставке стандартной галереи в Wordpres на страницу, из этих картинок можно сделать слайдер, если подключить bxslider. Подключается он очень просто. Достаточно прописать код в шапке или футере сайта. (далее…)
Часто требуется выводить блоки, чтобы они были одинаковой высоты и сами подстраивались под содержимое. Для этого вставляем следующий код
1 2 3 4 5 6 |
<ul class="products"> <li class="box height_fix">Содержимое блока 1</li> <li class="box height_fix">Содержимое блока 2</li> <li class="box height_fix">Содержимое блока 3</li> <li class="box height_fix">Содержимое блока 4</li> </ul> |
1 2 3 4 5 6 7 8 9 10 11 |
<script type="text/javascript"> jQuery(function($){ var max_col_height = 80; // максимальная высота, первоначально 80 $('ul.products li.box.height_fix').each(function(){ // цикл "для каждой из колонок" if ($(this).height() > max_col_height) { // если высота колонки больше значения максимальной высоты, max_col_height = $(this).height(); // то она сама становится новой максимальной высотой } }); $('ul.products li.box.height_fix').height(max_col_height); // устанавливаем высоту каждой колонки равной значению максимальной высоты }); </script> |
Тэги могут быть разными, вместо списков li могут, могут быть div.