tips and tricks

Подрузка видео по скролу

видео на сайте много весят, даже если сделаны для красоты, поэтому удобно их подгружать на действия пользователей, нашел интересный плагин, проверил, работает, советую
http://dinbror.dk/blazy/examples/?ref=blog

SSL сертификата порядок создания bundle.crt

в интернете много путаницы по очереди склеики сертификатов, развеем ее
если у вас нет уже объедененного файла, а есть root, intermediate и crt файл домена, их необходимо склеивать в один bundle.crt с последовательностью: домен -> intermediate -> root

Свойство раздела для переменных в header.php

При работе в header.php часто требуется использовать условия или значения, например текстовое описание страницы, а врапер использовать не хочется, решение - определить дополнительное поле для раздела (мы говорим о физическом разделе) в .section.php и получить его значение, быстро, удобно, юзабельно
.section.php

$arDirProperties = Array(
"page_top_description" => "Описание раздела"
);


header.php

<?if($page_top_description = $APPLICATION->GetProperty('page_top_description')):?>
<div class="p-top__text"><?=$page_top_description?></div>
<?endif;?>

Mapbox на русском языке


после отключения google maps для простых смертных, т.е. после включения платного режима пользования, все задаются вопросом, какие карты использовать на сайте, чтобы можно было стилизовать и еще бесплатно и тут быстро находится решение, которое не только не уступает гугл картам, но и превосходит их по функционалу и удобству использования - представляем вам mapbox

Переключить все названия на карте mapbox к русскому языку можно по инструкции https://www.mapbox.com/help/change-language/#multiple-layers-at-once


или через плагин 

var map = new mapboxgl.Map({
    container: 'map',
    style: 'mapbox://styles/mapbox/streets-v10',
    center: [-98, 38.88],
    minZoom: 2,
    zoom: 3
});
mapboxgl.setRTLTextPlugin('https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-rtl-text/v0.1.0/mapbox-gl-rtl-text.js');
map.addControl(new MapboxLanguage({
  defaultLanguage: 'ru'
}));


https://github.com/mapbox/mapbox-gl-language/

Очистка формы после submit


$(form).find('input[type="text"],input[type="tel"],textarea,input[type="number"],input[type="email"]').val('');

Минимизатор css / js для phpstorm


Assets Compressor

Refactor-> Compress и получаем нимимифицированный файл

Кнопки поделиться в социалках


взято отсюда
<script>
Share = {
        vkontakte: function(purl, ptitle, pimg, text) {
            url  = 'http://vk.com/share.php?';
            url += 'url='          + encodeURIComponent(purl);
            url += '&title='       + encodeURIComponent(ptitle);</div><div>            url += '&description=' + encodeURIComponent(text);
            url += '&image='       + encodeURI(pimg);
            url += '&noparse=true';
            Share.popup(url);
        },
        odnoklassniki: function(purl, text) {
            url  = 'http://www.odnoklassniki.ru/dk?st.cmd=addShare&st.s=1';
            url += '&st.comments=' + encodeURIComponent(text);
            url += '&st._surl='    + encodeURIComponent(purl);
            Share.popup(url);
        },
        facebook: function(purl, ptitle, pimg, text) {
            url  = 'http://www.facebook.com/sharer.php?s=100';
            url += '&p[title]='     + encodeURIComponent(ptitle);
            url += '&p[summary]='   + encodeURIComponent(text);
            url += '&p[url]='       + encodeURIComponent(purl);
            url += '&p[images][0]=' + encodeURIComponent(pimg);
            Share.popup(url);
        },
        twitter: function(purl, ptitle) {
            url  = 'http://twitter.com/share?';
            url += 'text='      + encodeURIComponent(ptitle);
            url += '&url='      + encodeURIComponent(purl);
            url += '&counturl=' + encodeURIComponent(purl);
            Share.popup(url);
        },
        mailru: function(purl, ptitle, pimg, text) {
            url  = 'http://connect.mail.ru/share?';
            url += 'url='          + encodeURIComponent(purl);
            url += '&title='       + encodeURIComponent(ptitle);</div><div>            url += '&description=' + encodeURIComponent(text);
            url += '&imageurl='    + encodeURIComponent(pimg);
            Share.popup(url)
        },
        google: function(purl) {
            url  = 'https://plus.google.com/share?';
            url += 'url='          + encodeURIComponent(purl);
            Share.popup(url)
        },

        popup: function(url) {
            window.open(url,'','toolbar=0,status=0,width=626,height=436');
        }
    };
