Метод «автомобиль клоуна»: применение адаптивных изображений в веб-дизайне.

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

В нашем распоряжении находятся изображения для переднего плана и фоновые изображения. У нас есть большие и маленькие дисплеи. Мы используем стандартные дисплеи и дисплеи с высоким разрешением. У нас есть соединения с высокой и низкой пропускной способностью. Мы можем использовать портретную и пейзажную ориентации.

Читать далее

Создание нового веб-приложения Файнэншл Таймс: тематическое исследование.

promo-500-compr

Когда в середине 2012 года появился экспериментальный макет нового приложения Файнэншл Таймс, мы поняли, что перед нами возникла реальная проблема. Многие члены нашей команды (включая меня) клялись, что некоторые части интерфейса невозможно было реализовать с помощью HTML5. Учитывая страсть команды к новым пользовательским интерфейсам, мы, засучив рукава, принялись за работу.

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

Читать далее

Создавать CSS шаблоны с помощью flexbox проще, чем испечь пирог.

figure1.1_mini

Эта статья представляет собой откорректированные выдержки из главы «Изменение стиля, перекодировка, изменение оформления с помощью CSS3» нашей книги Smashing Book #3, написанной Леа Веру и Дэвидом Стори. — Ред.

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

Читать далее

Адаптивный плагин лайтбокс Magnific Popup (для jQuery и Zepto.js).

Progressive image loading

Лайтбокс является одним из тех инструментальных средств, которые отлично работают на персональных компьютерах, но с которыми часто возникают проблемы при работе на небольших мобильных устройствах. На сегодняшний день довольно трудно найти плагин, обладающий достаточным уровнем гибкости и способный моментально отображать содержимое. По этой причине я создал Magnific Popup (всплывающее окно), лайтбокс плагин с открытым исходным кодом, ориентированный на производительность.

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

Читать далее

Слава Богу, у нас есть спецификация!

В этой статье описаны основные особенности и приведено множество полезных примеров работы с CSS3 анимацией. Если вы решили использовать данный эффект у себя в проекте, то стоит ознакомиться с представленной информацией. Пожалуйста, обратите внимание, что я не предлагаю никаких альтернативных вариантов и не даю советов о том, как обойтись без обсуждаемых эффектов. Алекс МакКоу когда-то написал очень проницательную и информативную статья под названием “Все, что нужно знать о CSS анимации“.

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

Читать далее

Введение в программирование системы типов.

Jelly bean

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

Язык программирования Си ведет обработку любых элементов как чисел. Любые символы, например, такие как a или 7 или % могут быть представлены в виде числа благодаря ASCII кодировке, представляющей их “истинное” и “ложное” значение в виде комбинации всего из двух цифр: 1 и 0.

Читать далее

Как извлечь пользу из CSS генерации контента и счетчиков.

Одной из первых функциональных возможностей CSS2 стала возможность генерации контента. В течение последних нескольких лет, эта функция была использована относительно небольшим числом веб-авторов, в основном из-за несовместимости поддержки браузерами. С выходом Internet Explorer 8 в 2009 году, возможность генерации контента вновь стала популярной и тут же появилось множество интересных реализаций. В этой статье мы обсудим некоторые возможные применения генератора контента.

Что такое генерация контента?

С технической точки зрения, генерация контента — это простая абстракция, созданная с помощью CSS в дереве документов. Таким образом, с практической точки зрения, сгенерированный контент существует только в формате веб-документа.

Читать далее

Адаптивная система Nav: простой JavaScript плагин для навигации.

Official site of Responsive Nav plugin.

Существует несколько способов создания адаптивной навигации и мы воспользуемся самым простым решением.
Читать далее

Подробный обзор Backbone.Marionette (Часть 2).

В первой части этой серии статей мы обсуждали приложение Backbone.Marionette. В этот раз мы рассмотрим модульную систему, встроенную в Backbone.Marionette. Попасть к списку модулей вы можете через пункт Application (приложение). Модули сами по себе – это довольно информативная тема, которая заслуживает подробного рассмотрения в отдельной статье.

Что такое модули?

Прежде чем мы углубимся в основные детали использования модульной системы Marionette, необходимо четко определиться со значением термина модуль. Модуль – это независимый фрагмент кода, который выполняет определенную функцию. Конкретно взятый модуль можно использовать совместно с другими модулями для создания целостной системы. Чем более независимым является фрагмент кода, тем легче его можно будет заменить или провести внутреннюю модификацию, не затрагивая другие части системы.

В этой статье мы в основном будем рассматривать идентификацию модулей. Если же вы хотите больше узнать о том, как правильно создавать модульный код, то можно воспользоваться множеством источников из интернета. Я хотел бы порекомендовать к ознакомлению главу «Удобство обслуживания зависит от модульности» из книги Подробно об одностраничных приложениях, которая к слову считается одной из лучших в своей области.

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

