Продолжение предыдущего поста: http://blog.e0ne.info/post/Modal-popup-with-HTML.aspx

Часть 2. Практика

Если есть проблема, то, обязательно, должно быть решение. Так как готового я не нашел (возможно, плохо искал), пришлось изобретать свое.  Решений, на самом деле, нашлось аж целых два, но так как я остановился лишь на одном, то это решение я рассмотрю более подробно и с примером.

Для начала рассмотрю тот вариант, который я не стал реализовывать.

Решение проблемы #1: манипуляции с свойством tabIndex.

Те, кто сталкивался с необходимостью навигацией по сайту с помощью клавиатуры непременно сталкивались с таким свойством элементов, как tabIndex. По умолчанию, для всех элементов <input /> (кроме <input type=”hidden” />) и <option /> tabIndex равен 0. Для других элементов свойство или не определено, или задано значение “-1” (минус еденица) В таком случае переход по элементам осуществляется в порядке их расположения в DOM-моделе. Если необходимо сделать так, чтоб при навигации по странице с помощью кнопки tab фокус на элемент не попадал, то значение tabIndex необходимо сделать -1.

Исходя из вышесказанного, можно сделать такой алгоритм создания модального окна:

  • реализовать диалоговое окно, как описано в предыдущем посте;
  • при вызове функции show() для всех элементов запоминаем текущее состояние tabIndex и ставим новое значение, равное “-1”;
  • в вызове функции hide() восстанавливаем прежние значения tabIndex.

Так как этот способ на практике я не реализовывал, то не могу сказать какие проблемы он может вызвать.

Решение проблемы #2: манипуляции с DOM.

Мой диалог работает следующим образом: базовая часть отображения остается без изменений, все изменения касаются только функций show и hide и некоторыми манипуляциями в DOM-модели.

Работает это следующим образом:

  • все содержимое тега body обрамляем контейнером:
    $(document.body).wrapInner("<div id='body-container' />");
  • делаем метку, где находится наш диалог:
    $("<div id='dlg-marker'/>").insertBefore($("#dlg-content"));
  • перемещаем содержимое диалога в начало тега body:
    $(document.body).prepend($("#dlg-content"));
  • ставим атрибут disabled=”true” для всех элементов, которые не находятся в диалоге:
    $("#body-container").attr('disabled', true);
    // for webkit based browsers
    $("#body-container > input, option").each(function(){
        $(this).attr('disabled', true);
    });
  • показываем диалог.

Соответственно, в методе hide() необходимо все вернуть на своё место:

  • убираем атрибут disabled:
    $('#body-container').removeAttr('disabled');
  • ставим диалог на то место, где он находился изначально; для этого нам и нужна была метка:
    $("#dlg-content").insertAfter($("#dlg-marker"));
  • удаляем ранее созданную метку:
    $("#dlg-marker").detach();
  • удаляем элемент, в который мы поместили содерживое body:
    var html = $('#body-container').html();
    $('#body-container').detach();
    $(document.body).html(html);
  • прячем диалог.

Этот код является слишком неоптимизированным - от него можно избавится, если элемент <div id='body-container' /> будет находится на странице всегда.

Манипуляции с возвращением диалога на прежнее место, прежде всего, необходимы для корректной работы приложений, написанных с помощью ASP.NET. Если этого не сделать, то будут проблемы c UpdatePanel и кнопками, которые находятся вне формы.

В файле advanced-popup-with-input.html я привожу базовую реализацию такого способа. Для использования в production его необходимо немного доработать напильником. А именно:
оформить это всё в виде плагина для jQuery или виджета jQueryUi;
решить проблему с производительностью и обработчиками событий при возвращении элементов в начальное положение относительно DOM-модели.

Сейчас похожая реализация успешно работает в production коде, единственное отличие состоит в том, что элемент <div id='body-container' /> всегда находится на странице и нет необходимости его добавлять и удалять.

Все примеры доступны на GitHub: https://github.com/e0ne/BlogSamples/tree/master/ModalDialog


Сегодня вчера состоялась первая встреча харьковского сообщества разработчиков под названием DevTime. Насколько я знаю, сейчас в Харькове активна лишь UNETA - харьковская .NET User group. В отличии от UNETA, организаторы DevTime планируют не зацикливаться на какой-то конкретной технологии или языке программирования, а делать встречи, посвященные разным технологиям.

Тематика первой встречи - Silverlight. Несмотря на то, что было целых три мини-доклада, докладчик был всего один - Андрей Каща (@anvaka). 

Мини-доклад #1. Введение в Silverlight.

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

Мини-доклад #2. Тестирование Silverlight-приложений.

(Не)большое разочарование для тестировщиков, но много интересного для разработчиков. Основная тема доклада - unit-тесты и как с этим обстоят дела в Silverlight. Андрей не обошел стороной и вопросы интеграции юнит-тестов и Continuous Integration. Доклад был интересным, но коротким, поэтому еще получился микро-доклад #2.5 о средствах для разработки Silverlight-приложений: Visual Studio (кудаже без нее?), Expression Blend и других.

