пятница, 31 июля 2009 г.

Исследование на полиграфе

Троцкий

Недавно проходил тестирование на полиграфе, более известном в широких массах как «детектор лжи». В банке, куда я устраивался, сама процедура тестирования называлась «психофизиологическое исследование» (ПФИ).


Не то, чтобы я стремился устроиться именно на работу в банк. Отнюдь! Но подвернулась такая возможность, и я решил попробовать. А уж когда узнал о «необходимости» проверки на «детекторе лжи», я просто не нашел в себе сил оказаться от подобного эксперимента. Тем более, что для меня это было впервые.


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


Тестирование проводил весьма солидный мужчина весьма солидного возраста. Вежливый и внимательный. Ежу понятно, что опытный психолог; и вообще создавалось впечатление, что «дяденька» отнюдь не так прост. Напрашивались ассоциации с определенными службами определенных ведомств.


Сама процедура проходит следующим образом. Сначала с тобой беседуют, рассказывают как будет проводиться тестирование, как работает полиграф, какие будут задаваться вопросы, что делать в случае если ответ на вопрос неоднозначен. Подписываешь расписку «о добровольном согласии в здравом уме и твердой памяти». Следом тебя просят ответить на примерные вопросы в письменном виде. Гадать не надо: большинство из этих вопросов – ключевые. Это подготовительный этап исследования. Цель его состоит в том, чтобы раскачать твою психику, сделать ее более мобильной.


Дальше идет непосредственно исследование. На тебя цепляют датчики, подключают их к полиграфу и лэптопу, а сам объект исследования усаживают в удобное кресло лицом к ровной однотонной поверхности. Тестирование проходит сериями «работа-отдых». Минут 6 ты "честно" отвечаешь на вопросы, минут 6 отдыхаешь. В моем случае таких серий было три. Некоторые вопросы могут повторяться; как правило это те вопросы, на которые твоя реакция была наиболее яркая. Делается это для повышения точности «попаданий».


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


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


© Эксклюзив от Ruby Brewed. Из серии «проверено на себе».


Читать дальше »

суббота, 25 июля 2009 г.

Комикс темы для iGoogle

Comic Con logo23 июля сего (2009) года в Сан-Диего начался ежегодный конвент Comic-Con, где по традиции представляются новые комиксы, видеоигры, а также теле- и кинопроекты в стиле Sci-Fi, фэнтези, ужасов и аниме.

Это событие проводится с 1970 года и длится 4 дня. В эти дни поклонники комиксов и фильмов со всей страны перевоплощаются в любимых персонажей и знакомятся с новинками поп-культуры.


Google тоже не обошел вниманием это событие
Google Comic Con


..и представил собственную подборку комикс-тем для iGoogle.
Комикс темы для iGoogle


Желающие могут оживить свою домашнюю страничку iGoogle персонажами из популярных комиксов.



Читать дальше »

понедельник, 20 июля 2009 г.

Google - Источник открытий

Узнайте, что вы сможете сделать с помощью Google прямо сейчас!


Google - Источник открытий

С Google в Интернете можно делать гораздо больше, чем просто искать: учить новые языки и путешествовать по неизведанным уголкам земли, не покидая своего кресла, решать задачи из высшей математики, поражать друзей нескончаемой эрудицией и быть в курсе последних новостей, находясь в чистом поле!


Совершайте свои открытия!


Читать дальше »

воскресенье, 19 июля 2009 г.

Rails Plugin подсветки синтаксиса

Rails Plugin для «клиентской» подсветки синтаксиса.


Установка


script/plugin install git://github.com/antono/sh2.git
rake -T sh2
rake sh2:install

Helpers


Подключение скриптов и стилей для плагина.

include_syntax_highlighter_assets(:themes => :midnight, :brushes => :all)

Поместить в layout, в тег head


Следующий хелпер запускает подсветку синтаксиса для полностью загруженной страницы.

sh2_highlight_code

Должен размещаться в конце страницы.


Пример использования


