programming languages

Тот еще COUNT

Иногда бывает под вечер зависнешь на какой-нибудь проверке и не можешь понять почему логика не складывается. Оказывается просто потому что,  не логично работают некоторые участки системы.

В частности столкнулся вот только что с функцией count в php для подсчета значений в массиве. В голове всегда было воспоминание что с ней что-то не так, вот пришлось их обновлять.

//$i = 1.05; // true
//$i = 1;  // true
//$i = '1'; // true
$i = array();// false
var_dump(count($i) > 0);

Логичнее наверное сделать что если переменная не массив, то возвращать NULL или false, так нет же надо возвращать 1.

Если var не является массивом или объектом, реализующим интерфейс Countable, будет возвращена 1. За одним исключением: если varNULL, то будет возвращён 0.

AJAX навигация по меткам

Итак задача, нужно сохранять состояние страницы после ajax запроса. Для этого приспособили метки у ссылок, URL будет вот такого вида http://site.ru/#/key:val/key1:val1/keyN:valN/

В js далеко не гуру, но все работает и нативно.

var Navigation = function()
{
this.isHash = function(){return (window.location.href.indexOf('#') !== -1 && window.location.hash.length > 1);};

/**
* Возвращает все параметры из url в виде объекта
*/
this.getQueryParams = function(){
if(this.isHash())
{
var _ar = window.location.hash.replace('#', '').split('/');
var _ob = {};

for(var i=0; i < _ar.length; i++){
if(_ar[i] !== "")
_ob[i] = _ar[i];
}

var returnObject = {};
for(var j in _ob){

if (_ob.hasOwnProperty(j)) {
var _ar_params = _ob[j].split(':');
returnObject[_ar_params[0]] = _ar_params[1];
}
}

return returnObject;
}

return false;
};

/**
* Устанавливает строку параметров, если есть сотрет что было
*/
this.setHash = function(objectParsms){

var ar = [], j = 0;
for(var i in objectParsms){
j++; ar[j] = i + ':' + objectParsms[i];
}

var hashString = ar.join('/');

if(hashString.length > 0)
window.location.hash = '#' + hashString + '/';
};

this._isEmptyObject = function(Obj)
{
var i = 0;
for(var o in Obj){
i++;
}

return i;
};

this._isKeyObject = function(obj, key){

for(var o in obj)
{
if(o === key)
return true;
}

return false;
};

/**
* Добавляет параметр в url, если параметр уже есть то заменит значение на новое
*/
this.addHashParam = function(objectParams){

if(this.isHash())
{
var params = this.getQueryParams();

for(var o in objectParams){
if(this._isKeyObject(params, o)){
params[o] = objectParams[o];
}
}

var arRes = [], k = 0;
for(var or in params){
k++;arRes[k] = or + ':' + params[or];
}

var str_hash = arRes.join('/');

var ar = [], j = 0;
for(var i in objectParams){
if(!this._isKeyObject(params, i)){
j++; ar[j] = i + ':' + objectParams[i];
}
}

if(ar.length > 0){
str_hash += ar.join('/') + '/';
}
else{
str_hash += '/';
}

window.location.hash = str_hash;
}
else
{
this.setHash(objectParams);
}
};

/**
* Удаляет параметр из url можно указывать несколько, принимает массив ключей
*/
this.delHashParams = function(arParams){
if(this.isHash())
{
var params = this.getQueryParams();

for(var a = 0; a <= arParams.length; a++){
delete params[arParams[a]];
}

if(this._isEmptyObject(params) > 0)
this.setHash(params);
else
window.location.hash = '';
};
};
};

Делать такую навигацию весьма трудоемко, но позволяет немного шире использовать ajax.

Предзагрузка изображений js [snippets]

2 рабочие функции для пред загрузки картинок, нативная и jQuery.

	

function preload(images) {
   if (typeof document.body == "undefined") return;
 	    try {

 	        var div = document.createElement("div");
 	        var s = div.style;
 	            s.position = "absolute";
 	        s.top = s.left = 0;
 	        s.visibility = "hidden";
 	        document.body.appendChild(div);
         div.innerHTML = "";
 	        var lastImg = div.lastChild;
 	        lastImg.onload = function() { document.body.removeChild(document.body.lastChild); };
 	     }
 	     catch(e) {
 	        // Error. Do nothing.
     }
 	}
 	});

	jQuery.preloadImages = function () {
	    var images = (typeof arguments[0] == 'object') ? arguments[0] : arguments;
	    for (var i = 0; i < images.length; i++) {
	        jQuery("").attr("src", images[i]);
	    }
	}

Найдено на просторах.
http://clip2net.com/clip/m11386/1304961837-clip-11kb.png

Конвертер валют для Bitrix [php, js]

Конвертер валют Битрикс

Конвертер валют Битрикс

Я редко что-то выкладываю готовое, но вот просто захотелось. Я не жадный, просто нет времени. Итак задача была сделать конвертер на js, для этого нам нужно иметь данные для подсчета, принципиально не захотел делать пересчет на аяксе так как это был бы не совсем js конвертер. Вариантов получения данных несколько, вот как сделал я.

В битриксе есть модуль «Валюты» он нам нужен для back-end нашего конвертера. Для автоматического обновления есть скрипт который обновляет курс, его можно запускать кроном или агентом, я выбрал крон. Там же в модуле валюты есть список курсов, с названиями и значениями курса по умолчанию, по большому счету нам нужны только названия валют оттуда. Его пришлось собирать ручками, по этому в архиве положу csv файл, загрузите его сами. Теперь когда back-end готов можно перейти к компоненту.

