Duff's device construction in C/C++/Java/PHP/Javascript

В 1983 году Томас Дуглас Дафф из Торонто во время оптимизации раскрутки одного цикла открыл необычную конструкцию на C:

switch(count%8){
case 0: do{ *to = *from++;
case 7:  *to = *from++;
case 6:  *to = *from++;
case 5:  *to = *from++;
case 4:  *to = *from++;
case 3:  *to = *from++;
case 2:  *to = *from++;
case 1:  *to = *from++;
  }while(--n>0);

Он обнаружил, что с выражением switch можно выделывать весьма хитрые фокусы. Пока вы соблюдаете синтаксис, вы можете вкладывать в выражение switch различные выражения выбора или итерации, что позволяет эффективно переходить в любую функцию или выходить из нее. Здесь можно ознакомиться с перепиской Даффа, где он рассказывает о своем открытии

Вот пара примеров:

// первая итерация начинается с определенной метки case
switch (num % 5) {
            case 0: do { i++;
            case 4:         i++;
            case 3:         i++;
            case 2:         i++;
            case 1:         i++;
                        }     while (--n > 0);

}

или так

switch (num % 2) {
    case 0:   do { std::cout << "num = " << num << std::endl;;
    case 1:           std::cout << "num = " << num << std::endl;;
                 }       while (--num > 0);

}

Причем все они компилируются и работают. Я встречал использование такого трюка в примерах написания так называемых сопрограмм, определяемых в макросах. Вот пример - msdn.
Стоит отметить, что данная особенность - при отсутствии break, управление внутри блока передаётся «вниз и насквозь» от инструкции, стоящей под одной меткой case, к инструкции, стоящей под следующей меткой case - характерна только для С и С++, в остальных языках мы будем получать предупреждения о синтаксической ошибке. Например, в Java компилятор будет ругаться на первой же метке case, так же ведет себя интерпретатор Javascript. Попытка проверки на PHP тоже завершилась сообщением интерпретатора об ошибке - Parse error: syntax error, unexpected 'case' (T_CASE).
Целесообразность и эффективность использования такой конструкции ставится под сомнение, сам Дафф в своей переписке - см. выше - указывает на ряд ограничений и слабой целесообразности такой конструкции. Но тем не менее, есть источники, указывающие на присутствие в коде реализации такой конструкции в протоколе SSH.
Think about it! 

NASM. Generate programms for DOS and Windows x86 OS

Ниже представлены примеры создания программ для таких систем как DOS и Windows x86 на ассемблере NASM. Создание приложения под DOS.
1. Cоздаем исходник hello.asm

SECTION .text

org 0x100

mov ah, 0x9
mov dx, hello
int 0x21

mov ah, 0x4c
mov al, 0
int 0x21

SECTION .data

hello db "Hello, world!", 0xd, 0xa, '$'

2. запускаем компилятор NASM nasm -f bin -o hello.com hello.asm
На выходе получаем hello.com, при запуске которого на консоль выведется всем нам привычное сообщение - Hello, world!


Создание приложения под Windows x86
1. Cоздаем исходник msgbox.asm

;подключение заголовочного файла (определяющий типы аргументов функций WinAPI)
%include "win32n.inc"

;объявление внешней функции MessageBoxA (идентификатор)
EXTERN MessageBoxA

;связывание объявленной функции с соответствующей динамической библиотекой
IMPORT MessageBoxA user32.dll

;объявление внешней функции ExitProcess
EXTERN ExitProcess

;связывание объявленной функции с соответствующей динамической библиотекой
IMPORT ExitProcess kernel32.dll

;секция (сегмент) кода
SECTION CODE USE32 CLASS=CODE ;метка для компоновщика, указывающая на точку входа

;передача аргументов производится согласно соглашению STDCAL
;аргументы передаются через стек в порядке справа налево (так же, как и в C)
;очистка стека входит в обязанности вызванной функции (аналогично языку Pascal)

;помещение в стек последнего аргумента отвечающего за тип окна (с единственной кнопкой - OK)
push UINT MB_OK

;помещение в стек указателя (адрес нуль-завершенной строки) на строку заголовка
push LPCTSTR title

;помещение в стек указателя на строку сообщения
push LPCTSTR banner

;помещение в стек аргумента указывающего на родительское окно в нашем случае оно отсутствует
push HWND NULL

;вызов функции Windows API - MessageBoxA 
call [MessageBoxA]

;аргумент ExitProcess - код возврата
push UINT NULL

;завершение процесса
call [ExitProcess] 

;секция статических данных
SECTION DATA USE32 CLASS=DATA

;строка сообщения с символом EOL
banner db 'Hello, world!', 0xD, 0xA, 0

;строка заголовка
title db 'Hello', 0
2. запускаем компилятор

nasm -fobj msgbox.asm

В результате получим объектный файл msgbox.obj, который нужно передать компоновщику alink

alink -oPE msgbox

Параметр -o определяет тип исполняемого файла (родным для Windows является тип PE). Как итог - на выходе исполняемый exe-файл - msgbox.exe




На последок немного дополнительной информации. Создание исполняемого файла состоит из двух этапов: компиляция и компоновка. На первом этапе - компиляция (трансляция) исходного кода программы в некоторый объектный формат. Объектный формат содержит машинный код программы, но символы (переменные и другие идентификаторы) в объектном файле пока не привязаны к адресам памяти. На втором этапе, который называется компоновкой или линковкой (linking), из одного или нескольких объектных файлов создается исполняемый файл. Процедура компоновки состоит в том, что компоновщик связывает символы, определенные в основной программе, с символами, которые определены в ее модулях (учитываются директивы EXTERN и GLOBAL), после чего каждому символу назначается окончательный адрес памяти или обеспечивается его динамическое вычисление.

Для выполнения данных примеров необходимо обратиться к следующим ресурсам:

https://sourceforge.net/projects/nasm - NASM ассемблер
http://alink.sourceforge.net/ - alink компоновщик
win32n.inc - подключаемый заголовочный файл, для вызовов Win API-функций

Всем хорошего дня, вечера или ночи ;)

