22 заметки с тегом

simplacms

SimplaCMS: Подсчёт количества введённых символов в поля SEO-параметров

Сеошники знают, что есть правила, которые ограничивают нам ввод длинных title или description. Чтобы не кидать каждый раз в Sublime для подсчёта символов, я набросал простенький скрипт, который показывает текущее значение каждого поля SEO-параметров.

Потестить можно на категориях, для которых в первую очередь и писался сам скрипт. Для этого откроем /simpla/design/html/category.tpl и заменим блок

на код ниже:

<div class="block layer">
<h2>Параметры страницы</h2>
<ul>
	<li><label id="url_count"class=property>Адрес</label><div class="page_url">/catalog/</div><input name="url" class="page_url" type="text" value="{$category->url|escape}" id="url_source" /></li>
	<li><label id="title_count" class=property>Заголовок</label><input name="meta_title" class="simpla_inp" type="text" value="{$category->meta_title|escape}" id="title_source" /></li>
	<li><label id="keys_count" class=property>Ключевые слова</label><input name="meta_keywords" class="simpla_inp" type="text" value="{$category->meta_keywords|escape}" id="keys_source" /></li>
	<li><label id="description_count" class=property>Описание</label><textarea name="meta_description" class="simpla_inp" id="description_source" >{$category->meta_description|escape}</textarea></li>
			</ul>
<script>
var urlname = document.getElementById("url_source");
var urlcount = document.getElementById("url_count");
var titlename = document.getElementById("title_source");
var titlecount = document.getElementById("title_count");
var keywordname = document.getElementById("keys_source");
var keywordscount = document.getElementById("keys_count"); 
var descriptionname = document.getElementById("description_source");
var descriptioncount = document.getElementById("description_count");                                   
window.onload = urlCount();
window.onload = titleCount();
window.onload = keywordsCount();
window.onload = descriptionCount();
urlname.oninput = urlCount;
titlename.oninput = titleCount;
keywordname.oninput = keywordsCount;
descriptionname.oninput = descriptionCount;                  
function urlCount() {
var x = urlname.value;
urlcount.innerHTML = "Адрес (" + x.length + ")";
}             
function titleCount() {
var y = titlename.value;
titlecount.innerHTML = "Заголовок (" + y.length + ")";
}                  
function keywordsCount() {
var z = keywordname.value;
keywordscount.innerHTML = "Ключевые слова (" + z.length + ")";
}
function descriptionCount() {
var xx = descriptionname.value;
descriptioncount.textContent = "Описание (" + xx.length + ")";
}                 
</script>
</div>
 2 комментария    161   2020   js   seo   simplacms

SimplaCMS: режим работы

У некоторых компаний есть клиенты, которые не могут долистать до страницы контакты и посмотреть режим работы. Специально для таких особей в шапку написал скрипт, который в зависимости от дня показывает определённое время работы компании.

{assign var=workdays value='Работаем: с 10:00 до 20:00'}
{assign var=saturday value='Суббота: с 10:00 до 16:00'}
{assign var=holiday value='Воскресенье: не работаем'}

{if $smarty.now|date_format:'%w' == '1' || $smarty.now|date_format:'%w' == '2' || $smarty.now|date_format:'%w' == '3' || $smarty.now|date_format:'%w' == '4' || $smarty.now|date_format:'%w' == '5'}{$workdays}{elseif $smarty.now|date_format:'%w' == '6'}{$saturday}{else}{$holiday}{/if}

С понедельника по пятницу будет отображаться режим работы с 10 до 20 часов.
В субботу — с 10 до 16 часов.
В воскресенье — не работаем.

 2 комментария    117   2019   simplacms

SimplaCMS: вывод закупочной цены

Потребовалось сделать вывод закупочной цены в админке. Итак, сначала добавим поля в шаблон в админке.

  1. Откроем /simpla/design/html/product.tpl и добавим колонки Закупка и Прибыль для вариантов товаров:
<li class="variant_move"></li>
<li class="variant_name">Название варианта</li>	
<li class="variant_sku">Артикул</li>
<li class="variant_fprice">Закупка, {$currency->sign}</li>	
<li class="variant_price">Цена, {$currency->sign}</li>	
<li class="variant_discount">Старая, {$currency->sign}</li>	
<li class="variant_amount">Кол-во</li>
<li></li>
<li>Прибыль</li>
  1. Далее добавим поля для указания данных в цикл $product_variants:
<li class="variant_move"><div class="move_zone"></div></li>
<li class="variant_name">      <input name="variants[id][]"            type="hidden" value="{$variant->id|escape}" /><input name="variants[name][]" type="" value="{$variant->name|escape}" /> <a class="del_variant" href=""><img src="design/images/cross-circle-frame.png" alt="" /></a></li>
<li class="variant_sku">       <input name="variants[sku][]"           type="text"   value="{$variant->sku|escape}" /></li>
<li class="variant_fprice">     <input name="variants[fprice][]"         type="text"   value="{$variant->fprice|escape}" /></li>
<li class="variant_price">     <input name="variants[price][]"         type="text"   value="{$variant->price|escape}" /></li>
<li class="variant_discount">  <input name="variants[compare_price][]" type="text"   value="{$variant->compare_price|escape}" /></li>
<li class="variant_amount">    <input name="variants[stock][]"         type="text"   value="{if $variant->infinity || $variant->stock == ''}∞{else}{$variant->stock|escape}{/if}" />{$settings->units}</li>
<li>{if $variant->fprice} +{math equation = $variant->price - $variant->fprice} {$currency->sign}{/if}</li>
  1. Теперь добавим отображение закупки в список товаров, для этого откроем файл /simpla/design/html/products.tpl и добавим в цикл $product_variants:
<li {if !$variant@first}class="variant" style="display:none;"{/if}>
	<i title="{$variant->name|escape}">{$variant->name|escape|truncate:30:'…':true:true}</i>
	<input class="fprice" type="text" name="fprice[{$variant->id}]" value="{$variant->fprice}" />
	<input class="price {if $variant->compare_price>0}compare_price{/if}" type="text" name="price[{$variant->id}]" value="{$variant->price}" {if $variant->compare_price>0}title="Старая цена &mdash; {$variant->compare_price} {$currency->sign}"{/if} />{$currency->sign}  
	<input class="stock" type="text" name="stock[{$variant->id}]" value="{if $variant->infinity}∞{else}{$variant->stock}{/if}" />{$settings->units}
</li>
  1. Отображение сделали, теперь нужно поработать над функционалом. Откроем файл /api/Variants.php и обновим в двух местах SQL-запрос для функции get_variants:
$query = $this->db->placehold("SELECT v.id, v.product_id , v.price, v.fprice, NULLIF(v.compare_price, 0) as compare_price, v.sku, IFNULL(v.stock, ?) as stock, (v.stock IS NULL) as infinity, v.name, v.attachment, v.position
  1. Теперь откроем файл /simpla/ProductsAdmin.php и добавим возможность управления закупочной ценой на списке товаров:
// Обработка действий 	
if($this->request->method('post'))
{
// Сохранение цен и наличия
$prices = $this->request->post('price');
$fprices = $this->request->post('fprice');
$stocks = $this->request->post('stock'); 
		    foreach($fprices as $id=>$fprice)
{
	$this->variants->update_variant($id, array('fprice'=>$fprice));
}
foreach($prices as $id=>$price)
{
	$stock = $stocks[$id];
	if($stock == '∞' || $stock == '')
	$stock = null;
	$this->variants->update_variant($id, array('price'=>$price, 'stock'=>$stock));
}
 Нет комментариев    193   2019   simplacms

SimplaCMS: подключаем dadata для клёвых подсказок

Есть клёвый сервис, который позволяет в вашей корзине вызывать подсказки.
Подсказки могут быть разными — фамилии, имена, отчества, адреса, почты, огрн, инн и ещё большая куча других подсказок. Для простых интернет-магазинов очень нужны ФИО, электропочты и адреса. Это реально упрощает процесс оформления заказа и в какой-то степени увеличивает конверсию.

Как подключить

  1. Регистрируемся на сайте dadata.ru, получаем API ключик.
  2. Открываем файл /design/ваша_тема/html/cart.tpl и добавляем в него:
{literal}
<link href="https://cdn.jsdelivr.net/npm/suggestions-jquery@19.4.2/dist/css/suggestions.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/suggestions-jquery@19.4.2/dist/js/jquery.suggestions.min.js"></script>
 <script type="text/javascript">
     $(".cart input[name='name']").suggestions({
         serviceUrl: "https://dadata.ru/api/v2",
         token: "a8fe6329cfa81666be66deb370d2c364ccfddeaa",
         type: "NAME",
         params: {
             parts: ["SURNAME", "NAME", "PATRONYMIC"]
         }
     });
     $(".cart input[name='address']").suggestions({
         serviceUrl: "https://dadata.ru/api/v2",
         token: "a8fe6329cfa81666be66deb370d2c364ccfddeaa",
         type: "ADDRESS"
     });
     $(".cart input[name='email']").suggestions({
        serviceUrl: "https://dadata.ru/api/v2",
        token: "a8fe6329cfa81666be66deb370d2c364ccfddeaa",
        type: "EMAIL",
        /* Вызывается, когда пользователь выбирает одну из подсказок */
        onSelect: function(suggestion) {
            console.log(suggestion);
        }
    });
 </script>
 {/literal}
  1. Чтобы скрипт заработал, нужно указать свой API-ключик во всех token-параметрах.
  2. Обратите внимание, что у меня используется нестандартный класс для формы корзины. Чтобы узнать какой класс формы корзины используется у вас, найдите в cart.tpl html-тег
    и посмотрите какой класс ему принадлежит. Далее просто замените cart на свой класс в этих полях:
$(".cart input[name='name']").suggestions({
...
$(".cart input[name='address']").suggestions({
...
$(".cart input[name='email']").suggestions({
...
}

Результат работы

 Нет комментариев    207   2019   simplacms

SimplaCMS: обновляем TinyMCE до 4 версии

Кривой TinyMCE 3 версии в 2019 году уже невозможно использовать. Он регулярно вставляет всякие спаны и непечатаемые пробелы, поэтому нужно было обновить его версию.

  1. Открываем /simpla/design/js/ и создаём папку tinymce
  2. Скачаем сам TinyMCE и положим содержимое папки js в папку tinymce. Краткая структура файлов и папок в папке tinymce должна быть такой:
-langs
-plugins
-skins
-themes
--jquery.tinymce.min.js
--tinymce.min.js
  1. Открываем файл /simpla/design/html/tinymce_init.tpl и меняем полностью его содержимое на:
<script language="javascript" type="text/javascript" src="design/js/tinymce/tinymce.min.js"></script>
<script language="javascript">
tinymce.init({
    selector: "textarea.editor_large,textarea.editor_small",
    language : "ru",
    plugins: [
        "advlist autosave autolink lists link image charmap print preview hr anchor pagebreak",
        "searchreplace wordcount charactercount charmap visualblocks visualchars code fullscreen",
        "insertdatetime media nonbreaking save table contextmenu directionality",
        "emoticons template paste textcolor colorpicker textpattern  "
   ],
   toolbar1: "undo redo | bold italic underline | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link unlink anchor | image media charmap blockquote | forecolor backcolor | removeformat print preview code emoticons ",
menubar: '',
   verify_html: false, 
   image_advtab: true,
        setup : function(ed) {
        if(typeof set_meta == 'function')
        {
            ed.on('keyUp', function() {
                set_meta();
            });
            ed.on('change', function() {
                set_meta();
            });
        }
    }
    {literal}}{/literal});
    function myCustomGetContent( id ) {
        if( typeof tinymce != "undefined" ) {
            var editor = tinymce.get( id );
            if( editor && editor instanceof tinymce.Editor ) {
                return editor.getContent{literal}({format : 'text'}{/literal}).substr(0, 512);
            } else {
                return  jQuery('textarea[name='+id+']').val().replace(/(<([^>]+)>)/ig," ").replace(/(\&nbsp;)/ig," ").replace(/^\s+|\s+$/g, '').substr(0, 255);
            }
        }
        return '';
    }
</script>
  1. Далее необходимо поправить автогенерацию meta description в админке. Для этого нужно полностью заменить функцию generate_meta_description() в файлах:
    • /simpla/design/html/product.tpl
    • /simpla/design/html/post.tpl
// Обновлённая функция, которую нужно вставить в файлы
function generate_meta_description()
{
	if( typeof tinymce != "undefined" )
	{
		return myCustomGetContent( "annotation" );
	}
	else
		return $('textarea[name=annotation]').val().replace(/(<([^>]+)>)/ig," ").replace(/(\&nbsp;)/ig," ").replace(/^\s+|\s+$/g, '').substr(0, 255);
}

В файле /simpla/design/html/category.tpl полностью обновляем функцию:

function generate_meta_description()
{
	if( typeof tinymce != "undefined" )
	{
		return myCustomGetContent( "description" );
	}
	else
		return $('textarea[name=description]').val().replace(/(<([^>]+)>)/ig," ").replace(/(\&nbsp;)/ig," ").replace(/^\s+|\s+$/g, '').substr(0, 255);
}

В файле /simpla/design/html/page.tpl полностью обновляем функцию:

function generate_meta_description()
{
	if( typeof tinymce != "undefined" )
	{
		return myCustomGetContent( "body" );
	}
	else
		return $('textarea[name=body]').val().replace(/(<([^>]+)>)/ig," ").replace(/(\&nbsp;)/ig," ").replace(/^\s+|\s+$/g, '').substr(0, 255);
}

Результат работы

 1 комментарий    178   2019   simplacms   tinymce

SimplaCMS: соседние товары, вывод бренда

Откроем файл /view/ProductView.php, отыщем строчку

//Соседние товары

И заменим содержимое блока на:

$next = $this->products->get_next_product($product->id);
		$next_brand = $this->brands->get_brand(intval($next->brand_id));
		$i = $this->products->get_images(array('product_id'=>$next->id));
		$next->image = reset($i);
		$next->brand = $next_brand;

		$prev = $this->products->get_prev_product($product->id);
		$prev_brand = $this->brands->get_brand(intval($prev->brand_id));
		$i = $this->products->get_images(array('product_id'=>$prev->id));
		$prev->image = reset($i);
		$prev->brand = $prev_brand;

Теперь, чтобы вывести бренд соседнего товара:

{$prev_product->brand->name} или {$next_product->brand->name}
 Нет комментариев    104   2019   simplacms

SimplaCMS: подключаем Яндекс Турбо для новостей

Создадим новый файл RssView.php в папке /view/ со следующим содержимым:

<?PHP
require_once('View.php');
class RssView extends View
{
  public function fetch()
  {
    $items_per_page = 20;
    $params = array();
    $params['visible'] = 1;
    $params['limit'] = $items_per_page;
     
    switch($this->request->get('type', 'string')) {
        default:
            $items = $this->blog->get_posts($params);  
            $category = 'Статьи компании';  
            $cat_url = $this->config->root_url.'/blog';
            $base_url = $this->config->root_url.'/blog/';
    }
    header("Content-Type: application/rss+xml; charset=UTF-8"); 
    $p = $items[0];
    $rssfeed = '<?xml version="1.0" encoding="UTF-8"?>';
    $rssfeed .= '<rss xmlns:yandex="http://news.yandex.ru" xmlns:media="http://search.yahoo.com/mrss/" xmlns:turbo="http://turbo.yandex.ru" version="2.0">';
    $rssfeed .= '<channel>';
    $rssfeed .= '<title>'.$this->settings->site_name.'</title>';
    $rssfeed .= '<link>'.$cat_url.'</link>';
    $rssfeed .= '<description>'.$this->settings->company_name.'</description>';
    $rssfeed .= '<language>ru-ru</language>';
    $rssfeed .= '<category>' . $category . '</category>';
    $rssfeed .= '<copyright>Copyright '.date('Y').' '.$this->settings->company_name.'</copyright>';
    $rssfeed .= '<pubDate>' . date("D, d M Y H:i:s O", strtotime($p->date)) . '</pubDate>';
    $rssfeed .= '<lastBuildDate>' . date("D, d M Y H:i:s O", strtotime($p->date)) . '</lastBuildDate>';
    foreach($items as $p) {
        $rssfeed .= '<item turbo="true">';
        $rssfeed .= '<guid isPermaLink="true">'. $base_url . $p->url . '</guid>';
        $rssfeed .= '<link>'. $base_url . $p->url . '</link>';
        $rssfeed .= '<turbo:content>';
        $rssfeed .= '<![CDATA[';
        $rssfeed .= '<header>';
        $rssfeed .= '<h1>' . $p->name . '</h1>';
        $rssfeed .= '</header>';
        $rssfeed .= '<p>'. ($p->text) . '</p>';
        $rssfeed .= '<div data-block="share" data-network="twitter, facebook"></div>';
        $rssfeed .= ']]>';
        $rssfeed .= '</turbo:content>';
        $rssfeed .= '<title>' . $p->name . '</title>';
        $rssfeed .= '<description><![CDATA[' . ($p->annotation) . ']]></description>';
        $rssfeed .= '<comments>'. $base_url . $p->url . '#comments</comments>';
        $rssfeed .= '<pubDate>' . date("D, d M Y H:i:s O", strtotime($p->date)) . '</pubDate>';
        $rssfeed .= '</item>';
    }
    $rssfeed .= '</channel>';
    $rssfeed .= '</rss>';    
    print($rssfeed);
    exit();
  }  
}

Далее откроем в корне сайта .htaccess и после строчки

RewriteRule ^blog(.*)$ /news$1 [L,R=301]

Добавим в него новое правило:

RewriteRule ^rss?$  index.php?module=RssView  [L,QSA]

Теперь у вас есть RSS лента, оптимизированная под Яндекс.Турбо по адресу ваш_сайт.ру/rss
Далее откроем Вебмастер Яндекса, откроем раздел Турбо Страницы -> Источники и добавим ссылку на ваш RSS-канал:

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

Теперь нужно несколько часов на модерацию вашего источника, а после завершения ваши новости будут в формате Яндекс Турбо ;-)

 149   2019   simplacms

Simpla CMS: названия изображений без хеша

Решение принадлежит DaVinci и большая ему благодарность за это.
Решение позволяет избавиться от хеша в названии изображения, что позволит изображениям залетать в индекс поисковых систем. Базовое имя у изображений весьма кривое:

В стандарной симпле адрес изображения имеет абракадабру на конце:

8b8a7e13a7e2e5a7ee9f

Чтобы от него изобавиться нужно открыть /resize/resize.php и закомментировать:

/*
if(!$simpla->config->check_token($filename, $token))
	exit('bad token');
*/

Далее открываем Design.php и добавим в функцию public function resize_modifier после переменных $resized_filename и $resized_filename_encode:

$size = ($width?$width:0).'x'.($height?$height:0).($set_watermark?"w":'');
        $image_sizes = array();
        if($this->settings->image_sizes)
            $image_sizes = explode('|',$this->settings->image_sizes);
        if(!in_array($size, $image_sizes)){
            $image_sizes[] = $size;
            $this->settings->image_sizes = implode('|',$image_sizes);
        }

В этой же функции ниже нужно закомментировать хвост у строчки:

return $this->config->root_url.'/'.$this->config->resized_images_dir.$resized_filename_encoded/*.'?'.$this->config->token($resized_filename)*/;

Далее открываем файл Image.php и в функцию function resize добавить после конструкции list:

$size = ($width?$width:0).'x'.($height?$height:0).($set_watermark?"w":'');
        $image_sizes = array();
        if($this->settings->image_sizes)
            $image_sizes = explode('|',$this->settings->image_sizes);
        if(!in_array($size, $image_sizes)){
            header("http/1.0 404 not found");
            exit();
        }

Всё. Теперь все изображения без абракадабры на конце.

 142   2019   simplacms

SimplaCMS: Итоговая стоимость на ThankYou Page

Не нашёл переменной, которая выводит стоимость заказа с учётом доставки, пришлось написать костылёк прям в шаблоне. Работает просто — забираем данные из переменных (total_price и delivery_price), складываем (math equation), преобразовываем в переменную (assign) и выводим значение в отформатированном виде (total|convert).

{math equation = $order->total_price + $order->delivery_price assign = 'total'}
{$total|convert} {$currency->sign}
 84   2018   simplacms

Simpla: Показываем JivoSite в определённое время

Сделал на одном сайте привязку кнопок «Обратный звонок» и «Отправить заявку» к JivoSite.
Возможно для кого-то это покажется дикостью, но это на самом деле удобно — обратный звонок должен происходить моментально, а не через три часа, когда менеджер по продажам, который отсиживает жопу на зарплате, накурится сигарет и напьется кофе. И JivoSite в этом плане оказался очень удобен.

Но столкнулся с интересной проблемой. В JivoSite есть настройки времени, когда можно совершать звонок с сайта. Чтобы появилась форма обратного звонка нужно нажать на соответствующую кнопку/ссылку. Конкретный пример:

Предположим мы поставим в настройках JivoSite часы работы с 9 до 18 часов. Как вы думаете, что произойдет, если мы нажмём на ссылку «Обратный звонок» в 18:02? Правильно. Ничего. Она не сработает, а это проёбаный лид. Техподдержке передал, но нужно сохранить лид уже сегодня и своими силами.

Чтобы лид остался с нами, нужно проверить сколько сейчас на часах и предложить альтернативу, например, оффлайн форму того же JivoSite. И в SimplaCMS это решалось так:

<a href="tel:{$settings->company_phone|escape}"><h3>{$settings->company_phone|escape}</h3></a>
{if $smarty.now|date_format:'%H.%M' > '09.00' && $smarty.now|date_format:'%H.%M' < '18.00' }
{literal}<a href="#" onclick="jivo_api.open({start : 'call'});">Обратный звонок</a>{/literal}
{else}
<a href="#" onclick="jivo_api.open();">Обратный звонок</a>
{/if}

Если время сервера попадает в заданный интервал, показать ссылку №1. В противном случае №2.

 155   2018   jivosite   simplacms
Ранее Ctrl + ↓