Компонент обрабатывает данные из модуля, он должен быть постоянно кэшированным так как при вычислении коэффициента для каждой валюты, создается большой кол-во запросов, благо они мелкие и легкие. Кэш компонента очищается при отработки скрипта на кроне, в коде это можно найти. Логика компонента возвращает 2 json объекта с которыми мы в дальнейшем работаем в шаблоне. В общем смотрим что получилось, улучшать там есть что, буду раз замечаниям.

Скачать архив

В папке cron скрипт для пересчета валюты, в flag флаги, их нужно положить в upload или поправить пути. Не забудьте подключить jQuery.

 

Send mail with attachment php

function XMailAttach($from, $to, $subj, $text, $ar_File)  
{  
	$un        = strtoupper(uniqid(time()));  
	$head      = "From: $from\n";  
	$head     .= "To: $to\n";  
	$head     .= "Subject: $subj\n";  
	$head     .= "X-Mailer: PHPMail Tool\n";  
	$head     .= "Reply-To: $from\n";  
	$head     .= "Mime-Version: 1.0\n";  
	$head     .= "Content-Type:multipart/mixed;";  
	$head     .= "boundary=\"----------".$un."\"\n\n";  
	$zag       = "------------".$un."\nContent-Type:text/html;\n";  
	$zag      .= "Content-Transfer-Encoding: 8bit\n\n$text\n\n";  
								 
	foreach ($ar_File as $file)
	{
		$f         = fopen($file, "rb");  
		$zag      .= "------------".$un."\n";  
		$zag      .= "Content-Type: application/octet-stream;";  
		$zag      .= "name=\"".basename($file)."\"\n";  
		$zag      .= "Content-Transfer-Encoding:base64\n";  
		$zag      .= "Content-Disposition:attachment;";  
		$zag      .= "filename=\"".basename($file)."\"\n\n";  
		$zag      .= chunk_split(base64_encode(fread($f,filesize($file))))."\n";  
	}
								 
	if (!mail($to, $subj, $zag, $head))  
	 	return false;  
	else  
		return true;  
}

Сколько лет пользователю сайта?

Немного лениво выглядит профиль пользователя на сайте, когда вместо надписи о количестве лет выводится дата его рождения. Снипед, для Битрикса, жаль что нету API функции.

if(strlen($ar_UserCabinet['PERSONAL_BIRTHDAY']) > 0)
{
	$ar_UserDateTo  = explode('.', $ar_UserCabinet['PERSONAL_BIRTHDAY']);
	$s_MetaDateTo   = mktime(0, 0, 0, $ar_UserDateTo[1], $ar_UserDateTo[0], $ar_UserDateTo[2]);
	$s_MetaDateFrom = mktime(0, 0, 0, date('m'), date('d'), date('Y'));
	$i_Meta = ($s_MetaDateFrom - $s_MetaDateTo) / 31276800;

	# проверим был ли у пользователя день рождения, если еще небыло то -1
	$s_DateRog = mktime(0, 0, 0, $ar_UserDateTo[1], $ar_UserDateTo[0], date('Y'));
	if($s_DateRog > $s_MetaDateFrom)
		$i_Meta -= 1;

	$arResult['USER_BIRTHDAY'] = intval($i_Meta);
}

Вывод в заголовок диапазона элементов [c 10 по 20]

Задача, вывести в пагинацию и в заголовок диапазон в котором находится пользователь в текущий момент т.е.  в конец добавлять текущую позицию в списке,  список [c 10 по 20]

Вот наброски кода который решает эту задачу $rs_Element объект типа arResult

if(is_array($ar_Navigatonparams))
{
    $ar_NavParams = array(
        'NavPageNomer'    => $rs_Element->NavPageNomer,
        'NavPageSize'     => $rs_Element->NavPageSize,
        'NavRecordCount'  => $rs_Element->NavRecordCount,
        'nEndPage'        => $rs_Element->nEndPage
    );

    function navigationIntervalList($ar_NavParams)
    {
        if(isset($_REQUEST['PAGEN_1']) && intval($_REQUEST['PAGEN_1']) > 0)
        {
            if(intval($ar_NavParams['NavPageNomer'])  > 1)
            {
                $_s = ($ar_NavParams['NavPageNomer'] * $ar_NavParams['NavPageSize']) - $ar_NavParams['NavPageSize'] + 1;
                $_p = $ar_NavParams['NavPageNomer'] * $ar_NavParams['NavPageSize'];

                if($ar_NavParams['nEndPage'] == $ar_NavParams['NavPageNomer'])
                    $_p = $ar_NavParams['NavRecordCount'];

                return 'список с '.$_s.' по '.$_p;
            }
        }
    }

    $s_nav = navigationIntervalList($ar_NavParams);
    $s_Nav = (!empty($s_nav)) ? ' / '.$s_nav : '';
    $s_Tit = (!empty($s_nav)) ? ', '.$s_nav : '';

    $APPLICATION->AddChainItem($s_TitleNavchain.$s_Nav);
    $APPLICATION->SetTitle($s_TitleNavchain.$s_Tit);
}

Python. Самое необходимое [книга]

Последнее время меня потянуло на что-то новое и я решил поковырять питон. Для этой благой цели я прикупил на озоне книжку  Python. Самое необходимое (+ DVD-ROM).

Как книжка, расскажу как прочитаю, брал специально чтобы получить базовые знания, а там видно будет что с ним делать.