PHP. Генератор случайных строковых значений

Здесь один нюанс: mt_rand() раза в 4 быстрее rand()

function generateRandomString($length = 10) {
        $randomString = "";
        $characters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
        $min = 0;
        $max = strlen($characters) - 1;
        for ($i = 0; $i < $length; $i++) {
            $randomString .= $characters[mt_rand($min, $max)];
        }
        return $randomString;

}

PHP4/5. Works with directories

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

function getCatalogStruct($path, array &$list) {
        $d = dir($path);
        while (false !== ($entry = $d->read())) {
            if (is_file($path."/".$entry)) {
                $list[] = $entry;
            }
            if (is_dir($path."/".$entry) && $entry !== "." && $entry !== "..") {
                $list[$entry] = array();
                getCatalogStruct($path."/".$entry."/", $list[$entry]);
            }
        }
        $d->close();
    }
   
    $catalogStruct = array();
    $path = "./debugMsg/";
   
    getCatalogStruct($path, $catalogStruct);
   
    echo "<pre>";
    print_r($catalogStruct);
    echo "</pre>";


Вот такая структурка на выходе:

Array
(
    [dir1] => Array
        (
            [subdir1] => Array
                (
                )

            [0] => subTestFile1.txt
            [1] => subTestFile2.txt
        )

    [dir2] => Array
        (
            [0] => subTestFile2.txt
        )

    [0] => testFile1.txt
    [1] => testFile2.txt
    [2] => testFile3.txt
    [3] => testFile4.txt
)

Jquery. Work with hidden iframes. Interaction between parent window and child iframes

Во время веб-разработки приходится решать различного рода задачи, во время решения некоторых из них прибегают к использованию так называемых фреймов - <iframe></iframe>
Внутри этих фреймов можно либо создать свои дополнительные DOM-элементы, например - добавить формы:

$(document).ready(function() {

    $('body').after('<iframe id="testIframe" width="1" height="1" align="center"></iframe>');
   
    $('#testIframe').load(function() {
        var form =     '<form id="testForm" action="test.php" method="post">' +
                        '<input type="text" name="testInput" value="testValue"/>' +
                    '</form>';
        $(this).contents().find('body').html(form);
    });
   
});


Здесь стоит оговориться: в Opera и Chrome этот пример не прокатит - форма так и не будет добавлена, нужно сразу же после создания фрейма добавлять свою форму (видимо это связано с тем, что в данном случае внутри фрейма документ пуст, ведь мы не указали через тег src на источник, поэтому метод $('#testIframe').load() не отработает должным образом)
Либо загружать другие документы. При этом не засоряется текущая структура документа. В большинстве случаев эти фреймы делают скрытыми, скрывая от глаз пользователей побочную работу веб-приложения. Но при этом встает вопрос: как можно общаться с дочерними фреймами. Если бы повсеместно использовался HTML5, то вопрос этот бы отпал, так как там есть методы для этих целей (window.postMessage). Но в настоящее время ситуация другая. Можно воспользоваться вот таким нехитрым способом. Во-первых, нам понадобится библиотека - jquery и дополнительный плагин к нему - jquery.form. А далее внутри создать форму, которая может обращаться к серверу. Перед отправкой данных на сервер необходимо передать эту форму методу упомянутого выше плагина ajaxForm. Этот метод позволит нам создать обработчик ответов сервера, что я и сделал, к тому же он доступен родительскому окну, точнее - документу. Так достигается своего рода общение между родительским документом и дочерними скрытыми фреймами:

$('#testButton').click(function(){
    var ref = $('#testIframe').contents().find('#testForm');
    // обработчик на стороне дочернего фрейма
    ref.ajaxForm(function(response) {
        if (response == 'catched') {
            // взаимодействие с "родителем"
            $('#result').html('<p>from testIframe1</p>');
        }
    });
    ref.submit();
}); 


В данных примерах я использую метод $('#testIframe').load(), который удобен тем, что в нем можно использовать свой callback, который будет вызываться только после полной загрузки документа внутри этого фрейма.    

Источник тестовых данных. Частотный список английских слов (7998)

На днях нужен был источник данных для проведения теста приложения. Казалось бы, можно было для этого воспользоваться списком английских слов из какого-либо справочника. Но так сразу найти его не удалось. Но все же такой источник был найден. Это список наиболее употребимых в речи и писменности английских слов. Всего слов - 7998. Источник представляет собой текстовый файлик с построчным распределением слов. Вот ссылка - download. Всем удачи :)

HTML5. Canvas. Fill text by special symbols ( html named entities )

Any character entity references in HTML have unicode character. For fill canvas by html named entities you can use a unicode escape sequences.

GREEK SMALL LETTER SIGMA:

σ -> &sigma; -> U+03C3

context.fillText( "\u03C3", x, y );

Javascript. Object oriented programming. Object literal

Как известно, javascript относится к объектно-ориентированному языку, хотя парадигма разрабатываемых структур программ (сценариев) может быть и не объектно - ориентированной. Но рано или поздно приходит осознание, что использование принципов объектно-ориентированного программирования (ООП) более естественно и более продуктивно в ходе разработки. ООП неразрывно связано с понятием классов, которые выступают с одной стороны как универсальные структуры данных (с точки зрения предметного подхода), а с другой стороны - как особый тип данных (с точки зрения архитектуры, "бинарный" подход). Именно в классах проявляются принципы ООП, реализуемые в соответствующих объектах, инстансах. В javascript основной акцент перемещен на менее абстрактный уровень - на уровень объектов. Рассмотрим как создаются объекты в C++:

