Развитие мобильной платформы. Мобильная форма Jquery

Проблема

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

Решение

Будем рассматривать данный кейс как продолжение предыдущего. Представим себе, что вы создали в Excel такой справочник:

Рис.2.1. Справочник: мэппинг статей БУ и УУ


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

(Кстати, английское слово mapping переводится как отображение или соответствие, поэтому справочник в данном случае - это некое общее правило того, как статьи БУ находят свое отображение в статья УУ).

Рис.2.2. Плоская таблица: отчет о затратах (из "Оборотов счета 20")


Обратим внимание, что в 7-м столбце появилась графа "Статья УУ". Напротив каждой статьи затрат мы проставили статью управленческого учета. Это можно сделать вручную, но гораздо удобнее воспользоваться таким инструментом:

Рис.2.3. Плоская таблица: отчет о затратах (из "Оборотов счета 20")


В нижней части формы указаны наименования страниц: "Главная" - это плоская таблица, в которой содержатся данные о затратах (рис.2.2), "спр" - это справочник (рис.2.1).

В верхней части формы указаны номер столбцов. Так, в данном случае, если данные в столбцах 1 справочника и 3 главной страницы совпадают, то данные из 2-го столбца справочника копируются в 7-й столбец главной страницы.

В этой форме также мнржество дополнительных опций. Например, можно включить галочки "Признак #2" и "Признак #3", и тогда перенесение данных из столбца 2 справочника в столбец 7 главной страницы будет возможно, если справочник и главная страница будуь совпадать сразу по двум или даже трем реквизитам.

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

Рис.2.4. Отчет по затратам арматурного цеха


Сравнение мэппинга с ВПР()

Многие пользователи хорошо знакомы и пользуются функцией ВПР() в такого рода ситуациях. Однако функция ВПР() хорошо работает только на небольших объемах данны, в то время как данная форма отлично справляется с обработкой таблтц Excel, даже если у вас в справочнике, скажем, 5000 строк, а на гоавной странице - 300 000 строк. Попробуйте проверить, и вы убедитесь, что на таких объемах ВПР() дает сбои. Кроме того, функция ВПР() создает значительную нагрузку на Excel, вынуждая его проводить большие объесы калькуляций. Форма мэппинга позволяет избежать этого недостатка: она запускается один раз, действует несколько секунд (при больших объемах минут) и после этого никаких дополнительных нагрузок на файл Excel уже не создается.


Часть 3. Отображение данных из таблицы (Операция LIST)

В предыдущей части были рассмотрены виды связей (один-к-одному, один-ко-многим, многие-ко-многим), а также один класс Book и его маппинг-класс BookMap. Во второй части обновим класс Book, создадим остальные классы и связи между ними, как это было изображено в предыдущей главе в Диаграмме баз данных, расположившейся над подзаголовком 1.3.1 Связи.

Код классов и маппингов (С комментариями)

Класс Книга

