Когда происходит событие «размытия», как я могу узнать, на какой элемент был сфокусирован элемент *?

Добавление событий к динамически созданным объектам

Для того чтобы повесить событие на элемент, которого ещё нет, можно использовать следующую конструкцию функции :

$(document).on(eventName, selector, handler);

// document или любой другой существующий родительский элемент
// eventName - имя события
// selector - селектор, осуществляющий фильтрацию потомков, для которых необходимо запустить обработчик события
// handler - обработчик события

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

Например, добавим событие к элементу, которого ещё нет на странице:

<button id="addButton" type="button">Добавить кнопку</button>

<script>
// при нажатии на элемент с id="addButton" добавить в начало страницы новую кнопку
$('#addButton').on('click', function(e) {
  $('body').prepend('<button class="deleteMe" type="button">Удалить меня</button>');
});
// добавить событие click, которое будет выполнено для элементов, которых ещё нет на странице
$(document).on('click','.deleteMe', function() {
  $(this).remove();
});
</script>

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

$(document).on('click','#comment a',function(e) {
  if(!(location.hostname === this.hostname || !this.hostname.length)) {
    e.preventDefault();
    location.href='away?link='+encodeURIComponent($(this).attr('href'));
  }
});

3 ответа

128

Лучший ответ

Используйте . blur().

24 сен. 2014, в 08:04
Поделиться

Для всех текстовых полей:

12 апр. 2017, в 07:39
Поделиться

Ещё вопросы

  • 1Android: ConcurrentModificationException с наложениями карты
  • 1Найдите ключ во вложенном объекте и замените его значение — Javascript
  • 1Как немедленно отобразить активное изображение с карусели на мой 2-й див, если я нажму следующий / предыдущий?
  • Приведение из базового класса в шаблон созданного класса
  • Кнопка загрузки не отвечает на ng-disabled в angularjs
  • 1Возвращаемые значения из метода php
  • 1Как выровнять фигуры с началом / концом столбца, отображаемого на оси даты?
  • не завершается цикл с cin в качестве условия c ++
  • 1Как назначить свойство глобальной функции изнутри этой функции
  • 1Dask: безопасно ли выбирать данные для последующего использования?
  • Изменить порядок div с помощью JavaScript
  • Почему обтекание вызывает размытие моего ввода?
  • Таблица HTML: вторая строка отображается рядом с первой, но не ниже
  • Функция JQuery загружает контент и удаляет его не повторяя
  • Отобразить HTML-код на HTML-странице
  • 1противоречивое поведение от BigDecimal и MathContext
  • 1Z3 Java API: когда располагать объекты выражений / Z3?
  • 1Android с ActionBar Шерлок. ImageButton не получает событие onClick
  • запись данных массива в текстовый файл в opencv
  • 1Если переменная не пустая отображаемая переменная без повторения имени переменной
  • Выражение должно иметь тип класса (База данных студентов)?
  • Шаблон ngfor в Angular 2 и аргумент в функции не работает
  • 1генерировать элементы div на основе строковых путей
  • 2Разверните окно браузера Firefox с помощью Selenium WebDriver C #
  • почему массив символов нельзя скопировать следующим образом: charArray = «некоторая строка»;
  • 1Невозможно запустить простой HTTP-клиент в Java
  • Чтение данных JSON из файла в d3.js не работает
  • Разрешение шаблона Variadic в VS2013 — Ошибка C3520
  • 1Как перехватить указатель мыши на событие элемента QTableWidget в pyqt?
  • Функция изменения класса jQuery только для первого ввода?
  • 1Отладка Java в ошибке затмения
  • 2как передать параметры по времени разрешения в автофаке
  • 1Вызов функции внешней библиотеки внутри VueJS
  • 1Doctrine2: использовать функции даты в QueryBuilder
  • 2«System.Net.Http.HttpRequestException» возникла в mscorlib.dll, но не была обработана в коде пользователя
  • Удаление граничной кавычки из JSON
  • 1JavaFX — исчезающие значки на кнопках панели инструментов
  • Включить содержимое меню с внешней страницы ASP, оставляя выбранным пункт меню
  • 1Имитация щелчка пользователя, чтобы элемент отображался в DOM
  • C # Имя ‘client’ не существует в текущем контексте // Ожидается идентификатор // Ожидаемый класс, делегат, перечисление, интерфейс или структура
  • 1Сравнение двух массивов, получающихся в третьем массиве
  • 2Добавление записей с использованием миграций Entity Framework CF
  • Как добавить новый столбец по отношению к существующему столбцу в MySql?
  • 2Сохранение файлов на Raspberry PI с Windows IoT
  • 1Не удалось найти свойство ‘android’ в корневом проекте
  • Ошибка выбора даты Jquery для исламского календаря
  • Я выполняю все этапы документации Unslider, но не работает
  • установить выбранное по умолчанию значение в <option> в angularjs
  • 1Процедура вызова по умолчанию без привязки значений к параметрам в Jdbc
  • 1Создание объектов со случайными входами

