Прозрачные PNG в IE6

Собственно сабж. Делаю проект, без прозрачных png тут что-то делать просто самоубийство — используются фоновые градиенты, закруглённые углы и всё это в резине. Вот так и нашёл фичу.

Раньше всегда выводил прозрачные PNG через фильтры, просто прописывал их в CSS, но технологии не стоят на месте и вот уже есть решение позволяющее выводить png в IE позиционируя его в блоке. Работает всё через behavior — прописывается htc-файл с JS-скриптом обрабатывающим нужный блок.

P.S. Меня эта штука просто спасла. =)

Рубрика: Кодинг Метки: , , Комментарии к записи Прозрачные PNG в IE6 отключены

Реализация Comet в среде php+javascript

Ну что ж, сказано — сделано. В этой статье я расскажу, что из себя представляет Comet и рассмотрю реализацию простой схемы с помощью PHP и JavaScript.

Для начала, Comet это что-то вроде теории о создания постоянного соединения между клиентом и сервером в универсальной среде, в общем без привязки к какому-то определённому языку программирования.

При инициализации клиент открывает соединение с сервером и повисает в таком состоянии, когда на сервере появляются какие-то новые данные он отправляет их по этому соединению клиенту.

Для того, чтобы реализовать подобную вещь на JavaScript нужно учесть, что работа ведётся, через AJAX по протоколу HTTP. На сервере же предположительно установлен веб-сервер Apache.

В условиях AJAX-запросов, после отправки данных сервер закрывает соединение, клиент обрабатывает данные, открывает соединение заново и ждёт новую порцию данных.

Особенности

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

// javascript class, connection manager
this.connection = function() {
        self.comet = $.ajax({
            type: "GET",
            url:  "backend.php",
            data: {'id':self.last},
            dataType: "text",
            timeout: self.timeout*1000,
            success: self.parseData,
            error: function(){
                // something wrong. but setInterval will set up connection automatically
                setTimeout(self.connection,1000);
            }
        });
    }
this.init = function() {
        //setInterval(self.connection,self.timeout*1000);
        self.connection();
    }
this.init();

В JavaScript все таймауты указываются в миллисекундах, поэтому мы их умножаем на тысячу.

На сервере рекомендую поставить max_execution_time в значение равное таймауту клиента. В самом скрипте нужно организовать вечный цикл, с регулярной проверкой данных для отправки.

// simple infinite loop in php
while (time()-$time<$limit) {
    // checking if something new was added to my test table
    $res = mysql_query('SELECT * FROM `comet` WHERE `id`>"'.$last_id.'" ORDER BY `id` ASC');
    if (mysql_num_rows($res)) {
        while ($item=mysql_fetch_array($res)) {
            echo 'self.putMessage("'.$item['id'].'","'.escape($item['name']).'","'.escape($item['text']).'");';
        }
        flush();
        exit;
    }
    sleep(5);
}

Реализация

Я напишу всё с использованием библиотеки jQuery. Итак, javascript:

function Messanger() {
    this.last = 0;
    this.timeout = 360;
    this.comet = 0;
    var self = this;
    this.putMessage = function(id,name,text) {
        // callback, добавляет сообщения на страницу, вызывается из полученных с сервера данных
        self.last = id;
        var b = document.createElement('div');
        b.innerHTML = '<span style="color: red;">'+name+'</span> '+text;
        $('#messages').append(b);
    }
    this.parseData = function(message) {
        // простая обработка данных полученных с сервера, разбиваем строки и выполняет функции
        var items = message.split(';');
        if (items.length<1) return false;
        for (var i=0;i<items.length;i++) {
            eval(items[i]);
        }
        setTimeout(self.connection,1000);
    }
    this.connection = function() {
        // здесь открывается соединение с сервером
        self.comet = $.ajax({
                type: "GET",
                url:  "backend.php",
                data: {'id':self.last},
                dataType: "text",
                timeout: self.timeout*1000,
                success: self.parseData,
                error: function(){
                    // something wrong. but setInterval will set up connection automatically
                    setTimeout(self.connection,1000);
               }
            });
    }
    this.init = function() {
        //setInterval(self.connection,self.timeout*1000);
        self.connection();
    }
    this.init();
}
function sendMessage() {
    // callback формы, для отправки сообщений на сервер
    if ($('#name').val()&&$('#text').val()) {
        var data = {
                name: $('#name').val(),
                text: $('#text').val()
            }
        $.post('add_new.php',data);
    } else {
        alert('Please fill the fields');
    }
}
$(document).ready(function(){
    // инициализация
    var msg = new Messanger();
});