Public class Book { //Уникальный идентификатор public virtual int Id { get; set; } //Название public virtual string Name { get; set; } //Описание public virtual string Description { get; set; } //Оценка Мира фантастики public virtual int MfRaiting { get; set; } //Номера страниц public virtual int PageNumber { get; set; } //Ссылка на картинку public virtual string Image { get; set; } //Дата поступления книги (фильтр по новинкам!) public virtual DateTime IncomeDate { get; set; } //Жанр (Многие-ко-Многим) //Почему ISet а не IList? Только одна коллекция (IList) может выбираться с помощью JOIN выборки, если нужно более одной коллекции для выборки JOIN, то лучше их преобразовать в коллекцию ISet public virtual ISet Genres { get; set; } //Серия (Многие-к-одному) public virtual Series Series { get; set; } //Мнение и другое (Один-к-одному) private Mind _mind; public virtual Mind Mind { get { return _mind ?? (_mind = new Mind()); } set { _mind = value; } } //Автор (Многие-ко-многим) public virtual ISet Authors { get; set; } //Заранее инициализируем, чтобы исключение null не возникало. public Book() { //Неупорядочное множество (в одной таблице не может присутствовать две точь-в-точь одинаковые строки, в противном случае выбирает одну, а другую игнорирует) Genres = new HashSet(); Authors = new HashSet(); } } //Маппинг класса Book public class BookMap: ClassMap { public BookMap() { Id(x => x.Id); Map(x => x.Name); Map(x => x.Description); Map(x => x.MfRaiting); Map(x => x.PageNumber); Map(x => x.Image); Map(x => x.IncomeDate); //Отношение многие-ко-многим HasManyToMany(x => x.Genres) //Правила каскадирования All - Когда объект сохраняется, обновляется или удаляется, проверяются и //создаются/обновляются/добавляются все зависимые объекты.Cascade.SaveUpdate() //Название промежуточной таблицы ДОЛЖНО быть как и у класса Genre! .Table("Book_Genre"); HasManyToMany(x => x.Authors) .Cascade.SaveUpdate() .Table("Book_Author"); //Отношение многие к одному References(x => x.Series); //Отношение один-к-одному. Главный класс. HasOne(x => x.Mind).Cascade.All().Constrained(); } }

Public class Author { public virtual int Id { get; set; } //Имя-Фамилия public virtual string Name { get; set; } //Биография public virtual string Biography { get; set; } //Книжки public virtual ISet Books { get; set; } //Инициализация Авторов public Author() { Books=new HashSet(); } } //Маппинг Автора public class AuthorMap: ClassMap { public AuthorMap() { Id(x => x.Id); Map(x => x.Name); Map(x => x.Biography); //Отношение многие-ко-многим HasManyToMany(x => x.Books) //Правила каскадирования All - Когда объект сохраняется, обновляется или удаляется, проверяются и создаются/обновляются/добавляются все зависимые объекты.Cascade.All() //Владельцем коллекции явл. другой конец отношения (Book) и он будет сохранен первым. .Inverse() //Название промежуточной таблицы ДОЛЖНО быть как и у класса Book! .Table("Book_Author"); } }

Класс Жанр

Public class Genre { public virtual int Id { get; set; } //Название жанра public virtual string Name { get; set; } //Английское название жанра public virtual string EngName { get; set; } //Книжки public virtual ISet Books { get; set; } //Инициализация книг public Genre() { Books=new HashSet(); } } //Маппинг жанра public class GenreMap: ClassMap { public GenreMap() { Id(x => x.Id); Map(x => x.Name); Map(x => x.EngName); //Отношение многие-ко-многим HasManyToMany(x => x.Books) //Правила каскадирования All - Когда объект сохраняется, обновляется или удаляется, проверяются и создаются/обновляются/добавляются все зависимые объекты.Cascade.All() //Владельцем коллекции явл. другой конец отношения (Book) и он будет сохранен первым. .Inverse() //Название промежуточной таблицы ДОЛЖНО быть как и у класса Book! .Table("Book_Genre"); } }

Класс Мнение:

Public class Mind { public virtual int Id { get; set; } //Мое мнение public virtual string MyMind { get; set; } //Мнение фантлаба public virtual string MindFantLab { get; set; } //Книга public virtual Book Book { get; set; } } //Маппинг Мind public class MindMap:ClassMap { public MindMap() { Id(x => x.Id); Map(x => x.MyMind); Map(x => x.MindFantLab); //Отношение один к одному HasOne(x => x.Book); } }

Класс Цикл(Серия):

Public class Series { public virtual int Id { get; set; } public virtual string Name { get; set; } //Я создал IList, а не ISet, потому что кроме Book, Series больше ни с чем не связана, хотя можно сделать и ISet public virtual IList Books { get; set; } //Инициализация книг. public Series() { Books = new List(); } } public class SeriesMap: ClassMap { public SeriesMap() { Id(x => x.Id); Map(x => x.Name); //Отношение один-ко-многим HasMany(x => x.Books) ////Владельцем коллекции явл. другой конец отношения (Book) и он будет сохранен первым. .Inverse() } }

Небольшое объяснение
public virtual ISet Genres { get; set; }
public virtual ISet Authors { get; set; }

Почему ISet, а не, к примеру, привычный многим IList? Если использовать вместо ISet - IList, и попробовать запустить проект, то разницы особой мы не заметим (Таблицы и классы создадутся). Но когда мы к классу Book LeftJoin-им одновременно таблицу Genre и Authors, да и еще пытаемся вывести неповторяющиеся записи из таблицы Book (Distinct Book.Id) в представление (View), Nhibernate выдаст исключение и ошибку.
Cannot simultaneously fetch multiple bags.
В таких случаях используем ISet, тем более множества для этого и предназначены (игнорируют дублирующие записи).

Отношение многие-ко-многим.

В NHibernate есть понятие, «главной» таблицы. Хотя отношения «многие-ко-многим» между таблицами “Book” и “Автор” равнозначны (У автора может быть много книг, у книги может быть множество авторов), Nhibernate требует, чтобы программист указывал таблицу, которая сохраняется второй (имеет метод.inverse()), то есть вначале будет создана/обновлена/удалена запись в таблице Book, а только потом в таблице Author.
Cascade.All означает выполнение каскадных операций при save-update и delete. То есть когда объект сохраняется, обновляется или удаляется, проверяются и создаются/обновляются/добавляются все зависимые объекты (Ps. Можно прописать вместо Cascade.All -> .Cascade.SaveUpdate().Cascade.Delete())
Метод.Table(«Book_Author»); создает «промежуточную» таблицу “Book_Author” в БД.

Отношение многие-к-одному, один-ко-многим.

Метод.Constrained() говорит NHibernate, что для записи из таблицы Book должна соответствовать запись из таблицы Mind (id таблицы Mind должен быть равен id таблицы Book)

Если сейчас запустить проект и посмотреть БД Bibilioteca, то появятся новые таблицы с уже сформированными связями.

Далее заполним созданные таблицы данными…
Для этого создадим тестовое приложение, которое будет сохранять данные в БД, обновлять и удалять их, изменив HomeController следующим образом (Ненужные участки кода комментируем):
public ActionResult Index() { using (ISession session = NHibernateHelper.OpenSession()) { using (ITransaction transaction = session.BeginTransaction()) { //Создать, добавить var createBook = new Book(); createBook.Name = "Metro2033"; createBook.Description = "Постапокалипсическая мистика"; createBook.Authors.Add(new Author { Name = "Глуховский" }); createBook.Genres.Add(new Genre { Name = "Постапокалипсическая мистика" }); createBook.Series = new Series { Name = "Метро" }; createBook.Mind = new Mind { MyMind = "Постапокалипсическая мистика" }; session.SaveOrUpdate(createBook); //Обновить (По идентификатору) //var series = session.Get(1); //var updateBook = session.Get(1); //updateBook.Name = "Metro2034"; //updateBook.Description = "Антиутопия"; //updateBook.Authors.ElementAt(0).Name = "Глуховский"; //updateBook.Genres.ElementAt(0).Name = "Антиутопия"; //updateBook.Series = series; //updateBook.Mind.MyMind = "11111"; //session.SaveOrUpdate(updateBook); //Удаление (По идентификатору) //var deleteBook = session.Get(1); //session.Delete(deleteBook); transaction.Commit(); } Genre genreAl = null; Author authorAl = null; Series seriesAl = null; Mind mindAl = null; var books = session.QueryOver() //Left Join с таблицей Genres .JoinAlias(p => p.Genres, () => .JoinAlias(p => p.Authors, () => authorAl, JoinType.LeftOuterJoin) .JoinAlias(p => p.Series, () => seriesAl, JoinType.LeftOuterJoin) .JoinAlias(p => p.Mind, () => mindAl, JoinType.LeftOuterJoin) //Убирает повторяющиеся id номера таблицы Book. .TransformUsing(Transformers.DistinctRootEntity).List(); return View(books); } }

Небольшое объяснение

  1. var books = session.QueryOver() Select * From Book ;
  2. .JoinAlias(p => p.Genres, () => genreAl, JoinType.LeftOuterJoin) - подобно выполнению скрипта SQL:
    SELECT *FROM Book
    inner JOIN Book_Genre ON book.id = Book_Genre.Book_id
    LEFT JOIN Genre ON Book_Genre.Genre_id = Genre.id
  3. .TransformUsing(Transformers.DistinctRootEntity) - Подобно выполнению скрипта SQL: SELECT distinct Book.Id... , (убирает дублирующие записи с одинаковыми id)

Виды объединений
.JoinAlias(p => p.Genres, () => genreAl, JoinType.LeftOuterJoin)

  1. LeftOuterJoin - выбирает все записи из левой таблицы (Book ), а затем присоединяет к ним записи правой таблицы (Genre ). Если не найдена соответствующая запись в правой таблицы, отображает её как Null
  2. RightOuterJoin действует в противоположность LEFT JOIN - выбирает все записи из правой таблицы (Genre ), а затем присоединяет к ним записи левой таблицы (Book )
  3. InnerJoin - выбирает только те записи из левой таблиц (Book ) у которой есть соответствующая запись из правой таблицы (Genre ), а затем присоединяет к ним записи из правой таблицы

Изменим представление следующим образом:

Представление index

@model IEnumerable @{ Layout = null; } Index

@Html.ActionLink("Create New", "Create")

@foreach (var item in Model) { @{string strSeries = item.Series != null ? item.Series.Name: null;} }
@Html.DisplayNameFor(model => model.Name) @Html.DisplayNameFor(model => model.Mind) @Html.DisplayNameFor(model => model.Series) @Html.DisplayNameFor(model => model.Authors) @Html.DisplayNameFor(model => model.Genres) Операции
@Html.DisplayFor(modelItem => item.Name) @Html.DisplayFor(modelItem => item.Mind.MyMind)@Html.DisplayFor(modelItem => strSeries) @foreach (var author in item.Authors) { string strAuthor = author != null ? author.Name: null; @Html.DisplayFor(modelItem => strAuthor)
}
@foreach (var genre in item.Genres) { string strGenre = genre!= null ? genre.Name: null; @Html.DisplayFor(modelItem => strGenre)
}
@Html.ActionLink("Edit", "Edit", new { id = item.Id }) | @Html.ActionLink("Details", "Details", new { id = item.Id }) | @Html.ActionLink("Delete", "Delete", new { id = item.Id })


Проверив поочередно все операции, мы заметим, что:
  • При операциях Create и Update обновляются все данные, связанные с таблицей Book (уберите Cascade=«save-update» или cascade=«all» и связанные данные не будут сохранены)
  • При удалении удаляются данные из таблиц Book, Mind, Book_Author, а остальные данные не удаляются, потому что у них Cascade=«save-update»

Маппинг для классов, у которых есть наследование.
А как маппить классы у которых есть наследование? Допустим, имеем такой пример:
//Класс Двумерных фигур public class TwoDShape { //Ширина public virtual int Width { get; set; } //Высота public virtual int Height { get; set; } } //Класс треугольник public class Triangle: TwoDShape { //Идентификационный номер public virtual int Id { get; set; } //Вид треугольника public virtual string Style { get; set; } }

В принципе, ничего сложного в этом маппинге нет, мы просто создадим один маппинг для производного класса, то есть таблицы Triangle.
//Маппинг треугольника public class TriangleMap: ClassMap { public TriangleMap() { Id(x => x.Id); Map(x => x.Style); Map(x => x.Height); Map(x => x.Width); } }
После запуска приложения, в БД Biblioteca появится следующая (пустая) таблица

Теги: Добавить метки

Данная статья является анонсом новой функциональности.
Не рекомендуется использовать содержание данной статьи для освоения новой функциональности.
Полное описание новой функциональности будет приведено в документации к соответствующей версии.
Полный список изменений в новой версии приводится в файле v8Update.htm.

Реализовано в версии 8.3.11.2867.

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

Планировщик

Объектная модель «мобильного» планировщика не изменилась, а вот способы взаимодействия пользователя с планировщиком поменялись, так как методы ввода информации на мобильных устройствах отличаются от тех, которые применяются в настольных компьютерах.

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

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

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

Форматированный документ

Еще один «новый» объект, который мы добавили в мобильную платформу, это ФорматированныйДокумент . С точки зрения пользователя «мобильный» форматированный документ отличается только тем, что его панель редактирования встроена в сам элемент управления, и является логической частью виртуальной клавиатуры. От вас, как от разработчиков, не требуется её отдельное добавление в конфигурацию. Панель редактирования имеет разный вид в зависимости от типа мобильного устройства (телефон или планшет).

Предварительный просмотр «мобильной» формы в конфигураторе

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

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

Тут же вы можете повернуть мобильное устройство.


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


Помимо этого вы можете просматривать «мобильные» формы в трех разных масштабах:

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

Пакетная обработка табличных документов

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

Развитие доставляемых уведомлений

Мы реализовали поддержку службы push-уведомлений Windows (WNS , Windows Notification Services). Теперь вы можете использовать функциональность доставляемых уведомлений при работе мобильного приложения на платформах семейства Windows.

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

Аппаратное ускорение в операционной системе Android

На версиях операционной системы Android 4.4.2 и выше мобильная платформа теперь использует аппаратное ускорение. Это позволило увеличить скорость отрисовки интерфейса в 1,5 – 3 раза.

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

Данные на 2014 год показывают, что только в одних США, у 90% взрослых есть мобильный телефон, из которых 58% -это обладатели смартфонов. 42% американцев владеют планшетами. В своем докладе, eMarketer прогнозировали, что к концу 2014ого люди будут пользоваться около 1.75 биллионами смартфонов по всему миру.

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

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

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

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

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

1. Включайте только самые важные детали в свою форму

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

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

2. Используйте выравнивание по высоте для лейблов и полей ввода.

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

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

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

3. Используйте разворачивающиеся меню и выпадающие списки

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

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

4. Используйте адекватные списки выбора

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

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

5. Простой ввод входных данных

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

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

6. Отформатируйте кнопки вашей формы

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

Сделайте кнопку “Подтвердить” привлекательной, установив ее ширину в 1/3 от вашей формы, либо покрасив ее в яркий цвет. А вместо того, чтобы просто использовать слова “Подтвердить” или “Отправить”, прибегайте к более красноречивым призывам к действию, например, “Зарегистрируйтесь сейчас” или “Отправьте заявку”.

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

7. Установите масштабирование с помощью мета-тега viewport

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

8. Предоставляйте возможность сохранять данные

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

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

9. Помогайте клиентам отслеживать свой прогресс

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

10. Сделайте так, чтобы форма загружалась быстро

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

И как всегда, тестируйте ваши формы на всех системах и устройствах

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

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

Типы HTML5 Input

HTML5 имеет кучу новых типов ввода для форм. Эти типы вводов позволяют лучше контролировать входные данные и проверять их. Некоторые из них особенно полезны для мобильных пользователей, у которых часто возникают трудности с работой HTML Input . Полный список типов входных данных приводится ниже:

  • color — выбор цвета
  • date — выбор даты
  • datetime — выбор даты и времени
  • email — валидация email-маски
  • number — ввод номер
  • range — слайдер диапзаонов
  • search — поле для поиска
  • tel — валидация маски телефона
  • time — выбор времени
  • url — валидация URL

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

1. Input type color

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

< input type = "color" / >

Пример работы:

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

Выберите Ваш цвет:

К сожалению, поддержка данного типа мобильными браузерами оставляет желать лучшего. Из всех существующих, корректное отображение можно найти только в Opera Mobile и Chrome Android . Для всех остальных обозревателей будет показано пустое текстовое поле. Это стоит иметь ввиду. Как вариант, можно набросать палитру на JS либо воспользоваться плагинами.

2. Input type date

Если поддерживается браузером, то предоставляет удобный блок для выбора даты.

< input type = "date" / >

Пример работы:

Выбор даты:

Обратите внимание, что тип ввода Date , а также варианты типа datetime и datetime-local предлагают полезные атрибуты, такие значения, как min и max , которые могут устанавливать ограничение и проверку данных, вводимых пользователем. Мы это продемонстрируем ниже по тексту.

Тип HTML Input Date поддерживается почти всеми браузерами. Исключение составляют Opera Mini и дефолтный браузер Android.

3. Input type datetime и datetime-local

Этот тип Input позволяет пользователю указывать дату и время в удобном формате. Если поддерживается, то будет отображен как родной виджет дата\время устройства. Разница между указанными типами ввода состоит в том, что первый привязывается к мировому времени, а второй не содержит никакой информации о временной зоне.

< input type = "datetime-local" / >

Пример работы:

Выбор даты и времени:

Не поддерживается в IE Mobile и Opera Mini. На остальных популярных обозревателях (мобильных) тип работает более мене корректно, однако не редки случаи багов и глюков. Имейте и это ввиду тоже, и не забывайте о запасных вариантов на JavaScript .

4. Input type email

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

< input type = "email" / >

Пример работы:

Введите Ваш e-mail адрес:

Перед отправкой, браузер проверяет корректность заполненного поля и сообщает пользователю в случае недопустимого формата ввода. Расчет идет по следующему выражению {text}@{domain}

5. Input type number и tel

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

Пример работы:

Выбор значения:

Диапазон по умолчанию в большинстве браузеров находится между 0 и 100. То есть крайнее левое положение ползунка соответствует 0, а правое 100. Можно изменить диапазон с помощью атрибутов min и Max. Мы также можем задать значение шага, через шаг атрибута. Так, чтобы указать диапазон от 5 до 50, с шагом 5, мы будем использовать:

< input type = "range" min = "5" max = "50" step = "5" / >

Поддержка всеми популярными браузерами, кроме Opera Mini.

7. Валидация формы

Весьма удобно задать специальные атрибуту HTML Input для проверки вводимых данных. К примеру, мы хотим создать поле, которое должно быть обязательно заполнено: