Две большие разницы

Я просто искал картинку с годной демонстрацией пощёчины, например из «6го эллемента» или другого фильма с Лесли Нильсоном. Мою «пощёчину» в поисковой строке они проигнорировали, и тогда мне оставалось только упростить и перефразировать запрос

«Дал по щеке» Yandex

«Дал по щеке» Google
существенная разница в подходах к поиску видна невооружённым взглядом, под катом


вопрос «Кто лучше» в отношении поисковиков для меня решён 🙂

на всякий случай, подборка ссылок на этот же запрос от
bing
baidu
yahoo

ссылка на оригинал статьи http://habrahabr.ru/post/171109/

Интернет-телевизор − самый недооцененный сегмент разработки

Disclamer

Всем привет! В компании JetStyle существует отдел занимающийся разработкой для Smart TV. Мы хотим рассказать про технологию Smart TV, которая, как нам кажется, является весьма недооцененной в сфере разработки.

Мы уже несколько лет плотно занимаемся этой темой — накопилось много всего, хочется поделиться и, возможно, облегчить жизнь другим разработчикам.
Для удобства мы разделили рассказ на 2 блока. В первом поговорим о том, что это вообще такое, а во втором расскажем об особенностях дизайна и разработки под Smart TV и, конечно же, о куче проблем, с которыми мы сами столкнулись в процессе.

Про терминологию

Итак, что мы понимаем под Smart TV?
В общих чертах, Smart TV — это интернет в телевизоре. Это может быть как современный телевизор со встроенным в него Smart TV, так и любой тв-ресивер, имеющий доступ к сети Интернет и подключенный к телевизору.
Smart TV строится на интерактивных сервисах и самом разнообразном мультимедиа-контенте. Именно интерактивные сервисы, виджеты и приложения, заточенные под работу с пультом вместо мышки, отличают Smart TV от обычного интернет-браузера на компьютере.

С технической точки зрения, Smart TV — это мобильная операционная система, заточенная специально под телевизоры. Представляя собой софт, Smart TV может внедряться в самые разные устройства: от самих телевизоров до blu-ray проигрывателей и игровых консолей.

В чем радость-то?

Почему Smart TV — это перспективно, модно и молодежно?

  • браузер, причем практически такой же, как и на настольком ПК. Почему “практически”, расскажем чуть позже;
  • быстрый доступ к информационному контенту. Например, погоде, пробкам, котировкам, новостям и т.д.;
  • онлайн видео — одно из огромных достоинств Smart TV. На данный момент существует достаточно большое количество библиотек бесплатного контента (ivi, tvigle, tvzavr и т.п.) и хороших платных сервисов, предоставляющих свежие фильмы в отменном качестве;
  • возможность играть в игры, которые в ближайшем времени приблизятся к консольным, типа Nintendo Wii;
  • возможность общаться в социальных сетях, лайкать котиков и прочее)
  • ну и наконец, мы можем запросто заказать пиццу или любую другую еду, не сходя с дивана.
Динамика рынка

image

Как же обстоит дело с ситуацией на рынке Smart TV?
Вообще сколько-нибудь заметно, технология Smart TV начала проникать на рынок в 2010 году. Тогда умных телевизоров было совсем мало, и стоили они достаточно дорого, виджетов почти не было, и большей частью они были разработаны in-house. Всё это счастье работало довольно медленно в силу того, что железо на телевизоре было еще достаточно слабое. Однако, стоит отметить, что в 2010 году Samsung вводит первые платные сервисы для США и Кореи.

В 2011 году доля рынка телевизоров со Smart TV растет и составляет около 10% от общего объема продаж. Активно подключаются сторонние разработчики, появляются действительно хорошие и удобные сервисы, например, youtube, ivi и другие онлайн-кинотеатры. Вообще, стоит отметить, что появление сервисов бесплатного легального онлайн-видео благотворно отразилось на рынке Smart TV.

За 2012 год, к сожалению, нам никакой особой статистики найти не удалось, но интерактивом начинают заметно интересоваться провайдеры. Приложений в маркетах становится все больше, добавляются новые видео-сервисы. Железо в телевизорах становится все “быстрее”.

На данный момент мы можем по-простому оценить общее количество телевизоров со Smart TV, которое предлагается на рынке. Например, на сайте LG на данный момент из 145 телевизоров 55 с функцией Smart TV — это порядка 35%, у Samsung 60% от всех продающихся на сайте телевизоров — со Smart TV. Поигравшись фильтрами на яндекс.маркете и выбрав из популярных марок телевизоров Samsung, LG, Sony, Philips, получаем что порядка 50% из всех представленных телевизоров идут со Smart TV. А если учесть, что к остальным телевизорам, в которых нет такой функции, мы можем подцепить цифровой ресивер со втроенным в него интерактивом, то можно предполагать, что скоро Smart TV, без преувеличения, будет в каждом доме.

Не все так просто

Что затормаживает бурный рост Smart TV на данный момент?
Smart TV — это до сих пор достаточно новый тренд, технология еще находится на начальном этапе развития. Вследствие чего мы получаем низкую осведомленность потенциальных покупателей о преимуществах, связанных с использованием данной технологии.
Многие люди, например, по-прежнему думают, что функцию Smart TV они будут использовать в основном для поиска в интернете. Консультанты в магазинах бытовой электроники также далеко не всегда могут четко сказать, зачем брать телевизор именно со Smart TV. Но люди, купившие Smart TV, быстро понимают очевидную выгоду: можно смотреть фильмы, сериалы, мультфильмы и т.д. на большом экране и в высоком качестве, не привлекая для этого никакую другую технику типа персонального компьютера, ноутбука и т.д.
Другой сдерживающий фактор, который до сих пор влияет на выбор Smart TV — это цена. Еще год назад цена такого телевизора не была соизмерима с обычным телевизором, но сейчас различия в ценах на телевизоры без и со Smart TV достаточно небольшие.

Со стороны операторов связи в России также пока наблюдается сдержанный интерес. Свои приставки с интерактивными сервисами имеет ограниченное количество компаний, например, Билайн, МТС, Триколор ТВ и Дом.ру.
Очевидно, что все они понимают перспективность затеи, но уровень реализации у большинства находится на начальном этапе (сервисов мало, схемы монетизации тоже не вполне понятны). Из вышеупомянутых отличился только Дом.ru у которого заметно больше сервисов по сравнению с остальными на текущий момент.

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

Платформы

image
Для создания Smart TV порталов используются программные оболочки — платформы, на которые уже прикручивается дизайн, стили, разрабатываются виджеты и т.д.