И PHP скрипт, отправляющий данные:

<?
// number of second the script allowed to run. setting to 6 minutes
$limit = 360;
$time = time();

// getting last loaded value
$last_id = (int)$_GET['id'];

// just to be sure that script will be killed
set_time_limit($limit+5);

mysql_connect('localhost','user','password');
mysql_select_db('database');

function escape($str) {
    return str_replace('"','\"',$str);
}

// цикл, проверяющий новые сообщения каждые 5 секунд
while (time()-$time<$limit) {
    // checking if something new was added to my test table
    $res = mysql_query('SELECT * FROM `comet` WHERE `id`>"'.$last_id.'" ORDER BY `id` ASC');
    if (mysql_num_rows($res)) {
        while ($item=mysql_fetch_array($res)) {
            // пишем js-скрипт, который выполнится у клиента
            echo 'self.putMessage("'.$item['id'].'","'.escape($item['name']).'","'.escape($item['text']).'");';
        }
        // выбрасываем все данные и выходим, чтобы клиент смог их обработать
        flush();
        exit;
    }
    // если данных нет - ждём 5 секунд
    sleep(5);
}

mysql_close();
?>

Мы получили фронтенд на JavaScript, который отправляет запросы на сервер в ожидании новых данных, сервер каждые 5 секунд проверяет не появились ли данные, когда появляются — он их отправляет клиенту и закрывает соединение. После этого клиент снова открывает соединение и всё повторяется. Если данных не поступило и сработал таймаут — клиент просто открывает соединение заново.

Обратите внимание, что и в классе на JS и в скрипте PHP задан таймаут, это сделано, чтобы избежать создание мёртвых процессов, одинаковые таймауты в теории должны поддерживать нагрузку сервера на минимуме.

Рубрика: Кодинг Метки: , , , 2 комментария

Социальные кнопки на сайт

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

На страничке Яндекса вы можете в пару кликов настроить и скопировать к себе код для подключения социальных кнопок, очень удобно, так что пользуюсь и сам. Самое главное — сервисом довольны и мои заказчики, такие кнопки их устраивают, а подключать их одно удовольствие! =)

P. S. Я себе на внутренних страницах постов здесь тоже поставил.

Рубрика: Кодинг Метки: , , Комментарии к записи Социальные кнопки на сайт отключены

До конца света осталось…

Как-то во время общения с другом всплыла идея сделать счётчик дней до «конца света». Ну, или проще – счётчик времени до того момента, когда все ждущие и верящие наконец-то будут окончательно повержены.

Собственно реализация: spectrox.ru/timebeforetheend/

Работает на JavaScript с небольшой погрешностью на загрузку страницы, учитывает разницу между серверным временем и пользовательским.

Ждём!

Рубрика: Кодинг Метки: , Комментарии к записи До конца света осталось… отключены

iFraming on the fly

Давно слышал о проблемах с созданием динамических iframe и заполнении их содержимым, но посмотреть что и как самому всё никак не доходили руки, теперь же, по причинам связанным с не приходящим сном, я эту тему затрону.

Для примера я набросал простую страничку создающую iframe по клику мыши. Изначально я записал всё одной функцией выполняющейся в один поток, но результата никакого небыло, решение было найдено — собственно участок кода, в котором происходит редактирование iframe я записал в функцию setTimeout, тем самым вынес его в отдельный поток выполнения:

setTimeout(function(){
        //редактируем iframe;
    },0);