<pre class="brush:ruby">
1000.times { puts 'Руби Руби Руби Руби' }
</pre>

Ссылка: Client-side Syntax Highlighter для Rails
Читать дальше »

понедельник, 13 июля 2009 г.

Cкрытый текст в сообщениях блога

Или «как в блоге прятать текст под спойлеры». Недавно написал небольшой javascript-компонент Widget SpoilerManager для использования скрытого текста в блоге. Собственно, это та «культурная программа», которой я посвятил прошлую субботу. Да, я псих.


UPD: Последний раз я доверил свои файлы богом проклятому сервису HotLinkFiles! Пусть горит в аду! Позже выложу в текстовом виде.


Пример:


Спойлер (от англ. spoil — портить) — в кино, компьютерных играх, литературе — преждевременно раскрытая важная информация, которая портит впечатление от игры/книги/фильма и разрушает их интригу, а также лишает читателя некоторой части удовольствия от сюжета.
цитата из Википедии: Спойлер (кино)


Как использовать


  1. Создай стили CSS для компонента:
    /* Стили для спойлера */
    .bar {
    background:#B2BDCB url('http://lh5.ggpht.com/_3_wwcvitlLc/SlqyHLMerfI/AAAAAAAABKk/T3rgvkvrTZY/spoiler.png') no-repeat;
    padding-left: 30px;
    color: #1A3457;
    height:26px;
    font-weight:bold;
    cursor:pointer;
    }
    /* Скрытый спойлер */
    .spoiler-hidden .bar {
    background-position: 0 0;
    }
    .spoiler, .spoiler-hidden .text {
    display: none;
    }
    /* Открытый спойлер */
    .spoiler-visible .bar {
    background-position: 0 -26px;
    }
    .spoiler-visible .copy {
    text-align:right; font-size:0.6em;
    }
    .spoiler-visible .text {
    display:visible;
    padding: 0 1em;
    border: 1px dashed #B2BDCB;
    border-top-width:0;
    }

  2. Включи код спойлера сразу перед закрывающим тегом </body> (см. апдейт)
    <script src='http://www.hotlinkfiles.com/files/2667809_ezrak/widget_spoiler.js' type='text/javascript'></script>
    <script type='text/javascript'>
    /* Для предотвращения проблем с кириллицей, задай надпись по умолчанию */
    WidgetSpoilerManager.setOption ("defaultTitleText", "Скрытый текст");
    /* Запусти виджет Спойлер-Менеджера */
    WidgetSpoilerManager.init();
    </script>

    UPD 19.07.2009
    Скрипт залит на файлохранилище №1.
    Подключать файл (первая строка предыдущего листинга) можно так:
    <script src='http://sites.google.com/site/railsdepot/files/widget_spoiler.js' type='text/javascript'></script>

    UPD 27.08.2009
    Полный код для второго пункта:
    <script src='http://sites.google.com/site/railsdepot/files/widget_spoiler.js' type='text/javascript'></script>
    <script type='text/javascript'>
    WidgetSpoilerManager.setOption ("defaultTitleText", "Скрытый текст");
    WidgetSpoilerManager.init();
    </script>

  3. Сохрани шаблон.

  4. В сообщениях используй следующий код:
    <div class="spoiler" title="здесь задай краткое описание">
    А здесь текст, который хочешь сделать скрытым
    </div>

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


© dotrb.blogspot.com


Читать дальше »

воскресенье, 12 июля 2009 г.

CSS колонки одинаковой высоты

Недавно мне задали вопрос, как бы я сделал в макете колонки одинаковой высоты. Предложил использовать способ с нижними «паддингами» и «маргинами». Или, русским языком – «полями» и «отступами».


CSS колонки одинаковой высоты

Код HTML:

<div class="cols">
<div class="col1">Налево пойдешь – коня потеряешь</div>
<div class="col2">Прямо пойдешь – лбом упрешься</div>
<div class="col3">Направо пойдешь – лучше не ходи..</div>
</div>


Стили CSS:

.cols{
overflow:hidden;
width:100%;/* Задать свойство hasLayout для IE6;
Можно использовать _zoom:1 (невалидное свойство) */
}
.cols .col1,.cols .col2,.cols .col3{
padding-bottom:10000px;
margin-bottom:-10000px;
}


UPD 2009.08.07
Стили CSS для отображения в виде колонок с разным цветом фона:

.cols .col1{width:25%; float:left; background:#999999;}
.cols .col2{width:50%; float:left; background:#E0E9EF;}
.cols .col3{width:25%; float:left; background:#5588AA;}


Пример реализации с Хабрахабра.
Читать дальше »

суббота, 11 июля 2009 г.

Новое в гад-же-то-Blogger-строении

Важная новость от Blogger Buzz! Команда Blogger запустила несколько расширений для Gadget API, которые позволят разработчикам ваять более релевантные, симпатичные и улыбчивые гаджеты для Blogger.


Каждый блог на данной платформе это контейнер гаджетов. Более того, благодаря Friend Connect, это еще и OpenSocial гаджет-контейнер. Это означает, что как разработчик ты можешь использовать social APIs для создания более удобных инструментов для блоггеров и их аудитории.


В добавок к использованию социальных инструментов, гаджеты теперь могут получать доступ к фидам (feeds) сообщений и комментариев блога через новые JSON APIs. Например, используя эти данные, ты можешь создать гаджет карты, на которой будешь отмечать географию сообщений, или гаджет популярных сообщений.


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


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

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


Читать дальше »

пятница, 10 июля 2009 г.

Объектно-ориентированное программирование

В продолжение программы по обновлению и дополнению «теоретического багажа» в данном посте разбираю парадигму ООП. Эта статья в первую очередь, – шпаргалка для себя. Поэтому постараюсь избежать излишней детализации. Дополнительные детали, на мой взгляд, «жизненно необходимы» лысеющим теоретикам, да судорожно содрогающимся студентам на экзаменах. ..Сдаваемых лысеющим теоретикам.


Объектно-ориентированное программирование (ООП) — парадигма программирования, в которой основными концепциями являются понятия объектов и классов.


Класс — это тип, описывающий устройство объектов. Понятие «класс» подразумевает некоторое поведение и способ представления. Понятие «объект» подразумевает нечто, что обладает определённым поведением и способом представления. Говорят, что объект — это экземпляр класса. Класс можно сравнить с чертежом, согласно которому создаются объекты. Обычно классы разрабатывают таким образом, чтобы их объекты соответствовали объектам предметной области.


Класс является моделью ещё не существующей сущности, объекта.


Объект — сущность, появляющаяся при создании экземпляра класса.


Основные понятия


Абстракция данных
Объекты представляют собою упрощенное, идеализированное описание реальных сущностей предметной области. Если соответствующие модели адекватны решаемой задаче, то работать с ними оказывается намного удобнее, чем с низкоуровневым описанием всех возможных свойств и реакций объекта.

Инкапсуляция
Инкапсуляция — это принцип, согласно которому любой класс должен рассматриваться как «чёрный ящик» — пользователь класса должен видеть и использовать только интерфейсную часть класса (т. е. список декларируемых свойств и методов класса) и не вникать в его внутреннюю реализацию. Поэтому данные принято инкапсулировать в классе таким образом, чтобы доступ к ним по чтению или записи осуществлялся не напрямую, а с помощью методов. Принцип инкапсуляции (теоретически) позволяет минимизировать число связей между классами и, соответственно, упростить независимую реализацию и модификацию классов.

Сокрытие данных
Сокрытие данных — неотделимая часть ООП, управляющая областями видимости. Является логическим продолжением инкапсуляции. Целью сокрытия является невозможность для пользователя узнать или испортить внутреннее состояние объекта.

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

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


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

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

Определение ООП


Объектно-ориентированный подход заключается в следующем наборе основных принципов:

  1. Всё является объектом.
  2. Вычисления осуществляются путём взаимодействия (обмена данными) между объектами, при котором один объект требует, чтобы другой объект выполнил некоторое действие. Объекты взаимодействуют, посылая и получая сообщения. Сообщение — это запрос на выполнение действия, дополненный набором аргументов, которые могут понадобиться при выполнении действия.
  3. Каждый объект имеет независимую память, которая состоит из других объектов.
  4. Каждый объект является представителем (экземпляром) класса, который выражает общие свойства объектов.
  5. В классе задаётся поведение (функциональность) объекта. Тем самым все объекты, которые являются экземплярами одного класса, могут выполнять одни и те же действия.
  6. Классы организованы в единую древовидную структуру с общим корнем, называемую иерархией наследования. Память и поведение, связанное с экземплярами определённого класса, автоматически доступны любому классу, расположенному ниже в иерархическом дереве.


Особенности реализации


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

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

Методы
Процедуры и функции, связанные с классом. Они определяют действия, которые можно выполнять над объектом такого типа, и которые сам объект может выполнять.


Взаимодействие объектов в абсолютном большинстве случаев обеспечивается вызовом ими методов друг друга.


Инкапсуляция обеспечивается следующими средствами:

Контроль доступа 
Поскольку методы класса могут быть как чисто внутренними, обеспечивающими логику функционирования объекта, так и внешними, с помощью которых взаимодействуют объекты, необходимо обеспечить скрытость первых при доступности извне вторых. Для этого в языки вводятся специальные синтаксические конструкции, явно задающие область видимости каждого члена класса. Традиционно это модификаторы:
  • public – открытые члены класса;
  • protected – члены класса, доступные только из классов-потомков;
  • private – скрытые, доступные только внутри класса.

Конкретная номенклатура модификаторов и их точный смысл различаются в разных языках.

Методы доступа 
Поля класса, в общем случае, не должны быть доступны извне, поскольку такой доступ позволил бы произвольным образом менять внутреннее состояние объектов. Поэтому поля обычно объявляются скрытыми (либо язык в принципе не позволяет обращаться к полям класса извне), а для доступа к находящимся в полях данным используются специальные методы, называемые методами доступа. Такие методы либо возвращают значение того или иного поля, либо производят запись в это поле нового значения. При записи метод доступа может проконтролировать допустимость записываемого значения и, при необходимости, произвести другие манипуляции с данными объекта, чтобы они остались корректными (внутренне согласованными). Методы доступа называют ещё аксессорами (от англ. access — доступ), а по отдельности — геттерами (англ. get — чтение) и сеттерами (англ. set — запись).

Свойства объекта
Псевдополя, доступные для чтения и/или записи. Свойства внешне выглядят как поля и используются аналогично доступным полям (с некоторыми исключениями), однако фактически при обращении к ним происходит вызов методов доступа. Таким образом, свойства можно рассматривать как «умные» поля данных, сопровождающие доступ к внутренним данным объекта какими-либо дополнительными действиями (например, когда изменение координаты объекта сопровождается его перерисовкой на новом месте). Свойства никаких новых возможностей не добавляют, а лишь скрывают вызов методов доступа. Конкретная языковая реализация свойств может быть разной.


Почитать по теме:


Читать дальше »

Программирование на языке Ruby

В дополнение к уже имеющемуся, планирую приобрести, или получить в подарок ;) такую книгу. Пока в «вишлисте».


Программирование на языке Ruby

Программирование на языке Ruby


“The Ruby Way”
Хэл Фултон
Ruby - относительно новый объектно-ориентированный язык, разработанный Юкихиро Мацумото в 1995 году и позаимствовавший некоторые особенности у языков LISP, Smalltalk, Perl, CLU и других. Язык активно развивается и применяется в самых разных областях: от системного администрирования до разработки сложных динамических сайтов. Книга является полноценным руководством по Ruby - ее можно использовать и как учебник, и как справочник, и как сборник ответов на вопросы типа "как сделать то или иное в Ruby". В ней приведено свыше 400 примеров, разбитых по различным аспектам программирования, и к которым автор дает обстоятельные комментарии.

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

В руках уже держал, но приобрести на тот момент еще не решился. И подарить же, блин, не подарили.


Читать дальше »

среда, 8 июля 2009 г.

DHTML Tab Connection Panel

Результат выполнения еще одного «тестового задания». ..И в который раз затрудняюсь с выбором кавычек. Выкладываю коды здесь, вдруг да когда пригодится. Использовался фреймворк Prototype. Сам текст задания, возможно, выложу позже.


Скриншот



Известные проблемы и ограничения в рамках тестового задания


  • при добавления большого количества вкладок отсутствуют боковые границы рядов;
  • на странице main.html не отслеживается обновление (через F5) страницы child.html
  • в IE 6 было замечено вертикальное смещение правой границы динамически созданных вкладок;
  • на странице child.html не отслеживается наличие открывающего документа document.opener (main.html);
  • скрипт бесполезно проверять инструментами вроде IETester. Как правило, эти инструменты не отслеживают document.opener;
  • отключена возможность удаления активной вкладки с помощью CSS, отсутствует контроль этого процесса средствами javascript.

Изображения




Изображения получены из открытых источников


main.html


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html dir='ltr' xmlns='http://www.w3.org/1999/xhtml'>
<head>
<title>Main Window</title>
<link type='text/css' rel='stylesheet' href='public/stylesheets/general.css' />
<script type="text/javascript" src="public/javascripts/prototype.js"></script>
<script type="text/javascript" src="public/javascripts/main.js"></script>
</head>
<body>
<p><input id="btnOpen" type="button" value="Изменить..." onclick="return btnOpen_onclick();" /></p>
<div id="connections"></div>
</body>
</html>


child.html


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>DHTML Tab Connection Panel</title>
<script type="text/javascript" src="public/javascripts/prototype.js"></script>
<link type='text/css' rel='stylesheet' href='public/stylesheets/general.css' />
<script type="text/javascript" src="public/javascripts/child.js"></script>
</head>
<body>
<p id="navBar">
<input id="btnAdd" type="button" tabindex="1" value="Добавить" onclick="tabView.addControl(); return false;" />
<a id="aTabPrev" href="#" tabindex="2" onclick="tabView.tabPrev(); return false;">←</a>
<kbd>Ctrl</kbd>
<a id="aTabNext" href="#" tabindex="3" onclick="tabView.tabNext(); return false;">→</a>
</p>

<div id="tabView1" class="tabView">
<div id="tabPanel" class="tabPane">
<div id="tabViewTab_0" class="tabActive" style="left: 0px;" onclick="tabView.tabSelect(0); return false;">
<div class="icon"></div>
<span tabindex="4"><span id="tabText_0" class="tabText">Guest</span>
<a href="#" onclick="tabView.destroy(0); return false;"><img class="close" width="8" height="8" src="public/images/icon_delete.gif" /></a>
</span>
<img class="tab_right" src="public/images/tab_right.gif" />
</div>
</div>
<div class="clear"></div>

<div id="aFormCont" class="aTab">
<form id="aForm" action="">
<input id="index" type="hidden" />
<div>Логин</div>
<div><input id="login" type="text" onchange="tabView.onChange();" /></div>
<div>Пароль</div>
<div><input id="password" type="password" onchange="tabView.onChange();" /></div>
<div><input id="remember_login" type="checkbox" onchange="tabView.onChange();" /><label for="remember_login">Запомнить логин</label></div>
<div><input id="remember_password" type="checkbox" onchange="tabView.onChange();" /><label for="remember_password">Запомнить пароль</label></div>
<div><input id="auto_login" type="checkbox" onchange="tabView.onChange();" /><label for="auto_login">Входить автоматически</label></div>
<p style="text-align:right;">
<input id="button_submit" type="button" value="Подключить" onclick="tabView.onChangeStatus();" />
</p>
</form>
</div>
</div>
</body>
</html>

general.css


/* General */
body{
margin:10px;
font-size:0.9em;
}

/* Main */
#connections p {
border:1px solid #919B9C;
padding: 0 0.2em;
width: 500px;
font-family: Trebuchet MS, Lucida Sans Unicode, Arial, sans-serif;
}

/* Child */
a{
color:#F00;
}
.tabView {
width:500px;
height:400px;
}
.tabPane{
height:21px; /* Height of tabs */
border-bottom:1px solid #919b9c;
}
.aTab{
border-left:1px solid #919b9c;
border-right:1px solid #919b9c;
border-bottom:1px solid #919b9c;
font-family: Trebuchet MS, Lucida Sans Unicode, Arial, sans-serif;
padding:5px;

}
.tabPane div{
float:left;
height:100%; /* Height of tabs */
padding-left:3px;
vertical-align:middle;
background-repeat:no-repeat;
background-position:bottom left;
cursor:pointer;
position:relative;
bottom:-1px;
margin-left:0px;
margin-right:0px;
}
.tabPane .tabActive{
background-image:url('../images/tab_left_active.gif');
margin-left:0px;
margin-right:0px;
z-index:10;
}
.tabPane .tabInactive{
background-image:url('../images/tab_left_inactive.gif');
margin-left:0px;
margin-right:0px;
z-index:10;
}
.tabPane .inactiveTabOver{
background-image:url('../images/tab_left_over.gif');
margin-left:0px;
margin-right:0px;
}
.tabPane span{
font-family:arial;
vertical-align:top;
font-size:11px;
padding-left:3px;
padding-right:3px;
line-height:21px;
float:left;
}
.tabPane .tabActive span{
padding-bottom:1px;
line-height:20px;
position: relative;
padding-left: 4px;
padding-right: 12px;
}
.tabPane .tabInactive span{
padding-bottom:1px;
line-height:20px;
position: relative;
padding-left: 3px;
padding-right:10px;
}
.tabPane img{
float:left;
}
.tabPane .tabActive img.tab_right {
background-image:url(../images/tab_right_active.gif);
}
.tabPane .tabInactive img.tab_right {
background-image:url(../images/tab_right_inactive.gif);
}
.tabActive a {
display:none;
}
.icon {
background-image:url(../images/globe_icon.gif);
background-repeat:no-repeat;
background-position:bottom left;
width:15px;
}
img.close {
position: absolute;
top: 6px;
right: 0;
border:0;
}
a img.close {
opacity:.01;
filter: alpha(opacity=1); /* IE */
-moz-opacity: 0.01; /* Firefox */
}
a:hover img.close {
opacity:1;
filter: alpha(opacity=100); /* IE */
-moz-opacity: 1; /* Firefox */
}
.tabText{
min-width:30px;
display:inline-block;
}
.clear {
clear: both;
}

/* Navigation Bar */
#navBar {
width:500px;
text-align:right;
}
#navBar input {
float:left;
}
#navBar a {
text-decoration:none;
}
#navBar kbd {
font-size:larger;
}