Инициализация модуля.

Давайте начнем с основных пунктов инициализации модуля. Как уже упоминалось, перейти к списку модулей можно через раздел Application. Все действия мы будем подкреплять примерами. Затем мы сможем использовать команду module для инициализации модуля.

var App = new Backbone.Marionette.Application();
var myModule = App.module(‘myModule’);

Это довольно просто, правда? Так и есть, но это всего лишь пример создания простейшего модуля. А что конкретно мы создали? По сути, мы сказали приложению, что хотим создать шаблон модуля, без добавленного нами функционала, и что он будет называться myModule (в соответствии с аргументом, который мы передали в module). Но что такое шаблон модуля? Это экземпляр объекта Marionette.Module.

Module содержит встроенные функциональные возможности, такие как обработка событий (через EventAggregator, которые мы подробно обсудим в следующей статье), начиная с инициализаторов (как у Application) и заканчивая финализаторами (мы рассмотрим их в разделе «Запуск и отключение модулей»).

Стандартная инициализация модуля.

Теперь давайте рассмотрим пример инициализации модуля для заданных нами функциональных требований.

App.module("myModule", function(myModule, App, Backbone, Marionette, $, _){

    // Private Data And Functions
    var privateData = "this is private data";
    var privateFunction = function(){
        console.log(privateData);}
    // Public Data And Functions
    myModule.someData = "public data";
    myModule.someFunction = function(){
        privateFunction();
        console.log(myModule.someData);}
});

Как вы видите, здесь представлено много команд. Давайте посмотрим на первую строку и разберем последовательность действий. Как и раньше, мы вызываем App.module и присваиваем имя модулю. Но теперь мы также передаем значение функции. Функция содержит несколько аргументов. Готов поспорить, вы можете определить какие именно, просто взглянув на имена, которые я им задал, но я все равно объясню:

  • myModule является тем самым модулем, который вы пытаетесь создать. Помните, что он уже создан для вас, и это новый экземпляр объекта Module. Возможно, что вы захотите расширить его при помощи каких-то новых свойств или методов; в противном случае можно просто придерживаться краткого синтаксиса, который не требует передачи в функцию.
  • App — это Application объект, который вызывается функцией module.
  • Backbone — это, естественно, ссылка на Backbone библиотеку.
  • Marionette — это ссылка на Backbone.Marionette библиотеку. На самом деле к ней можно попасть через Backbone, но вы также можете создать псевдоним и сделать имя короче.
  • $-это ваша DOM библиотека, которая будет либо JQuery либо Zepto (или, возможно, что-то еще в будущем).
  • _ — это ссылка на Underscore или Lodash, в зависимости от того, что вы используете.

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

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

  • Когда появляется необходимость сократить имена аргументов, для экономии байтов памяти.
  • Если вы используете RequireJS или другой модуль загрузки, вам нужно только, создать зависимость объекта от функции Application. Все остальное будет доступно благодаря аргументам, вызываемым функцией Module.

Как бы там ни было, но давайте вернемся к объяснению остальных действий, выполняемых кодом выше. Внутри функции, вы можете использовать символы закрытия и создавать частные переменные и функции, что мы, собственно говоря, и сделали. Вы также можете представлять данные и функции открыто, добавляя их в качестве свойств myModule. Это и есть процедура создания и расширения нашего модуля. Нет необходимости что-либо возвращать, потому что модуль будет доступен непосредственно через команду App, обо всем этом я расскажу в теме “доступ к модулю” в разделе ниже.

Примечание: убедитесь, что вы всего лишь добавляете свойство к module переменной и не устанавливаете ее значение равным чему-нибудь (например, myModule = {…}). В случае, если вы все же присвоили какое-то значение module переменной, то поменяется адресация, и позже в модуле появятся соответствующие изменения.

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

App.module("myModule", function(myModule, App, Backbone, Marionette, $, _, customArg1, customArg2){
    // Create Your Module
}, customArg1, customArg2);

Как вы уже могли заметить, если вы передаете дополнительные аргументы в module, то они будут переданы и в функцию, которая описывает данный модуль. Главное преимущество, которое я вижу от этого действия – это экономия нескольких байт памяти; кроме этого, никакой пользы я больше не вижу.

Еще один момент, который следовало бы отметить это то, что ключевое слово this доступно в функции и на самом деле относится к модулю. Это означает, что не нужно обязательно использовать первый аргумент, но вы должны иметь ввиду, что потеряете преимущество экономии памяти. Давайте переделаем представленный выше код, используя ключевое слово this. Вы увидите, что данный пример кода во многом похож на пример с myModule.