class CRectangle {
    int width, height;
  public:
    void set_values (int, int);
    int area (void) {return (width * height);}
};

void CRectangle::set_values (int a, int b) {
  width = a;
  height = b;
}
 
 
И в основной точке инстанцируем следующие объекты:

CRectangle a;
CRectangle * b = new CRectangle; 
 
Не забывая при выходе вызвать явно деструктор для объекта b:

delete b;
 
Отсюда видим, что прежде, чем создавать тот или иной объект, нам необходимо заложить общую будущую структуру в виде класса, определив при необходимости конструктор, деструктор, поля с соответствующими уровнями доступа и методы, также имеющие уровни внешнего доступа (private, public и protected).
Теперь рассмотрим как сие происходит в javascript. Есть несколько способов создания объектов: - посредством литерала {}:

var Obj = {};

- либо посредством функции-конструктора:

var Obj = new Object();

Конструктор Object создает пустой объект, как если бы использовался литерал {}, возвращая ссылку на созданный объект. Стоит отметить, что Object относится к базовым встроенным конструкторам, к которым относятся и такие как Array, Date, RegExp и прочие, но помимо этого есть возможность и в определении собственных конструкторов, например вот так:

function Dog( name ) {
    this.name = name || '';
}

var MyDog = new Dog( 'Rex' );

Как видим в javascript шаблоном объекта выступает не класс, а объект ( функции в javascript являются объектами ). Конечно, второй способ, где есть возможность определять свой конструктор дает больше возможностей для дальнейших манипуляций с объектами. Есть немало литературы, где больше освещается использование именно данного способа. Но меня больше заинтересовало использование первого способа - литерала объекта (Object literal), так как в данном случае мы немного стеснены в своих возможностях в силу отсутствия своего конструктора.

Рассмотрим общее использование литерала объектов. Для этого создадим объект Obj с определенными свойствами:

var Obj = {
    // внутреннее свойство
    value: '',
    // установка значения свойства value
    setValue: fuction( value ) {
        this.value = value || '';
    },
    // извлечение значения свойства value
    getValue: function() {
        return this.value;
    }
};

Обращаться к свойству объекта можно через точку (.), напоминает статические объекты в C++:

Obj.setValue('Obj'); 
console.log( Obj.getValue() ); // output: Obj  

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


var Obj = {
    reference: Obj
};
console.log( Obj.reference ); // output: undefined

А если попытаться получить ссылку на себя так:

var Obj = {
    reference: this
};
console.log( Obj.reference ); // output: window

То как видим на выходе получаем ссылку на глобальный объект - window. Все это указывает на то, что во время определения свойств сам объект еще не с конструировался. Этого можно избежать путем создания пустого объекта, с последующим определением его свойств:

var Obj = {
    reference: null
};
Obj.reference = Obj;
console.log( Obj.reference ); // output: Object { reference={...}}

Теперь рассмотрим вопрос с организацией доступа к свойствам объектов. Как было продемонстрировано выше, изначально все свойства доступны извне, это сравнимо с уровнем доступа - public. Но как быть с такими уровнями как - private и protected. Сначала рассмотрим создание частных свойств. Для литералов объектов можно воспользоваться так называемыми - замыканиями (closure):

var A = {};

A.a = ( function(){
    var a = 16;
    A.getA = function(){ return a; };
    A.setA = function( value ){ a = value || 0 };
    return null;
})();

A.b = ( function(){
    var b = 16;
    A.getB = function(){ return b; };
    A.setB = function( value ){ b = value || 0 };
    return null;
})();


// a null   
// b null
// getA function()
// getB function()
// setA function()
// setB function()


В объекте A при обращении к свойствам a или b в попытках что-то прочитать или внести изменения никак не скажутся на сокрытых a или b в областях просмотра анонимных функций. Можно вообще скрыть ненужные свойства во внутренних объектах:

var B = {};

B.a = ( function(){
    var value = 0;
    return {
        getValue: function(){ return value; },
        setValue: function( val ){ value = val; }
    };
})();

B.b = ( function(){
    var value = 0;
    return {
        getValue: function(){ return value; },
        setValue: function( val ){ value = val; }
    };
})();
   
// a Object { getValue=function(), setValue=function()}
// b Object { getValue=function(), setValue=function()}


В итоге в объекте B наружу торчат только те методы, через которые можно работать со скрытыми свойствами. При желании также можно скрывать и методы, но по мне все это может только усложнить поиск и устранение багов. Стоит отметить, что такого рода инкапсуляция свойств за счет замыканий через анонимные функции возможна благодаря не умирающим ссылкам на эти области просмотра, на самом деле это не просто некая область, это объект вызова, который создается при каждом вызове той или иной функции, а так как анонимные функции возвращают наружу ссылки на них, поэтому они и не уничтожаются по окончании вызова. Также эти объекты вызова именуются как объекты активации (activation object). Получается, что объект вызова выступает как пространство имен, к которому мы и обращаемся извне.

Теперь рассмотрим как можно использовать наследование между литерал объектами. Создание в одном из своих свойств ссылку на нужный объект - это не наследование:

var A = { name: 'A' }; // parent object
var B = { name: 'B', A: A }; // child object
console.log( B.A.name ); // output: A

В этом случае мы просто имеем ссылку на родительский объект ( к ссылочным типам в javascript относятся - Array, Object, Function ). В javascript у каждого конструктора объекта имеется свойство __proto__, в котором хранится ссылка на объект с конструктором (прототип). Это своего рода внутренняя ссылка. Если присвоить этому свойству ссылку на другой объект, то мы получим наследование. Причем в данном случае говорят о прототипном наследовании (prototype inheritance) за счет возможности образования прототипных цепочек (prototype chain):

var A = {
  x: 10,
  calculate: function ( z )
  {
    return this.x + this.y + z;
  }
};