/* Form elements */
input[type="text"], input[type="password"] {border:1px solid #919b9c;}
/* for IE */
input { border:expression((this.type=='text')||(this.type=='password') ? '1px solid #919b9c' : ''); }

main.js


// <!CDATA[
var pPrefix = "connection_";
var prefixLogin = "login_";

document.addConnection = addConnection;
document.updateConnection = updateConnection;
document.destroyConnection = destroyConnection;
document.updateConnectionStatus = updateConnectionStatus;

/* Open Child document */
function btnOpen_onclick(){
open("child.html", "Child");
}

/* Helpers */
bool2human = function(value){
return (value == true) ? "да" : "нет";
}

humanStatus = function(value){
return (value == true) ? "Подключен" : "Отключен";
}

/* Dynamic template for #connections P.innerHTML */
getTemplate = function(attr){
return 'Логин: <span class="login">'+ attr.login +'</span><br />'+
'Пароль: <span class="password">'+ attr.password +'</span><br />'+
'Запомнить: логин (<span class="remember_login">'+ bool2human(attr.remember_login) +'</span>),'+
' пароль (<span class="remember_password">'+ bool2human(attr.remember_password) +'</span>)<br />'+
'Входить автоматически (<span class="auto_login">'+ bool2human(attr.auto_login) +'</span>)<br />'+
'<span class="status">'+ humanStatus(attr.status) +'</span>';
}

/* functions called by Child document */
function addConnection(attr){
try {
var p1 = document.createElement("p");
p1.id = pPrefix + attr.index;
var template = getTemplate(attr);
p1.innerHTML = template;
$("connections").appendChild(p1);
}
catch (e) {
alert(e.description);
}
}

function updateConnection(attr){
try {
var p1 = $(pPrefix + attr.index);
var template = getTemplate(attr);
p1.innerHTML = template;
}
catch (e) {
alert(e.description);
}
}

function destroyConnection(index){
var p1 = $(pPrefix + index);
Element.remove(p1);
}

function updateConnectionStatus(index, status){
var cssExpr = $$("#"+ pPrefix + index +" .status");
cssExpr[0].innerHTML = humanStatus(status);
}
// ]]>

child.js


document.onkeydown = navigateTabs;

function navigateTabs (event){
if (window.event) event = window.event;
if (event.ctrlKey){
switch (event.keyCode ? event.keyCode : event.which ? event.which : null){
case 0x25:
tabView.tabPrev();
break;
case 0x27:
tabView.tabNext();
break;
}
}
}

/* Class: Tab View */
TabView = function(){
this.tabPrefix = "tabViewTab_";
this.tabTextPrefix = "tabText_";
this.tabPanelId = "tabPanel";
this.items = new Array();
this.cnActive = "tabActive";
this.cnInactive = "tabInactive";
this.patternTabActive = "#tabView1 ." + this.cnActive;
this.tabIndexShift = 4; //сдвиг tabindex

this.init = function(){
this.add("Guest", "guest", true, true, false, false);
}

this.destroy = function(index){
if ( $(this.tabPrefix + index) != undefined ){
this.items[index] = null;
this.destroyConnection(index);
Element.remove(this.tabPrefix + index);
}
}

this.add = function(login, password, remember_login, remember_password, auto_login, status){
var index = this.items.length;
var Item = new Object();
Item.index = index;
Item.login = login;
Item.password = password;
Item.remember_login = remember_login;
Item.remember_password = remember_password;
Item.auto_login = auto_login;
Item.status = status;
this.items.push(Item);
this.addConnection(Item);
}

/* Functions for Document.Opener */
this.addConnection = function(obj){
opener.document.addConnection(obj);
}
this.updateConnection = function(obj){
opener.document.updateConnection(obj);
}
this.destroyConnection = function(index){
opener.document.destroyConnection(index);
}
this.updateConnectionStatus = function(index, status){
opener.document.updateConnectionStatus(index, status);
}

/* Helpers */
this.humanStatus = function(value){
return (value == true) ? "Отключить" : "Подключить";
}

this.checkbox2bool = function(value){
return (value == null) ? false : true;
}

/* DOM Functions */
this.addControl = function(){
this.add("", "", false, false, false, false);

var index = this.items.length-1;
var p1 = document.createElement("p");
var div1 = document.createElement("div");
div1.id = this.tabPrefix + index;
div1.className = this.cnInactive;//;
div1.onclick = function(){ tabView.tabSelect(index); return false; };

var div2 = document.createElement("div");
div2.className = "icon";
div1.appendChild(div2);

var span1 = document.createElement("span");
span1.setAttribute("tabindex", index*1 + this.tabIndexShift);

var span2 = document.createElement("span");
span2.id = this.tabTextPrefix + index;
span2.className = "tabText";
span1.appendChild(span2);

var a1 = document.createElement("a");
a1.href = "#";
a1.onclick = function(){ tabView.destroy(index); return false; };

var img1 = document.createElement("img");
img1.className = "close";
img1.setAttribute("width", 8);
img1.setAttribute("height", 8);
img1.setAttribute("src", "public/images/icon_delete.gif");
a1.appendChild(img1);
span1.appendChild(a1);

var img2 = document.createElement("img");
img2.className = "tab_right";
img2.setAttribute("src", "public/images/tab_right.gif");

div1.appendChild(span1);
div1.appendChild(img2);
$(this.tabPanelId).appendChild(div1);
}

this.fillForm = function(obj){
$("index").value = obj.index;
$("login").value = obj.login;
$("password").value = obj.password;
$("remember_login").checked = obj.remember_login;
$("remember_password").checked = obj.remember_password;
$("auto_login").checked = obj.auto_login;
$("button_submit").value = this.humanStatus(obj.status);
}

this.tabSelect = function(index){
//scope for each() function
cnActive = this.cnActive;
cnInactive = this.cnInactive;
if ( $(this.tabPrefix + index) != undefined ){
//off
$$(this.patternTabActive).each( function(elem){
Element.removeClassName(elem, cnActive);
Element.addClassName(elem, cnInactive);
});
//on
Element.removeClassName(this.tabPrefix + index, this.cnInactive);
Element.addClassName(this.tabPrefix + index, this.cnActive);
this.fillForm(this.items[index]);
return true;
}
return false;
}

/* onModyfy functions */
this.onChange = function(){
var index = $F("index");

var Item = this.items[index];
Item.index = index;
Item.login = $F("login");
Item.password = $F("password");
Item.remember_login = this.checkbox2bool( $F("remember_login") );
Item.remember_password = this.checkbox2bool( $F("remember_password") );
Item.auto_login = this.checkbox2bool( $F("auto_login") );

$(this.tabTextPrefix + index).innerHTML = Item.login;

this.updateConnection(Item);
}

this.onChangeStatus = function(){
var index = $F("index");
var Item = this.items[index];
Item.status = (Item.status == true) ? false : true;
this.updateConnectionStatus(Item.index, Item.status);
$("button_submit").value = this.humanStatus(Item.status);
}

/* Navigation through Tabs */
this.tabPrev = function(){
var index = $F("index");
for (var i = index*1-1; i >= this.items.first().index; i--){
if (this.tabSelect(i)){
break;
}
}
}

this.tabNext = function(){
var index = $F("index");
for (var i = index*1+1; i <= this.items.last().index; i++){
if (this.tabSelect(i)){
break;
}
}
}

this.init();
}
// End: Class TabView

// Init tabView
tabView = new TabView();
Event.observe(window, "load", function() {
tabView.fillForm(tabView.items[0]);
});

Вот как-то так :).