После чего код начал работать. Буквально пару часов спустя, я показал описанное выше @chaos_8 и он разъяснил, что суть не в вызове setTimeout(), а в том, что после создания iframe нужно дождаться события onload (как и при работе с объектом Image).

Получившийся исходный код:

function start() {
    var fB = document.getElementById('frame_block');
    var frame = document.createElement('iframe');
    frame.setAttribute('width','640');
    frame.setAttribute('height','480');
    frame.onload = function() {
        var doc = frame.contentWindow.document;
        doc.body.innerHTML = 'Test it';
    }
    fB.appendChild(frame);
}

Рубрика: Кодинг Метки: , , 1 комментарий

Несколько слов о НДС

Столкнулся я недавно с необходимостью расчёта НДС. При том не только в виде «вычислить 18% от цены», а в виде просчёта НДС для счетов-фактур и других официальных документов, где необходим просчёт по позициям. Смысл статьи в описании 2х основных моментов, которые мной были замечены.

Введение

Существует 2 основные проблемы при расчёте НДС:

  1. Необходимость просчётов в вариантах, когда НДС уже включен в цену товара, и варианта, когда НДС будет просчитан сверху, из цены товара.
  2. Проблемы связанные с погрешностью округления. Эта погрешность может создать различие между НДС расчитанным по позициям товара, и НДС получающийся из общей суммы товара.

Вроде бы всё просто, но давайте разберёмся с этими примерами поподробнее.

Варианты просчёта НДС

В любимой нами всеми программе от существует 2 вариант просчёта НДС:

  1. НДС в сумме. Это когда НДС уже содержится в цене товара и для его просчёта используется формула:

    СуммаНДС = Сумма * 18 / 118

    Формула это выходит из логики начальной школы. Сначала высчитываем сколько будет рублей в 1% (Сумма/118), затем умножаем на 18, и получаем 18% (из расчёта того, что НДС 18%. хотя он не всегда бывает таковым).

  2. НДС сверху. В этом варианте необходимо расчитать сумму НДС исходя из цены товара без НДС, т.е.:

    СуммаНДС = Сумма * 0.18

    или

    СуммаНДС = Сумма * 18 / 100

    Тут думаю всё понятно.

А теперь немного о самой проблеме: «Различия в расчётах между двумя этим видами».

Цена с НДС

В общем мои наблюдения показали, что в случае расчёта в сумме, вся счёт-фактура расчитывается исходя из цены с НДС, и цена за единицу товара без НДС, может не быть несколько округлённой. Т.е. вся счёт фактура подстраивается под сумму с НДС, без предварительного расчёта цены без НДС. Например, чтобы расчитать цену за единицу товара мы используем формулу:

Цена_за_единицу_товара = Округление( (Сумма_с_НДС — Сумма_НДС) / Количество_товара )

Мы не расчитываем сумму товара, умножением его цены на количество. Это не верный путь, для данного варианта расчёта НДС.

Сумму НДС мы можем расчитать следующим образом:

Сумма_НДС = Округление( Сумма_с_НДС * 18 / 118 )

Затем, мы используем следующую формулу для расчёта суммы товара без НДС:

Сумма_без_НДС = Округление( Сумма_с_НДС — Сумма_НДС )

Таким образом, мы явно видим, что все цены подогнаны под сумму с НДС.

Цена без НДС

Если же счёт-фактура расчитывается исходя из цены без НДС, то все расчёты ведутся по логике действий. Сначала вычисляется сумма без НДС, затем из суммы без НДС, вычисляется сумма НДС и соответственно, в итоговой сумме пишется просто «Сумма_без_НДС + Сумма_НДС».

Если вы захотите заного просчитать счёт-фактуру, изходя из данных полученных после прошлого просчёта (где НДС расчитывался другим способом), вы можете увидеть некоторую разницу в расчётах. В моём случае разница составляла одну копейку. Позже, я постораюсь добавить пример, на котором всё это хорошо видно.

Рубрика: Кодинг Метки: Комментарии к записи Несколько слов о НДС отключены