var B = {
  y: 20,
  __proto__: A
};

var C = {
  y: 30,
  __proto__: A
};

// вызов унаследованного метода
console.log( B.calculate(30) ); // 60
console.log( C.calculate(40) ); // 80


Как видно из этого примера, объекты B и C за счет ссылки на  объект A унаследовали метод calculate, это произошло за счет прототипной цепочки: объект B не найдя у себя затребованного метода обращается к свойству __proto__ и по этой ссылке пытается обратиться к другому объекту, наружу, чтобы попытаться найти метод, если и там его не будет найдено, далее также будет обращение к этому свойству. Так и образуются цепочки: own -> proto -> proto -> proto -> null. В классовом же наследовании (абстрактно): own -> class -> superclass -> superclass -> null. В конечном счете окажется, что у некоторого объекта эта ссылка будет замкнутой ( можно в замыкающем объекте определить сие свойство в null значение ) и тогда мы получим либо undfined, либо сообщение об ошибочности нашего обращения. Также стоит обратить внимание на ключевое слово this. Оно всегда ссылается на конечный объект в цепочке прототипов. Обратите внимание на конечный результат таких цепочек в следующем примере.

var Parent = {
    a: 'Parent',
    getName: function()
    {        

          console.log( this );
    }
};

var Child = {
    b: 'Child',
    __proto__: Parent
};


// Object { b="Child", a="Parent", getName=function()}
Child.getName();


В итоге в наследуемом объекте Parent оказываются все свойства и методы наследника Child. Рассмотрим еще пример:

var Man = {
    head:
    {
        hair: 'black',
        eyes: 'black',
        nose: 'direct'
    },
    body:
    {
        hands: 'normal',
        feet: 'normal',
        brawn: 'normal'
    },
    getPattern: function(){
            console.log( 'Man pattern:' );
            console.log( this.head );
            console.log( this.body );
    },
    pattern:{}
};

Man.pattern.__proto__ = Man;


// output: Man pattern
// output: head Object{}
// output: body Object{}
Man.pattern.getPattern();


Вот так просто можно обращаться из вложенных (дочерних) объектов к объекту родителю.
Приведенный выше способ манипуляции с прототипами считается устаревшим, в новом стандарте javascript - ECMAScript 5th Edition ( JavaScript 1.8.5 ) для этих целей есть соответствующие методы: getPrototypeOf() и create(). Рассмотрим их подробней.
Метод create() используется в момент создания нового объекта с возможностью передачи в аргументе объекта, свойства которого необходимо унаследовать во вновь создаваемом объекте.

var A = {
    name: 'A'
};

var B = Object.create( A );

// output: A
console.log( B.name );

Если нет необходимости в унаследовании, то в аргументе передается null, так в прототипе явно уазывается, что он ни на кого не ссылается:

var C = Object.create( null );

Второй метод - getPrototypeOf() - используется для существующих объектов, он возвращает прототип объекта, указываемого в аргументе, в который можно прописать необходимую ссылку для реализации наследования.

var A = {
    name: 'A'
};   

var B = {};

Object.getPrototypeOf( B ).name = A.name;

// output: A
console.log( B.name );

В этом примере мы получаем прототип объекта B и сразу же  в него добавляем новое свойство name, которое ссылается на свойство name объекта A. Имя свойство необязательно должно совпадать с наследуемым свойством, но все же так правильней, логичней и прозрачней. Есть одно но: нельзя передавать непосредственно возвращаемому прототипу ссылки на свойства или объекты, интерпретатор будет ругаться ( связано это с тем, что возвращается объект ):

// либо так
Object.getPrototypeOf( B ) = A;

// либо так
Object.getPrototypeOf( B ) = A.name;

Оба варианта - нерабочие. Нужно обязательно обращаться через свойства.

Ниже приведу дополнительно примеры с этими методами:


//var myObj = {__proto__: {property1_OfProto: 1}}
var myObj = Object.create({property1_OfProto: 1});
 
//myObj.__proto__.property2_OfProto = 2
Object.getPrototypeOf(myObj).property2_OfProto = 2; 


Напоследок стоит сказать, что данные методы в определенных браузерах не поддерживаются, для решения данной проблемки можно воспользоваться библиотекой - github.com/kriskowal/es5-shim, также можно почитать в блоге Джона Резига - http://ejohn.org/blog/objectgetprototypeof/

  

PHP5 / Javascript. Сollaboration with Unix timestamps

В большинстве случаев реализация на серверной стороне связана с манипуляциями массивов дат. И удобнее всего использовать так называемые метки времени Unix (целое число, равное разнице в секундах между заданной датой/временем и началом так называемой Эпохи Unix (1 января 1970 00:00:00)). В PHP5 (PHP4) для этого можно воспользоваться следующими методами:

mktime - возвращает метку времени Unix для заданной даты

time - возвращает текущую метку времени Unix

strtotime - преобразует текстовое представление даты в метку времени Unix

Как правило даты на стороне сервера либо приходящие с клиентской стороны, либо отсылаемые клиентской стороне. И часто на стороне клиента нужно не просто отправлять или принимать эти временные данные, но также умеючи их обрабатывать, конечно все зависит от логики вашего приложения. Javascript также предоставляет методы для работы с такого рода метками времени Unix:

Date.parse

Date.UTC

Date.valueOf()

getTime 

...

javascript. Date compare object

Задачка. Как можно адекватно сравнить две даты? К сожалению объект Date не имеет встроенных методов для решения такого рода задачек. Ниже представлен один из способов такого решения.

// вспомогательный объект для сравнения дат в заданном формате, например так - dd.mm.yyyy, или так - yy.dd.mm
var Dates = {
                format : "",   // формат сравниваемых дат
                formatPattern : /^(dd|mm|yy|yyyy)(\.|\-)(?!\1)(dd|mm|yy|yyyy)\2(?!\1)(?!\3)(dd|mm|yy|yyyy)$/gi,                         formatAssoc :     { 1 : 0, 3 : 1, 4 : 2 },   // порядок соответствия индексов формата

                position :         { year : 0, month : 1, day : 2 },  // порядок сравнения частей дат  (год, месяц, день)
                separator : "",                                                      // разделитель (. или -)
                status :         { less : -1, equal : 0, larger : 1 },   // статусные биты
                compare :     function( date1, date2, format )   // основной метод: сравнение дат по заданному формату                                                    
                            {
                                // получение сравниваемых дат
                                var date1 = date1,
                                date2 = date2;
                               
                                // сохранение заданного формата
                                this.setFormat( format );
                               
                                // сравнение дат с первоначальной проверкой заданного формата на валидность использования.
                                // сравнение идет по изначально определенным индесам заданного формата
                                if ( this.checkFormat() )
                                {
                                    // разделение дат по разделителю формата на части (год, месяц, день)
                                    date1 = date1.split( this.separator );
                                    date2 = date2.split( this.separator );
                                   
                                    // сравнение дат по годам:
                                   
                                    if ( date1[ this.position.year ] > date2[ this.position.year ] )
                                    {
                                        return this.status.larger;
                                    }

                                    if ( date1[ this.position.year ] < date2[ this.position.year ] )
                                    {
                                        return this.status.less;
                                    }

                                    if ( date1[ this.position.year ] = date2[ this.position.year ] )
                                    {

                                        // сравнение дат по месяцам:
                                   
                                        if ( date1[ this.position.month ] > date2[ this.position.month ] )
                                        {
                                            return this.status.larger;
                                        }

                                        if ( date1[ this.position.month ] < date2[ this.position.month ] )
                                        {
                                            return this.status.less;
                                        }

                                        if ( date1[ this.position.month ] = date2[ this.position.month ] )
                                        {

                                            // сравнение дат по дням:
                                       
                                            if ( date1[ this.position.day ] > date2[ this.position.day ] )
                                            {
                                                return this.status.larger;
                                            }

                                            if ( date1[ this.position.day ] < date2[ this.position.day ] )
                                            {
                                                return this.status.less;
                                            }

                                            if ( date1[ this.position.day ] = date2[ this.position.day ] )
                                            {
                                                return this.status.equal;
                                            }

                                        }

                                    }

                                }
                                // при отрицательном результате проверки формата на валидность
                                else
                                {
                                    return false;
                                }
                            },
                setFormat : function( format )    // сохранение формата
                            {
                                this.format = format;
                            },
                checkFormat : function()           // проверка заданного формата на валидность  дольнейшего использования 
                            {
                                // проверка формата по шаблону
                                var checkResult = this.formatPattern.exec( this.format );

                                // положительная проверка
                                if ( checkResult != null )
                                {
                                    // распределение индексов формата по порядку сравнения частей дат  (год, месяц, день)
                                    for ( var index in checkResult )
                                    {
                                        // по годам
                                        if ( checkResult[index] == 'yy' || checkResult[index] == 'yyyy' )
                                        {
                                            this.position.year = this.formatAssoc[index];
                                        }
                                        // по месяцам
                                        if ( checkResult[index] == 'mm' )
                                        {
                                            this.position.month = this.formatAssoc[index];
                                        }
                                        // по дням
                                        if ( checkResult[index] == 'dd' )
                                        {
                                            this.position.day = this.formatAssoc[index];
                                        }
                                    }

                                    // установка разделителя для частей дат
                                    this.separator = checkResult[2];

                                    // сброс ресурса
                                    delete checkResult;

                                   
                                    // сброс внутреннего индекса шаблона проверки
                                    this.formatPattern.lastIndex = 0;

                                    return true;

                                }
                                // отрицательная проверка
                                else
                                {
                                    return false;
                                }

                            }
            };


Обратите на одну особенность в проверке формата по шаблону в методе checkFormat


var checkResult = this.formatPattern.exec( this.format );

Каждый второй вызов данного метода будет приводить к неоднозначности и связано это будет со спецификой поиска совпадений: будет возвращаться null. Этого в нашем случае не требуется, чтобы этого избежать введен сброс внутреннего индекса шаблона проверки ():
  
this.formatPattern.lastIndex = 0;

Желаю Всем удачи в нашем нелегком деле :)

PHP5. Особые случаи в условных и циклических выражениях

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

1 случай. Неоднозначность результата использования составных предикатов в условиях

Для наглядности - пример. Пусть даны первоначальные параметры:

$flag = false;
$n = 1;


А также дано такого рода условие:

if ( $flag && $n++ )
{
    // some code
}


Что мы получим на выходе? Вроде бы $n за счет посткрементной формы должен увеличиться на 1, то есть должны получить число - 2, но этого не произойдет, даже если воспользуемся прекрементной формой (++$n).
Так как параметр $flag равен false, то интерпретатор далее условие не просматривает, он "знает", что если один из предикатов установлен в false, то конечный результат логического сравнения также даст false. Помните правило конъюнкции ( логическое умножение ) из булевой алгебры! :) Поэтому далее вычисление не происходит.

Похожая ситуация возникает и в следующем условии:

if ( $flag || $n++ )
{
    // some code
}


Если $flag установлен в false, то все хорошо - далее проходит вычисление, но если $flag будет установлен в true, тогда вычисление не произойдет. Снова имеем дело с булевой алгебры - правило дизъюнкции ( логическое сложение ): в данном случае если один из предикатов установлен в true, то независимо от состояния ( true или false ), результатом логического сравнения будет true. В этом причина отсутствия вычисления.

Такого рода проявления вызваны оптимизацией работы интерпретатора с условными выражениями: быстро посмотрел, оценил и принял соответствующее решение. Логично, не так ли?!

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