</script>


<a onclick="Share.vkontakte('URL','TITLE','IMG_PATH','DESC')"> {шарь меня полностью}</a>
<a onclick="Share.facebook('URL','TITLE','IMG_PATH','DESC')"> {шарь меня полностью}</a>
<a onclick="Share.mailru('URL','TITLE','IMG_PATH','DESC')"> {шарь меня полностью}</a>
<a onclick="Share.odnoklassniki('URL','DESC')"> {шарь меня полностью}</a>
<a onclick="Share.twitter('URL','TITLE')"> {шарь меня полностью}</a>

Количество символов в строке PHP (utf-8, латиница)


$length = strlen(utf8_decode($s));

Сортировка по родительскому разделу в result_modifier bitrix


if($arParams['SORT_BY_COMPLEX']){

$sectionsName = $COMPLEX_OBJECT_SECTION_INF = array();
$arFilter = Array('IBLOCK_ID' => OBJECT_MAIN_IBLOCK_ID, 'ACTIVE' => 'Y', 'DEPTH_LEVEL' => 1);//'!UF_SITE_ID'=>false
$db_list = CIBlockSection::GetList(Array('SORT' => 'ASC'), $arFilter, false, array('ID','NAME','UF_SITE_ID','IBLOCK_ID','UF_COMPLEXE_LOGO','CODE'));
while ($ar_result = $db_list->Fetch()) {
$COMPLEX_OBJECT_SECTION_INF[$ar_result['ID']] = $ar_result;
}

foreach ($arResult['ITEMS'] as &$arItem){
$res = CIBlockSection::GetByID($arItem["IBLOCK_SECTION_ID"]);
$arItem['LAST_SECTION_INF'] = $res->Fetch();

$tempArResult[$COMPLEX_OBJECT_SECTION_INF[$arItem['LAST_SECTION_INF']['IBLOCK_SECTION_ID']]['SORT']][] = $arItem;
}

if($arParams['SORT_BY_COMPLEX']=='ASC'){
ksort($tempArResult);
}
else {
krsort($tempArResult);
}

$arResult['ITEMS'] = array();
foreach ($tempArResult as $sort_key=>$group_items){
LOG_INTERFACE::debugToConsole($sort_key,'$sort_key');
foreach ($group_items as $item){
$arResult['ITEMS'][] = $item;
}
}
}

gzip сжатие и кеширование изображений и других ресурсов для браузера

.htaccess
<IfModule mod_expires.c>
ExpiresActive on
ExpiresDefault "access plus 1 week"
ExpiresByType image/jpeg "access plus 1 week"
ExpiresByType image/gif "access plus 1 week"
ExpiresByType image/png "access plus 1 week"
ExpiresByType text/css "access plus 1 week"
ExpiresByType text/svg "access plus 1 week"
ExpiresByType text/svg+xml "access plus 1 week"
ExpiresByType application/javascript "access plus 1 week"
</IfModule>


<ifModule mod_gzip.c>
mod_gzip_on Yes
mod_gzip_dechunk Yes
mod_gzip_item_include file .(html?|txt|css|js|php|pl|svg)$
mod_gzip_item_include handler ^cgi-script$
mod_gzip_item_include mime ^text/.*
mod_gzip_item_include mime ^application/x-javascript.*
mod_gzip_item_exclude mime ^image/.*
mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
</ifModule>

постоянный 301 редирект (htaccess)

внимание! редирект кешируется браузером и говорит поисковику о постоянном(не временном) переезде страницы
Redirect 301 /some-shit-section/ http://webkernel.ru/

PHPStorm Decrypt Password

Decrypt Password in webServers.xml
$pwd = "Your encrypted password here.";
$decrypted = '';
while (strlen($pwd) > 0) {
$decrypted .= chr(hexdec(substr($pwd, 0, 4)) ^ hexdec('dfaa'));
$pwd = substr($pwd, 4, strlen($pwd) - 1);
}
echo $decrypted;