Ловушка фокусаСкопировать ссылку

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

Ловушку фокуса не стоит путать с ловушкой клавиатуры. Ловушки клавиатуры — это ситуации, когда невозможно закрыть виджет или перейти к другому компоненту из-за вложенного цикла плохо прописанной логики.

Практический пример того, как вы могли бы использовать ловушку фокуса — это модальное окно:

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

Почему это важно?Скопировать ссылку

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

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

Как это сделать?Скопировать ссылку

Надёжно управлять фокусом — дело сложное. Нужно прибегнуть к JavaScript, чтобы:

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

Зачем нам это?Скопировать ссылку

Не стану врать: все эти действия отнимают много времени. Но всё же, управление фокусом и удобный порядок фокусировки являются частью WCAG (руководства по обеспечению доступности веб-контента). Тема достаточна важна, чтобы считать её частью международного правового стандарта о юзабилити.

ВидимостьСкопировать ссылку

Существует небольшой трюк, с помощью которого можно легко ограничить видимость и интерактивность элемента.

У скринридеров есть режим взаимодействия, который позволяет им проходить по странице или просматривать её с помощью виртуального курсора. А ещё виртуальный курсор позволяет пользователю скринридера обнаруживать неинтерактивные части страницы (заголовки, списки и т. д.). В отличие от использования Tab, виртуальный курсор доступен только пользователям скринридера.

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

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

Включаем фокусировку на любом элементе: tabindex

Многие элементы по умолчанию не поддерживают фокусировку.

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

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

Это можно изменить HTML-атрибутом .

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

То есть: если у нас два элемента, первый имеет , а второй , то находясь в первом элементе и нажав Tab – мы переместимся во второй.

Порядок перебора таков: сначала идут элементы со значениями от и выше, в порядке , а затем элементы без (например, обычный ).

При совпадающих элементы перебираются в том порядке, в котором идут в документе.

Есть два специальных значения:

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

    Обычно используется, чтобы включить фокусировку на элементе, но не менять порядок переключения. Чтобы элемент мог участвовать в форме наравне с обычными .

  • позволяет фокусироваться на элементе только программно. Клавиша Tab проигнорирует такой элемент, но метод будет действовать.

Например, список ниже. Кликните первый пункт в списке и нажмите Tab:

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

Свойство тоже работает

Мы можем добавить из JavaScript, используя свойство . Это даст тот же эффект.

ФОРМЫ

Форма входаФорма регистрацииФорма оформления заказаКонтактная формаФорма входа в соц сетиРегистрацияФорма с иконкамиРассылка по почтеСложенная формаАдаптивная формаФорма всплывающаяФорма линейнаяОчистить поле вводаКопирование текста в буфер обменаАнимированный поискКнопка поискаПолноэкранный поискПоле ввода в менюФорма входа в менюПользовательский флажок/радиоПользовательский выборТумблер перключательУстановить флажокОпределить Caps LockКнопка запуска на EnterПроверка пароляПереключение видимости пароляМногоступенчатая формаФункция автозаполнения

Методы focus/blur

Методы и устанавливают/снимают фокус.

Например, запретим посетителю переключаться с поля ввода, если введённое значение не прошло валидацию:

Это сработает во всех браузерах, кроме Firefox (bug).

Если мы что-нибудь введём и нажмём Tab или кликнем в другое место, тогда вернёт фокус обратно.

Отметим, что мы не можем «отменить потерю фокуса», вызвав в обработчике потому, что срабатывает после потери фокуса элементом.

Потеря фокуса, вызванная JavaScript

Потеря фокуса может произойти по множеству причин.

Одна из них – когда посетитель кликает куда-то ещё. Но и JavaScript может быть причиной, например:

  • переводит фокус на себя – элемент теряет фокус (событие ), а когда закрывается – элемент получает фокус обратно (событие ).
  • Если элемент удалить из DOM, фокус также будет потерян. Если элемент добавить обратно, то фокус не вернётся.

Из-за этих особенностей обработчики могут сработать тогда, когда это не требуется.

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

Включение и отключение кнопки на чистом JavaScript

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

<html>
    <head>
        <script>
            function toggleButton()
            {
                var username = document.getElementById('username').value;
                var password = document.getElementById('password').value;
 
                if (username && password) {
                    document.getElementById('submitButton').disabled = false;
                } else {
                    document.getElementById('submitButton').disabled = true;
                }
            }
        </script>
    </head>
    <body>
        <div>
            <form action="/submit.php" method="post">
                Username:<input type="text" name="username" id="username" onchange="toggleButton()">
                Password:<input type="password" name="password" id="password"  onchange="toggleButton()">
                <input id="submitButton" type="submit" value="Submit" disabled/>
            </form>
        </div>
    </body>
</html>

Данный код создает простейшую форму с двумя полями для ввода текста и кнопкой для отправки введенных данных на сервер

Важно отметить, что во время загрузки страницы кнопка формы находится в отключенном состоянии – для этого в коде по умолчанию используется свойство disabled

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

Функция toggleButton проверяет, ввел ли пользователь данные в оба обязательных поля. Если пользователь ввел имя и пароль, функция изменит состояние disabled на false, что в итоге приведет к активации кнопки отправки введенных данных. Если же одно из обязательных полей осталось незаполненным, свойство disabled получает параметр true, и как следствие этого, кнопка остается неактивной.

В приведенном выше примере для создания кнопки используется элемент <input>, но при желании также можно использовать HTML-кнопку <button>, как показано ниже:

<button id="submitButton" disabled/>Submit</button>

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

DOMContentLoaded

Событие срабатывает на объекте .

Мы должны использовать , чтобы поймать его:

Например:

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

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

На первый взгляд событие очень простое. DOM-дерево готово – получаем событие. Хотя тут есть несколько особенностей.

Когда браузер обрабатывает HTML-документ и встречает тег , он должен выполнить его перед тем, как продолжить строить DOM. Это делается на случай, если скрипт захочет изменить DOM или даже дописать в него (), так что должен подождать.

Поэтому DOMContentLoaded определённо случится после таких скриптов:

В примере выше мы сначала увидим «Библиотека загружена…», а затем «DOM готов!» (все скрипты выполнены).

Скрипты, которые не блокируют DOMContentLoaded

Есть два исключения из этого правила:

  1. Скрипты с атрибутом , который мы рассмотрим немного позже, не блокируют DOMContentLoaded.
  2. Скрипты, сгенерированные динамически при помощи и затем добавленные на страницу, также не блокируют это событие.

Внешние таблицы стилей не затрагивают DOM, поэтому их не ждёт.

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

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

Так как дожидается скриптов, то теперь он так же дожидается и стилей перед ними.

Firefox, Chrome и Opera автоматически заполняют поля при наступлении .

Например, если на странице есть форма логина и пароля и браузер запомнил значения, то при наступлении он попытается заполнить их (если получил разрешение от пользователя).

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

jQuery — Отмена стандартного поведения события

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

Например, отменим стандартное поведение всех ссылок на странице, имеющих класс :

$('a.service').on('click',function(e){
  //отменяем стандартное действие браузера
  e.preventDefault();
  // действия, которые будет выполнять ссылка
  ...
});

Что такое всплытие и как его остановить

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

текущий элемент (цель) -> родительский элемент цели -> прародительский элемент -> ... -> document -> window

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

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

<div class="mark">Некоторый текст...<span class="mark">фрагмент...</span>...продолжение...</div>
...
<script>
$('.mark').on('hover',
  function(e){
    e.stopPropagation();
    $(this).css('color',orange);
  },
  function(e){
    e.stopPropagation();
    $(this).css('color',black);
  }
});
</script>

В данном случае если не указывать метод , то при поднесении курсора к элементу с классом данное событие возникнет не только у него, но и у всех его родительских элементов. А это в этом примере приведёт к тому, что изменится цвет не только текста, заключенного в , но и всего абзаца.

Если вам необходимо отменить стандартное поведение браузера и остановить всплытие события, то в jQuery вместо вызова двух этих методов можно просто вернуть в качестве результата функции значение .

$('a').on('click', function(e){
  //e.preventDefault();
  //e.stopPropagation();
  ...
  return false;
});

ИЗОБРАЖЕНИЯ

Слайд шоуГалерея слайд шоуМодальное изображениеЛайтбоксОтзывчивая сетка изображенийСетка изображенийГалерея вкладокЭффект наведения на изображениеНаложение слайда на изображениеНаложение на изображениеНаложение заголовка на изображениеНаложение иконки на изображениеЭффект к изображениюЧерно-белое изображениеТекст на изображенииИзображение с текстовым блокомИзображение c прозрачным текстомИзображение на всю страницуФорма на изображенииИзображение герояРазмытое фоновое изображениеФоновое изображениеВыравненные изображенияОкругленные изображенияИзображение аватарОтзывчивое изображениеИзображение по центруМинитюрное изображениеЗнакомство с командойЛипкое изображениеЗеркальное изображениеДрожание изображенияГалерея портфолиоПортфолио фильтрЗум изображенияЛупа изображенияПолзунок сравнения

Итак … в любом случае, какая польза от наброска?

Я нашел очень сухой веб-сайт, который хорошо все объясняет.

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

Обратите внимание, как вы можете определить, где находится фокус, даже не щелкнув поле ввода?

А теперь давайте попробуем на нашем надежном

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

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

Теперь сравните это с тем же шаблоном, если мы сохраним схему:

Итак, мы установили следующие

  1. Очертания уродливые
  2. Удаление их усложняет жизнь.

Управление фокусомСкопировать ссылку

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

Полезные практики управления фокусомСкопировать ссылку

В 99% случаев вам стоит оставить порядок фокуса в покое. Не устану это повторять.

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

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

Следует: узнать побольше про атрибут Скопировать ссылку

делает элементы фокусируемыми. В качестве значения он принимает число, в зависимости от которого меняется поведение фокуса.

Не следует: устанавливать там, где это не надоСкопировать ссылку

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

Следует: устанавливать для фокуса с помощью JavaScriptСкопировать ссылку

Атрибут используется для создания доступных интерактивных виджетов посредством JS. Прописав , вы сделаете элемент фокусируемым для JS, а также по клику или тапу, но недоступным через клавишу Tab.

Не следует: использовать положительное значение Скопировать ссылку

Это антипаттерн. Установив положительное значение , вы переопределите ожидаемый порядок элементов для фокуса через Tab и запутаете пользователя. Сделать так один раз — уже плохо, несколько — полный кошмар. Серьёзно, не надо так.

Не следует: создавать собственный порядок фокусировкиСкопировать ссылку

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

ЕЩЁ

Полноэкранное видеоМодальное окноШкала времениИндикатор прокрутки Индикатор выполненияПанель навыковПолзунок диапазонаПодсказки при наведенииВсплывающие окнаСкладная секцияКалендарьВключить HTMLСписок делЗагрузчикиЗвездный рейтингПользовательский рейтингНаложениеКонтактные чипыКарточкиФлип-картаКарточка профиляКарточка товараОкно тревогиВыноска сообщенияПримечаниеМеткиКругиHR Горизонтальная линияКупонГруппа списковОтзывчивый текстВырезанный текстСветящийся текстФиксированный подвалЛипкий элементРавная высота столбцовОчистка поплавкаОтзывчивые поплавкиСнэк-бар/тостПолноэкранное режимЧертеж при прокруткеПлавная прокруткаГрадиент фонаЛипкий заголовокИзменить заголовок при прокруткеОтзывчивые столбцы ценПараллаксСоотношение сторонПереключатель нравится/не нравитсяПереключатель скрыть/показатьПереключаель текстаПереключатель классаДобавить классУдалить классАктивный классДревовидное представлениеУдалить свойствоАвтономный режим обнаруженияСделать скрытый элементПеренаправление веб страницыУвеличить при наведенииФлип-боксЭлемент вертикально по центруПереход при наведении курсораСтрелкиФигурыСсылка для скачиванияПолная высота элементаОкно браузераПользовательская полоса прокруткиРазличные устройстваЦвет заполнителяЦвет выделения текстаЦвет макераВертикальная линияАнимированные иконкиТаймер обратного отсчетаПишущая машинкаСтраница заставкиСообщение чатаВсплывающее окно чатаРазделенный экранРекомендацииСчетчик разделаСлайд-шоу цитатЗакрываемые злементы спискаТипичные точки прерыванияПеретаскиваемый HTML элементМедиа запросы JSПодсветка синтаксисаJS анимацииПолучить элементы Iframe

Рейтинг
( Пока оценок нет )
Понравилась статья? Поделиться с друзьями:
Все про сервера
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!:

Adblock
detector