App.module("myModule", function(){ // Private Data And Functions
    var privateData = "this is private data";
    var privateFunction = function(){
        console.log(privateData);}
    // Public Data And Functions
    this.someData = "public data";
    this.someFunction = function(){
        privateFunction();
        console.log(this.someData);}
});

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

Разбиение процесса инициализации.

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

// File 1
App.module("myModule", function(){
    this.someData = "public data";});
// File 2 
App.module("myModule", function(){ // Private Data And Functions
    var privateData = "this is private data";
    var privateFunction = function(){
        console.log(privateData);}
    this.someFunction = function(){
        privateFunction();
        console.log(this.someData);}
});

Этот код дает тот же результат, что и предыдущая инициализация, с тем лишь отличием, что она распределена. Это работает, потому что в File 2 происходит вызов модуля, который мы инициализировали в File 1 (при условии, что File 1 был запущен до File 2). Если вы пытаетесь получить доступ к частной переменной или функции, она должна быть определена в модуле инициализации, там, где она используется, потому что доступ возможен только в рамках структурного блока.

Вызов модуля.

Что хорошего в создании модулей, если мы не можем получить к ним доступ? Для полноценного использования модуля необходимо правильно организовать функцию его вызова. В самом первом примере фрагментов кода, вы видели, что когда я вызывал функцию module, я присвоил ее возвращение значения переменной. Это потому, что мы используем один и тот же метод и инициализации и вызова модулей.

 var myModule = App.module("myModule"); 

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

Однако, это не единственный способ вызова модулей. Когда модуль будет создан, он получит привязку непосредственно к Application объекту, для которого был создан. Это означает, что вы можете также использовать нормальное обозначение точки доступа к модулю; но на этот раз, обозначение должно быть определено заранее, иначе вы получите неопределенность.

 // Works but I don't recommend it 
 var myModule = App.myModule;

Хотя представленный синтаксис короче, но он не передает нужный смысл для других разработчиков. Я бы рекомендовал использовать функцию module для получения доступа к нужным модулям. Прежде всего потому, что очевидным становится вызов модуля, а не какого-то из свойств App. Одновременно это удобно и рискованно, ведь вам придется создавать новый модуль, если он еще не существует. Риск заключается в возможной ошибке написания имени модуля. У вас не будет никакого способа проверить правильность работы модуля и его существование, пока вы не попытаетесь организовать его вызов.

Подмодули.

Модули также могут содержать подмодули. К сожалению, функция Module не имеет своего собственного module метода, поэтому вы не можете добавлять к ней подмодули напрямую, но это нас не остановит. Вместо того чтобы создавать подмодуль, вы вызываете функцию module на App, как вы это привыкли делать; но для имени модуля, вам необходимо поставить точку (.) после имени родительского модуля, а затем разместить название подмодуля.

 App.module('myModule.newModule', function(){ ... }); 

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

Доступ к подмодулям.

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

// These all work. The first example is recommended
var newModule = App.module('myModule.newModule');
var newModule = App.module('myModule').newModule;
var newModule = App.myModule.newModule;
// These don't work. Modules don't have a 'module' function
var newModule = App.myModule.module('newModule');
var newModule = App.module('myModule').module('newModule');

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

Запуск и остановка модулей.

Если вы читали предыдущие публикации статей из серии о функции Application (приложение), то знаете, что организацию функции Application нужно начинать с команды start. Подобная организационная структура запуска применяется и к модулями, а остановлены они могут быть с помощью команды stop.

Как вы помните (если вы читали предыдущую статью), вы можете добавить инициализаторы с помощью команды addInitializer к функции Application, и они будут вызываться одновременно при запуске функции (или будут немедленно вызваны, если функция Application уже работает). Несколько другие события происходят, когда вы начинаете работу с функции Application. Вот все события по порядку:

  • срабатывание initialize:before события,
  • начинается вызов всех инициализированных модулей,
  • запускаются все инициализаторы в том порядке, в котором они были добавлены,
  • срабатывание initialize:after события,
  • срабатывание start события.

Функция Module ведет себя очень похожим образом. Число событий, и некоторые из имен событий различны, но в целом это тот же самый процесс. При запуске модуля, это:

  • срабатывание before:start события,
  • начинается вызов всех его инициализированных подмодулей,
  • запускаются все его инициализаторы в том порядке, в котором они были добавлены,
  • срабатывание start события.

Метод stop также имеет схожие действия. Вместо добавления инициализаторов, вы должны добавлять финализаторы. Это можно сделать с помощью команды addFinalizer, и, передавать значение функции, которая сработает при вызове команды stop. В отличие от инициализаторов, никакие данные или опции не передаются функциям. При вызове команды stop происходят следующие события:

  • срабатывание before:stop события,
  • остановка работы подмодулей,
  • запуск финализаторов в том порядке, в котором они были добавлены,
  • срабатывание stop события.

