• Как мы :hover на iOS побеждали…

      Ни для кого, думаю, не секрет, что touch-устройства обрабатывают «мышиные» события несколько иначе, не так, как это происходит на десктоп-браузерах…

      Самый яркий для меня пример, это обработка псевдокласса :hover. Для начала iOS7, например, не будет реагировать на hover если только на элемент, или его родителя, не навешена обработка события click. Это хорошо видно вот на этом примере: jsfiddle.net/H8EmG — сколько не тыкай пальцем в текст — никаких подчеркиваний не увидишь. А в этом примере jsfiddle.net/H8EmG/1 «тычок» пальцем в текст будет приводить к его подчеркиванию. Интересный факт — пока не ткнем в другой элемент, текст так и будет сидеть под ховером…

      Другой интересный пример, это обработка появления элементов «по-наведению»: jsfiddle.net/ASRm9/1 Попробуйте нажать на текст. Сперва вы увидите текст «HOVER!», появившийся внутри строки, а вот второе нажатие уже вызовет alert('click'). Это происходит потому, что iOS понимает что за :hover что-то скрыто, и старается не сломать поведение, заложенное автором сайта.

      Но однажды мы столкнулись с такой багой, объяснить которую мы не смогли до сих пор, а на ее локализацию потребовался не один день отладки на iPad… Желающие подробностей, а также хитрого, как мне кажется, способа решения, наверное, всех проблем с :hover разом — прошу под кат…

      Читать дальше →
    • Выполнение задач в бэкграунде

        На Stackoverflow часто встречаются вопросы по выполнению на Android фоновых задач, в т.ч. и повторяющихся с заданным промежутком времени. Как правило, первое, что используется, это Service.

        Такой подход в некоторых случаях может привести к тормозам и низкой скорости ответа пользовательского интерфейса. Расскажу когда так бывает и как с этим бороться…
        Читать дальше →
      • Делаем простейший сборщик ошибок для Android

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

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

          Что же делать? На помощь приедет возможность языка Java обрабатывать исключения (Exceptions), в том числе и непойманные (unhandled).

          Читать дальше →
        • Мошеннические Android-приложения. Ковыряем врага

            Я являюсь разработчиком Android-приложения и слежу за появлением новых ссылок на него с помощью подписок Google. Сегодня утром я с радостью обнаружил в ящике письмо, в котором присутствовала новая ссылка на мое приложение. Все отлично! И отзыв положительный, и количество загрузок отличное от 0 вот только версия почему-то старая и… размер APK целых 3 мегабайта против оригинальных ~200К

            После загрузки и распаковки APK (вспоминаем что APK это просто ZIP-архив) в нем обнаружилась «набивка» из 153 PNG файлов (переименованных зачем-то в .temp) со свидетелем из Фрязино и собственно «приложение»…

            Как и следовало ожидать, от оригинального приложения там ничего не осталось. Ни иконки, ни, тем более, кода. А при дальнейшем рассмотрении (похоже что) ВСЕ файлы на androides-os.com — одна и та же программа! Я скачал несколько разных программ из разных разделов и все они были одного размера и с одинаковым содержимым!

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

            Читать дальше →
          • Простой, казалось бы, вопрос по JavaScript

              Есть простейший с виду код:

              setInterval(function(){
                   var xhr = new XMLHttpRequest();
                   xhr.open('GET', 'json.txt', true);
                   xhr.onreadystatechange = function() {
                      if(this.readyState == 4 && this.status == 200) {
                         console.log(this.responseText);
                      }
                   };
                   xhr.send('');
              }, 500);
              


              Если оставить этот код работающим в, например, Google Chorme, скажем, на 1 час, он съедает память. Съедает методично. Если посмотреть в Developer Tools на профиль использования памяти видно что память таки чистится GC но не до конца. Со временем минимальная точка на графике после GC растет.

              image

              Аналогично рост потребления памяти видно и по about:memory. «Отжир» памяти стабильно видно и в FF…

              Важное...
              • Файл json.txt лежит на localhost, его загрузка не занимает более 500мс гарантированно (я проверял).
              • Вывод в консоль я тоже отключал — память по прежнему отжирается.
              • EDIT без включенных developer tools — тоже течет, видно на about:memory.


              Кроме этого кода более на данной странице никакого кода нет вообще.

              Возможно я не понимаю как работает GC в JS, но по моему понятию тут нечему течь и нечему жить вечно. Может кто-то объяснить почему?

              P.S. «Настоящей» утечки таки нет, если обновить страницу — память очищается.
              P.P.S. Есть локальная жизненна потребность («требования бизнеса») оставлять подобный по структуре код на гораздо большие промежутки чем 1 час.

              UPD: Оказывается есть даже тикет в хромиуме: code.google.com/p/chromium/issues/detail?id=52411
              UPD: Якобы fixed in 9, но я проверяю на 10.
            • Библиотека для работы с API Яндекс.Денег и демонстрационное Android-приложение

                Добрый день, хабросообщество.

                Хочу поделиться своей разработкой — Android-библиотекой для работы с API Яндекс.Денег.

                Не далее чем 15 апреля Яндекс открыл API для работы с Я.Деньгами. Как и все ранее открытые API по работе с сервисами Яндекса, он основывается на авторизации через OAuth. В текущей реализации API позволяет запрашивать информацию об аккаунте, запрашивать список операций по счету и совершать платежи по шаблонам. Подробно — в документации, вопросы можно задать в клубе разработчиков.

                В результате была запилена библиотека и демо-приложение для Android, работающее с кошельком через API.
                Далее подробности
                • +29
                • 2,9k
                • 2
              • Геопланировщик Hypocampo — теперь с Яндекс.Картами

                   

                  С момента первого анонса на хабре геопланировщика Hypocampo вышло несколько апдейтов, как с новым функционалом, так и с багфиксами. Многим понравилась идея, но для боле удобного использования не хватало Яндекс.Карт. Последняя версия, 0.1.4, преодолела это ограничение и теперь наряду с провайдером геокодирования можно выбрать и провайдера карт (поддерживаются Google и Yandex).
                  О прочих полезных нововведениях - под катом...
                • Интеграционное тестирование web-приложения с Selenium WebDriver

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

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

                    О том, как можно Unit-тестировать JavaScript я писал ранее, сейчас же расскажу о процессе интеграционного тестирования, применяемого в команде.
                    Читать дальше →
                  • Hypocampo — геопланировщик


                      Добрый день, %username%.

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

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

                      Hypocampo — приложение для Android, позволяющее планировать задачи привязывая их не ко времени, а к месту. Суть проста — выбираем место, добавляем к нему задачи. При нахождении вас в точке, для которой имеются запланированные активные задачи срабатывает напоминание.
                      Читать дальше →
                    • Небольшое замечание для тех, кто переходит на 1.4.3

                        Особенность в 1.4.3 — проявляется в FF3.6.11

                        Простой пример:
                        <table>
                        	<tr>
                        		<td myAttr='1'>1.1</td>
                        		<td>1.2</td>
                        		<td>1.3</td>
                        		<td myAttr='1'>1.4</td>
                        	</tr>
                        	<tr>
                        		<td myAttr='1'>2.1</td>
                        		<td>2.2</td>
                        		<td>2.3</td>
                        		<td myAttr='1'>2.4</td>
                        	</tr>
                        </table>
                        


                        Ранее, до 1.4.3, результат выполнения следующей jQuery-инструкции был равен 2 (выбраны элементы 1.2 и 1.3)
                            $('tr').eq(0).find('td').eq(0).nextUntil('td[myattr=1]').length
                        


                        В 1.4.3 результат будет равен… 3 (выбираются элементы 1.2, 1.3 и 1.4).
                        Судя по всему, дело в изменении алгоритмов поиска jQuery а именно, переходе на использование matchesSelector. Чтобы вернуть поведение в нужное русло надо взять значение аттрибута в кавычки:

                            $('tr').eq(0).find('td').eq(0).nextUntil('td[myattr="1"]').length
                        


                        Легкой отладки тебе, %username%!

                        UPD: Что интересно, IE8 (а скорее всего IE<9) не подвержен «багу». У него просто не реализован matchesSelector!

                        UPD: Есть подозрение, что это баг в FF3.6.11. В Chrome7 (у него есть matchesSelector!) баг не воспроизводится.
                      • Юнит-тестирование и CodeCoverage для Javascript-кода

                          В этой заметке расскажу о своем опыте юнит-тестирования JS-кода, опыте использования среды выполнения тестов js-test-driver, ее возможности code coverage и скручивании ежа с ужом, а именно данных о code coverage от js-test-driver и генератора отчетов о покрытии PHP_CodeCоverage. Расскажу и покажу как получить вот такие отчеты о покрытии кода...
                          Читаем дальше...
                        • Яндекс.Пробки: получаем области покрытия пробками + альтернативный пробочный гаджет

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

                            У Яндекс.Пробок наряду с trf.maps.yandex.net/trf/stat.js есть еще trf.maps.yandex.net/trf/coverage.js. Этот скрипт рассказывает нам, какие регионы покрыты данными о пробках (ну или хотя бы такая информация поддерживается).

                            Вот что отдает данный скрипт...
                          • Размещаем слой с пробками на своей Я.Карте

                              API Яндекс.Карт на текущий момент не позволяет «автоматически» нанести на карту слой с пробками (UPD: имеется ввиду официально документированный способ, сопутствующие котнтролы, etc...) Впрочем, данная проблема все же решается довольно просто средствами API.

                              API имеет методы для размещения на карте собственного слоя. Слой карты характеризуется источником тайлов (YMaps.TileDataSource). Для создания источника требуется указать шаблон URL с тайлами.

                              Источник тайлов


                              Первая проблема — узнать адрес источника, используемого Я.картами. Решается просто — смотрим с помощью FireBug на карту с пробками и видим в самом верху <img /> с [src=http://trf.maps.yandex.net/tiles?l=trf&x=2500&y=1244&z=12&tm=1267986241] Здесь x,y и z — координаты тайла и информация о зуме карты. tm — временная отметка, за которую отдаются данные о пробках. Без указания параметра tm сервер тайлов отдает 404…
                              Читать дальше →
                            • Реализуем DI-контейнер на PHP5 с помощью Reflections

                                Этот топик для тех, кто представляет, что такое DI (Dependency Injection) но никогда не задумывался «как оно там унутре все работает».
                                Прочитать, что такое DI, можно например тут или тут

                                Не ставилось целью разработать свой Production DI-фреймворк. Хотелось разобраться как можно реализовать подобную функциональность наиболее удобно (Phemto, упомянутый выше, показался менее удобным, чем, например, способ от Microsoft Unity)

                                Реализованный вариант конфигурируется в коде (не через XML, как некоторые другие реализации, хотя это кому как удобнее).
                                Каждый используемый тип должен быть предварительно зарегистрирован, но не надо перечислять его аргументы, как например в Phemto — контейнер сам выяснит типы аргументов конструктора через Reflection.

                                Посмотреть код реализации...
                              • Интересная техника сокрытия кодов JS «вируса»

                                  Сегодня скинули код, дропающий на машину штатный вирус «отправьте SMS для разблокировки». Предысторию и методику чистки изложил force

                                  Попробовал расковырять. Взял код, отформатировал, стал дебагать… Хм, интересно… В коде идет вызов (после приведения к читабельному виду)

                                  window['eval'](var2);

                                  А вот в var2 — бинарные данные. Ух ты… Но ведь eval не может выполнять бинарные данные!!!

                                  И почему же в eval оказались бинарные данные?
                                • Получаем SPListItem из SPList. Очень быстро и очень медленно

                                    При профилировании веб-части для SharePoint с удивлением обнаружил узкое место в SPListItemCollection.this[Guid]… Получение элемента списка по Guid'у, фактически первичному ключу, занимало уйму времени на большой коллекции.
                                    Происходило это так

                                    var uniqId = new Guid(/* get GUID somehow */);
                                    SPList list = /* get list somehow */

                                    SPListItem anItem = list.Items[uniqId];


                                    * This source code was highlighted with Source Code Highlighter.
                                    Под катом объяснение почему так и что с этим делать...
                                  • Хочу коктейль! Сервис подборки коктейлей

                                      imageНа далее как вчера на хабре был анонсирован сервис Яндекса по поиску коктейлей.

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

                                      В общем лучше один раз увидеть, чем сто раз услышать.

                                      Хочу коктейль!

                                      UPD: Сервис по сути оффлайновый. Может работать на локали без внешнего подключения. Разве что картинки не будут подгружаться. База коктейлей в статике (как и в оригинальном сервисе)

                                      UPD: Основное отличие от, скажем, inshaker.ru — более релевантная выдача по запрошенным компонентам.
                                    • Оптимизация с помощью замыканий

                                        Дано — раз в секунду дергается AJAX'ом скрипт, в нем несколько вызовов одной функции (назовем ее updater) с разными аргументами. Функция в соответствии с аргументами апдейтит некоторый набор DOM-элементов (меняет контент, скрывает, показывает) на текущей странице. Используется jQuery, визэффекты и т.п. Т.е. на клиента приходит примерно такой код…
                                        updater('id1', 10, 20);
                                        updater('id33', 11, 22);
                                        updater('id181', 102, 27);


                                        * This source code was highlighted with Source Code Highlighter.

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

                                        Требуется по-возможности быстро и безболезненно, не меняя верстку и не отказываясь от jQuery оптимизировать процесс.
                                        Далее...
                                      • C#-like cобытия для PHP. Reflection, closures…

                                          Задача — сделать на PHP эвенты а-ля C# т.е. произвольный объект может генерировать события. Другие объекты могут на эти события подписываться непосредственно у экземпляра генерирующего объекта.

                                          Основное отличие от того что видел ранее — строгая проверка навешиваемого хука. Проверяется наличие метода, количество его аргументов, etc…
                                          Читать дальше →