jquery to console

jquery в консоль
var jq = document.createElement('script'); jq.src = "https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"; document.getElementsByTagName('head')[0].appendChild(jq);

Скрипт для выполнения по шагам, ajax, админ панель, битрикс


https://dev.1c-bitrix.ru/community/webdev/user/11948/blog/2047/

проверка ajax запроса


if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
// do something
}

сортировка элементов по массиву


if($arParams['BEST_SORT_ARRAY']){
foreach($arParams['BEST_SORT_ARRAY'] as $parent_news_id){
foreach($arResult["ITEMS"] as $key=> $one_item){
if($one_item['ID']==$parent_news_id)
$new_items_arr['ITEMS'][$key] = $one_item;
}
}
$arResult["ITEMS"] = $new_items_arr['ITEMS'];
}

логический фильтр из ID для CIBlockElement::GetList

необходимо привести массив к такому виду:
$arrFilter = array(
array(
'LOGIC'=>'OR',
array('ID'=>1749305),
array('ID'=>1994586)
)
);

приводим:
$arrFilter = array(
array(
"LOGIC" => "OR",
),
); $res = CIBlockElement::GetList(Array(), $arFilter, false, Array("nTopCount"=>20), array('PROPERTY_SOME_ID'));
while($ob = $res->Fetch())
{
$arrFilter[0][] = array("ID"=>$ob['PROPERTY_SOME_ID_VALUE']);
}

запрет прокрутки окна браузера (еще раз)


$(document).bind("mousewheel", stop_scroll);
$(window).bind("scroll mousewheel", stop_scroll);

function stop_scroll(event) {
event.preventDefault();
$(document).scrollTop(top);
} // отключаем запрет $(document).unbind('mousewheel'); $(window).unbind("scroll mousewheel");

получить из строки число js


$("#phone").val().replace(/\D/g,'')

Сменить владельца для папкок и файлов

необходимость может возникнуть при особой настройке сервера, когда права на файлы созданные/измененные по shh будут отличаться от создаваемых сервером(apache), в этом случае может даже не получиться создать/изменить файл/папке с помощью битрикса, если права владения на родительскую папку будут отличаться. Скрипт ниже рекурсивно изменит владельца на папки и файлы директории public_html:
chown -R bitrix:bitrix /absolute/path/to/site-dir/

закрыть сайт паролем .htaccess, .htpasswd

размещаем .htpasswd в корне, пароль генерируем через онлайн сервисы в md5 формат, должна получиться запись в стиле: admin:$apr1$4U6Sd3mX$GRTmqSENCrK9mMTFPV7TE1
AuthType Basic
AuthName "Thats protected Area!"
AuthUserFile /home/bitrix/www/.htpasswd
Require valid-user
<Files .htpasswd>
deny from all
</Files>

Удобное добавление lang языковых файлов к файлам компонента

можно например использовать при ajax запросе файла в шаблоне компонента, после добавление вызова просто вызываем функцию GetMessage(), как в шаблоне компонента: например создали файлик props.php в шаблоне компонента и соответственно создаем одноименный файл в /lang директории для соответствующего языка, радуемся жизни.
<? $this_file_name = pathinfo(__FILE__); require_once($BX_DOC_ROOT.'/bitrix/components/some_space/some_component/templates/.default/lang/'.LANGUAGE_ID.'/'.$this_file_name['basename']); ?>

ajax запрос


$.ajax({       
type: "POST",
url: $(this).attr("action"),
data: $(this).serialize()
,

dataType: 'json'
})
.done(function(data) {
console.log(data);
});

доступ к битрикс api


require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");

нежадное вытаскивание значение между


preg_match_all('/d="(.*)"/sU',$some_var,$matches, PREG_SET_ORDER);

логирование под админом


global $USER; if($USER->IsAdmin()):
print_r($arrResult);
endif;

масштабированное отображение на мобильных девайсах


<meta name="viewport" content="width=device-width">

вызов jQuery last version и других


<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>

Запрет прокрутки окна браузера


$('.some-class').on('focus', function(){
        OffScroll();  //Запустили отмену прокрутки
    });

