Email already exists перевод

4. Контроль обмена данными с сервером

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

  1. Нажатие на ссылку отправит для получения новой страницы и её рендеринга.
  2. Отправка формы отправит POST или GET с последующим рендерингом новой страницы.
  3. Внедрение изображения или объекта отправит GET асинхронно с последующим рендерингом.

Простота такой модели очень привлекательна, и сейчас всё определённо усложнилось, когда речь идёт о понимании, как получать и отправлять информацию.

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

Вероятно, самый раздражающий артефакт старого веба

Именно поэтому веб как платформа для приложений оставался неполноценным без JavaScript. Ajax представлял собой огромный скачок вперед с точки зрения удобства в части публикации информации пользователем.

Сейчас у нас есть множество API (XMLHttpRequest, WebSocket, EventSource, это лишь некоторые из них), которые дают полный и чёткий контроль над потоком данных. Кроме возможности публиковать пользовательские данные через форму, у нас появились новые возможности по улучшению UX.

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

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

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

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

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

Предупреждение

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

История веб-разработки

История веб-разработки началась в конце 1980-х годов, когда инженер Тим Бернерс-Ли в Исследовательском центре CERN в Швейцарии разработал язык разметки гипертекста (HTML) и протокол передачи гипертекста (HTTP).

Тим Бернерс-Ли

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

6 августа 1991 года был создан первый веб-сайт, который содержал информацию об исследовательском проекте World Wide Web (WWW). Это был максимально простой сайт, по сегодняшним меркам.

Самый первый в Мире сайт

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

В 2000-х веб-разработка продолжила развиваться с появлением новых технологий, таких как AJAX, которая позволяла обновлять содержимое страницы без ее полной перезагрузки. Также появились новые библиотеки и фреймворки, такие как jQuery, Angular и React, которые упростили процесс разработки веб-приложений и сделали его более системным.

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

Реакция на изменение данных

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

Уходит в прошлое модель передачи по HTML данных, которые остаются статичными до тех пор, пока пользователь не обновит страницу (традиционные веб-сайты) или не взаимодействует с ней (Ajax).

Ваш UI должен обновляться автоматически.

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

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

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

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

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

Однопользовательское приложение тоже может получить пользу от «реактивности»

Полезно представлять всю информацию, которая отправляется пользователю как «реактивную». Синхронизация сессии и состояния авторизации — один из примеров универсального подхода. Если у пользователей вашего приложения одновременно открыто несколько вкладок, то окончание рабочей сессии на одной из них должно сразу деактивировать авторизацию на всех остальных. Это неизбежно ведёт к улучшению безопасности и лучшей защите конфиденциальной информации, особенно в ситуациях, когда несколько человек имеют доступ к одному устройству.

Каждая страница реагирует на состоянии сессии и статус авторизации

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

Представьте, что вы закрываете крышку ноутбука и открываете её через несколько дней. Как будет вести себя приложение?

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

Пример того, что происходит в случае некорректного обновления связи

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

5. Не ломай историю, улучшай её

Если не считать отправки форм, то при использовании в веб-приложении одних только гиперссылок у нас будет полностью функциональная навигация «Вперёд/Назад» в браузере.

К примеру, типичную «бесконечную» страницу обычно делают с помощью кнопки на JavaScript, которая запрашивает дополнительные данные/HTML и вставляет их. К сожалению, немногие при этом помнят о необходимости вызова или как обязательного шага.

Вот почему я использую слово «ломать». С простой моделью первоначального веба такая ситуация была невозможна. Каждое изменение состояния основывалось на изменении URL.

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

Это как рассматривать кнопку «Назад» в качестве кнопки из веб-приложения и применить к ней принцип № 2: немедленно реагировать на действие пользователя. Главное, что у вас есть возможность решить, как организовать кеширование предыдущей страницы и мгновенно вывести её на экран. Вы можете затем применить принцип № 3, а потом информировать пользователя о поступлении новых данных на эту страницу.

Всё ещё остаётся несколько ситуаций, когда вы не можете контролировать поведение кеша. Например, если вы отрендерили страницу, затем ушли на сторонний сайт, а потом пользователь нажал «Назад». Этому маленькому багу особенно подвержены приложения, которые рендерят HTML на стороне сервера, а потом модифицируют его на стороне клиента:

Некорректная работа кнопки «Назад»

Ещё один способ сломать навигацию — игнорирование памяти о состоянии прокрутки. Ещё раз, страницы, которые не используют JS и ручное управление историей, скорее всего, не будут иметь тут проблем. Но динамические страницы будут. Я протестировал две самые популярные новостные ленты на основе JavaScript в интернете: Twitter и Facebook. У обоих обнаружилась амнезия на прокрутку.

Бесконечное листание страниц — обычно, признак скроллинг-амнезии

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

Изменение вида комментариев нужно сохранять в истории

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

Переводчик с английского на русский онлайн бесплатно

Используйте наш бесплатный переводчик с английского на русский и переводите свои тексты в режиме онлайн. Для перевода с английского введите текст в верхнее поле редактирования. Затем нажмите на зеленую кнопку «Перевести», и текст будет переведен.

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

  /5000✕

Переводчик с русского на английский

Инструменты и технологии

Языки программирования

Существует множество языков программирования, которые используются для веб-разработки. Некоторые из наиболее популярных:

  • JavaScript – это один из наиболее популярных языков программирования, используемых для frontend разработки. Он используется для создания интерактивных и динамических элементов на веб-страницах.
  • PHP – это язык программирования, который широко используется для создания серверной логики веб-приложений. Он часто используется в сочетании с базами данных, такими как MySQL, для создания динамических веб-страниц.
  • Python – это язык программирования, который часто используется для backend разработки. Он известен своей простотой и удобством в использовании, а также благодаря множеству библиотек и фреймворков, доступных для использования.
  • Ruby – это язык программирования, который часто используется для backend разработки веб-приложений. Чаще всего используется как фреймворк Ruby on Rails.
  • Java – это язык программирования, который известен своей масштабируемостью и надежностью.

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

Библиотеки и фреймворки

Библиотеки и фреймворки для веб-разработки упрощают процесс создания сайтов и приложений и позволяют разработчикам быстрее создавать их и проще поддерживать.

Некоторые из наиболее популярных библиотек и фреймворков:

  • React – это библиотека JavaScript, которая используется для создания интерактивных пользовательских интерфейсов.
  • Angular – это фреймворк JavaScript, который используется для создания больших масштабируемых веб-приложений.
  • Vue.js – это прогрессивный фреймворк JavaScript, который используется для создания интерактивных пользовательских интерфейсов.
  • Laravel – это фреймворк PHP.
  • Django – это фреймворк Python.
  • Ruby on Rails – это фреймворк Ruby.
  • Express.js – это фреймворк Node.js, который используется для создания серверной логики веб-приложений.

Системы контроля версий

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

Некоторые из наиболее популярных систем:

  • Git – это наиболее распространенная система контроля версий, используемая для управления изменениями в коде. Git позволяет разработчикам работать совместно над проектом и отслеживать версии кода.
  • SVN (Subversion) – это другая распространенная система контроля версий, используемая для управления изменениями в коде. SVN обеспечивает более простой интерфейс, чем Git, и может быть удобнее в использовании для менее опытных разработчиков.
  • Mercurial – это еще одна система контроля версий, которая похожа на Git, но имеет некоторые отличия в функциональности и интерфейсе.
  • Perforce – это коммерческая система контроля версий, которая широко используется в больших компаниях и организациях, где необходимо управлять изменениями в больших проектах.

Среды разработки

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

  • Visual Studio Code – это бесплатный инструмент от Microsoft, который поддерживает множество языков программирования. Он имеет большое сообщество пользователей и огромное число плагинов.
  • WebStorm – это платный IDE, который разработан специально для веб-разработки..
  • Atom – это бесплатный IDE с открытым исходным кодом.
  • Sublime Text – это платный IDE, который также поддерживает множество языков программирования.

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

Возможности языка программирования JavaScript

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

JavaScript поддерживает четыре простых типа данных: целый, вещественный, строковый, булевый или логический.

Для присваивания переменным значений основных типов применяются литералы — буквенные значения данных соответствующих типов.

Целые литералы являются последовательностью цифр и представляют обычные целые числа со знаком или без знака: 123 (целое положительное число), -123 (целое отрицательное число), +123 (целое положительное число)

Для задания вещественных литералов используется синтаксис чисел с десятичной точкой, отделяющей дробную часть числа от целой, или запись вещественных чисел в научной нотации с указанием после символа “e” или “E” порядка числа. Пример правильных вещественных чисел:

1.25 , 0.125e01, 12.5E-1, 0.0125E+2

Строковый литерал — последовательность алфавитно-цифровых символов, заключенная в одинарные (`) или двойные кавычки (“), например: “Ира”, `ИРА’. При задании строковых переменных нельзя смешивать одинарные и двойные кавычки. Недопустимо задавать строку, например, в виде “Ира’. Двойные кавычки — это один самостоятельный символ, а не последовательность двух символов одинарных кавычек. Если в строке нужно использовать символ кавычек, то строковый литерал необходимо заключать в кавычки противоположного вида: “It’s a string” // Значение строки равно It’s a string

Булевы литералы имеют два значения: true и false, и используются для обработки ситуаций да/нет в операторах сравнения.

Люди уже давно изобрели множество разных языков программирования, которые выступают в роли посредника между человеком и машиной. Язык программирования — это программа, которая читает текст исходного кода, содержащего более привычные команды, такие как print (печать) или сору (копировать), и автоматически преобразует их в двоичные машинные команды. По способу преобразования исходного кода в машинный код языки программирования подразделяются на компилируемые и интерпретируемые. Компилируемые языки программирования — это код, написанный на компилируемом языке, передается в программу — компилятор, которая, прежде всего, проверяет код на наличие ошибок, а затем переводит текст программы в бинарный машинный код и сохраняет результат в исполняемом файле (с расширением ехе) или в библиотеке программных модулей (с расширением .dll). Если компилятор обнаруживает в исходном коде ошибки, процесс компиляции останавливается и разработчику отправляется список ошибок. После исправления ошибок компиляция начинается сначала. Таким образом, невозможно скомпилировать программу, в коде которой есть синтаксические ошибки. К сожалению, компилятор не защищает разработчика и будущих пользователей от логических ошибок в коде программы, которые уже невозможно исправить в конечном файле.

Другая проблема состоит в несовместимости программ, созданных для разных операционных систем и компьютерных платформ. Так, для того чтобы программа, написанная на С++, работала на компьютерах с операционными системами Windows, OS/2 и Масiпtоsh, необходимо использовать соответствующие компиляторы. Кроме этого, часто приходится вносить изменения в исходный код программы, поскольку компиляторы разных систем стандартизированы не в полной мере. К компилируемым языкам программирования относятся языки семейства С (С, С++ и C#), java и многие другие.

6. Обновление кода через push-сообщения

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

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

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

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

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

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

Если серверный push-канал работает, то пользователю можно выслать уведомление о доступности нового кода. Если нет, то номер версии можно добавить в заголовок исходящих HTTP-запросов. Сервер может сравнить его с последней известной версией, согласиться на обработку запроса или нет, и выдать задание для клиента.

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

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

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

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

Типы веб-разработки

Front-end веб-разработка

Front-end разработка – это разработка пользовательских интерфейсов для веб-сайтов и приложений, которые пользователи видят и с которыми непосредственно взаимодействуют.

Задачи front-end разработчика включают в себя:

  • Разработка HTML-разметки, которая определяет структуру веб-страницы.
  • Создание каскадных таблиц стилей (CSS), которые определяют внешний вид веб-страницы.
  • Разработка JavaScript, который позволяет реализовывать интерактивность на веб-страницах и фоновый обмен данными с сервером.
  • Оптимизация веб-страниц для ускорения загрузки и улучшения пользовательского опыта.
  • Работа с библиотеками и фреймворками, такими как React, Angular и Vue.js, для создания динамических интерфейсов и управления состоянием приложения.

Для успешной работы front-end разработчик должен иметь знания в области HTML, CSS, JavaScript и современных фреймворков и библиотек, а также понимать принципы дизайна пользовательского интерфейса и взаимодействия пользователя с веб-страницами и приложением.

Back-end веб-разработка

Back-end разработка – это процесс создания серверной части веб-приложения. Она включает в себя разработку баз данных, серверной логики, API (Application Programming Interface) и других компонентов, которые управляют функциональностью веб-сайта или приложения.

Back-end разработчики работают с языками программирования, такими как PHP, Ruby, Python, Java, C#, Node.js и другими, и используют специализированные фреймворки и библиотеки для ускорения и упрощения процесса разработки и поддержки проекта.

Для хранения и управления данными, используемыми в веб-приложении, используются базы данных (БД), такие как MySQL, PostgreSQL, MongoDB и другие.

Full-stack

Full-stack разработка означает создание как клиентской (frontend) части веб-приложения, так и серверной (backend) части.

Заключение

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

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

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

Выводы

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

Одним из основных преимуществ веб-разработки является то, что она является относительно доступной профессией. Вы можете начать изучение веб-разработки даже без предварительного опыта программирования, используя онлайн-курсы и ресурсы, часть из которых бесплатны (например, ролики на youtube).

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

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

Понравилась статья? Поделиться с друзьями:
Опытный компьютерщик
Добавить комментарий

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