Для заметки можно также подметить, что такого рода условные проверки встречаются во многих языках и даже в SQL.  

2 случай. Неоднозначность результата в циклах

Рассмотрим простой цикл.

for ( $i = 0; $i < 5; $i++ )
{
    if ( $i == 3 )
        continue;
       
    print( $i.'</br>' );       
}


Данный цикл отрабатывая выдает последовательность чисел: 0 1 2 4, 3 из этой последовательности выпадает: на этом шаге условие становится истинным, срабатывает инструкция continue; которая вынуждает цикл перейти к следующей итерации. Ну тут все понятно. Но что будет, если в иструкции continue; мы случайно
не проставим завершающее любое выражение точку с запятой, то есть:

for ( $i = 0; $i < 5; $i++ )
{
    if ( $i == 3 )
        continue
       
    print( $i.'</br>' );       


По идее, интерпретатор в этом случае должен выбросить исключение, но что же происходит на самом деле.
Если запустить данный цикл, то на выходе получим следующее: 3. Неожиданно, покрайней мере для меня это было неожиданно. Такой же результат можно получить и в следующем цикле:

for ( $i = 0; $i < 5; $i++ )
{
    if ( $i == 3 )
        break
       
    print( $i.'</br>' );       
}


С чем это может быть связано? Происходят такие чудеса по двум причинам: 1 - у блока условия явно не определена область действия, а инструкции continue и break в свою очередь пытаются отыскать завершающие ; и в это же время на пути
встречается инструкция print( $i.'</br>' ), которая выводит соответствующее число, и далее выражение завершается на искомом завершающем символе. Что в итоге получается? Получается, что интерпретатор расширил область действия
данного условия, поэтому только число 3 и выводится. Таким образом интерпретатор был введен в замешательство, такого не произошло бы, если мы имели дело с компилятором, например в C++.

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

for ( $i = 0; $i < 5; $i++ )
{
    if ( $i == 3 )
    {
        continue
    }
       
    print( $i.'</br>' );       
}


Если же теперь попытаться повторить приведенные выше "чудеса" - ничего не выйдет, интерпретатор укажет вам на наличие
ошибки. Но если внутри этого блока также проставить команду с завершающим ; все снова отработает как ни в чем не бывало. М-да.

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

Oracle SQL Developer. ORA-12705: Cannot access NLS data files or invalid environment specified. Resolve

Столкнулся с проблемой подключения Oracle SQL Developer к СУБД Oracle 11g XE. При попытке создать соединение к стандартному для  Oracle 11g XE экземпляру БД (SID) - XE получаю ошибку - ORA-12705: Cannot access NLS data files or invalid environment specified. И это не смотря на то, что подключение через SQL Plus проходит успешно. Проверил запись в tnsnames.ora. Вроде все хорошо.


Но все же проблема была найдена. Все дело в локали. Для устранения данной ошибки нужно в настройках SQL Developer - \sqldeveloper\ide\bin\ - в файлик - ide.conf - добавить следующие строчки:

AddVMOption -Duser.region=us
AddVMOption -Duser.language=en


Рестартуйте Ваш SQL Developer, если он был запущен, и вуаля - все готово. Ниже приведен скриншот успешного тест-коннекта. Всем успехов.


Oracle 11g XE. Install SCOTT/TIGER scheme

Для тестирования СУБД Oracle очень удобно пользоваться стандартной схемой SCOTT/TIGER. Но в последнем релизе, доступном для общедоступного пользования - Oracle Database Express Edition 11g Release 2 она отсутствует. Как быть? Можно конечно самому спроектировать некую базу данных, создать пользователя, наделить его правами и в путь дорожку. Но часто на глаза попадают мануалы, где рассматриваются возможности СУБД именно с использованием старого доброго малого - SCOTT/TIGER. Для выполнения последующих шагов воспользуемся утилитой - SQL Plus.

CONNECT SYS/пароль AS SYSDBA;

CREATE USER SCOTT
IDENTIFIED BY TIGER

DEFAULT TABLESPACE USERS
TEMPORARY TABLESPACE TEMP;

GRANT CONNECT TO SCOTT;

GRANT RESOURCE TO SCOTT;

ALTER USER SCOTT DEFAULT ROLE CONNECT, RESOURCE;

GRANT UNLIMITED TABLESPACE TO SCOTT;


Далее нужно выполнить sql-скрипт (проверьте правильность Вашего пути):

@C:\oraclexe\app\oracle\product\10.2.0\server\RDBMS\ADMIN\scott.sql


Ну вот и все, все готово :)

PHP5. Ссылки на объекты. Внешние и внутренние