$('.some-class').on('blur', function(){ $(window).unbind('scroll'); //Выключить отмену прокрутки });
function OffScroll () { var winScrollTop = $(window).scrollTop(); $(window).bind('scroll',function () { $(window).scrollTop(winScrollTop); }); }

html5 для старых версия браузеров


<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>

разбивка списка на блоки


<ul>
<li>
<?foreach($arResult["ITEMS"] as $key=>$arItem):?>
<?if(($key+1)%3==0 &&$arItem!=end($arResult["ITEMS"])):?>
</li><li>
<?endif?>
<?endforeach;?>
</li>
</ul>

css стили для placeholder


::-webkit-input-placeholder { color: #646464}
::-moz-placeholder { color: #646464}/* Firefox 19+ */
:-moz-placeholder { color: #646464}/* Firefox 18- */
:-ms-input-placeholder { color: #646464}

ссылки со слешем в конце и без:


RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI}
RewriteRule ^(.*)$ http://%{HTTP_HOST}/$1/ [R=301,L]

заголовок файлового раздела:


$sSectionName = ""; 
$sPath = $_SERVER["DOCUMENT_ROOT"].$APPLICATION->GetCurDir().".section.php";
<h1><?=$sSectionName?></h1>

свойства физического раздела в битриксе можно получить вот так:


$APPLICATION->GetProperty("shown_menu");

подьем на верх окна jquery


$('body,html').animate({scrollTop: 0}, 400);

создание/обрезка изображения превью/большой картинки + водяной знак/watermark:

запись сего в result_modifier.php компонета


$param_sharpen = 30;
$arFilter = array("name" => "sharpen", "precision" => $param_sharpen);  //  можно просто false
foreach($arResult['ITEMS'] as $item_key=>$item){
$arFile = CFile::GetFileArray($one_pic_id);
$arFileTmp = CFile::ResizeImageGet(
$item['PREVIEW_PICTURE'],
array("width" => 183, "height" => 159),
BX_RESIZE_IMAGE_EXACT,
true, $arFilter
);
$arResult["OUR_WORKS_PICS"][$item_key] = array(
"SRC" => $arFileTmp["src"],
'WIDTH' => $arFileTmp["width"],
'HEIGHT' => $arFileTmp["height"],
);
$arBigFileTmp = CFile::ResizeImageGet(
$item['PREVIEW_PICTURE'],
array("width" => $item['PREVIEW_PICTURE']['WIDTH'], "height" => $item['PREVIEW_PICTURE']['HEIGHT']),
BX_RESIZE_IMAGE_PROPORTIONAL,
true,
$arFilters = Array(array(
"name" => "watermark",
"position" => "center",
"size"=>"real",
'type'=>'image',
'alpha_level'=>30,
"text"=>'sometext',//  это поле не выводится (
"file"=>$_SERVER['DOCUMENT_ROOT']."/bitrix/templates/.default/img/logo.png")
)
);
$arResult["OUR_WORKS_BIG_PICS"][$item_key] = array(
"SRC" => $arBigFileTmp["src"]
);
}

CIBlockSection::GetList


$arFilter = Array('IBLOCK_ID'=>$arResult['IBLOCK_ID'], 'GLOBAL_ACTIVE'=>'Y', 'ID'=>$arResult['ID']);
$db_list = CIBlockSection::GetList(Array(), $arFilter, false,array('ID','UF_ADDITIONAL_DESC'));
if($ar_result = $db_list->GetNext())
{
$arResult['UF_ADDITIONAL_DESC'] = $ar_result['~UF_ADDITIONAL_DESC'];
}

редирект с несуществующих поддоменов на основной


RewriteCond %{HTTP_HOST} !^www.webkernel.ru$ [NC]
RewriteRule ^(.*)$ http://www.webkernel.ru/$1 [R=301,L]

переопределение lang файлов компонента, если их нет в шаблоне компонента


требуется создать такой файл: /bitrix/php_interface/user_lang/ru/lang.php с требуемой lang переменной

$MESS["/bitrix/components/bitrix/catalog.section/lang/ru/component.php"]["CATALOG_SECTION_NOT_FOUND"] = "Мой раздел не найден";

градиент-эффект перетекания в прозрачный css

пример на странице интересного дизайн продукта для маковки
-webkit-mask-position: 0 0;
-webkit-mask-size: 100% 100%;
-webkit-mask-image: linear-gradient(90deg, hsla(0, 0%, 0%, 0), hsla(0, 0%, 0%, .2) 50%, hsla(0, 0%, 0%, .8) 80%, hsla(0, 0%, 0%, 1) 100%);

вызов FirePHP в init.php

прекрепляю сам файлик FirePHP.class.php и ссылку на расширение для chrome
Как думаете, для чего нужен такой дебагер, если можно написать свой и чтоб js писал в консоль?,
а нужен FirePHP например для ajax запросов в json формате и firephp не ломает ответ сервера и вообще не участвует в теле ответа запроса, так же, firephp не оставляет в html следов дебага, которые могут восприниматься поисковиками или элементарно ломать верстку, в общем всем советую для определенного круга задач
require_once($_SERVER['DOCUMENT_ROOT'].'/bitrix/templates/.default/FirePHP.class.php');
$firephp = FirePHP::getInstance(true);
$options = array(
'maxObjectDepth' => 15,
'maxArrayDepth' => 15,
'maxDepth' => 15,
'useNativeJsonEncode' => true,
'includeLineNumbers' => true
);
$firephp->setOptions($options);

объявление крос шрифта css



@font-face {
font-family: 'robotolight';
src: url('../fonts/roboto-light-webfont.eot');
src: url('../fonts/roboto-light-webfont.eot?#iefix') format('embedded-opentype'),
url('../fonts/roboto-light-webfont.woff') format('woff'),
url('../fonts/roboto-light-webfont.ttf') format('truetype'),
url('../fonts/roboto-light-webfont.svg#robotolight') format('svg');
font-weight: normal;
font-style: normal;
}

e-mail из главного модуля


$strEmail = COption::GetOptionString('main','email_from');

валидация с jQuery Validation Plugin, ajax post и оборачивание контента в fancybox

var validator_list_top_form = $("#top-feedback-form").validate({
        errorPlacement: function(error, element) {
            error.prependTo(element.parent(".one-field-top-form-wrapper").find('.error-label-wrapper'));
        },
        errorClass: "error-form-field",
        rules:{
            top_name:{
                required: true,
                minlength: 1,
                maxlength: 100
            },
            top_phone:{
                required: true,
                digits: true,
                minlength: 5,
                maxlength: 11
            }
        },
        messages:{
            top_name:{
                required: "Это поле обязательно для заполнения",
                minlength: "Минимальная длина поля 1 символ",
                maxlength: "Максимальное число символов - 100"
            },
            top_phone:{
                required: "Это поле обязательно для заполнения",
                digits: "Требуется ввести числовое значение",
                minlength: "Минимальная длина телефона 5 символов",
                maxlength: "Максимальная длина телефона 11 символов"
            }
        }
    });
$('#top-feedback-form').submit(function(){     
if(validator_list.errorList.length==0){
var property = new Object();
property.trigger_name = 'feedback-message';
property.name = $('#top-feedback-form input[name="name"]').val();
property.phone = $('#top-feedback-form input[name="phone"]').val();
var request = $.post(
"/bitrix/templates/.default/ajax-answers/mail-sender.php",
{
"trigger_name" : property.trigger_name,
"name" : property.name,
"phone" : property.phone
},
function(msg){
console.log(msg);
if(msg.error==false){
$.fancybox.open({
height : 50,
autoSize : false,
content : '<div class="server-error-message" >'+msg.error_message+'</div>',
maxWidth : 250,
maxHeight : 10
});
}
else if (msg.error==true){
$.fancybox( '<div class="server-error-message" style="color: red">'+msg.error_message+'</div>' );
}
},
"json"
);
request.fail(function(jqXHR, textStatus) {
alert( "Request failed: " + textStatus );
});
}
return false;
});

удаление тега регулярным выражением php


preg_replace('/<a(.*)>|<\/a>/sU','',$text)


Вы должны авторизоваться, чтобы оставлять комментарии.

Загрузка ...
some text