Среди платформ, получивших наибольшее распространение, два мастодонта — Samsung Smart Hub и LG NetCast Platform, на которых строятся Smart TV у соответствующих производителей. В России, да и в мире, наверное, эти платформы наиболее популярны и развиты сейчас по ряду причин, среди которых популярность самих телевизоров, огромное количество документации для разработчиков под эти платформы, значительное комьюнити и т.д. Очень многие приложения поддерживают русский язык.
Эти платформы используются исключительно на телевизорах Samsung и LG, и их нельзя перекинуть на сет-топ-боксы либо какие-то другие проигрыватели.

Opera TV — кроссплатформенное решение для умных телевизоров, т.е. можно прошить платформу на какую-нибудь приставку, плеер или прямо в телевизор, и все будет работать независимо от фирмы-производителя. У платформы также есть свой портал
Opera tv store, который, в отличие от LG и Samsung, располагается непосредственно на серверах Opera, а не на конечном устройстве пользователя. Таким образом, у пользователя находится только интерфейс, а приложения подгружаются динамически. Это дает возможность разработчикам изменять, дополнять, исправлять свои приложения, а для пользователя этот процесс будет совершенно незаметным (если только мы сами не заходим уведомить пользователя, что приложение обновилось). В России данная платформа пока не очень распространена, и появилась только на blu-ray и телевизорах Sony, произведенных в 2012 году, в руках еще не вертели, но размах впечатляет, и в данном направлении Opera займет свое место под солнцем.