В PHP5 все переменные - это ссылки на содержимое переменной. Для получения доступа к содержимому переменной используются ссылками. Важно помнить, что эти ссылки не есть указатели как в C/C++, которые содержат адреса на ячейки памяти, они лишь ссылаются на некоторое содержимое. Так же дело обстоит и с ссылками в python`е. Но сейчас не об этом. В PHP5 ссылка по-сути своей определяет жизнь переменной, точнее того, куда она ссылается: при удалении переменной ее содержимое может не сразу удалиться. С чем это может быть связано? За такую очистку как мы знаем отвечает сборщик мусора (garbage collector). А он смотрит как раз на то, есть ли ссылки на данные или нет, если нет, то все будет почищено, а иначе зачистка будет пропущена. Продемонстрирую на примере.

class Node
{
    var $str; // внутренние данные
    var $ref; // внетренняя ссылка
  
    // получение внутренних данных
    function getStr()
    {
        return $this->str;
    }
  
    // установить внутренние данные
    function setStr( $str )
    {
        $this->str = $str;
    }
  
    // получить внешнюю ссылку
    function getNext()
    {
        return $this->ref;
    }
  
    // установить внешнюю ссылку
    function setNext( &$ref )
    {
        $this->ref = $ref;
    }
  
    function __construct()
    {
        echo 'constructor<br/>';
    }
  
    function __destruct()
    {
        echo 'destructor -> '.$this -> getStr().'<br/>';
    }
  
}

// Создаем первый объект. Переменная получает ссылку на данный объект
$first = new Node;
// Создаем второй объект. Переменная получает ссылку на данный объект
$second = new Node;

// Помещаем данные в первый объект
$first->setStr( '$first' );
// Помещаем данные во второй объект
$second->setStr( '$second' );

// Привязываем первый объект ко второму за счет ссылки внутреннего члена $ref на второй объект
$first->setNext( $second );
// Привязываем второй объект к первому за счет ссылки внутреннего члена $ref на первый объект
$second->setNext( $first );

// Удаляем переменную $first, тем самым мы уничтожаем ее ссылку на объект
unset( $first );
// Удаляем переменную $second, тем самым мы уничтожаем ее ссылку на объект
unset( $second );

echo 'Debug<br/>';


Если мы запустим данный код на исполнение, то получим следующий результат:

constructor
constructor
Debug
destructor -> $first
destructor -> $second


Вроде бы ничего особенного, но присмотритесь на месторасположение слова Debug. Ведь мы уничтожили все переменные до момента вывода этого слова командами unset( $first ) и unset( $second ). То есть должны были сработать деструкторы наших объектов. Но на деле видим, что это не так. В чем дело? На самом деле мы создали перекрестные ссылки между первым и вторым объектами. Эти ссылки внутренние, и поэтому когда мы уничтожили наши переменные, мы уничтожили лишь внешние ссылки на объекты. В то время как объекты продолжали свое существование. Ну а на момент завершения сценария, как мы знаем, освобождаются все ресурсы, вот и получаем в конце вызовы деструкторов.
Теперь попробуйте закомментировать строчки, где идет создание внутренних перекрестных ссылок:

// $first->setNext( $second);
// $second->setNext( $first );


В результате получаем следующий результат:

constructor
constructor
destructor -> $first
destructor -> $second
Debug


Отсюда видим, что теперь наши объекты спокойно уничтожаются, что подтверждается сообщениями от их деструкторов до слова Debug. Все верно, ведь теперь на них ничто и никто не ссылается, вот и срабатывает сборщик мусора. Обратите внимание в описании класса Node на метод setNext() который работает непосредственно со ссылками. Всем удачи!
input

construct new object

construct new object

construct new object

output
object(Node)[3]
  public 'str' => string 'third' (length=5)
  public 'ref' => 
    object(Node)[2]
      public 'str' => string 'second' (length=6)
      public 'ref' => 
        object(Node)[1]
          public 'str' => string 'first' (length=5)
          public 'ref' => null
third
destruct of -> third
second
destruct of -> second
first
destruct of -> first

class Node
{
    var $str;
    var $ref;
    function __construct() { echo '<br/>construct new object<br/>'; }
    function __destruct() { echo '<br/>destruct of -> '.$this -> str.'<br/>'; }
}

echo '<br/>input<br/>';

//
$first = new Node;
$first -> str = 'first';

//
$second = new Node;
$second -> str = 'second';
$second -> ref = $first;
$first = $second;
unset( $second ); //

//
$second = new Node;
$second -> str = 'third';
$second -> ref = $first;
$first = $second;
unset( $second ); //

echo '<br/>output<br/>';

var_dump( $first );

//
echo $first -> str;

$first = $first -> ref;

//
echo $first -> str;

$first = $first -> ref;

//
echo $first -> str;

$first = $first -> ref;

// Notice: Trying to get property of non-object
// echo $first -> str;
// $first = $first -> ref;

//for ( ; $first -> ref ; $first = $first -> ref )

// $first -> ref = NULL;

// var_dump( $first );

------------------------

input

construct new object

construct new object

construct new object

output
object(Node)[3]
  public 'str' => string 'third' (length=5)
  public 'ref' => 
    object(Node)[2]
      public 'str' => string 'second' (length=6)
      public 'ref' => 
        object(Node)[1]
          public 'str' => string 'first' (length=5)
          public 'ref' => null
thirdsecondfirst
destruct of -> third

destruct of -> second

destruct of -> first



 class Node
{
    var $str;
    var $ref;
    function __construct() { echo '<br/>construct new object<br/>'; }
    function __destruct() { echo '<br/>destruct of -> '.$this -> str.'<br/>'; }
}

echo '<br/>input<br/>';

//
$first = new Node;
$first -> str = 'first';

//
$second = new Node;
$second -> str = 'second';
$second -> ref = $first;
$first = $second;
// unset( $second ); //

//
$second = new Node;
$second -> str = 'third';
$second -> ref = $first;
$first = $second;
// unset( $second ); //

echo '<br/>output<br/>';

var_dump( $first );

//
echo $first -> str;

$first = $first -> ref;

//
echo $first -> str;

$first = $first -> ref;

//
echo $first -> str;

$first = $first -> ref;

// Notice: Trying to get property of non-object
// echo $first -> str;
// $first = $first -> ref;

//for ( ; $first -> ref ; $first = $first -> ref )

// $first -> ref = NULL;

// var_dump( $first );

-------------

// Реализация обновления поля hr_id
    $('#fio').change( function() {
        $('#hr_id').val('');
    });

-------

example on Java

html. fixed header with scrolling content

Ниже рецептик по созданию таблицы с зафиксированной шапкой с прокручиваемым содержимым.  Причем прокрутка появится только при условии превышения максимальной высоты, в нашем случае - max-height:100px

<div style="border: solid 1px black; width:300px;">
    <div>      
        <table style="width:100%; text-align:center;" border="1" cellspacing="0">
            <thead>
                <tr>
                    <th style="width:100px;">Col#1</th>
                    <th style="width:100px;">Col#2</th>
                    <th>Col#3</th>
                </tr>
            </thead>
        </table>
    </div>
    <div style="max-height:100px; overflow-y:auto;">
        <table border="1" cellspacing="0" style="width:100%; text-align:center;">
            <tbody>  
                    <tr>
                        <td style="width:100px">11</td>
                        <td style="width:100px">12</td>
                        <td>13</td>
                    </tr>
                    <tr>
                        <td style="width:100px">21</td>
                        <td style="width:100px">22</td>
                        <td>23</td>
                    </tr>
                    <tr>
                        <td style="width:100px">31</td>
                        <td style="width:100px">32</td>
                        <td>33</td>
                    </tr>
                    <tr>
                        <td style="width:100px">41</td>
                        <td style="width:100px">42</td>
                        <td>43</td>
                    </tr>
                    <tr>
                        <td style="width:100px">51</td>
                        <td style="width:100px">52</td>
                        <td>53</td>
                    </tr>
                    <tr>
                        <td style="width:100px">61</td>
                        <td style="width:100px">62</td>
                        <td>63</td>
                    </tr>
                    <tr>
                        <td style="width:100px">71</td>
                        <td style="width:100px">72</td>
                        <td>73</td>
                    </tr>
                    <tr>
                        <td style="width:100px">81</td>
                        <td style="width:100px">82</td>
                        <td>83</td>
                    </tr>
            </tbody>  
        </table>
    </div>  
</div>



Небольшой сервис для тестинга регулярных выражений. Regular expression tester (based on javascript)

Регулярные выражения - вещь очень мощная и полезная. Грамотно их составлять - дело не из простых. Решил на tumblr`е организовать небольшой сервис для помощи в этом деле:

http://regexptester.tumblr.com/

Javascript. Loop condition. To be or not to be

Для пробега по массиву мы все пользуемся вот такой формой:

for (i = 0; i < tempArray.length; i++) { // Some code }

Но есть и вот такой способ:

for (i = 0; tempArray[] !== undefined; i++) { // Some code }

Как он Вам? :)

Simple ColorPicker

Ниже представлена несложная реализация ColorPicker`а - цветовая палитра. Может кому и сгодится. Наверно Вы сталкивались с явлением, когда цвета, указанные в html контейнерах (тегах) с помощью десятичных чисел, например - rgb(127,127,127) работает некорректно. Все меняется, когда в дело идет 16-теричный код, например -  #e5e5e5. Но так или иначе, бывают потребности в получении именно десятичного кода цвета.

<html>
    <haed>
        <title>
            ColorPicker
        </title>
        <script type="text/javascript" src="jquery-1.10.1.js"></script>
        <script>
            $(document).ready(function(){
           
                $(".abc").click(function() {
                    alert("class");
                });
           
                $("[name=color_picker]").click(function() {
                   
                    var hexColorValue = $(this).attr("bgcolor");
                    var hexColorArray = Array();
                  
                    // Находим регуляркой пары 16-теричных чисел (цветовой код)
                    if ( ( hexColorArray = hexColorValue.match( /[0-9a-fA-F]{2}/g ) ) !== null) {
                      
                        // Переводим полученные числа в 10-тичную систему счисления
                        for (i = 0; i < hexColorArray.length; i++) {
                            rgbColorArray[i] = parseInt( hexColorArray[i], 16 );                       
                        }

                         // Объединяем элементы массива в строку с разделителем ','
                         var rgbColorValue = rgbColorArray.concat();
                         // Можно и так
                         // var rgbColorValue = rgbColorArray.join(',');
                       
                    }
                  
                    // Все готово
                    alert( 'rgb(' + rgbColorValue + ')' );
                   
                });           
           
            });
        </script>
    </head>
    <body>
        <p class="abc">Color Picker</p>
        <table cellpadding="0" cellspacing="1" border="1">
            <tr>
                <td bgcolor="#ffffff" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#e5e5e5" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#cccccc" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#b2b2b2" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#999999" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#7f7f7f" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#666666" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#4c4c4c" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#333333" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#191919" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#000000" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="" width="15" height="17" ><img src="ColorPickerClose.gif" /></td>
            <tr>
            <tr>
                <td bgcolor="#7f0000" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#7f3f00" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#7f7f00" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#3f7f00" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#007f00" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#007f3f" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#007f7f" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#003f7f" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#00007f" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#3f007f" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#7f007f" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#7f003f" width="15" height="17" name="color_picker" ></td>
            <tr>
            <tr>
                <td bgcolor="#bf0000" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#bf5f00" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#bfbf00" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#5fbf00" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#00bf00" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#00bf5f" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#00bfbf" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#005fbf" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#0000bf" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#5f00bf" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#bf00bf" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#bf005f" width="15" height="17" name="color_picker" ></td>
            <tr>
            <tr>
                <td bgcolor="#ff0000" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#ff7f00" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#ffff00" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#7fff00" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#00ff00" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#00ff7f" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#00ffff" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#007fff" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#0000ff" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#7f00ff" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#ff00ff" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#ff007f" width="15" height="17" name="color_picker" ></td>
            <tr>
            <tr>
                <td bgcolor="#ff5656" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#ffaa56" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#ffff56" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#aaff56" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#56ff56" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#56ffaa" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#56ffff" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#56aaff" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#5656ff" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#aa56ff" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#ff56ff" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#ff56aa" width="15" height="17" name="color_picker" ></td>
            <tr>
            <tr>
                <td bgcolor="#ffaaaa" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#ffd4aa" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#ffffaa" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#d4ffaa" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#aaffaa" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#aaffd4" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#aaffff" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#aad4ff" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#aaaaff" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#d4aaff" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#ffaaff" width="15" height="17" name="color_picker" ></td>
                <td bgcolor="#ffaad4" width="15" height="17" name="color_picker" ></td>
            <tr>
        </table>
    </body>
</html>


ColorPicker