Завершил эту встречу мини-доклад #3 с достаточно громким названием: HTML5 vs Silverlight.

Для разработчиков веб-приложений тема не новая, но актуальная. Беглое сравнение возможностей HTML5 и Silverlight, упоминание стандартов, флеша и цитаты С.Балмера. Просто, лаконично, в большей степени интересно. Не понравились, на мою точку зрения, не совсем правдивые сравнения производительности HTML5 vs Silverlight vs Flash, но это тема отдельного поста и, возможно, встречи разработчиков (хм, а неплохая идея для следующей втреци UNETA или DevTime: круглый стол с 3-мя экспертами по вышеназванным технологиям).

Осталось только еще раз поблагодарить докладчика за доклады и сказать пару слов об организации.

Вика aka Vikkimus (http://dev-time.org/?page_id=2) является организатором многих ИТ-мероприятий в Харькове, поэтому организация мероприятий на должном уровне стала практически стандартом: нормальный зал (в этот раз, в столовой Ciklum'а), проектор, чай, кофе, печеньки. При регистрации всем выдавали такие вот бейджики:

 

Еще организаторы в который раз пытаются устроить так называемый networking zone, но аудитория не понимает главной фичи всего этого. Я сам, к сожалению, не всегда пользуюсь такой возможностью, т.к. вещь достаточно новая на отечественных ИТ-мероприятиях. На этот раз дажы были заготовки для визиток для знакомств, но аудитория еще не готова (и я тоже), но это не значит, что идею надо забрасывать, а, скорее, наоборот - стараться активней проталкивать ее в массы.

Первая встреча DevTime, на мой взгляд, прошла успешно, надеюсь что продолжение будет... to be continued...


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

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

Возможно это было в книге  С. Макконнелла “Совершенный код”, возможно в другой, сейчас книги нет под рукой и я точно не помню, была высказана отличная, на мой взгляд, идея прототипирования. Основная идея создания прототипа - быстро написать какой-то прототип будущего программного продукта для того, чтобы понять что вообще хотят пользователи/заказчики и как всё должно взаимодействовать и работать. При использовании такого подхода в прототипировании необходимо придерживаться следующих правил:

  • время создания прототипа должно быть минимальным;
  • желательно, весь код прототипа выкинуть и не использовать в готовом продукте;
  • для достижения предыдущего пункта прототип можно писать на другом языке программирования (например, вы пишете на C#, а прототип - на Java или Python).

Исходя из вышесказанного принципа, становится понятно,что в таком прототипе просто не может быть “качественного кода”, но такой код/подход всё-равно будет очень полезным. Главное, не забыть избавится от кода прототипа в финальном варианте.

Посмотри теперь что нам предлагает методология XP: постоянный рефакторинг, постоянное написание тестов перед написанием кода (TDD - Test Driven Develepment), быстрое создание архитектуры. При таком на первых стадиях/итерациях проекта невозможно добиться качественного кода. Код будет рабочим (привет TDD), но будет ли он качественным? Не всегда. А постоянный рефакторинг? Это ещё один признак того, что код не идеален. Только не сделайте вывод, что если применять XP - не получится писать качественный код. Просто надо понимать, что это самое качество будет всегда повышаться благодаря рефакторингу и unit-тестам.

Всё вышесказанное больше похоже на теорию. А как у нас обстоят дела на практике?

А практика нам показывает, что писать так хорошо, как нам хочется, не всегда можно. Сразу оговорюсь, я имею в виду написание кода на работе: мы пишем код (делаем свою работа), нам платят за это деньги. Программирование, в большей степени - это бизнес. А как известно в бизнесе: время - деньги. У кого не было ситуации, когда прибегает Project Manager или заказчик и требует что сделать эту фичу / пофиксить этот баг нужно было ещё вчера. В лучшем случае - не вчера, но через два часа всё должно быть готово. И кто в таком случае будет думать об архитектуре и качестве кода? Нужно смотреть правде в глаза: в таких случаях всем ясно, что главное выполнить требование, а качество уходит на задний план. Мы поставим комментария вида “TODO: refactor it after …” и отправим код в репозитарий. А что будет дальше с этим кодом - это уже отдельная история.

Ещё, как пример из практики, хочу привести такой случай: команда получила на аутсорс проект, который до этого разрабатывался другой командой разработчиком. У другой команды могут быть другие критерии качества кода, банально, может быть другой профессиональный уровень. Но вы ведь не будет переписывать все? Такое желание есть, но нет возможности: заказчик не выделяет на это времени, денег, говорит что этот код ещё саппортится его разработчиком и поэтому всё должно быть именно так, как есть. Вот и приходится писать в том же стиле, в котором написан проект или пытаться дописывать новые вещи уже по своим стандартам качественного кода...

Подводя итог скажу следующее:

Я не призываю вас писать некачественный код. Я, всего-лишь, призываю вас смотреть правде в лицо: говонокод пишут все. Некоторые больше, некоторые меньше. Всё дело в том, что бывают ситуации, когда это нужно. Главное, не делать этого всегда.