Google TV — платформа на Android.
На данный момент, на сколько нам известно, платформа представлена всего одним устройством Sony (о нем можно прочитать здесь: habrahabr.ru/post/146511/), есть возможность открывать android-приложения, на борту несет достаточно большой набор различных приложений. Имеется достаточно обширная документация по платформе, комьюнити, блоги, различные документации обо всем на свете, руководство по адаптации существующих приложений на андроиде на телевизор. Единственный большой минус для нас — на данный момент мы не заметили каких-либо признаков того, что платформа распространяется в России (http://www.google.com/tv/get.html)

Microsoft mediaroom — платформа, как уже понятно, от Microsoft. Является кроссплатформенной, может работать на персональном компьютере, на телевизоре, на приставке и телефоне. В своей разработке ребята из Редмонда опираются на максимальное масштабирование для того, чтобы платформа работала на максимальном количестве устройств, к примеру можно подключить портал даже к xbox360. Для разработчиков приложений предусмотрен пакет инструментов, входящий в пакет разработки приложений Microsoft Mediaroom Application Development Kit, который представляет собой открытую платформу. Приложения для Microsoft mediaroom являются приложенями ASP.NET.
На Российском рынке Microsoft mediaroom заметно используется компанией Beeline в их STB.

Особенности разработки

Он такой же, но квадратный и другой

Телевизор — это не компьютер, поэтому дизайн и разработка под него достаточно сильно отличается.
Даже если у нас есть готовый сайт на HTMLl+CSS+javascript, мы не сможем просто перенести его на телевизор и пользоваться им как обычно.
Во-первых, у нас нет мышки, но есть пульт управления с кнопками, нет клавиатуры, но есть виртуальная клавиатура, нет монитора перед глазами, но есть большой экран на расстоянии 2-3 метров.
Давайте разбираться по порядку.

Нет мышки

Нет мышки — нет мультиков — это одно из главных отличий в разработке и дизайне для телевизора. Мы не можем навестись в произвольное место в нашем приложении, но взамен мы можем визуально показывать ховер на активных элементах. Клик мышки заменяет нам кнопка “ок”, движение мышки по элементам эмулируется четырехпозиционным джойстиком, запрограммированным на перескакивание по блокам в соответствующих направлениях. Тут стоит отметить, что разные производители стараются как-то решить проблему ввода и предлагают альтернативные способы ввода, облегчающие пользователю жизнь. Однако пока что все эти способы носят лишь дополнительный характер, и опереться на них полностью, с радостью забыв опостылевший пульт, мы не можем. Еще очень долго мы будем обязаны поддерживать пульт как основной способ ввода при разработке.

Нет клавиатуры

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

Как мы можем облегчить жизнь пользователям?

Первое, что приходит на ум: если клавиатура позволяет кастомизацию, мы можем для каждых конкретных случаев выводить клавиатуру с нужным набором кнопок. Например, для ввода пин-кода или телефона можем показывать только цифровую клавиатуру, для ввода e-mail нам нужна только английская раскладка клавиатуры и небольшой набор символов. Кстати, для ввода телефона или любой другой информации, состоящей исключительно из цифр, мы можем вообще не выводить клавиатуру, а предложить пользователю, используя цифровой блок на клавиатуре, набрать эти цифры, а мы уже сами обработаем нажатие клавиш, не прибегая к экранной клавиатуре. Правда делать это можно лишь как дополнительный бонус, а не как основной или единственный способ ввода (почему так – ответ ниже).

Дисплей

Следующим по списку у нас идет монитор, а точнее достаточно здоровый по сравнению с монитором экран, однако при этом мы сидим в нескольких метрах от него. Здесь накладываются серьезные ограничения по дизайну, мы не будем в них углубляться, т.к. это отдельная интересная тема (если интересно — можно выдать про это отдельный пост), стоит сказать только, что мы должны использовать шрифты размером не меньше 18px, учитывать так называемую “безопасную зону” телевизоров, в которой не должно быть интерактивных элементов и навигации (здесь могут быть только бэкграунд и фуллскрин-видео).

Промежуточные итоги

Разработка под телевизор структурно напоминает разработку мобильных приложений.
Мы не можем просто дать ссылку на сайт, к примеру, yandex, 2gis, facebook, но можем предложить функционал тех же сайтов в виде приложения.
В приложении мы уже учли специфику управления, адаптировали шрифты, сделали большие и понятные блоки-ссылки и т.д.
Ну и понятно что приложение, по осравнению с веб-сервисом — гораздо проще запустить с пульта.

Перейдем к особенностям разработки под Smart TV.
Возьмем наиболее популярные сейчас платформы Samsung и LG, и на их примере посмотрим, с какими проблемами и особенностями мы столкнулись при разработке под телевизор.

Проблемы разработки

Верстка

В принципе верстать можно практически как в web’е, используя доступные стандарты, но есть несколько очень важных моментов:

  • обязательно стараться делать как можно меньше вложенность тегов в HTML, при этом соблюдая баланс читаемости: вдруг еще вернетесь к этому проекту через год. Нам это важно, в первую очередь, из-за скорости доступа к элементу из javascript, во-вторых нужно помнить про маленькую память устройства и не самую быструю скорость рендеринга страницы;
  • желательно, по возможности, использование чистого javascript, хотя, конечно, это далеко не всегда получается за счет разных очень нужных плагинов на том же jquery. Jquery, на самом деле, нормально отрабатывает на всех платформах, на которых мы разрабатывали, но только в том случае, если мы используем достаточно простые селекторы, и DOM дерево не имеет размеров небоскреба.
  • Желательно использовать как можно меньше элементов, положение на странице которых зависит от других элементов. К примеру, для списка постеров в фильмах мы использовали сначала inline-block’и, и скорость перемещения фокуса по ним была далека от идеальной, затем попробовали переделать на float:left, скорость возросла, но не критично. После приняли решение сделать блоки абсолютным позиционированием, и только тогда достигли желаемого эффекта. Способ, прямо скажем, не самый красивый, нам приходится каждому блоку давать top и left, но когда все остальное уже не помогает, приходится чем-то жертвовать, иначе пользователи не простят нам тормозов;
  • даже при поддержке CSS3, не нужно использовать его везде.

При разработке под один STB мы столкнулись с тем, что у нас в распоряжении есть практически полный CSS3, transition, rotation, HTML5 и т.д. Глаза наши горели, а сердца учащенно бились, но все встало на свои места, когда мы дошли до реализации дизайна в верстку.
Тогда мы спустились на землю нашу грешную и начали искать баланс между использованием box-shadow, crossfade’ами, slide-эффектами и прочим и комфортным для глаз отображением, без дерганий изображений и т.д. Несмотря на драконовские ограничения, наложеные нами же самими на себя, мы в принципе можем прикрутить любые эффекты и анимации в последствии, в случае, если приставка у оператора внезапно апгрейдится, и железо станет быстрее.

Версионность ПО

Это еще одна печалька. Как известно, Smart TV совсем недавно начал появляться в телевизорах и, в самом начале имел достаточно слабое ПО для приложений. Например, в 2010-2011 годах в Smart TV Samsung был браузер Maple.
Вот его спецификация:
HTML4.01, XHTML1.0, XML1.0 Markup language specifications
HTTP1.0/1.1
CSS1, CSS2, CSS TV Profile 1.0
DOM1, DOM2
JavaScript 1.6

Здесь может быть непонятным, наверное, CSS TV Profile 1.0. На самом деле это спецификация для ТВ устройств, на основе CSS2 и нескольких параметрах из CSS3, на w3c представлена табличка сравнения поддерживамых параметров и их значений в сравнении с CSS2. Спецификация на данный момент уже устаревшая (и сейчас, по крайней мере в последних телевизорах, не используется), но любознательный читатель может почитать поробности тут: www.w3.org/TR/css-tv.

LG скромно называет свой браузер LG browser, он создан на движке Webkit. На ранних этапах уже поддерживает CSS3, работает с flash, мы можем разрабатывать виджеты под HD качество (вернее даже не можем, а должны — такое требование документации), поддержка HTML5, canvas и прочее, правда и на разработчиков они вышли несколько позже Samsung: первое SDK выпущено в 2011 году и уже поддерживало CSS3 и HTML5.

В 2012 году случилось чудо, и на телевизорах этого года стоят Webkit браузеры с поддержкой 2d/3d transform, CSS3 селекторами. Появилась поддержка и HTML5 тегов video, audio, canvas.
LG много времени уделяет эмулятору, который обрастает новыми фичами, внедряет WYSIWYG редактор дизайна приложений, различные валидаторы кода и т.д.

Помимо разных спецификаций новые версии, естественно, награждают нас новым доступным разрешением для виджетов.
На данный момент это 1280х960 (предыдущее разрешение 960×540).
Что это значит для нас?
Во-первых, приложения разработанные для разрешения 1280 не пойдут на старых телевизорах на разрешении 960px, что выливается либо в поддержку заведомо меньшего разрешения 960 и растягивании его на 1280 телевизоре, либо разработку резинового приложения, либо разработку двух независимых приложений.
Так или иначе, Samsung не позволяет нам выкатить одно приложение, которое будет и 960 и 1280 в зависимости от платформы. Для этого нам придется в любом случае делать два приложения, т.к. разрешение задается в приложениях фиксированно в файле config.xml, и править динамически мы его не можем. У Samsung выложен список изменений, так что, отслеживая всегда эту информацию, мы не должны столкнуться с проблемами.

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

Быстродействие.

Браузер Maple в телевизоре Samsung отличается плохооптимизированным javascript’ом, утечкой памяти из-за незначительных погрешностей в коде (о которых в вебе нет необходимости задумываться), плохой работой с изображениями, отсутствием CSS3 параметров (но с барского плеча мы получаем text-overflow:ellipse, достаточно часто применяемый и нужный параметр, спасибо, уже хоть что-то).

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

Чтобы зря не наговаривать на браузер, стоит отметить что 50% скорости работы приложения обеспечивает все-таки железо телевизора, так что быстродействие определяется не только софтом, но и железом.

Предложения по оптимизации javascript для виджетов 2011 года:
— если в приложении мы часто меняем структуру DOM, используя к примеру innerHTML и создаем XMLHTTPRequest-объекты раз за разом, то память телевизора закончится очень быстро, и дальше приложение может вести себя непредсказуемо. На это Samsung дает нам достаточно скудную информацию для размышления:

 if (this.XHRObj != null) this.XHRObj.destroy(); this.XHRObj =  new XMLHttpRequest(); 

— если идет повторный вызов xmlhttprequеst, удаляем из памяти прошлый. В одном из наших приложений, к примеру, была необходимость использовать порядка 6 различных feed-выгрузок для отображения только одного экрана.

— допустим мы заменяем html содержимое с помощью innerHTML. Замена содержимого состоит из двух шагов: удаление соответствующего узла из DOM-дерева, и создание и подключение к дереву нового узла. Так вот узел, который мы удаляем, сохраняется в памяти, и если мы будем часто заменять контент таким образом, рано или поздно память телевизора переполнится, и наше приложение может зависнуть, вылететь, вплоть до перезагрузки самого телевизора (проверили на собственном опыте).
Поэтому есть нативный метод putInnerHTML, который позволяет избежать такой утечки памяти. Используется он несколько иначе, чем innerHTML:

putInnerHtml(‘<h1>Заголовок</h1>’,document.getElementById(‘title’)); 

В Samsung’е обнаружилась проблема еще и с большим количеством изображений. Если в DOM находится более 100 тегов img, то заполнение памяти гарантировано, и в лучшем случае, на картинках более 100 мы просто увидим пустое место, в худшем — получим непредсказуемое поведение приложения. Решается элементарно: не используем больше 100 изображений, а вообще стараемся использовать максимум 50 картинок, чтобы не приближаться к этому страшному лимиту (как сказал доктор “не делайте так”).

Следующий пример

function test() {    var a = new Image();    document.getElementById("foo").appendChild(a); } 

приведет к утечкам в памяти, т.к. конструктор new не очищается из памяти, если мы не удалим его через delete или не присвоим null. Поэтому создавать изображение можем следующим образом:

function test() {    var a = document.createElement("img");    document.getElementById("foo").appendChild(a); } 

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

Похожая проблема возникает с removeChild.
Чем плох такой код?

element.removeChild(element.firstChild); 

Тем, что removeChild возвращает нам значение, а т.к. мы не присваиваем это значение ничему, то возникает исключение, и память не будет освобождена.
Нам представляют на это 2 варианта решения:
— можем просто подставить переменную влево

var a = element.removeChild(element.firstChild); 

— а можем использовать нативный метод Samsung deleteChild, который не нуждается в переменной:

element.deleteChild(element.firstChild); 

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

Отслеживание ошибок в CSS и HTML с помощью w3c валидатора также будет очень даже не лишней операцией: чем меньше мы напрягаем интерпретатор, тем быстрее мы получим картинку приложения.

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

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

Хранение данных

Очень быстро в разработке приложений мы приходит к тому, что нужно куда-то сохранять данные. Это могут быть как настройки приложения, которые нам нужно хранить все время существования приложения в телевизоре, так и кэширование данных.
Вариантов здесь несколько.
В случае с Samsung, выпущенном в 2010, мы не имеем ничего кроме сохранения данных в локальный файл на телевизор:

var fileSystemObj = new FileSystem(); var fileObj = fileSystemObj.openCommonFile(curWidget.id + '/testFile.data', 'w');    fileObj.writeLine('something to write.');    fileSystemObj.closeCommonFile(fileObj); 

Прочитать данные из файла так же просто, как записать:

var fileSystemObj = new FileSystem(); var fileObj = fileSystemObj.openCommonFile(curWidget.id + '/testFile.data', 'r'); var strResult = fileObj.readAll(); 

Для записи используем директорию с ID нашего приложения в названии.
Этот способ работает достаточно быстро, и никаких проблем с ним нет.
В 2011 году появилась возможность работать с cookie.

LG до 2012 года позволял работать с cookie, с 2012 года мы можем использовать HTML5 sessionStorage и localStorage. Этого вполне достаточно для сохранения настроек пользователя.

Экранная клавиатура.

Это отдельная песня для разработчика.
К примеру при разработке для одного STB нам досталась полностью нативная клавиатура, если можно так выразиться, без возможности внести правки в дизайн, в ее код, хоть во что-нибудь. Работала клавиатура посредством перекидывания focus() на input. В любых случаях, когда мы хотим вызвать клавиатуру, нет других способов кроме фокуса на инпуте, а все потому что получить введенное с ее помощью значение мы можем, только проверяя состояние input на onchange(). Т.е, когда мы закрывали клавиатуру, происходило событие onchange на инпуте, и мы могли взять это значение. К тому же мы столкнулись с еще одной проблемой: input (как и некоторые другие элементы, типа a textarea button iframe) поддерживает focus(), и если мы, находясь на каком-то сайте, начнем нажимать кнопку “tab”, к примеру, фокус будет перемещаться по этим элементам. В приставке таким образом перемещается ховер при нажатии на любую кнопку четырехпозиционного джойстика (в силу того, что там был движок Opera). Поэтому если у нас есть input на странице, мы перемещаемся по блокам (визуальный ховер находится на блоках), но настоящий фокус стоит на input, и когда мы нажимаем “ок”, ожидая, что перейдем по ссылке на блоке, у нас открывается клавиатура. Мы это решили добавлением свойства disable к каждому инпуту, и когда нам нужно, убираем этот параметр и делаем focus() на инпуте (подобные ухищрения с инпутами были обусловлены дизайном в метро-стиле).

Клавиатуру в Samsung отличает то, что мы можем вызвать ее программно без всяких инпутов. Можем перехватить вводимые данные в любом момент ввода. К тому же клавиатура имеет удобный старый добрый T9. Нужные символы при должной сноровке вводятся раза в 2 быстрее полных qwerty клавиатур. Также можем переключить клавиатуру в qwerty режим. Можем добавить окошко с инпутом, и с любым описанием к нему. Можем управлять координатами всех окон клавиатуры. Мы прикручивали к ней автодополнение на выбор города, клавиатура не сопротивлялась. Единственное, что нельзя — изменять дизайн клавиатуры, доступа к этому нет (клавиатура).

Клавиатура LG не настолько прокаченная, как Samsung, но имеет свои преимущества. Клавиатура представлена отдельной js-библиотекой, и может быть подключена или не подключена в наше приложение, это значит, что мы можем поменять общий вид клавиатуры, дизайн кнопок, поставить свои иконки на кнопки. Но руководство по использованию данной клавиатуры запрещает нам вносить изменения в js-файлы. Печаль в данном случае в том, что мы имеем жестко ограниченную структуру кнопок, и менять ее не можем, разве что перекрашивать. Это связано с тем, что если мы изменим CSS, и переставим или удалим какие-то кнопки, то работать она будет уже неправильно.

Дебаг и тестирование

Одна из самых важных задач — это, конечно, дебаг приложений.
Здесь у Samsung отличное решение, встроенное в SDK.
С помощью alert() мы можем выводить значения нужных нам переменных (в телевизоре alert() не вызывает никаких всплывающих сообщений, а предназначен именно для дебага). Сама консоль выводит подробнейшую информацию о том, что происходит с нашим приложением. Единственное на что дебаг не ругался, а просто молчал — это переполнение памяти, тут уже приходилось искать ошибки самостоятельно. Также SDK Samsung’a содержит эмулятор под все версии платформы. Эмуляторы соответствуют действительности где-то на 95%. В разных эмуляторах по разного рода данным типа утечек памяти или некоторым параметрам CSS можно увидеть существенные отличия. Например мы столкнулись с тем, что в одной из версий отсутствующий line-height приравнивался к какому-то фиксированному значению, около 10 пикселей.

В LG предусмотрен аналогичный Samsung дебаг, только вместо alert’a сообщения можно выводить более привычным образом через console.log. Логирование можно вести в отдельный файл. В отличие от Samsung логер не выводит нам полной информации о работе виджета, а только ошибки и сообщения, которые мы генерируем сами. С 2012 года появляется ресурс монитор, правда мониторить пока можем только эмулятор, а мониторинг загрeзки телевизора заявлен на будущее. В 2013 году появился voice input, тестирование голосовых команд, также можно менять шрифт в эмуляторе (мега полезная фича), делать скриншоты.

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

Авторизация

Для девайсов, у которых нет мышки или тача, существует значительная проблема авторизации, например, в соц. сетях. Возьмем для примера facebook. Мы можем разместить вход через facebook на своем сайте, для этого мы можем использовать oauth2.0, в iframe откроется окошко facebook’a с предложением ввести логин/пароль, и вот мы залогинились. Если попробуем сделать также на телевизоре, то столкнемся с очевидной проблемой: как нам ввести свои данные в iframe окне facebook’а? Дело в том, что политика безопасности не позволяет нам иметь доступ к iframe-окну, если его контент находится не на нашем домене. Соответственно, мы не можем прописать в это окно обработку нажатий кнопок пульта, и в итоге мы совершенно беспомощны в наших попытках ввести свои данные – Видит око, да глаз неймёт.
Решается эта проблема с помощью пин-кодов.
На компьютере на Facebook регистрируем наше приложение, получаем app_id. В приложении используя этот app_id делаем запрос на получение кода https://graph.facebook.com/oauth/device?type=device_code&client_id=150792241632891, затем идем на компьютер, вводим код на предложенной странице facebook.com/device/ и подтверждаем доступ к нашему аккаунту. После этого на телевизоре мы можем сделать запрос на получение токена
https://graph.facebook.com/oauth/device?type=device_token&client_id=150792241632891&code=123456. Дальше, используя этот токен может запрашивать информацию с facebook’a.
Также работает авторизация и на youtube. Способ придуман не нами, так же авторизуются приложения youtube или facebook под xbox.

Тестирование на ТВ

Samsung, помимо неплохого тестирования на эмуляторе, имеет достаточно простой способ тестирования непосредственно на телевизоре. Для этого в SDK предусмотрена возможность запаковать приложение в понятный телевизору формат.
После этого размещаем получившийся widget.xml и папку с приложением в корне нашего локального сервера.
На телевизоре мы должны залогиниться под developer’ом и в настройках, указав IP адрес нашего сервера, выгрузить пакет на телевизор. Приложение появится в списке приложений.
Что немаловажно: запуская это приложение на телевизоре, мы в консоли SDK можем отслеживать состояние нашего приложения точно так же, как если бы мы запускали приложение в эмуляторе.

Тестирование на ТВ LG отличается от Samsung и напоминает выполнение квеста в каком-нибудь RPG.

  • Для начала мы регистрируем аккаунт на LG Apps TV.
  • Затем с помощью SDK запаковываем наше приложение в zip архив.
  • После этого мы можем залить данный архив на LG Developer сайт, и после этого мы можем скачать с сайта сформированный DRM пакет нашего приложения.
  • Дальше мы распаковываем DRM пакет обычным архиватором.
  • Видим папку с числовым значением — это ID нашего приложения.
  • Далее, создаем в корне флешки папку lgapps, в ней папку installed и в нее уже помещаем нашу папку с ID.
  • Вставляем флешку в телевизор.
  • Дальше еще идёт саб-квест: если вдруг в региональных настройках стоит не наша страна (как именно он это определяет — нам не известно), то мы не сможем протестировать наше приложение.
  • И вот только если все ОК, мы нажимаем на кнопочку “my apps”, проматываем все приложения которые там есть до конца, и … аллилуйя, вот оно наше приложение!

Если учесть, что в начале 2012 года, когда мы делали виджет под LG, пытались протестировать на телевизоре, мы прошли 9 кругов ада, и в конце оказалось что my apps не работает, т.к. LG еще не подключила к тестам Россию. Можно представить сколько было радости.

Выкатка в продакшн

Для Samsung: регистрируем информацию о продукте в Селлер офисе, получаем ID приложения и заголовок.
Селлер офис — это место, где мы видим информацию по нашему приложению, отсюда мы можем передать приложение для размещения в Samsung Smart TV App Store. Также используется для наблюдения за загрузкой нашего приложения, историей, состоянием приложения и т.д.
После регистрации в селлер офисе мы можем загрузить наше приложение. После размещения приложения мы ожидаем рассмотрения заявки Samsung’ом.
Как только Samsung проводит тестирование приложения и подтверждает нашу заявку, приложение размещается в Smart TV App Store. Подробное описание всех этапов есть на сайте разработчиков Samsung.

Для LG: регистрируемся в селлер лаундж. Читаем руководство по сабмиту приложений. Собственно, добавляем наше приложение. В этом же селлер лаундже можем отслеживать статус нашего приложения. Ожидаем одобрения нашего приложения. Проверка приложения проходит по заранее известным документированным критериям, доступным разработчикам. После одобрения приложения, мы можем увидеть его в LG Apps tv.

Антракт

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

В общем, очень ждем ваших отзывов.

ссылка на оригинал статьи http://habrahabr.ru/post/171107/

Click2Call на Mac OS X

Еще до появления в инфраструктуре нашей организации Asterisk-сервера у меня регулярно возникало желание совершать звонки с помощью отдельно стоящего на столе телефона на номера, которые я вижу на экране монитора не набирая их на аппарате. Далее речь пойдет о реализации этого функционала на связке Mac OS X + Asterisk.

Читатели могут возразить: подключение гарнитуры к компьютеру и настройка программного SIP-клиента решает проблему.

Но лично для меня есть несколько причин решить задачу иначе:

  1. пока еще сильна привычка говорить по телефону держа трубку в руке (при необходимости можно включить громкую связь;
  2. был опыт использования проводной и беспроводной гарнитуры, но не прижилось из-за периодически возникающих технических неувязок;
  3. удобной фичей может быть перенаправление звонка на SIP-клиент мобильника и тогда, например, можно говорить с любимой не в кабинете при коллегах, а в коридоре или находящемся за стеной кафе (даже bluetooth гарнитура в этом сценарии не подойдет).

Теория

Первым делом я попытался найти уже существующее Asterisk совместимое Click2Call ПО, но ни один из немногих найденных проектов не заработал. Тем не менее я получил общее представление о технологии взаимодействия и будучи программистом решил освоить тему самостоятельно.

Используемые компоненты:

  • инициатор звонка — Mac OS X 10.8.2
  • веб-сервер — Apache + PHP
  • SIP сервер — Asterisk 1.6.2
  • SIP телефон — Yealink VP-2009

Процесс инициации звонка состоит из следующих этапов

  1. локальный скрипт формирует url и отправляет запрос на веб-сервер
  2. php на веб-сервере подключается к менеджеру Asterisk и формирует звонок
  3. Asterisk звонит на SIP номер моего телефона и после ответа соединяет с вызовом удалённого абонента

Поскольку я основывался на примерах настройки возможности заказа обратного звонка через сайт, то в схеме присутствует необязательный элемент — отдельный веб-сервер с PHP. Необязательный он еще и по той причине, что в текущей версии скрипта я вынужден использовать интерпретатор PHP на стороне своего Mac и, следовательно, при необходимости можно перенести весь функционал подключения к менеджеру Asterisk на локальную машину. Тем не менее я оставил 3х компонентную схему для возможности инициации звонка из браузера мобильного телефона, а не с компьютера.

Практика

Процесс настройки всех трех компонентов буду излагать в таком порядке: Asterisk, WEB, Mac OS.

1. Настраиваем Asterisk

Прежде всего нужно добиться от Asterisk возможности вызывать локального абонента А и соединять его с вызовом абонента Б. Автоматизировать этот процесс можно помещая файл с нужными параметрами вызова в папку /var/spool/asterisk/outgoing сервера Asterisk или передавая эти параметры через менеджер процессу Asterisk.

Например файл вызова может быть таким

Channel: Local/7777 MaxRetries: 1 RetryTime: 60 WaitTime: 30 Context: default Extension: +79201234567 Priority: 1 

Важно правильно указать параметр Context, который в конфигурации Asterisk соответствует, например, контексту для исходящих вызовов.

Тестирование я проводил первым способом — файловым, а боевую систему настроил с использованием второго. Для этого включаем на SIP сервере менеджер Asterisk

manager.conf

[general] enabled = yes webenabled = yes port = 5038  [asterisk] secret=mysecretpassword deny=0.0.0.0 permit=A.B.C.0                       ; адрес подсети вебсервера read=system,call,log,verbose,command,agent,user,originate write=system,call,log,verbose,command,agent,user,originate 

Не забываем в межсетевом экране открыть доступ к порту 5038 для вебсервера.

2. Готовим web

На вебсервере создаем php-скрипт

<?php $receiver = str_replace(array(" ","(", ")", "-", "."), "", $receiver);  switch (strlen($receiver)) {     case 0:         exit;     break;      case 6:         $receiver="84722".$receiver;     break;      case 10:         $receiver="8".$receiver;     break; }  // IP сервера с Asterisk $sys_ip = "1.2.3.4";  // имя пользователя для менеджера $User_str = "asterisk"; // ... и его пароль $Secret_str = "mysecretpassword"; $our_exten = "Local/$sender";  $WaitTime = "10"; $domain = "127.0.0.1"; // это будет отображено в sip-клиенте, если звонок пойдёт куда-либо на SIP/xxx $strCustdata = "Call to ".($name!=""?$name:$receiver);  $oSocket = fsockopen ($sys_ip, 5038, $errnum, $errdesc) or die ("Connection to host failed"); sleep (1);  fputs ($oSocket, "Action: login\r\n"); fputs ($oSocket, "Username: $User_str\r\n"); fputs ($oSocket, "Secret: $Secret_str\r\n\r\n");  $wrets = fgets ($oSocket,128);  echo $wrets;  fputs ($oSocket, "Events: off\r\n\r\n"); fputs ($oSocket, "Action: originate\r\n"); fputs ($oSocket, "Channel: $our_exten\r\n"); fputs ($oSocket, "WaitTime: $WaitTime\r\n"); fputs ($oSocket, "CallerId: $strCustdata\r\n"); fputs ($oSocket, "Exten: $receiver\r\n"); fputs ($oSocket, "Context: default\r\n"); fputs ($oSocket, "Async: yes\r\n"); fputs ($oSocket, "Priority: 1\r\n\r\n"); fputs ($oSocket, "Action: Logoff\r\n\r\n"); sleep (2);  fclose ($oSocket); ?> 

Важными параметрами при формировании вызова, как я уже говорил, являются Channel, Exten и Context.

3. Готовим инициатор звонков

Создаём в Apple Script Editor и сохраняем в папку ~/Library/Address Book Plug-Ins/ скрипт

using terms from application "Contacts" 	 	on action property 		return "phone" 	end action property 	 	on action title for p with e 		return "Dial from Yealink" 	end action title 	 	on should enable action for p with e 		if value of e is missing value then 			return false 		else 			return true 		end if 	end should enable action 	 	on perform action for p with e 		set theName to name of p 		set telephone to the value of e 		tell application "Terminal" 			set param to "`echo \"<?php echo 'http://webserver/click2call/call.php?sender=7777&receiver='.urlencode('" & telephone & "').'&name='.urlencode('" & theName & "')?>\" | php`" 			do shell script "/opt/local/bin/wget -q -O - " & param & " >/dev/null 2>&1 & sleep 1" 			quit saving no 		end tell 	end perform action 	 end using terms from 

Скрипт формирует URL, обращается к нему через wget и затем закрывает терминальное приложение. Мне пришлось использовать локальный PHP для кодирования UTF8 строк в URL. Все найденные функции AppleScript не справлялись с задачей в полном объёме. Если вы постоянно держите открытым Terminal.app для работы, то возможно прийдется убрать команду закрытия приложения.

Теперь в приложении Contacts в контекстном меню появится пункт «Dial from Yealink». Замечу, что после внесения правок в скрипт и его сохранения нужно каждый раз перезагружать приложение Contacts для тестирования этих правок.

Для добавления пункта в контекстное меню Services любого приложения нужно создать сервис через Automator. Добавляем блок Run Shell Script, вводим сам скрипт

/opt/local/bin/wget -q -O - "http://webserver/click2call/call.php?sender=7777&receiver=$1" > /dev/null 2>&1 

Настраиваем передачу входных данных в качестве аргументов, а не на стандартный ввод.

Итог.

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

Спасибо за внимание.

ссылка на оригинал статьи http://habrahabr.ru/post/170315/

Фабрика виджетов jQuery UI

Все jQuery UI виджеты создаются на простой основе — Фабрике Виджетов. Она обеспечивает гибкую основу для создания сложных, структурированных плагинов с совместимым API. С её помощью можно создавать не только плагины jQuery UI, но и любые объектно-ориентированные компоненты, не изобретая велосипедов. Она не зависит от других компонентов jQuery UI, наоборот, большая часть компонентов UI зависит от неё.

Что это?

Фабрика виджетов это метод глобального объекта jQuery — jQuery.widget — принимающий 2 или 3 аргумента.

jQuery.widget(     'namespace.widgetname',      namespace.superwidget, // не обязательно - прототип существующего виджета                            // от которого будет наследоваться ваш виджет      {...}                  // литерал объекта,                            // который послужит прототипом вашего виджета );

Первый аргумент строкового типа, содержащий пространство имен для вашего виджета, и его имя, разделяются точкой. Пространство имен обязательно, и ссылается на место в глобальном объекте jQuery, где будет храниться прототип виджета. Если пространство имен не задано, фабрика создаст вам его. (прим. переводчика — Но плагин без неймспейса попросту не заработает, во всяком случае у меня не получилось. Да и вообще неймспейсы полезно.) Имя плагина хранится как имя плагина и прототипа. Например:

jQuery.widget("demo.multi", {...})

создаст jQuery.demo.multi и jQuery.demo.multi.prototype.

Второй (не обязательный) аргумент, прототип для наследования от него. Например, в jQuery UI есть плагин «mouse», на котором основаны все плагины для взаимодействий [с мышью]. Для достижения этого, draggable, droppable и т. п. наследуются от плагина «mouse»:

jQuery.widget( "ui.draggable", $.ui.mouse, {...} );

Если вы не указываете этот аргумент, виджет наследуется напрямую от «основного виджета» jQuery.Widget (обратите вниманию на разницу между jQuery.widget с маленькой w и jQuery.Widget с большой W).

Последний аргумент — литерал объекта, который будет использоваться в качестве прототипа для каждого экземпляра виджета. Фабрика создает цепочку прототипов, соединяя прототип виджета со всеми виджетами от которого он наследуется, вплоть до базового jQuery.Widget.

При вызове jQuery.widget в прототипе jQuery (jQuery.fn) создается новый метод, соответствующий имени виджета, в нашем случае это будет jQuery.fn.multi. Метод .fn служит интерфейсом между элементами DOM, получаемыми в объекте jQuery и экземплярами виджета. Экземпляр виджета создается для каждого элемента в объекте jQuery.

Польза

Упрощенный подход, описанный в Гайдлайнах по разработке плагина, оставляет много вопросов с конкретной реализацией, когда дело касается структурированного кода и ООП ориентированных плагинах. Кроме того, они не предлагают никаких решений для общих задач. Фабрика виджетов предоставляет API jQuery UI, для связи с экземпляром плагина и решения нескольких повторяющихся задач.

  • Создание неймспейса и прототипа
    Кроме этого, для запросов и фильтрации генерируется псевдо-селектор на основе неймспейса и имени, например $(":demo-multi").
  • Связь между прототипом и jQuery.fn
    Реализуется через jQuery.widget.bridge
  • Слияние пользовательских настроек с настройками по умолчанию
    Настройки по умолчанию могут быть изменены (прим. переводчика — видимо имеются ввиду настройки по умолчанию для всех экземпляров виджета — можно изменить дефолтные настройки в прототипе своего виджета в конфиге для конкретной страницы, например).
  • Экземпляр плагина доступен через $("#something").data("pluginname")
    Ссылка на объект jQuery, содержащий DOM элемент (прим. переводчика — имеется ввиду ссылка на конкретный DOM элемент, на котором в данный момент отрабатывает экземпляр плагина) доступна в качестве свойства экземпляра this.element, поэтому становится очень легко взаимодействовать с плагином и элементом.
  • Методы виджета доступны через аргументы метода прототипа jQuery — $("#something").multi("refresh") — или напрямую через экземпляр — $("#something").data("multi").refresh().
  • Предотвращает появление нескольких экземпляров на одном элементе
    Механизм коллбеков, на которые может подписываться пользователь: this._trigger("clear")
    • Подписаться:
      $( "#something" ).multi({ clear: function( event ) {} });

    • Или, если через .bind:
      $( "#something" ).bind( "multiclear", function( event ) {} );

      (прим. переводчика — обратите внимание имя события склеилось из имени плагина и события)

  • Механизм облегчающий изменение опций плагина после инициализации
  • Просто включать/отключать или уничтожать экземпляр и возвращаться к изначальному состоянию. (прим. переводчика — смотрите дальше приватные методы _destroy и т. д.)

Создание собственного прототипа

Инфраструктура

Литерал объекта, передаваемый в качестве прототипа может быть устроен как угодно, но он обязательно должен содержать options (прим. переводчика — опции по умолчанию), коллбеки _create, _setOption, и destroy.

Пример

(function( $ ) {   $.widget( "demo.multi", {     // These options will be used as defaults     options: {        clear: null     },       // Set up the widget     _create: function() {     },      // Use the _setOption method to respond to changes to options     _setOption: function( key, value ) {       switch( key ) {         case "clear":           // handle changes to clear option           break;       }         // In jQuery UI 1.8, you have to manually invoke the _setOption method from the base widget       $.Widget.prototype._setOption.apply( this, arguments );       // In jQuery UI 1.9 and above, you use the _super method instead       this._super( "_setOption", key, value );     },       // Use the destroy method to clean up any modifications your widget has made to the DOM     destroy: function() {       // In jQuery UI 1.8, you must invoke the destroy method from the base widget       $.Widget.prototype.destroy.call( this );       // In jQuery UI 1.9 and above, you would define _destroy instead of destroy and not call the base method     }   }); }( jQuery ) );

Инкапсуляция в методах

Ваш объект скорей всего будет содержать методы, для обработки различных специфичных операций, например построение и вставка новых элементов или обработка событий. Разумно было бы использовать изолированные методы для каждой операции, вместо обработки кучи всего в методе _create. Это позволит не дублировать код, в случае изменений.

Например, в гипотетическом виджете, расширяющим <select multiple>, кто-то захочет пробежаться по дочерним <option>, для создания соответствующих <li> и <ul>. Это можно реализовать через метод _create:

_create: function() {     var self = this;     this.list = $( "<ul>" ).insertAfter( this.element );      this.element.hide().find( "option" ).each(function( i, el ) {         var $el = $( el ),             text = $( el ).text(),             item = $( "<li class='multi-option-item'>" + text + "</li>" );          item.appendTo( self.list ).click(function(){              console.log( $el.val() );         });     }); }

К сожалению, если оставить так код в _create, это создаст сложности в определении связей между оригинальным элементом <option> и пунктами списка который мы создаем, или проблему при изменении состояния элементов <option>, которые были добавлены или удалены из изначального <select> уже после инициализации виджета. Вместо этого мы сделаем метод refresh, отвечающий за работу с элементом, и вызывающийся из метода _create. Мы также вынесем отдельно обработку щелчков по элементам списка, и будем использовать делегирование события, что бы не навешивать новые обработчики, после создания нового пункта.

Пример

_create: function() {     this.list = $( "<ul>" )         .insertAfter( this.element )         .delegate( "li.multi-option-item", "click", $.proxy( this._itemClick, this ) );     this.element.hide();     this.refresh(); },  refresh: function() {     // Keep track of the generated list items     this.items = this.items || $();      // Use a class to avoid working on options that have already been created     this.element.find( "option:not(.demo-multi-option)" ).each( $.proxy(function( i, el ) {         // Add the class so this option will not be processed next time the list is refreshed         var $el = $( el ).addClass( "demo-multi-option" ),             text = $el.text(),              // Create the list item             item = $( "<li class='multi-option-item'>" + text + "</li>" )                 .data( "option.multi", el )                 .appendTo( this.list );          // Save it into the item cache         this.items = this.items.add( item );     },this));      // If the the option associated with this list item is no longer contained by the     // real select element, remove it from the list and the cache     this.items = this.items.filter( $.proxy(function( i, item ) {         var isInOriginal = $.contains( this.element[0], $.data( item, "option.multi" ) );         if ( !isInOriginal ) {             $( item ).remove();         }         return isInOriginal;     }, this )); }, _itemClick: function( event ) {      console.log( $( event.target ).val() ); }

Приватные v. Публичные методы

Как вы наверное заметили, некоторые методы мы написали с нижним подчеркиванием вначале, в то время как некоторые без него. Методы с префиксом обрабатываются как «приватные». Фабрика блокирует все попытки вызвать их через $.fn

$( "#something" ).multi( "_create" )

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

$( "#something" ).data( "multi" )._create()

Как же принять правильное решение? Если пользователям ваших виджетов понадобятся определенные методы, то сделайте их публичными. Пример с refresh показателен: раз пользователь может управлять элементами селекта, мы должны обеспечить ему возможность обновить его. С другой стороны, служебная функция для обработки событий, как например _itemClick, требуется только для внутреннего использования, и совсем не нужна в публичном интерфейсе плагина.

Свойства

this.element

Элемент, используемый экземпляром плагина. Например:

$( "#foo" ).myWidget()

В этом случае this.element будет объектом jQuery, содержащим элемент с id foo. Для нескольких элементов, для которых вызывается .myWidget(), отдельный экземпляр плагина будет вызван для каждого элемента. Другими словами this.element будет всегда содержать только один элемент.

this.options

Опции, используемые для настройки плагина. При создании экземпляра, любые опции, переданные пользователем, автоматически объединяются с заданными в $.demo.multi.prototype.options. Пользовательские опции перезаписывают опции по умолчанию.

this.namespace

Пространство имен плагина, в нашем случае «demo». Как правило не используется в плагинах.

this.name

Имя плагина, в нашем случае «multi». Немного полезней чем this.namespace, но в большинстве случаев также не используется.

this.widgetEventPrefix

Свойство, использующееся для именования событий плагина. Например, dialog имеет коллбек close, при его исполнении всплывет событие dialogclose. Имя события состоит из префикса события и имени коллбека. По умолчанию значение widgetEventPrefix такое же как и имя виджета, но может быть перезаписано. Например, если пользователь начал перетаскивать элемент, мы не хотим что бы всплывало событие draggablestart, мы хотим что бы оно называлось dragstart, для этого мы делаем префикс события равным «drag». Если имя коллбека совпадает с префиксом события, то событие будет без префикса. Это позволит избежать событий наподобие dragdrag.

this.widgetBaseClass

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

element.addClass( this.widgetBaseClass + "-active" )

Для большинства плагинов это не обязательно, потому что проще написать что-то вроде .addClass( "demo-multi-active" ). Приведенный пример актуальнее для самой фабрики и абстрактных плагинов, таких как $.ui.mouse.

Методы

(прим. переводчика — лучше всего, конечно, ознакомиться напрямую с документацией)

_create

Метод, в котором настраивается всё, относящееся к вашему виджету — создание элементов, навешивание событий и т. д. Метод вызывается один раз, сразу после создания экземпляра.

_init

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

destroy

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

option

Используется для задания опций после создания экземпляра. Сигнатура метода похожа на методы .css() и .attr(). Вы можете задать только имя, что бы получить значение, или имя вместе со значением, для того что установить его, либо передать объект, для установки нескольких значений. Метод вызывает _setOptions, поэтому он не должен меняться сторонними плагинами.

_setOptions

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

_setOption

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

_setOption: function(key, value) {     if (key === 'title') {         this.titleElement.text(value);     }     $.Widget.prototype._setOption.apply(this, arguments); }

Вызывая родительский метод _setOption, мы устанавливаем новое значение опции. Это не должно выполняться _setOption. Иногда требуется сравнить старое и новое значения, что бы определить корректное поведение. Вы можете сравнить this.options[key] со значением, так как вызов родительского метода _setOption происходит уже в самом конце. Если вам не нужно ничего сравнивать, вы можете делать вызов родительского _setOption в самом начале метода.

enable

Хелпер, вызывающий option('disabled', false). Вы также можете отлавливать вызов этого хелпера, проверяя:

if (key === "disabled")

в вашем _setOption.

disable

Хелпер, вызывающий option('disabled', true). Вы также можете отлавливать вызов этого хелпера, проверяя:

if (key === "disabled")

в вашем _setOption.

_trigger

Этот метод необходимо использовать для всех коллбеков. Имя выполняемого коллбека единственный обязательный параметр. Все коллбеки также триггерят событие (см. описание this.widgetEventPrefix выше). Вы можете также передать объект события, запустившего коллбек. Например, событие drag запускается событием mousemove, и оно должно передаваться в _trigger. Третий параметр, объект с данными, которые передаются в обработчики коллбека и события. Данные, передаваемые в этом объекте должны относиться только к текущему событию, и не должны отдаваться другими методами плагина.

ссылка на оригинал статьи http://habrahabr.ru/post/150549/

StackOverflow по-русски

Все, конечно же, знают о платформе StackOverflow, которая не раз помогала нам в решении тех или иных задач. Но далеко не каждый интересовался остальными проектами сети StackExchange. Одним из таких проектов является Area 51, основная задача которого — предложение новых FAQ-сайтов для сети StackExhange. В последние дни начало набирать активность предложение пользователя diffycat по созданию русского аналога для StackOverflow.

Конечно, русская локализация не единственная. Например турецкая версия совсем недавно перешла в стадию закрытого бета-тесирования. Чем мы хуже? Сейчас предложение находится на стадии определения, и ему остается 29 вопросов с оценкой 10 и выше для перехода в следующую фазу.

Зачем?

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

Процесс создания нового сайта

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

Определение

Самая первая фаза, с которой начинается предложение нового сайта. На этом этапе пользователи создают примеры вопросов, которые будут на сайте, и голосуют за них. Для перехода на следующую фазу, предложению необходимо набрать минимум 40 вопросов с оценкой «10» и выше, а так же минимум 60 фоловеров.

Сбор подписей

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

Бета-тестирование

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

  • 15 — среднее количество вопросов в день
  • 90% — процент вопросов, получивших ответ
  • 150, 10 и 5 — количество пользователей с репутацией 200+, 2000+ и 3000+ соответственно
  • 2.5 — среднее количество ответов на один вопрос
  • 1500 — количество ежедневных просмотров сайта

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

Итого

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

P.S. этот пост планировался для хаба Социальные сети и сообщества, но, увы, не хватило кармы.

ссылка на оригинал статьи http://habrahabr.ru/post/171101/