Creative Commons License
DHTML Tab Connection Panel by JCDen (aka Croaker) is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License.
Читать дальше »

пятница, 3 июля 2009 г.

We were born in this hole...

И действительно, «нафига попу гармонь»? Делюсь ссылкой на статью, которая не так давно широко меня улыбнула.


Десять лет назад (кто-то подсказывает: «почти двадцать») на голову фирмам разной масти и толка свалился Интернет. Осмелюсь предположить, что для большей части из них он стал скорее обузой, чем благом. С одной стороны: «у всех уже есть чёртов сайт, что мы хуже, что ли?», с другой: «да нафиг оно надо? We were, так сказать, born in this hole. And we will die in this hole». В конце концов всё как-то устаканилось. У всех появились ужасные сайты-визитки, с ужасными улыбками на лицах гендиректоров, и «новостями» за позапрошлый год. Через некоторое время, когда очки, нанизанные на… скажем, хвост, не помогали, разумный директор средней руки по-своему торжествовал, отечески похлопывая по плечу унылого премиум-айтишника. «Я же говорил, что дурная затея? А ты — «большие возмо-ожности, много новых клие-ентов». Мой клиент — такой же старый бобёр как я (надевая шапку из сородича и кряхтя). Открыл газету, ткнул пальцем, цена низкая? вот и славно, вот и позвонил. Хорошо хоть недорого обошлось...»

Дальше шире: Вашей фирме (не)нужна социальность.


Читать дальше »