Инициализаторы и финализаторы могут иметь и несколько другое применение. На самом деле, они являются весьма полезными при использовании в модуле определения. Таким образом, вы можете инициализировать модуль без фактического создания любых объектов, которые будут использоваться, а затем написать собственные инициализаторы, чтобы начать создавать объекты и их установки, такие, как в примере ниже.

App.module("myModule", function(myModule){
    myModule.startWithParent = false;
    var UsefulClass = function() {...}; // Constructor definition
    UsefulClass.prototype ... // Finish defining UsefulClass...
    myModule.addInitializer(function() {
        myModule.useful = new UsefulClass();
        // More setup
    });
    myModule.addFinalizer(function() {
        myModule.useful = null;// More tear down
    });
});

Автоматический и ручной запуск.

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

Вы можете убрать автоматический запуск модуля, изменяя его инициализацию одним из двух способов. Внутри блока инициализации, можно разместить команду startWithParent со значением false, или вы можете передать значение объекта (вместо функции) в module, который уже имеет команду startWithParent со значением, установленным на false и свойство define, чтобы заменить нормальную функцию.

// Set 'startWithParent' inside function
App.module("myModule", function(){
    // Assign 'startWithParent' to false
    this.startWithParent = false;});
// -- or --
// Pass in object 
App.module("myModule", {
    startWithParent: false,
define: function(){
        // Define module here }
});
App.start();
// myModule wasn't started, so we need to do it manually
App.module('myModule').start("Data that will be passed along");

Сейчас у модуля не будет автозапуска. Вы должны вызвать команду start вручную, чтобы запустить его, как сделал я в приведенном выше примере. Данные, которые передаются командой start, могут быть абсолютно любого типа, и они будут приняты вместе с подмодулями, когда те начнут свое действие, инициализаторами, и событиями before:start и start.

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

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

Я уже упоминал, что Module содержит некоторые встроенные функциональные возможности, такие как EventAggregator. Мы можем использовать команду on для модуля, чтобы наблюдать за событиями, связанными с запуском и остановкой. Это еще не все. Если нет никаких других встроенных событий, то модуль может определить и инициировать свои собственные события. Взгляните:

App.module('myModule', function(myModule) {
    myModule.doSomething = function() {
        // Do some stuff
        myModule.trigger('something happened', randomData); }
});

Теперь, когда мы вызвали doSomething в модуле, произойдет вызов события something happened (что-то случилось), на которое вы можете подписаться:

App.module('myModule').on('something happened', function(data) {
    // Whatever arguments were passed to `trigger` after the name of the event will show up as arguments to this function
    // Do something with `data`
});

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

Как в действительности можно использовать модуль.

Способ инициализации модулей в Marionette очень похож на определение модулей любой другой библиотеки, на самом деле они используются не для тех целей, для которых были разработаны. Встроенные команды start и stop являются показателем этого. Модули, которые содержит Marionette, призваны для организации значительно больших подсистем приложений. Например, давайте посмотрим на Gmail.

Gmail является единственным приложением, которое на самом деле состоит из нескольких небольших приложений: почтовое приложение, чат-приложение, приложение для телефонных звонков и менеджер контактов. Каждое из них является независимым — оно может существовать само по себе — но все они расположены в рамках одного приложения и могут взаимодействовать друг с другом. Когда мы впервые запускаем Gmail, менеджер контактов не появляется, также нет и окна чата. Если бы мы попытались представить такую структуру с помощью приложения Marionette, каждое из этих подчиненных приложений будет представлено в виде модуля. Когда пользователь нажимает кнопку чтобы открыть менеджер контактов, нужно сначала остановить приложение электронной почты (потому что оно скрывается для нормальной скорости работы, хотя мы можем оставить его работающим и просто убедиться, что оно не отображается в объектной модели документов DOM), а затем запускать менеджер.

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

Естественно, что мы не ограничены в использовании модулей Marionette для подобных случаев, хотя это и трудно использовать в традиционном смысле. Все потому, что модули Marionette полностью содержат значения объектов, в то время как традиционные модули “классы” предназначены для создания экземпляров.

Вывод.

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

Источник изображения на первой странице: ruiwen.

(al) (ea)

До свидания, Zen Coding. Привет, Emmet!

Emmet Demonstration - Initializers

Еще в 2009 году, Сергей Чикуенок написал статью, представляя новый способ написания HTML и CSS кода. Этот революционный плагин, под названием Zen Coding, помогал разработчикам на протяжении многих лет и в настоящее время достиг нового уровня.

Emmet, ранее известный как Zen Coding, является самым производительным и экономичным по времени плагином текстового редактора, который вы когда-либо увидите. Моментально оборачивая простые и краткие фрагменты кода в сложные, Emmet может помочь вам работать более продуктивно.

Читать далее