Backbone — загрузка изображений на сервер


Содержание

Шаблон Backbone Backbone Template

Шаблон Backbone SPA было написано с Кази Манзур Рашид The Backbone SPA Template was written by Kazi Manzur Rashid

Для начала работы, быстрого создания интерактивных клиентские веб-приложений с помощью предназначен данный шаблон Backbone.js SPA Backbone.js. The Backbone.js SPA template is designed to get you started quickly building interactive client-side web apps using Backbone.js.

Шаблон предоставляет начальной основу для разработки приложения Backbone.js в ASP.NET MVC. The template provides an initial skeleton for developing a Backbone.js application in ASP.NET MVC. Изначально он предоставляет функции базового пользовательского входа в систему, включая сброс пароля регистрации, входа в систему пользователя и подтверждение пользователя с помощью шаблонов базовый адрес электронной почты. Out of the box it provides basic user login functionality, including user sign-up, sign-in, password reset, and user confirmation with basic email templates.

Создание проекта шаблона магистрали Create a Backbone Template Project

Скачайте и установите шаблон, нажав кнопку «скачать» выше. Download and install the template by clicking the Download button above. Шаблон упаковывается в формате Visual Studio Extension (VSIX). The template is packaged as a Visual Studio Extension (VSIX) file. Может потребоваться перезапустить Visual Studio. You might need to restart Visual Studio.

В шаблоны области выберите установленные шаблоны и разверните Visual C# узла. In the Templates pane, select Installed Templates and expand the Visual C# node. В разделе Visual C# выберите Web. Under Visual C#, select Web. В списке шаблонов проектов выберите веб-приложение ASP.NET MVC 4. In the list of project templates, select ASP.NET MVC 4 Web Application. Имя проекта и нажмите кнопку ОК. Name the project and click OK.

В новый проект мастера можно выбрать проект SPA Backbone.js. In the New Project wizard, select Backbone.js SPA Project.

Нажмите клавиши Ctrl-F5, чтобы построить и запустить приложение без отладки, или нажмите клавишу F5, чтобы запустить программу с отладкой. Press Ctrl-F5 to build and run the application without debugging, or press F5 to run with debugging.

Нажав кнопку «Моя учетная запись» можно открыть страницу входа: Clicking «My Account» brings up the login page:

Пошаговое руководство. Код клиента Walkthrough: Client Code

Давайте начинается со стороны клиента. Let’s starts with the client side. Сценарии приложений клиента находятся в папке

/Scripts/application. The client application scripts are located in the

/Scripts/application folder. Приложение создается на языке TypeScript (TS-файлы) которые компилируются в код JavaScript (JS-файлов). The application is written in TypeScript (.ts files) which are compiled into JavaScript (.js files).

Приложение Application

Application определяется в application.ts. Application is defined in application.ts. Этот объект Инициализирует приложение и выступает в качестве корневого пространства имен. This object initializes the application and acts as the root namespace. Это обеспечивает сведения о конфигурации и состояния, который совместно используется приложение, например является ли пользователь выполнил вход. It maintains configuration and state information that is shared across the application, such as whether the user is signed in.

application.start Метод создает модальных представлений и присоединяет обработчики событий для события уровня приложения, например вход пользователя. The application.start method creates the modal views and attaches event handlers for application-level events, such as user sign-in. Далее создается по умолчанию маршрутизатором и проверяет, задано ли любой URL-адрес на стороне клиента. Next, it creates the default router and checks whether any client-side URL is specified. Если нет, он перенаправляет на URL-адрес по умолчанию (#! /). If not, it redirects to the default url (#!/).

События Events

События всегда важны, при разработке слабо связанными компонентами. Events are always important when developing loosely coupled components. Приложения часто выполняют несколько операций в ответ на действия пользователя. Applications often perform multiple operations in response to a user action. Магистраль предоставляет встроенные события с компонентами, такими как модель, коллекции и представления. Backbone provides built-in events with components such as Model, Collection, and View. Вместо создания зависимостей между среди этих компонентов, в шаблоне используется модель «pub/sub»: events Объект, определенный в events.ts, выступает в роли концентратора событий для публикации и подписки на события приложения. Instead of creating inter-dependencies among these components, the template uses a «pub/sub» model: The events object, defined in events.ts, acts as an event hub for publishing and subscribing to application events. events Объекта является единственным. The events object is a singleton. Ниже показано, как подписаться на событие и последующего инициирования события: The following code shows how to subscribe to an event and then trigger the event:

Маршрутизатор Router

В Backbone.js маршрутизатор предоставляет методы для маршрутизации страниц на стороне клиента и соединить их действия и события. In Backbone.js, a router provides methods for routing client-side pages and connecting them to actions and events. Шаблон определяет одним маршрутизатором, в router.ts. The template defines a single router, in router.ts. Маршрутизатор создает activable представления и поддерживает состояние, при переключении представлений. The router creates the activable views and maintains the state when switching views. (В следующем разделе описываются представления activable.) Изначально проект имеет два представления фиктивный, Home и About. (Activable views are described in the next section.) Initially, the project has two dummy views, Home and About. Он также содержит представления не найдено, которая отображается в том случае, если маршрут не известен. It also has a NotFound view, which is displayed if the route is not known.

Представления Views

Представления определяются в

/Scripts/application и представлений. The views are defined in

/Scripts/application/views. Существует два вида представления activable и представления модальное диалоговое окно. There are two kinds of views, activable views and modal dialog views. Activable представления вызываются маршрутизатором. Activable views are invoked by the router. При отображении activable представление всех остальных activable представлений становятся неактивными. When an activable view is shown, all other activable views become inactive. Создание представления «activable», расширение представления с Activable объекта: To create an activable view, extend the view with the Activable object:

Расширение с помощью Activable добавляет два новых метода в представление activate и deactivate . Extending with Activable adds two new methods to the view, activate and deactivate . Маршрутизатор вызывает эти методы для активации и deactive представления. The router calls these methods to activate and deactive the view.

Модальные представления реализуются как Twitter Bootstrap создания дочерних модальных диалогов. Modal views are implemented as Twitter Bootstrap modal dialogs. Membership И Profile представления являются модальным. The Membership and Profile views are modal views. Модели представления может быть инициировано любые события приложения. Model views can be invoked by any application events. Например, в Navigation показано представление, щелкнув ссылку «Моя учетная запись», либо Membership представления или Profile представление, в зависимости от того, вошел ли пользователь. For example, in the Navigation view, clicking the «My Account» link shows either the Membership view or the Profile view, depending on whether the user is logged in. Navigation Вкладывает щелкните обработчики событий, чтобы все дочерние элементы, имеющие data-command атрибута. The Navigation attaches click event handlers to any child elements that have the data-command attribute. Вот HTML-разметка: Here is the HTML markup:

Ниже приведен код в navigation.ts для подключения событий: Here is the code in navigation.ts to hook up the events:

Модели Models

Модели определяются в

/Scripts/application/моделей. The models are defined in

/Scripts/application/models. Все модели имеют три основных действия: атрибуты по умолчанию, правила проверки и конечную точку на стороне сервера. The models all have three basic things: default attributes, validation rules, and a server-side end point. Вот типичный пример: Here is a typical example:

Подключаемые модули Plug-ins

/Scripts/application/lib содержит несколько подключаемых модулей под рукой jQuery. В файле form.ts определяется подключаемый модуль для работы с данными формы. The

/Scripts/application/lib folder contains a few handy jQuery plug-ins. The form.ts file defines a plug-in for working with form data. Часто необходимо сериализовать или десериализовать данные формы и какие-либо ошибки проверки модели. Often you need to serialize or deserialize form data and show any model validation errors. Подключаемый модуль form.ts содержит методы, такие как serializeFields , deserializeFields , и showFieldErrors . The form.ts plug-in has methods such as serializeFields , deserializeFields , and showFieldErrors . В следующем примере показано, как сериализовать форму в модель. The following example shows how to serialize a form to a model.

Подключаемый модуль flashbar.ts предоставляет различные виды сообщений обратной связи для пользователя. The flashbar.ts plug-in gives various kinds of feedback messages to the user. Методы являются $.showSuccessbar , $.showErrorbar и $.showInfobar . The methods are $.showSuccessbar , $.showErrorbar and $.showInfobar . На самом деле его используется для отображения хорошо анимированных сообщения оповещения Twitter Bootstrap. Behind the scenes, it uses Twitter Bootstrap alerts to show nicely animated messages.

Подключаемый модуль confirm.ts заменяет браузера подтверждения, несмотря на то, что API немного отличаются: The confirm.ts plug-in replaces the browser’s confirm dialog, although the API is somewhat different:

Пошаговое руководство. Серверный код Walkthrough: Server Code

Теперь давайте взглянем на стороне сервера. Now let’s look at the server side.

Контроллеры Controllers

В одностраничное приложение сервер играет лишь малую роль в пользовательском интерфейсе. In a single page application, the server plays only a small role in the user interface. Как правило сервер отображает начальную страницу и затем отправляет и получает данные JSON. Typically, the server renders the initial page and then sends and receives JSON data.

Этот шаблон содержит два контроллера MVC: HomeController отображает начальную страницу, и SupportsController используется для подтверждения новых учетных записей пользователей и сбрасывать пароли. The template has two MVC controllers: HomeController renders the initial page, and SupportsController is used to confirm new user accounts and reset passwords. Все остальные контроллеры в шаблоне являются контроллерами веб-API ASP.NET, отправляющие и получающие данные JSON. All other controllers in the template are ASP.NET Web API controllers, which send and receive JSON data. По умолчанию контроллеры используют новый WebSecurity классом для выполнения задач, связанных с пользователем. By default, the controllers use the new WebSecurity class to perform user-related tasks. Тем не менее они также имеют дополнительные конструкторы, которые позволяют передавать в делегаты для выполнения следующих задач. However, they also have optional constructors that let you pass in delegates for these tasks. Это упрощает тестирование и позволяет заменить WebSecurity по-другому, используя контейнер IoC. This makes testing easier, and lets you replace WebSecurity with something else, by using an IoC Container. Пример: Here is an example:

Представления Views

Представления предназначены модульная структура: Каждый раздел страницы имеет свой собственный выделенный представление. The views are designed to be modular: Each section of a page has its own dedicated view. В одностраничное приложение довольно часто для включения, у которых нет любой соответствующий контроллер представления. In a single page application, it is common to include views that do not have any corresponding controller. Представление можно включить путем вызова @Html.Partial(‘myView’) , но это становится несколько занудным. You can include a view by calling @Html.Partial(‘myView’) , but this gets tedious. Чтобы облегчить эту задачу, шаблон определяет вспомогательный метод, IncludeClientViews , который выполняет визуализацию всех представлений в указанной папке: To make this easier, the template defines a helper method, IncludeClientViews , that renders all of the views in a specified folder:

Если имя папки не указан, по умолчанию папка называется «ClientViews». If the folder name is not specified, the default folder name is «ClientViews». Если представление вашего клиента также использует разделяемые представления, имя частичного представления с символа подчеркивания (например, _SignUp ). If your client view also uses partial views, name the partial view with an underscore character (for example, _SignUp ). IncludeClientViews Метод исключает все представления, имена которых начинаются с символа подчеркивания. The IncludeClientViews method excludes any views whose name starts with an underscore. Чтобы включить частичное представление в представление клиента, вызовите Html.ClientView(‘SignUp’) вместо Html.Partial(‘_SignUp’) . To include a partial view in the client view, call Html.ClientView(‘SignUp’) instead of Html.Partial(‘_SignUp’) .

Отправка сообщения электронной почты Sending Email

PHP. Загрузка изображений на сервер

Итак, мы продолжаем обсуждать тему загрузки файлов на сервер. Если вы ещё не читали статью «Что необходимо учитывать при загрузке файлов на сервер», то рекомендую начать именно с неё.

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

  1. Корректную загрузку картинки на сервер.
  2. Проверку, выбран файл или нет.
  3. Проверку на размер файла.
  4. Грамотную проверку расширения файла.

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

Для начала определим, какие файлы и папки будут в нашем проекте:

  1. index.php – обработчик отправки формы
  2. functions.php – библиотека с двумя функциями
  3. img – папка, в которую будут загружаться изображения

Посмотрим на содержимое индекса.

Кода много, но, пожалуйста, не пугайтесь! Большая часть знакома вам из предыдущей статьи.

Главное — просто понять схему работы данного скрипта. У нас есть две функции:

  1. can_upload – производит все проверки: возвращает true либо строку с сообщением об ошибке
  2. make_upload – производит загрузку файла на сервер

Соответственно, если форма была отправлена, мы сначала вызываем функцию can_upload. Если она подтвердила, что файл подходит нам по всем параметрам, то мы вызываем функцию make_upload. Иначе просто распечатываем сообщение об ошибке.

Здесь всё достаточно коротко и логично. Схема стандартная. Поэтому нас больше интересует, а что именно делают эти загадочные функции can_upload и make_upload!

Загрузка изображений — фукнции.

Рассмотрим файл functions.php

Сначала всего пару слов про функцию make_upload, поскольку она проще. Обратите внимание на то, что мы перед именем файла вставляем mt_rand(0, 10000), т.е, случайное число от 0 до 10000. Делается это для того, чтобы у файла было уникальное имя. В противном случае, при загрузке двух картинок с одинаковыми именами, вторая заменит первую.

Кстати, если вы задались резонным вопросом, а где же закрывающий тег php в данном файле, значит, вы явно не читали статью «Ошибка headers already sent»!

Необходимые проверки

Основной же интерес для нас представляет функция can_upload.

($file[‘name’] == ») — мелочь, знакомая вам по предыдущей статье.

А вот ($file[‘size’] == 0) — это забавно! Особенно с учётом того, что мы говорим при этом, что файл слишком большой! Разгадка кроется в том, что если файл был больше, чем разрешено в настройках сервера, то он не будет загружен вообще. А если файл не загружен, то вполне логично, что его размер равен нулю.

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

Вот собственно говоря и всё! Скрипт надёжный, аккуратный и лаконичный.

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

Backbone JavaScript-клиент для WordPress REST API

WordPress REST API «из коробки» включает в себя клиентскую JavaScript-библиотеку на основе фреймворка Backbone.js.

Библиотека предоставляет интерфейс к WP REST API, используя модели и коллекции Backbone для всех конечных точек (эндпоинтов) в схеме API.

Как использовать

Тут варианта всего два: либо напрямую подключить wp-api :

Либо поставить данный скрипт в зависимости к любому из своих внутри темы или плагина:

Библиотека парсит корневые эндпоинты и создаёт соотношения Backbone-моделей и коллекций. После чего вам становятся доступными два корневых объекта: wp.api.models и wp.api.collections .

Модели включают в себя:

  • Category
  • Comment
  • Media
  • Page
  • PageMeta
  • PageRevision
  • Post
  • PostMeta
  • PostRevision
  • Schema
  • Status
  • Tag
  • Taxonomy
  • Type
  • User

Коллекции включают в себя:

  • Categories
  • Comments
  • Media
  • PageMeta
  • PageRevisions
  • Pages
  • Posts
  • Statuses
  • Tags
  • Taxonomies
  • Types
  • Users

Используя эти эндпоинты, как есть, вы можете читать, обновлять, создавать и удалять записи, причём работает это всё на стандартных методах Backbone ( fetch , sync , save и destroy для моделей, sync для коллекций). Эти объекты очень просто расширяются, благодаря чему вы с легкостью можете построить свои представления поверх них.

Значения по умолчанию

Каждая модель или представление включают в себя ссылку на значения по умолчанию. Например, для wp.api.models.Post.prototype.args это:

  • author: null
  • comment_status: null
  • content: null
  • date: null
  • date_gmt: null
  • excerpt: null
  • featured_image: null
  • format: null
  • modified: null
  • modified_gmt: null
  • password: null
  • ping_status: null
  • slug: null
  • status: null
  • sticky: null
  • title: null

Доступные методы

Каждая модель или коллекция содержит список поддерживаемых методов. Например, модели, созданные для wp.api.models.Post , имеют такой массив методов:

Разрешенные параметры

Каждая модель или коллекция содержит список опций, которые принимает соответствующая конечная точка, например, у wp.api.collections.Posts.prototype.options это:

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

Локализация схемы API

Клиент получает и использует cхему как часть объекта wpApiSettings .

В настоящее время схема не передается по умолчанию, вместо этого клиент делает ajax-запрос к API для загрузки cтруктуры, а затем кэширует его в сессионом хранилище браузера (если доступно).

При включенном SCRIPT_DEBUG плагин client-js начинает использовать локализованную схему.

Ждём загрузку клиента

Клиент стартует асинхронно. Если схема API локализована — клиент стартует немедленно, если нет — клиент делает ajax-запрос для загрузки схемы. Вся магия заключена в промисах (promise):

Примеры моделей

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

Примеры коллекций

Работа с ревизиями

Ддя доступа к ревизиям поста или страницы есть специальные коллекции PostRevisions или PageRevisions .

Если вы добавляет кастомные эндпоинты в API, то они также становятся доступным в качестве моделей и коллекций. Например, вы получите рабочие модели и коллекции, если при регистрации поста через register_post_type() или при регистрации таксономии через register_taxonomy() , если вы добавите ключ массива ‘show_in_rest’ => true .

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

Ajax и PHP. Загрузка изображения на сервер

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

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

На самом деле особых сложностей быть не должно, алгоритм действий:

  • Выбрать картинку
  • Нажать кнопку “Отправить”
  • Перехватить вызов формы с помощью JavaScript (jQuery)
  • Передать содержимое в специальный php скрипт-обработчик
  • Вернуть результат выполнения
  • Обработать результат при помощи JavaScript (jQuery)
  • Вывести пользователю информацию о загрузке


Кратко о jQuery и AJAX

Немного отклонюсь от темы и объясню что такое jQuery. jQuery — это специальная JavaScript библиотека, которая помогает упростить разработку веб приложений в несколько раз, также данная библиотека предоставляет API для работы с AJAX. Простыми словами, мы напишем меньше кода, чем если бы это делали на чистом JS.

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

Я склоняюсь к тому, что если есть инструмент, который позволяет вам ускорить разработку без последствий, то почему бы его не использовать? Но чистый JS тоже не помешало бы знать(хоть и лично мой уровень владения JS равен уровню копипаста примеров со stackoverflow �� ).

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

Нам понадобится 3 простых файла, это:

  • Страница с формой
  • php обработчик
  • файл js

index.html

Обычная html страница с формой. Обратите внимание на enctype=»multipart/form-data» , это нужно для передачи файлов, параметр указывает на способ кодирования данных. Если передаете файлы, значение всегда должно быть multipart/form-data .

handler.php

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

ajaxupload.js

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

Функция printMessage создана для вывода информации об успешной или провалившейся попытке загрузки файла. Подробно не рассматриваем, ничего особенного не представляет.

Перехват формы и её обработка. При клике на кнопку «Отправить» событие будет перехвачено скриптом и при помощи функции .preventDefault() форма не отправит данные в index.html . .preventDefault() служит для отмены вызова каких-либо событий.

Объект FormData нужен нам для создания POST запроса к нашему скрипту, это намного проще чем вписывать каждый элемент формы в строку. Создали объект, заполнили данными, отдали в наш ajax .

Ну и собственно сам запрос AJAX. Поскольку мы используем библиотеку jQuery, составить и выполнить такой запрос не вызовет у вас никаких проблем.

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

AJAX загрузка файлов на сервер с помощью jQuery

В этой заметке вы узнаете, как реализовать AJAX загрузку файлов на сервер с использованием jQuery. Это не так уж сложно!

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

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

Ну, меньше слов, приступим!

Для начала предположим, что у нас есть такой HTML код: поле и кнопка загрузки:

1. Получение данных файла из поля file

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

Этот код сохранит данные поля type=»file» в переменную files , с которой мы будем работать дальше.

2. Загружаем файлы по клику

Теперь, нам нужно повесить событие клика на кнопку » Загрузить файлы «. Тут и будет посылаться AJAX запрос с данными файлов.

Создадим функцию, повесим ее на событие click и отправим AJAX запрос с данными файлов. Этот запрос отличается от обычного AJAX запроса, и тут не подходит обычная отправка POST данных:

Что делает функция? Создает новый объект new formData() , добавляет в него данные файлов из массива files . Затем этот объект данных формы передается в AJAX запрос. 2 параметра нужно установить в false обязательно:

  • processData — потому что jQuery будет конвертировать массив files в строку, и сервер не сможет получить данные.
  • contentType — потому что дефолтные установки jQuery равны application/x-www-form-urlencoded , что не предусматривает отправку файлов. А еще, если установить этот параметр в multipart/form-data , похоже это ничего не даст.

3. Загрузка файлов на сервер

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

Создадим файл submit.php и добавим в него этот код (предполагается что submit.php лежит в той же папке, где и файл, с которого отправляется AJAX запрос):

Не используйте этот код напрямую! Пишите свой!

Заключение

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

Чтобы не собирать весь вышеописанный код вручную, скачайте вот этот архив: ajax-file-upload.zip . Загрузите его содержимое на ваш php сервер, зайдите в паку из архива, и попробуйте загрузить файл. Вы увидите, как все это работает, сможете «пошаманить» над кодом и разобраться подробнее в реальных условиях.

Также, рекомендую к прочтению статью о базовых знаниях для создания AJAX запросов в WordPress:

Знания из этой статьи вам очень пригодятся при создании AJAX загрузки файлов под WordPress.

Цукерберг рекомендует:  7 навыков идеального веб-разработчика
Автор: Тимур Камаев

Насколько полезным был этот пост?

Нажмите на звезду, чтобы оценить этот пост!

Средний рейтинг: 4.3 / 5. Количество голосов: 9

jQuery AJAX загрузка файлов на сервер

Как загружать любые файлы, например, картинки на сервер с помощью AJAX и jQuery? Делается это довольно просто! И ниже мы все обстоятельно разберем.

В те «древние» времена, когда еще не было jQuery, а может он был, но браузеры были не так наворочены, загрузка файла на сайт с помощью AJAX была делом муторным: через всякие костыли вроде iframe. Я те время не застал, да и кому это теперь интересно. А интересно теперь другое — что сохранение файлов на сайт делается очень просто. Даже не обладающий опытом и пониманием, того как работает AJAX, вебмастер, сможет быстро разобраться что-куда. А эта статья ему в помощь. Если подкрепить эти возможности функциями WordPress, то безопасная обработка и загрузка файлов на сервер становится совсем плевым и даже интересным делом (пример с WordPress смотрите в конце статьи).

Однако, как бы все просто не было, нужно заметить, что минимальный опыт работы с файлами и базовые знания в Javascript, jQuery и PHP все же необходимы! Минимум, нужно представлять как загружаются файлы на сервер, как в общих чертах работает AJAX и хоть немного надо уметь читать и понимать код.

Описанный ниже метод довольно стабилен, и по сути опирается на Javascript объект new FormData() , базовая поддержка которого есть во всех браузерах.

Для более понятного восприятия материала, он разделен на шаги. На этом все, полетели.

AJAX Загрузка файлов: общий пример

Начинается все с наличия на сайте input поля типа file . Нет необходимости, чтобы это поле было частью формы (тега

Ускорить сайт с множеством картинок: руководство по отложенной загрузке изображений Материал редакции

Перевод материала сооснователя сервиса для оптимизации изображений ImageKit Рахула Нанвани.

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

Но изображения часто много весят, и это в первую очередь влияет на размер страницы. Согласно данным сайта HTTP Archive, средний вес страницы на компьютере составляет 1511 КБ. Изображения занимают почти 650 КБ, что примерно 45% от общего числа.

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

Основные возможности — вкратце

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

Что такое отложенная загрузка

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

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

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

Инструменты

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

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

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

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

Способы реализации

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

Отложенную загрузку изображений можно разделить на два этапа.

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

Чтобы загрузить изображение через отложенную загрузку, нужно поместить URL-адрес изображения в атрибут «src». Допустим, указываем URL-адрес изображения в атрибуте «data-src» тега «image». Теперь, когда «src» пуст, браузер не начинает загрузку изображения.

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

Загрузка изображений с помощью событий JavaScript

В этом методе используем отслеживание событий прокрутки (scroll), изменения размера (resize), смены ориентации (orientationChange) в браузере.

Когда происходит одно из этих событий, находим все изображения на странице, которые ещё не загружены. Проверяем, какие из них теперь находятся в окне просмотра. Это можно определить с помощью свойств «offset top», «scroll top» и «window height».

Если изображение вошло в окно просмотра, берём URL из атрибута «data-src» и помещаем его в атрибут «src». Это запускает загрузку изображения. Также удаляем класс «lazy», определяющий изображения, которые будут загружаться позже. После загрузки всех изображений удаляем инструменты для отслеживания событий.

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

Первые три изображения в примере загружаются заранее. URL-адрес присутствует непосредственно в атрибуте «src» вместо атрибута «data-src». Это необходимо для хорошего пользовательского опыта. Поскольку эти изображения находятся в верхней части страницы, их следует сделать видимыми как можно скорее. Мы не должны ждать события или выполнения JavaScript, чтобы загрузить их.

Загрузка изображений с помощью Intersection Observer API

Intersection Observer API — относительно новый API в браузерах. Он определяет, когда элемент входит в окно просмотра, и начинает действовать. В предыдущем методе приходилось связывать события, учитывать производительность и подсчитывать время появления элемента в окне просмотра.

Intersection Observer API делает процесс проще, помогает избежать вычислений и обеспечивает хорошую производительность.

Ниже — пример использования Intersection Observer API для отложенной загрузки изображений.

Как только API обнаруживает, что элемент вошёл в окно просмотра, используя свойство «isIntersecting», выбираем URL из атрибута «data-src» и перемещаем его в атрибут «src», чтобы запустить отложенную загрузку. Как только это будет сделано, удаляем класс «lazy» из изображения, а также удаляем оттуда обсервер.

Если вы сравните время загрузки изображения двух методов — с отслеживанием событий и Intersection Observer API, — то обнаружите, что с помощью Intersection Observer API загрузка изображения запускается гораздо быстрее, и сайт уже не смотрится «вялым» при скроллинге.

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

Однако, как и всё новое, поддержка Intersection Observer API доступна не во всех браузерах. Таким образом, приходится возвращаться к методу отслеживания событий в браузерах, где Intersection Observer API не поддерживается. Учли этот момент в приведённом выше примере.

Отложенная загрузка фоновых изображений CSS

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

С фоновыми изображениями CSS не всё так просто. Чтобы загрузить фоновые изображения CSS, браузер должен создать дерево DOM (объектная модель документа), а также дерево CSSOM (объектная модель CSS), чтобы решить, применяется ли стиль CSS к узлу DOM в текущем документе.

Если правило CSS, определяющее фоновое изображение, не применяется к элементу в документе, то браузер не загружает фоновое изображение. Если применяется — загружает.

Поначалу это может показаться сложным, но такой же принцип лежит в основе техники отложенной загрузки фоновых изображений. Так мы обманываем браузер, не применяя свойство CSS «background-image» к элементу, пока этот элемент не попадёт в окно просмотра. Ниже рабочий пример отложенной загрузки фонового изображения CSS.

Здесь следует отметить, что код JavaScript для отложенной загрузки остаётся прежним. Мы используем Intersection Observer API, возвращаясь затем к отслеживанию событий. Хитрость заключается в CSS.

Элемент с идентификатором «bg-image» имеет заданное свойство «background-image» в CSS. Однако когда класс «lazy» добавляется к этому элементу, в CSS мы переопределяем свойство «background-image» и меняем его на значение «none».

Так как по правилам комбинация «bg-image» с «.lazy» имеет более высокое предпочтение в CSS, чем просто «bg-image», браузер применяет свойство «background-image: none» к элементу изначально.

Когда прокручиваем страницу вниз, the Intersection Observer (или отслеживание событий) определяет, что изображение находится в окне просмотра, и удаляет класс «lazy». Это изменяет применяемый сейчас CSS и применяет свойство «background-image» к элементу, начавшему загрузку фонового изображения.

Улучшить пользовательский опыт

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

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

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

1. Правильный дизайн плейсхолдеров

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

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

Плейсхолдер доминирующего цвета

Этот метод давно используется для результатов поиска изображений в Google и Pinterest.

Может показаться, что это сложно реализовать. Но есть простой способ — сначала уменьшить изображение до пикселя 1×1, а затем масштабировать его до размера плейсхолдера — грубое приближение, но оно помогает легко получить один доминирующий цвет. Используя ImageKit, плейсхолдер доминирующего цвета можно получить с помощью цепного преобразования, как показано ниже.

Размер изображения-плейсхолдера составляет всего 661 байт, по сравнению с исходным изображением, которое имеет размер 12 700 байт — в 19 раз меньше. И это обеспечивает более приятный опыт перехода от плейсхолдера к изображению.

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

Плейсхолдер низкого качества (LQIP)

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


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

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

Рабочий пример и код для использования техники LQIP — по ссылке.

2. Добавление буферного времени

Часто пользователи быстро прокручивают страницу, и для загрузки и отображения картинки на экране требуется некоторое время. Событие «load image» может сработать с задержкой, как и плейсхолдеры. Это плохо влияет на пользовательский опыт.

Решение

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

С помощью Intersection Observer API можно использовать параметр «`root`» вместе с параметром «rootMargin» (работает по стандартному принципу поля CSS), чтобы увеличить границы рамки.

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

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

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

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

Если не заметили ранее, во всех примерах третье изображение (image3.jpg) всегда загружается сразу, даже если оно находится вне области просмотра. Это было сделано в соответствии с тем же принципом: выполнить загрузку немного заранее для лучшего пользовательского опыта.

3. Как избежать смещения содержимого

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

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

Как показано в этом материале Smashing Magazine, смещение контента и видео — довольно неприятный опыт для пользователя.

Решение

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

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

4. Не стоит применять отложенную загрузку для всех изображений

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

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

  • Любое изображение, которое присутствует в окне просмотра или в начале страницы, не должно загружаться с помощью отложенной загрузки. Это касается любого изображения-заголовка, рекламных баннеров, логотипов. Пользователь должен видеть их, как только страница загрузится. Помните, что мобильные и десктопные устройства будут иметь разные размеры экрана и, следовательно, разное количество изображений, которые будут видны на экране изначально. Таким образом, необходимо учитывать тип устройства, чтобы решить, какие изображения загружать изначально, а какие нет.
  • Любое изображение, которое частично видно в окне просмотра, не должно загружаться с помощью отложенной загрузки. Это происходит по принципу, который обсуждался выше, — загружать чуть заранее. Любое изображение, находящееся, допустим, в 500 px от области просмотра, может быть загружено заранее.
  • Если страница не длинная, её можно пролистать за несколько движений. Или если за пределами окна просмотра меньше пяти изображений, то отложенную загрузку можно не использовать. Это не принесёт существенной выгоды пользователю с точки зрения производительности. Дополнительный JavaScript, который вы загружаете на страницу, чтобы включить отложенную загрузку, компенсирует выигрыш от отложенной загрузки такого небольшого количества изображений.

Популярные JavaScript-библиотеки

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

  • yall.js (Yet Another Lazy Loader) — использует Intersection Observer API и возвращается к отложенной загрузке на основе событий. Поддерживает все основные типы элементов HTML, но не «background-image». Также работает на Internet Explorer 11 и старших версиях.
  • lazysizes — библиотека с обширной функциональностью. Поддерживает адаптивные изображения «srcset» и атрибут «sizes». Высокая эффективность даже без Intersection Observer API.
  • jQuery Lazy — простая, основанная на jQuery, библиотека отложенной загрузки.
  • WeltPixel Lazy Loading Enhanced — расширение для Magento 2 для отложенной загрузки изображений.
  • Magento Lazy Image Loader — расширение для Magento 1.x для отложенной загрузки изображений.
  • Shopify Lazy Image Plugin — расширение для Shopify для отложенной загрузки изображений. Платная.
  • WordPress A3 Lazy Load — плагин отложенной загрузки изображений для WordPress.

Как проверить, всё ли работает

Самый простой способ — открыть инструменты разработчика в браузере Chrome. Перейдите на вкладку «Сеть» → «Изображения». Здесь при первом обновлении страницы должны загружаться только те изображения, которые должны присутствовать на странице изначально.

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

Другой способ — запустить расширение Lighthouse от Google Chrome на странице после внесения изменений и найти предложения в разделе Offscreen images.

Если не работает

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

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

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

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

Ничего-то вы не понимаете. Сегодня нельзя просто так взять и сверстать страничку, как это делалось 15 лет назад — чтобы она просто тупо работала, быстро и надёжно. За это никто вам денег сегодня не заплатит. И на работу вас не возьмёт. А вот когда вы научитесь обклеивать эту несчастную страничку реактами, ангулярами, анимациями, шрифтами, параллаксами и отложенными загрузками, как ёлку мишурой, и превращать её в прогрессивное и реактивное веб-приложение, способное вызвать у пользователя вопрос «Да что там, опять майнер, что ли?» — вот тогда вы профессионал, тогда у вас есть з/п и вам есть что написать в резюме.

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

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

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

Добавлю. Недавно в работу попал интернет-магазин дилерский русского света, их домен rs24.ru
Посмотрите, как формируется контент страниц. Прилетает json, и на его основе рисуется страница категории, товара.

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

Будьте проще и заходите через парадный вход. У нас есть json, который прилетает на страницу, зачем нам их куцый api?

Яркий пример криворукости всего айти-состава организации. Снизу доверху все гнилое, а руководство устраивает, как медленно грузятся страницы.
Хотя, можно и с другой стороны посмотреть, это просто пример изящного решения, как на слабеньком железе показать каталог на 420000 товаров.

Backbone — загрузка изображений на сервер

Backbone.Model File Upload

A concise, non-iframe, & pure XHR2/AJAX Backbone.model file upload. (Good for IE >= 10, FF, Chrome.)

This plugin upgrades the current save method to be able to upload files using the HTML5’s File API and FormData class.

Grab the File object from the DOM, set it to an attribute, then call save . That’s it! ( save with the attribute parameter works as well)

model.set( [file attribute], [file object], [options] )

model.save( [file attribute], [file object], [options] )

In terms of how to use these methods, they have not changed. The only difference is that it has the capability to take a File object grabbed from the DOM (i.e. ).

File, Blob, and FileList are all valid in the model. Once set it will be uploaded when ready.

As the file is being uploaded, a trigger progress fires as the browser sends chunks of data. The progress trigger sends a progress status in percents.

If you want to force not using FormData, add the option < formData: false >and the whether or not you have a file object in the model, it’ll try to send it as part of the JSON object. Opposite is true (for whichever circumstance) is that if you set < formData: true >, it will force the usage of FormData. Not setting it will leave it automatic and it’ll try to detect if there is the file in the model.

The attribute file is the default. As you can see from the example above, you can set it to whatever you want.

This plugin will use the FormData class to wrap all the attributes in. That basically means it’s making what we used to know as the old-fashioned «form» into a data object. The old-fashion «form» only took key-value pairs, so the same applies here. The attributes gets converted into a FormData object then is sent through as a «multipart/data-form». So it is recommended to use a flattened model for easier parsing as Jeremy Ashkenas himself usually recommends for all scenarios.

Included here is a «node» js mock file server so you can use to test.

What happens to a model with nested objects/arrays?

The model will be flattened and the nested value will be separated with it’s own unique composite «breadcrumb» key. The key parsing will reflect the array or object with the index or property respectively.

Will parse into

Remember, you would need to «unflatten» the model in the back-end. If you are a «node» user, please see my «mock-file-server» to see what I did there to «unflatten» the model. After the file has been Posted (or Put), send the «unflattened» version back to the client. That way, the Backbone Model will be in sync. Also remember, nested arrays are parsed as objects, so its advised that you don’t have nested arrays. The warnings can go on and on. Basic rule, try to avoid nesting if you can.

The plugin is non-destructive to the existing behaviors. When a file object is detected, then the method is tweaked and converted to a FormData object.

Ускоренное изучение Backbone. Часть 1

Backbone.js имеет жесткую зависимость от библиотеки underscore.js и слабую от JQuery. Он состоит из следующих модулей:

  • Views (Представления)
  • Events (События)
  • Models (Модели)
  • Collections (Коллекции)
  • Routers (Маршрутизаторы)

Мы разберем все эти модули на простых примерах и первое, с чего мы начнем, — это приложение, которое выводит Привет, мир.

Для начала работы скачайте этот простой HTML файл. Этот файл содержит ссылки на библиотеки, которые нам понадобятся (JQuery, Underscore.js, Backbone.js и Backbone-localStorage.js) и обозначенные места для вашего HTML и JS кода. Не беспокойтесь о библиотеках, мы обязательно объясним для чего они нужны.

После загрузки вышеупомянутого файла, обратите внимание на HTML, где вся ваша страница будет построена с использованием класса Backbone.Views!

Ваше JS приложение будет загружено вот сюда:

Views (Представления)

Backbone-представления являются эквивалентом «контроллеров» MVC-фреймворков (например, Ruby On Rails). Представления в Backbone.js отвечают за отображение данных приложения, а также могут реагировать на события, которые возникают в моделях, коллекциях или реагировать на события DOM-элементов.

Для создания представления нужно всего-навсего расширить класс Backbone.View . Изучите представленный ниже код с комментариями, а затем вставьте его в яваскрипт-блок загруженного HTML файла.

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

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

Backbone и шаблоны

Поскольку Backbone тесно работает с библиотекой под названием underscore.js (или просто _.js), вы можете воспользоваться доступным в ней шаблонизатором. Также, вы можете воспользоваться любым другим шаблонизатором, который вам нравится, например mustache, или handlebars. Давайте для простоты придерживаться _.js.

Шаблоны в Underscore имеют следующий синтаксис:

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

[data] — объект с данными, необязательный патаметр.

С помощью необязательного параметра [settings] мы можем переопределить любые настройки шаблонизатора, заданые в templateString

Давайте посмотрим его в действии и перепишем наш ‘Привет, мир‘ используя шаблонизатор в Underscore.

Запустите приложение снова и убедитесь, что оно работает с шаблоном.

Начнем снова с HTML болванкой, использованной ранее. Теперь, вместо div#container давайте добавим следующий код:

Мы собираемся реализовать неупорядоченный список ul элементов с чекбоксами.

Models (Модели)

Модели — сердце каждого приложения. Они содержит интерактивные данные и логику, с ними связанную, такую как получение, установка и проверка данных, значения по умолчанию, инициализации данных, преобразования и д.р. Для нашего примера, мы собираемся создать модель под названием Todo , которая будет хранить строку текста (title) и была ли задача была завершена, или нет (completed).

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

Протестируем наш код. Для этого откройте консоль браузера (в Хроме: ctrl + shift + i , или ⌘ + alt + i ) и попробуйте ввести следующий код, чтобы ознакомиться с моделями:

Коллекции в Backbone (Backbone.Collection)

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

Цукерберг рекомендует:  Ios - Языки для экосистемы Apple - зачем изучать старьё

Коллекции позволяют сохранять данные (в базе данных, файлах, памяти) и это требует ссылку на нее. Поэтому, необходимо указать параметр url с относительнным URL, где ресурс модели будет расположен на сервере. В противном случае, вы получите такую ошибку: A «url» property or function must be specified (Свойство «url», или функция должна быть указана).

Для упрощения, мы не будем импользовать сервер (я сделаю отдельный урок для этого); вместо этого мы будем использовать локальное хранилище (local storage) HTML5 для persistence через Backbone плагин. Таким образом, мы должны определить свойство LocalStorage вместо URL. Необходимо подключить backbone-localstorage.js с остальными вашими библиотеками как в примере.

Протестируем наш код. Для этого снова откройте консоль браузера и попробуйте ввести следующий код:

Backbone.View

Как уже упоминалось выше, Представления в Backbone не имеют HTML-меток для нашего приложения, зато они (как контроллеры в MVC-фреймворке) обрабатывают данные и связывают их с шаблонами и рендерят HTML-код, основываясь на событиях и изменении данных.

Представления имеют 4 основных свойства: el, initialize, render и events. Мы уже видели в деле первые три, а совсем скоро познакомимся с четвертым. Вы ведь не забыли еще наш «Привет, мир»:

Каждое представление должно ссылаться на DOM-элемент и el — это и есть та самая ссылка. this.el создается из таких свойств Представления, как el, tagName, className, id, или attributes. Если ни один из них не указан, то this.el является пустым div. view.$el — это закешированный jQuery объект элемента представления (view.el).

С помощью функции initialize у вас есть возможность передать параметры, которые будут прикреплены к модели, коллекции, или view.el.

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

События (events) записываются в следующем формате:


В jQuery мы бы написали:

Теперь вернемся к нашему To-Do приложению: Нам нужно Представление, которое отрендерит каждый объект из модели Todo на страницу. Шаблон item-template и Представление app.TodoView сделают то, что нам нужно.

В следующем блоке кода мы описываем Представление, используя заданный выше шаблон ( #item-template ) чтобы вывести заголовок из model.

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

Также обратите внимание, что он использует tagName: li вместо el . Это означает, что новые отрендеренные элементы будут помещены в

Backbone.Events

Этот модуль может быть смешан с каким-либо объектом, чтобы придать ему поведение издатель-подписчик. События предоставляют несколько методов, из которых мы будем обсуждать следующие: on , off и trigger . Если это вы знакомы с JQuery, то имеете представление как они работают.

Метод on привязывает функцию обратного вызова к объекту. Формат записи:

Здесь event — событие, callback — вызываемая функция, context — контекст вызова (необязательный параметр)

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

Каждый раз, когда добавляется новая единица в Backbone.Collection, запускается событие add . В вышеуказанном примере после запуска события, запускается функция обратного вызова addAll() и текущий объект передается с this в качестве контекста.

События можно также установить на произвольные объекты, используя underscore.js с помощью функции extend :

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

В заключительной части нашего урока по Ускоренному изучению Backbone мы узнаем, как реализовать создание, чтение, обновление и удаление для моделей!

Backbone — загрузка изображений на сервер

Backbone.js придает структуру веб-приложениям с помощью моделей с биндингами по ключу и пользовательскими событиями, коллекций с богатым набором методов с перечислимыми сущностями, представлений с декларативной обработкой событий; и соединяет это все с вашим существующим REST-овым JSON API.

Русская версия документации размещается на GitHub.

Оставляйте баг-репорты и обсуждайте фичи в багтрекере на GitHub’е, на IRC-канале Freenode #documentcloud, задавайте вопросы в группу Google, добавляйте страницы в вики, или шлите твиты @documentcloud.

Backbone — это компонент DocumentCloud c открытым исходным кодом.

Загрузка и зависимости (ПКМ и «Сохранить как»)

Версия для разработки (1.0.0) 58кб, полный код, много комментариев
Production-версия (1.0.0) 6.3кб, упакованная и gzip-ованная
(Source Map)
Edge Version (master) Последняя версия из репозитория, используйте на свой страх и риск

Единственная жесткая зависимость в Backbone — Underscore.js ( >= 1.4.3). Для RESTful-персистентности, поддержки истории с помощью Backbone.Router и операций с DOM в Backbone.View, подключите json2.js, и либо jQuery ( > 1.7.0) либо Zepto.

Введение

При работе с веб-приложением, которое включает в себя много JavaScript, первое, чему вы научитесь — это перестать связывать ваши данные с DOM, потому что это подходит только для создания простых JavaScript приложений, которые в конечном итоге выглядят, как запутанные груды jQuery-селекторов и коллбэков, которые отчаянно пытаются хранить актуализированные данные в UI, JavaScript логике и базе данных на сервере. Для сложных клиентских приложений часто бывает полезным более структурированный подход.

Работая с Backbone, вы представляете ваши данные как Модели (Models), которые могут быть созданы, провалидированы, удалены, и сохранены на сервере. Всякий раз, когда в интерфейсе изменяется атрибуты модели, модель вызывает событие «change»; все Представления (Views), которые отображают состояние модели, могут быть уведомлены об изменении атрибутов модели, с тем чтобы они могли отреагировать соответствующим образом — например, перерисовать себя с учетом новых данных. В готовом приложении на Backbone, вы не должны писать код, ищущий элемент с определенным id в DOM и обновлять HTML вручную. При изменении модели представление просто обновит себя самостоятельно.

Если вы новичок и еще не совсем уверены, что Backbone вам подходит, начните с просмотра списка проектов, использующих Backbone.

Многие из следующих примеров работоспособны. Нажмите кнопку play, чтобы запустить их.

Обновление до версии 1.0

Backbone версии 0.9 должна быть достаточно безболезненно обновлена до версии 1.0. Ниже представлены несколько наиболее важных изменений:

  • Если вам нужно «умное» обновление коллекции, добавление новых моделей, удаление недостающих и объединение уже существующих, вы должны использовать метод set (ранее «update»), по аналогии с методом set модели. Такое поведение теперь является стандартным при вызове метода fetch коллекции. Чтобы получить прежнее поведение, передайте в хэше options.
  • Если в ваших URL есть символы, требующие кодирования, Backbone декодирует их для вас и ваши обработчики роутов получат их в качестве аргументов.
  • В версии 0.9.x в событиях Backbone появились два метода: listenTo и stopListening, которые упрощают управление событиями при удалении (remove) представления.
  • Теперь валидация модели по умолчанию включена только для метода save. Чтобы отвалидировать модель при set, необходимо передать в хэше options. Валидация модели теперь запускает событие "invalid" вместо "error".

Backbone.Events

Events — это модуль, который может расширить возможности любого объекта, давая ему способность отслеживать и вызывать именованные пользовательские события. События должны быть объявлены после примешивания модуля. В событие можно передавать аргументы. Например:

Например, можно сделать удобный диспетчер событий, который будет координировать события между различными областями приложения:
var dispatcher = _.clone(Backbone.Events)

on object.on(event, callback, [context]) Синоним: bind
Привязывает функцию-обработчик callback к объекту, который будет вызываться всякий раз, когда сработает событие event. Если у вас используется множество различных событий на странице, следует использовать двоеточия в названиях: "poll:start", или "change:selection". Строка названия события (event) может состоять из разделенных пробелами нескольких событий.

Чтобы сохранить контекст, с которым должен быть вызван обработчик, передайте третий необязательный аргумент context:
model.on('change', this.render, this)

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

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

off object.off([event], [callback], [context]) Синоним: unbind
Удаляет привязанный ранее обработчик. Если параметр context не задан, все версии обработчика будут удалены, независимо от контекста. Если не указан обработчик, будут удалены все обработчики для события event. Если не указано событие, обработчики для всех событий будут удалены.

Помните, что вызов model.off(), удалит все события модели — в том числе события, которые используются внутри Backbone.

trigger object.trigger(event, [*args])
Вызывает срабатывание события event (или группы событий — разделенных пробелами). Последующие аргументы в trigger будут переданы вместе с событием в обработчик.

once object.once(event, callback, [context])
Ведет себя так же, как on, за исключением того, что будет удалён после первого срабатывания события. Можно произнести как "В следующий раз, когда что-то призойдёт, сделай это".

listenTo object.listenTo(other, event, callback)
Указывает объекту object прослушивать конкретное событие другого объекта other. Преимущество использования этого метода вместо other.on(event, callback) в том, что listenTo позволяет объекту object отслеживать события, которые позже могут быть удалены все сразу.

stopListening object.stopListening([other], [event], [callback])
Указывает объекту object перестать слушать события. Вызов метода stopListening без аргументов удалит все зарегистрированные обработчики. Также можно указать определённый объект, событие или обработчик.

listenToOnce object.listenToOnce(other, event, callback)
Похож на listenTo, за исключением того, что будет удалён после первого срабатывания события.

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

  • "add" (model, collection, options) — когда модель добавляется в коллекцию.
  • "remove" (model, collection, options) — когда модель удаляется из коллекции.
  • "reset" (collection, options) — когда всё содержимое коллекции заменяется.
  • "sort" (collection, options) — когда коллекция была отсортирована.
  • "change" (model, options) — когда атрибут модели меняется.
  • "change:[attribute]" (model, value, options) — когда меняется конкретный атрибут модели.
  • "destroy" (model, collection, options) — когда модель уничтожена.
  • "request" (model, xhr, options) — когда модель (или коллекция) отправляет запрос на сервер.
  • "sync" (model, resp, options) — когда модель была успешно синхронизирована с сервером.
  • "error" (model, xhr, options) — когда вызов save провалился на сервере.
  • "invalid" (model, error, options) — модель не прошла валидацию на клиенте.
  • "route:[name]" (params) — когда один конкретный роут находит соответствие.
  • "route" (router, route, params) — когда любой из роутов находит соответствие.
  • "all" — это специальное событие срабатывает каждый раз, когда срабатывает любое событие, передавая имя события первым аргументом.

Если при вызове метода, который генерирует событие (model.set, collection.add, и пр.) вы не хотите, чтобы события были вызваны, вы можете передать в хэше options. Обратите внимание, что это не является хорошей практикой. Вместо этого хорошей идеей будет передача специального флага через хэш options, который скажет обработчику события, что его нужно проигнорировать.

Backbone.Model

Модели — это самое сердце любого JavaScript-приложения. Они содержат как интерактивные данные, так и большую часть соответствующей логики: конвертации, валидации, вычисленные свойства и контроль доступа. Вы расширяете Backbone.Model методами своей предметной области, а Model предоставляет базовый набор функциональности по управлению изменениями.

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

extend Backbone.Model.extend(properties, [classProperties])
Чтобы создать свой собственный класс моделей, нужно расширить Backbone.Model и предоставить свойства экземпляра в параметре properties; опциональный параметр classProperties отвечает за свойства, которые будут прицеплены напрямую к функции-конструктору.

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

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

constructor / initialize new Model([attributes], [options])
Можно передать начальные значения атрибутов, создавая экземпляр модели — параметр attributes будет передан в метод set. Если вы определите функцию initialize, она будет вызвана после создания модели.

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

Если вы передаёте в качестве параметра options, модель получит свойство collection, которое будет использовано для индикации того, к какой коллекции принадлежит данная модель, и для того, чтобы вычислить свойство url. В противном случае свойство model.collection будет добавлено автоматически в момент первого добавления модели в коллекцию.

При создании новой модели могут быть переданы следующие опции: и/ или которые определяют пользовательские URL-эндпоинты.

Если при создании передать в хэш options, атрибуты перед добавлением в модель будут пропущены через функцию parse.

get model.get(attribute)
Отдаёт текущее значение атрибута модели, например: note.get("title")

set model.set(attributes, [options])
Хэш attributes устанавливает значения атрибутам (одному или многим). Если любой из атрибутов изменяет состояние модели, то сработает событие "change". События изменения для каждого из атрибутов также сработают, и вы можете привязаться к ним тоже, например: change:title, или change:content. Также можно передать отдельный ключ и значение:

escape model.escape(attribute)
Этот метод похож на get, но возвращает HTML-безопасную версию атрибута. Если вы вставляете данные из модели в HTML, использование escape для получения атрибута предотвратит XSS-атаки.

has model.has(attribute)
Возвращает true, если атрибут установлен не в null и не в undefined.

unset model.unset(attribute, [options])
Убирает атрибут, удаляя его из внутреннего хэша атрибутов. Запускает событие "change", если не передать silent в опциях.

clear model.clear([options])
Убирает все атрибуты из модели, включая id. Запускает событие "change", если не передать silent в опциях.

id model.id
Специальное свойство модели id — произвольная строка (целый id или UUID). Если вы указываете id в хэше атрибутов, он будет скопирован в свойство модели напрямую. Модели могут быть вытащены из коллекций по id, и id используется для генерации URL по умолчанию.

idAttribute model.idAttribute
Уникальный идентификатор модели хранится в атрибуте id. Если вы напрямую общаетесь с бэкендом (CouchDB, MongoDB), который использует другой уникальный ключ, вы можете указать idAttribute, чтобы прозрачно мапить этот ключ на id.

cid model.cid
Специальное свойство моделей cid (от "client id", клиентский id) — уникальный идентификатор, автоматически назначающийся всем моделям в момент создания экземпляра. cid'ы удобны, когда модель ещё не была сохранена на сервер и не имеет своего настоящего id, но уже должна быть отображена в UI.

attributes model.attributes
Свойство attributes — это внутренний хэш, содержащий состояние модели — как правило (но не обязательно) это JSON-объект, представляющий модель на сервере. Лучше использовать метод set для обновления атрибутов вместо прямого изменения этого хэша.

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

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

changed model.changed
Свойство changed — это внутренний хэш, содержащий все атрибуты, которые были изменены с тех пор, как последний раз срабатывало событие "change". Пожалуйста, не обновляйте changed напрямую, потому что его состояние поддерживается внутри методами set и change. Копию changed можно получить при помощи метода changedAttributes.

defaults model.defaults или model.defaults()
Хэш (или функция) defaults используется для указания значений атрибутов по умолчанию. Если в момент создания экземпляра модели какие-то атрибуты не будут указаны, то они примут значения по умолчанию.

Помните, что в JavaScript объекты передаются по ссылке, так что, если какое-либо значение по умолчанию будет объектом, оно будет одним для всех экземпляров. Вместо этого определите defaults как функцию.

toJSON model.toJSON()
Возвращает копию поля attributes для превращения в JSON-строку. Метод может быть использован для персистентности, сериализации или для аугментации перед отправкой на сервер. Имя этого метода несколько сбивает с толку, так как он на самом деле не возвращает JSON-строку, но именно так работает JavaScript API для JSON.stringify.

sync model.sync(method, model, [options])
Использует Backbone.sync для обеспечения персистентности состояния модели с сервером. Может быть переопределён для пользовательского поведения.

fetch model.fetch([options])
Обновляет состояние модели данными с сервера с помощью Backbone.sync. Возвращает jqXHR-объект. Полезен, если модель никогда не наполнялась данными, или если вы хотите удостовериться, что вы имеете актуальные данные. Событие "change" сработает, если состояние сервера отличается от текущих атрибутов. Принимает коллбэки success и error в хэше options, в которые передаются (model, response, options) в качестве аргументов.

save model.save([attributes], [options])
Сохраняет модель в БД (или другой слой персистентности) при помощи Backbone.sync. Возвращает jqXHR объект, если валидация прошла успешно, и false в противном случае. Хэш attributes (так же, как в set), должен содержать атрибуты, которые вы хотите изменить — ключи, которые не были указаны, не будут изменены. Однако на сервер будет послано полное представление ресурса. Так же, как и в set, можно передать отдельный ключ и значение вместо хэша. Если у модели определен метод validate и валидация не проходит успешно, модель не будет сохранена. Если флаг isNew модели установлен в true, сохранение будет действием "create"(HTTP-действие POST); если модель уже существует на сервере — "update" (HTTP-действие PUT).

Если вместо этого вы хотите отправить на сервер только изменённые атрибуты, вызовите model.save(attrs, ). В таком случае будет отправлен PATCH запрос к серверу, который будет содержать только измененные атрибуты.

Вызов save с новыми атрибутами немедленно вызовет срабатывание события "change", событие "request" будет вызвано перед совершением Ajax-запроса на сервер, а событие "sync" — после того, как сервер известит об успешном изменении. Передайте , если хотите подождать ответа сервера, прежде чем устанавливать новые значения атрибутов модели.

Обратите внимание, как в следующем примере наша переопределённая версия Backbone.sync получает запрос "create" в первый раз, когда сохраняется модель, и "update" во второй раз.

save принимает коллбэки success и error в хэше options, в которые передаются соответственно (model, response, options) и (model, xhr, options) в качестве аргументов. Если проваливается валидация на стороне сервера, верните не-2XX HTTP-статус, вместе с описанием ошибки в тексте или в JSON.

destroy model.destroy([options])
Уничтожает модель на сервере с помощью HTTP-запроса DELETE через Backbone.sync. Возвращает jqXHR-объект или false, если флаг isNew истинен. Принимает коллбэки success и error в хэше options в которые передаются соответственно (model, response, options) и (model, xhr, options) в качестве аргументов. Запускает событие "destroy" на модели, которое также всплывет на всех коллекциях, которые содержат её, событие "request" перед совершением Ajax-запроса на сервер и событие "sync" после того, как сервер известит об успешном удалении модели. Передайте , если хотите подождать ответа сервера, прежде чем удалять модель.

Методы Underscore (6)
Backbone проксирует 6 методов Underscore.js для операций над моделями. Они не описываются в данной документации, но вы можете обратиться к документации Underscore, чтобы найти их полное описание:

validate model.validate(attributes)
Этот метод оставлен неопределенным; поощряется переопределять его со своей логикой валидации — если у вас есть такая, которую можно выполнить на стороне клиента. По умолчанию метод validate вызывается только перед save, но также может быть вызван при выполнении set, если передать в хеше options. При вызове validate ему передаются атрибуты модели и хэш options, с которым вызван метод set или save. Если атрибуты валидны, не возвращайте ничего из validate; если нет, возвращайте любую ошибку на ваш выбор — как просто строку с сообщением, которое надо отобразить, так и сложный объект, программно описывающий ошибку. Если validate вернул ошибку, выполнение save прервётся и атрибуты модели на сервере не будут изменены. Проваленная валидация запустит событие "invalid", а значение, полученное методом validate будет установлено в свойcтво validationError модели.

События "invalid" полезны для грубой обработки ошибок на уровне модели или коллекции.

validationError model.validationError
Значение, полученное методом validate во время последней неудачной валидации.

isValid model.isValid()
Запускает валидацию, чтобы проверить состояние модели.

url model.url()
Возвращает относительный URL, по которому ресурс модели должен располагаться на сервере. Если ваши модели расположены в другом месте, переопределите этот метод с правильной логикой. По умолчанию генерирует URL'ы вида: "/[collection.url]/[id]", но вы можете переопределить это поведение, явно указав urlRoot, тогда URL коллекции не будет принят во внимание. Значение url можно передать при создании экземпляра модели.

Обращается к Collection#url, чтобы сгенерировать URL, так что удостоверьтесь, что он определён, или к свойству urlRoot модели, если все модели этого класса разделяют общий корневой URL. Модель с id равным 101, хранящяяся в коллекции с url равным "/documents/7/notes", будет иметь такой url: "/documents/7/notes/101"

urlRoot model.urlRoot или model.urlRoot()
Укажите urlRoot, если вы используете модель вне коллекции, чтобы дефолтный метод url генерировал URL'ы, исходя из id. "/[urlRoot]/id"
Как правило, вам не нужно будет указывать это значение. Обратите внимание, что urlRoot также может быть функцией.

parse model.parse(response, options)
Метод parse вызывается каждый раз, когда данные модели возвращаются сервером, в методах fetch и save. Функции передаётся «сырой» объект response, и она должна возвратить хэш атрибутов, который будет передан методу set. Реализация по умолчанию просто пробрасывает JSON-ответ. Переопределите этот метод, если вы работаете с уже существующим API, или чтобы лучше заворачивать в пространства имён ответы сервера.

Если вы работаете с Rails версии 3.1 и ниже, вы наткнётесь на то, что реализация по умолчанию to_json отдаёт атрибуты модели в пространстве имён. Чтобы устранить это поведение для лучшей интеграции с Backbone, установите:

clone model.clone()
Возвращает новый экземпляр модели с идентичными атрибутами.

isNew model.isNew()
Была ли модель уже сохранена на сервер? Модель считается новой, если ещё не имеет атрибута id.

hasChanged model.hasChanged([attribute])
Была ли модель изменена с последнего события "change"? Если передан attribute, возвращает true, если этот атрибут был изменён.

Обратите внимание, что этот метод и следующие, касающиеся изменений, полезны только во время обработки события "change".

changedAttributes model.changedAttributes([attributes])
Возвращает хэш только тех атрибутов модели, которые были изменены, или false, если все атрибуты остались без изменений. Опционально может быть передан внешний хэш атрибутов; в этом случае возвращаются те атрибуты из этого хэша, которые отличаются от таковых в модели. Может быть полезно для выяснения, какие части представления надо обновить, или какие вызовы надо сделать, чтобы синхронизировать изменения с сервером.

previous model.previous(attribute)
Во время события "change" этот метод позволяет получить предыдущее значение изменённого атрибута.

previousAttributes model.previousAttributes()
Возвращает копию предыдущих атрибутов модели. Полезно, чтобы получить diff между версиями модели, или вернуться в валидное состояние после ошибки.

Backbone.Collection

Коллекции — это упорядоченные наборы моделей. Вы можете навесить слушателей: на событие "change", чтобы получать оповещения, когда любая модель в коллекции изменяется; на события "add" и "remove"; на получение (fetch) коллекции с сервера — и использовать полный набор методов Underscore.js.

Любое событие, которое сработает на модели в коллекции также сработает и напрямую — для удобства — на коллекции. Это позволяет напрямую слушать события изменения отдельных атрибутов любой модели в коллекции. Например: documents.on("change:selected", . )

extend Backbone.Collection.extend(properties, [classProperties])
Чтобы создать собственный класс коллекции, расширьте Backbone.Collection, предоставив свойства экземпляра в хэше properties и опциональные свойства класса в classProperties, которые станут свойствами функции-конструктора.

model collection.model
Переопределите это свойство, чтобы указать класс моделей, которые будет содержать эта коллекция. Если это свойство определено, можно передавать «сырые» хэши объектов (и массивы) в методы add, create, и reset, и атрибуты будут сконвертированы в модели соответствующего типа.

Свойство model также можно определить функцией.

constructor / initialize new Collection([models], [options])
При создании экземпляра коллекции можно передать начальный массив моделей (в параметре models). В options может быть передана функция-компаратор. Чтобы отключить сортировку, нужно передать false как значение функции-компаратора. Метод initialize вызывается после создания экземпляра коллекции. Если следующие опции указаны, они автоматически станут свойствами коллекции: url, model и comparator.

models collection.models
Прямой доступ к массиву моделей коллекции. Обычно используются методы get, at или методы Underscore, чтобы получить модели, но порой необходима прямая ссылка на массив.

toJSON collection.toJSON()
Возвращает массив, содержащий хэш атрибутов каждой модели в коллекции. Используется в сериализации и сохранении коллекции целиком. Название несколько сбивает с толку потому, что соответствует JSON API.

sync collection.sync(method, collection, [options])
Использует Backbone.sync для обеспечения персистентности состояния коллекции с сервером. Может быть переопределён для пользовательского поведения.

Методы Underscore (28)
Backbone проксирует методы Underscore.js, чтобы предоставить доступ к 28 функциям, итерирующим по Backbone.Collection. Они не все документированы здесь; см. документацию Underscore.

add collection.add(models, [options])
Добавляет модель (или массив моделей) в коллекцию, при этом запускает событие "add". Если свойство model определено, можно передавать «сырые» атрибуты и они будут оживлены в экземпляры моделей. Чтобы вставить модель по специфичному индексу, передайте . Если вы добавляете в коллекцию модели, которые уже предствлены в коллекции, они будут пропущены, только если не передана опция , в этом случае их атрибуты будут совмещены в существующую модель, и запущено событие "change" для всех изменённых атрибутов.

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


remove collection.remove(models, [options])
Удаляет модель (или массив моделей) из коллекции. Запускает событие "remove", которое вы можете подавить наличием ключа silent в хэше options. Если есть обработчик события "remove", в него будет передан индекс, под которым находилась удалённая модель — в параметре options.index.

reset collection.reset(models, [options])
Добавлять и удалять модели по одной — хорошо и правильно, но иногда надо изменить столько моделей, что проще обновить коллекцию целиком. Используйте reset, чтобы заменить коллекцию новым массивом моделей (или хэшей атрибутов). При этом сработает одно событие "reset" в конце. Для удобства при использовании "reset" список моделей, находившихся в коллекции, доступны как options.previousModels.

Вот пример использования reset для предзагрузки коллекции в приложении на Rails:

Вызов collection.reset() без передачи каких-либо моделей сделает коллекцию пустой.

set collection.set(models, [options])
Метод set выполняет "интеллектуальное" обновление коллекции переданным списком моделей. Если модель из списка не присутствует в коллекции, она будет добавлена; если модель уже присутствует в коллекции, её атрибуты будут объединены с имеющейся моделью; оставшиеся в коллекции модели, которые не присутствуют в списке, будут удалены. При этом все соответствующие события — "add", "remove" и "change" — будут вызываться по мере происходящего. Если вы хотите настроить поведение, вы можете выключить соответствующие операции, передав в опциях: , или .

get collection.get(id)
Возвращает модель из коллекции по её id, cid или по переданной модели.

at collection.at(index)
Возвращает модель из коллекции по индексу. Полезно, если ваша коллекция отсортирована; если нет, то этот метод возвращает модели по порядку вставки.

push collection.push(model, [options])
Добавляет модель в конец коллекции. Принимает те же аргументы, что и add.

pop collection.pop([options])
Удаляет последнюю модель из коллекции и возвращает её. Принимает те же аргументы, что и remove.

unshift collection.unshift(model, [options])
Добавляет модель в начало коллекции. Принимает те же аргументы, что и add.

shift collection.shift([options])
Удаляет первую модель из коллекции и возвращает её. Принимает те же аргументы, что и remove.

slice collection.slice(begin, end)
Вернет неполную коллекцию моделей этой коллекции, используя те же параметры что и Array#slice.

length collection.length
Подобно массивам, коллекции поддерживают свойство length, равное количеству моделей, которые они содержат.

comparator collection.comparator
По умолчанию коллекции не определяют функцию-компаратор. Если вы определяете компаратор, он будет использован, чтобы поддерживать коллекцию в отсортированном виде. Это означает, что когда модели добавляются, они вставляются по корректному индексу в collection.models. comparator может быть определён как функция, подходящая для sortBy из Underscore (функция одного аргумента), или как функция, подходящая для Array.sort (функция двух аргументов), а также может быть определён как строка, указывающая атрибут для сортировки.

Компараторы типа "sortBy" принимают модель и возвращают численное или строковое значение, по которому модель должна быть отсортирована относительно других. Компараторы типа "sort" принимают две модели, и должны возвращать: -1, если первая модель должна идти перед второй; , если у них одинаковая позиция; и 1, если первая модель должна идти после второй.

Отметьте, что хотя главы в данном примере добавляются в обратном порядке, в коллекции они расположены в верном порядке:

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

sort collection.sort([options])
Заставляет модель выполнить пересортировку. Обычно нет необходимости вызывать этот метод вручную, так как коллекции с компаратором всегда сами сортируются при добавлении моделей. Чтобы отключить сортировку при добавлении моделей, передайте при вызове метода add. При вызове метода sort срабатывает событие коллекции "sort".

pluck collection.pluck(attribute)
Собирает значения атрибута из каждой модели в коллекции. Эквивалентно вызову map с возвратом одного атрибута из итератора.

where collection.where(attributes)
Возвращает массив всех моделей, подходящих под переданный хэш attributes. Полезно для простой фильтрации.

findWhere collection.findWhere(attributes)
Ведёт себя так же, как where, но возвращает только первую модель в коллекции, которая подходит под переданный хэш attributes.

url collection.url или collection.url()
Свойство (или функция) url предназначена для того, чтобы указывать положение коллекции на сервере. Модели в коллекциях с определённым url будут использовать его, чтобы конструировать свои собственные URL'ы.

parse collection.parse(response, options)
parse вызывается каждый раз, когда модели коллекции приходят с сервера, в методе fetch. Функция принимает «сырой» объект response и должна вернуть массив атрибутов моделей, которые будут добавлены в коллекцию методом add. Реализация по умолчанию просто пробрасывает JSON-ответ. Переопределите этот метод, если вы работаете с уже существующим API, или чтобы лучше заворачивать в пространства имён ответы сервера.

clone collection.clone()
Вернёт новый экземпляр коллекции с идентичным списком моделей.

fetch collection.fetch([options])
Получает дефолтный набор моделей с сервера и применяет его для этой коллекции. В хэш options могут быть переданы коллбэки success и error, которым передаются коллекция, ответ сервера, и опции (collection, response, options) в качестве аргументов. Когда данные моделей придут с сервера, коллекция вызовет метод set для "интеллектуального" совмещения полученных моделей, изменить это поведение можно, передав , тогда будет вызван метод reset. Внутри fetch обращается к Backbone.sync, чтобы можно было создать свою стратегию персистентности, и возвращает jqXHR-объект. Серверный обработчик запросов fetch должен возвращать JSON-массив моделей.

Поведение метода fetch можно изменить, используя опции метода set. Например, чтобы при получении данных с сервера для всех новых моделей срабатывало событие "add", а для уже существующих, изменённых моделей срабатывало событие "change", но при этом с удалёнными моделями ничего не происходило, можно сделать так: collection.fetch()

Опции jQuery.ajax также могут быть напрямую переданы в fetch, чтобы, например, получить определённую страницу пагинированной коллекции: documents.fetch(>)

Заметьте, что fetch не должен использоваться, чтобы наполнять коллекции на этапе загрузки страницы — все модели, необходимые во время загрузки должны быть предзагружены. fetch предназначен для «ленивой» загрузки моделей для интерфейсов, которые не нужны немедленно: например, документы с коллекциями заметок, которые могут быть открыты или закрыты.

create collection.create(attributes, [options])
Удобное создание модели внутри коллекции. Эквивалентно созданию экземпляра модели с хэшем attributes, сохранению модели на сервер и добавлению модели в набор после успешного создания. Возвращает новую модель. Если валидация на клиенте не проходит, модель не будет сохранена с ошибкой валидации. Для корректной работы у коллекции должно быть свойство model. Метод create может принимать либо хэш атрибутов, либо существующую несохранённую модель.

Создание модели немедленно и автоматически запускает событие "add", событие "request" будет вызвано, как только модель отправлена на сервер и событие "sync", как только модель успешно создастся на сервере. Передайте , если вы хотите подождать ответа сервера перед добавлением.

Backbone.Router

Веб-приложения часто предоставляют возможность зафиксировать своё состояние, сделав закладку. Это делается с помощью добавления к URL фрагмента определённого вида. До недавнего времени для этих целей использовались исключительно хэши (#page), но с появлением History API стало возможно использовать URL обычного вида (/page). Backbone.Router предоставляет методы для маршрутизации на стороне клиента, а также связывания этих действий с событиями. Для браузеров, которые не поддерживают History API, Router весьма элегантно проделает то же самое, используя фрагментарную структуру URL.

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

extend Backbone.Router.extend(properties, [classProperties])
Создавая свой класс-маршрутизатор, нужно расширить Backbone.Router. Определите для него actions — действия, которые будут выполнены, когда часть текущего URL совпадет с заданным фрагментом, — и предоставьте хэш роутов (routes), в котором будут описаны паттерны URL и соответствующие им действия.
На заметку: нельзя начинать название роута со слэша.

routes router.routes
Хэш роутов описывает соответствие паттернов URL функциям вашего роутера с аргументами, аналогично тому, как это происходит с хэшем событий представлений. Роут может содержать параметрические части, :param, каждая из которых будет соответствовать единственному фрагменту URL между слэшами, и *splat-части, которые могут соответствовать любому количеству фрагментов URL. Чтобы пометить часть роута как опциональную, нужно обернуть её в круглые скобки, например (/:optional).

Например, роут "search/:query/p:page" соответствует фрагменту "#search/obama/p2", и аргументы obama и p2 будут переданы в action.

Роут "file/*path" соответствует #file/nested/folder/file.txt и в action в качестве аргумента будет передана строка "nested/folder/file.txt".

Роут "docs/:section(/:subsection)" соответствует #docs/faq и #docs/faq/installing, в первом случае в action в качестве аргумента будет передан "faq", во втором случае будут переданы два аргумента "faq" и "installing".

Слеш в конце фрагмента рассматривается как чаcть URL и поэтому будет обработан как отдельный роут. docs и docs/ вызовут разные колбэки. Если вы хотите этого избежать, оберните слеш в круглые скобки "docs(/)", такой роут будет соответствовать обоим фрагментам.

Когда пользователь нажимает кнопки «назад/вперёд» или вводит в адресную строку URL, который соответствует какому-либо роуту, будет сгенерировано событие (event), одноимённое action'у этого роута, таким образом, другие объекты тоже могут слушать роутер и «быть в курсе» происходящих событий. В приведённом ниже примере посещение "#help/uploading" приведёт к тому, что роутер сгенерирует событие route:help.

constructor / initialize new Router([options])
Создавая роутер, вы можете задать его роуты, передав их в качестве свойства объекта options, если хотите. Кроме того, объект options целиком будет передан в определённую вами функцию initialize.

route router.route(route, name, [callback])
С помощью этого метода можно добавить новый роут к объекту после инициализации. Аргумент route может быть строкой-роутом или регулярным выражением. Части URL, соответствующие заданному роуту или регулярному выражению, будут переданы функции callback в качестве аргументов. Аргумент name будет использован для того, чтобы сгенерировать события вида "route:name" при совпадении фрагмента URL и роута. Если аргумент callback опущен, то будет использована router[name]. Последний добавленный роут может переопределить добавленный раннее.

navigate router.navigate(fragment, [options])
Когда вы решите, что ваше приложение находится в состоянии, которое желательно было бы сохранить, вызовите navigate чтобы обновить URL, передав в качестве аргумента fragment необходимый фрагмент URL. Если при этом вы хотите вызвать функцию роутера, то установите свойство trigger в true. Для того, чтобы обновить URL без создания записи в истории браузера, установите свойство replace в true.

Backbone.history

History служит глобальным роутером (в пределах фрейма), обрабатывая события hashchange или вызовы pushState, находя сопоставление с подходящим роутом и запуская коллбэки. Вам не надо даже вручную создавать ничего из этого — просто используйте ссылку на Backbone.history.

Поддержка pushState существует в Backbone в сугубо опциональной форме. Старые браузеры, которые не поддерживают pushState будут продолжать использовать хэш-фрагменты адресов, и если поддерживающий pushState браузер зайдёт на URL с хэшем, этот URL будет прозрачно заменён настоящим URL'ом. Отметьте, что использование таких адресов требует от веб-сервера корректной отдачи таких страниц, так что могут потребоваться изменения и на сервере. Например, если у вас есть роут /documents/100, ваш сервер должен отдать эту страницу, если браузер зайдёт на неё напрямую. Для полной индексации поисковиками лучше всего, если сервер генерирует полный HTML для страницы, но если речь идёт о веб-приложении, достаточно просто отдавать тот же контент, что и для корневой страницы, и дополнять оставшееся с помощью JS и представлений Backbone.

start Backbone.history.start([options])
Когда созданы все ваши роутеры и все роуты корректно установлены, вызовите Backbone.history.start() чтобы начать отслеживать события hashchange и диспетчеризовать роуты.

Чтобы обозначить, что вы хотите использовать поддержку pushState из HTML5 в вашем приложении, вызовите Backbone.history.start(). Если вы хотите использовать pushState для современных браузеров, но чтобы устаревшие браузеры полностью перезагружали страницу, как при обычных переходах по ссылкам, передайте опцию в хеше options.

Если приложение отдаётся не с корневого адреса (/) домена, обязательно укажите History, где находится корень, с помощью опции Backbone.history.start()

Во время вызова, если в роутах находится соответствие с текущим адресом, Backbone.history.start() возвращает true. Если ни один из существующих роутов не подходит к текущему адресу, будет возвращено значение false.

Если сервер уже отрисовал всю страницу, и вы не хотите, чтобы начальный роут сработал, когда стартует History, передайте silent: true.

Так как хэш-навигация в IE полагается на , вызывайте start() только после готовности DOM.

Backbone.sync

Backbone.sync — функция, которую Backbone вызывает каждый раз, когда пытается прочитать/сохранить модель с/на сервер. По умолчанию она использует (jQuery).ajax, чтобы делать RESTful JSON-запросы, и возвращает jqXHR. Её можно переопределить, чтобы использовать другую стратегию персистентности — WebSocket'ы, XML-транспорт, или localStorage.

Сигнатура метода — sync(method, model, [options])

  • method — метод CRUD ("create", "read", "update", or "delete")
  • model — модель для сохранения (или коллекция для чтения)
  • options — коллбэки success и error на успех и на ошибку, и любые другие опции, которые принимает jQuery.ajax.

В реализации по умолчанию, когда Backbone.sync посылает запрос на сохранение модели, её атрибуты будут переданы, сериализованные как JSON, и посланы в теле HTTP с контент-типом application/json. Возвращая JSON-ответ, посылайте атрибуты модели, которые были изменены сервером, и должны быть обновлены на клиенте. Отвечая на запрос "read" от коллекции (Collection#fetch), посылайте массив атрибутов моделей.

Всякий раз, когда модель или коллекция начинает синхронизацию с сервером, генерируется событие "request". Если запрос завершился успешно, будет вызвано событие "sync", в противном случае — "error".

Функция sync может быть переопределена глобально как Backbone.sync или на более тонком уровне — добавлением метода sync в коллекцию Backbone или в отдельную модель.

Обработчик sync по умолчанию мапит CRUD в REST таким образом:

Для примера, обработчик в Rails, отвечающий на вызов "update" из Backbone, может выглядеть так: (В настоящем коде никогда не используйте update_attributes слепо и всегда перечисляйте атрибуты, разрешённые к изменению, с помощью «белого списка».)

Ещё один совет по интеграции с Rails версии 3.1 и ниже: отключить заворачивание в пространство имён для вызовов to_json на моделях, установив ActiveRecord::Base.include_root_in_json = false

ajax Backbone.ajax = function(request) < . >;
Если хотите использовать собственную AJAX-функцию, или ваш сервер по какой-то причине не поддерживает взаимодействие при помощи jQuery.ajax API, вы можете определить свою функцию Backbone.ajax.

emulateHTTP Backbone.emulateHTTP = true
Если необходимо работать со старым сервером, который не поддерживает подход по умолчанию REST/HTTP, можно включить эмуляцию HTTP-действий Backbone.emulateHTTP. Установка этой опции будет подделывать запросы PUT и DELETE с помощью HTTP POST, устанавливая заголовок X-HTTP-Method-Override в настоящий метод. Если опция emulateJSON также включена, настоящий метод будет передан, как дополнительный параметр _method.

emulateJSON Backbone.emulateJSON = true
Если необходимо работать со старым сервером, который не может обрабатывать запросы, закодированные как application/json, выставление Backbone.emulateJSON = true; заставит JSON сериализоваться в параметр model, и запрос будет сделан с MIME-типом application/x-www-form-urlencoded, как если бы это была HTML-форма.

Backbone.View

Представления в Backbone — это скорее соглашение, нежели код: они никак не влияют на ваш HTML и CSS, и могут быть использованы с любой шаблонной библиотекой. Основная идея — организовать ваш интерфейс в логически выделенные представления, опирающиеся на модели, каждое из которых может быть обновлено независимо, когда модель изменяется, без необходимости перерисовывать страницу. Вместо того, чтобы копаться в JSON-объекте, выискивать элемент в DOM-дереве и обновлять HTML вручную, вы привязываете метод render представления к событию "change" модели — и теперь везде, где бы ни отображались данные модели, они немедленно становятся актуальными.

extend Backbone.View.extend(properties, [classProperties])
Создание своего класса представления. Нужно переопределить метод render, декларативно указать события и, возможно, tagName, className или id корневого элемента представления.

Свойства tagName, id, className, el, и events могут быть переданы как функции, если вы хотите, чтобы они были заданы во время исполнения.

constructor / initialize new View([options])
При создании экземпляра представления опции, которые вы передаёте в хэше options, объединяются с уже имеющимися опциями представления и после этого будут доступны как this.options внутри него. Есть несколько особенных опций, которые, будучи переданы, будут доступны как прямые свойства представления: model, collection, el, id, className, tagName и attributes. Если представление определяет метод initialize, он будет вызван в момент создания экземпляра. Если вы хотите создать представление, которое ссылается на элемент, уже присутствующий в DOM, передайте его в опциях: new View(). В дальнейшем он так же будет доступен как this.el.

el view.el
Все представления всегда имеют DOM-элемент в любой момент времени (свойство el), вставлены они в документ или нет. Таким образом, представления могут быть отрендерены в любое время и вставлены в DOM-дерево все разом — это приводит к высокопроизводительному интерфейсу с минимальным количеством переформатирований и перерисовываний (reflows and repaints). Свойство this.el создаётся из свойств tagName, className, id и attributes, если они указаны. Если нет — el будет пустым div'ом.

$el view.$el
Закешированный объект jQuery c элементом данного представления — то же самое, что $(this.el). Удобная ссылка — замена постоянному оборачиванию DOM-элемента.

setElement view.setElement(element)
Если вы хотите применить Backbone-представление к другому DOM-элементу, используйте setElement, который также создаст закешированную ссылку $el и перенесёт делегированные события со старого элемента на новый.

attributes view.attributes
Хэш атрибутов, которые будут установлены DOM-элементу el (id, класс, data-атрибуты, и т.д.), или функция, которая возвращает такой хэш.

$ (jQuery) view.$(selector)
Если jQuery подключён на странице, каждое представление имеет функцию $, которая выполняет DOM-запросы внутри элемента представления. Используя эту функцию, вы не нуждаетесь в использовании id модели как части вашего запроса, чтобы получить определённые элементы в списке, и можете полагаться на HTML-класс. Это эквивалентно такому вызову: view.$el.find(selector)

render view.render()
Метод render по умолчанию реализован как пустая функция. Переопределите её своим кодом отрисовки шаблона с данными модели и обновления this.el новым HTML. Хорошее соглашение — делать return this в конце render, чтобы иметь возможность делать цепочные вызовы.

Backbone ничего не знает о ваших предпочтениях создания HTML. Ваш метод render может просто конкатенировать HTML-строку или использовать document.createElement, чтобы генерировать DOM-дерево. Как бы то ни было, мы предлагаем выбрать хорошую шаблонную библиотеку. Mustache.js, Haml-js и Eco являются хорошими альтернативами. Так как на странице уже присутствует Underscore.js, доступная функция _.template является превосходным выбором, если вы предпочитаете шаблоны с простыми включениями JavaScript.

На какой бы стратегии шаблонизации вы бы не остановились, она хороша, если вы никогда не помещаете строки с HTML в ваш JavaScript. В DocumentCloud мы используем Jammit, чтобы упаковать наши JS-шаблоны, хранящиеся в /app/views, как часть нашего главного пакета ассетов в core.js.

remove view.remove()
Удаляет представление из DOM, после этого вызывает stopListening для удаления событий, которые представление прослушивает.

delegateEvents delegateEvents([events])
Использует функцию on из jQuery для декларативного описания обработчиков DOM-событий внутри представления. Если хэш events не передан явно, используется this.events. События записываются в следующем формате . Обработчик может быть как именем метода представления, так и напрямую функцией. Если опустить селектор, то событие будет привязано к корневому элементу представления (this.el). По умолчанию delegateEvents вызывается внутри конструктора за вас, так что если ваш хэш events прост, все ваши DOM-события уже будут снабжены обработчиками, и вам не придётся вызывать этот метод вручную.

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

Использование delegateEvents предоставляет несколько преимуществ перед ручным навешиванием обработчиков с помощью jQuery во время рендеринга. Все присоединённые коллбэки привязываются к представлению перед передачей их в jQuery, так что при их вызове this продолжает ссылаться на экземпляр представления. Когда delegateEvents запускается снова (возможно, с другим хэшем событий) все коллбэки удаляются и делегируются заново, что удобно для представлений, которым нужно менять поведение в разных режимах.

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

undelegateEvents undelegateEvents()
Удаляет все делегированные события. Применяется, если нужно временно деактивировать либо удалить представление из DOM.

Utility

Backbone.noConflict var backbone = Backbone.noConflict();
Откатывает объект Backbone в предыдущее значение. Можно использовать возвращенное из Backbone.noConflict() значение, чтобы хранить ссылку на Backbone. Находит применение при внедрении Backbone на сторонние сайты, где вы не хотите испортить существующий Backbone.

Backbone.$ Backbone.$ = $;
Если у вас несколько копий jQuery на странице или если вы хотите приказать Backbone использовать определённый объект в качестве библиотеки DOM / Ajax, то это функция для вас.

Примеры

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

www.bookfinder.com.ua — это книжный поисковый сервис по интернет-магазинам Украины. Веб-приложение базируется на Backbone.js.

Разработчик: Кащеев Сергей (github.com/ginger/) Основные модели:
- книга (название, авторы, url, url картинки, описание, цена, валюта, магазин и др.)
- состояние поиска (запрос, выбранный фильтр, сортировка, текущая страницы и др.)

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

Широко используются коллекции книг с методами для подсчёта цен, сортировок и др. и один основной роутер, который маршрутизирует запросы вида #!/search/запрос/фильтр/сортировка/номер_страницы

Приложение также использует jQuery, RequireJS, Underscore.js, localStorage (jStorage — для хранения закладок). Серверная сторона — это ASP.NET 2.0 с JSON для обмена данными.

Jérôme Gravel-Niquet создал пример приложения списков Todo, которое находится в репозитории. Если вы не знаете, с чего вообще начать в Backbone, потратьте минутку, чтобы прочесть исходный код с аннотациями. Это приложение использует адаптер к localStorage, чтобы прозрачно сохранять все ваши todo в браузере, вместо отсылки их на сервер. Также есть версия, расположенная localtodos.com.

DocumentCloud

Рабочее пространство DocumentCloud построено на Backbone.js, и Документы, Проекты, Заметки, и Счета — все являются моделями и коллекциями Backbone. Если вам интересна история — и Underscore.js и Backbone.js были изначально извлечены из кода DocumentCloud codebase и упакованы, как самостоятельные JS-библиотеки.

LinkedIn Mobile

LinkedIn использует Backbone.js, чтобы создать их HTML5 мобильное веб-приложение следующего поколения. С Backbone просто сохранять приложение модульным, организованным и расширяемым, что сделало возможным запрограммировать сложности UX LinkedIn. Приложение также использует Zepto, Underscore.js, SASS, iScroll, localStorage и сanvas.

Foursquare

Foursquare — небольшой забавный стартап, который помогает встречаться с друзьями, открывать новые места и экономить деньги. Модели Backbone широко используются в ядре API, а представления движут многие популярные фичи, как карта на домашней странице и списки.

Khan Academy

Khan Academy выполняет миссию предоставления бесплатного образования мирового уровня всем и везде. С тысячью видео, сотнями работающих на JS упражнений, и большими планами на будущее, Khan Academy использует Backbone, чтобы сохранять фронтенд-код модульным и организованным. Профили пользователей и установка целей рализованы с помощью Backbone, jQuery и Handlebars, и большая часть работы по новым фичам сдвигается на клиентскую сторону, сильно увеличивая качество API.

Basecamp Mobile

37Signals использовали Backbone.js, чтобы создать Basecamp Mobile, мобильную версию их популярного ПО управления проектами. Есть доступ ко всем вашим проектам в Basecamp, можно постить новые сообщения и комментировать майлстоны (все они внутри представлены как модели Backbone.js).

Больше чем один способ сделать это
Часто люди начинают обращаться с примерами, приведёнными на этой странице, как с какой-то божественной истиной. На самом деле Backbone.js предназначен быть довольно агностичным насчёт многих частых паттернов клиентского кода. Например:

Отношения между моделями и представлениями могут осуществляться многими способами. Некоторым нравится иметь прямые указатели, когда представления соотносятся 1:1 с моделями model.view и view.model). Другие предпочитают иметь промежуточный "контроллер", который дирижирует созданием и организацией представлений в иерархию. Другие всё ещё предпочитают событийный подход и всегда запускают события вместо прямого вызова методов. Всё это прекрасно работает.

Групповые операции над моделями часто встречаются, но лучший способ обработки зависит от серверной стороны. Некоторых не заботят индивидуальные AJAX-запросы. Другие создают явные ресурсы для RESTful групповых операций: /notes/batch/destroy? :

Создавайте свои события. Backbone.Events спроектирован так, что вы можете внедрять его в любой объект или прототип. Так как можно использовать любую строку в качестве имени события, часто удобно привязываться и запускать свои собственные события: model.on("selected:true") или model.on("editing")

Отрисовывайте UI, как считаете нужным. Backbone ничего не знает о том, используете вы шаблоны Underscore, Mustache.js, прямые DOM-манипуляции, сгенерированные на сервере кусочки HTML или jQuery UI в методе render. Иногда вы создаёте представление для каждой модели, иногда есть представление, которое отображает тысячи моделей разом, в одном цикле. Оба подхода могут подходить одному приложению в зависимости от количества данных и сложности UI.

Вложенные модели и коллекции
Нередко коллекции вкладываются внутрь моделей в Backbone. Например, рассмотрим модель Mailbox, которая содержит много моделей Message. Есть хороший паттерн организации этого всего: иметь коллекцию this.messages для каждого ящика, делая возможным ленивую загрузку сообщений, когда ящик открывается первый раз. Возможно, в паре с представлениями MessageList, слушающими события "add" и "remove".

Если нужно что-то более строгое — существует много плагинов, которые добавляют сложные ассоциации между моделями.

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

  • Отражать структуру SQL БД или структуру NoSQL БД.
  • Использовать модели с массивами "внешних ключей" и джойнить их в коллекции верхнего уровня (a-la таблицы).
  • Для многочисленных связей использовать диапазоны > Предзагрузка моделей
    Когда ваше приложение грузится, обычно имеется набор начальных моделей, которые точно понадобятся, чтобы отобразить страницу. Вместо того чтобы сделать ещё один AJAX-запрос с помощью fetch, лучшим паттерном будет иметь их данные уже загруженными в страницу. Тогда можно будет использовать reset, чтобы наполнить коллекции начальными данными. В DocumentCloud в ERB-шаблоне для рабочего пространства мы делаем так:

Не забудьте сделать escape Расширяя Backbone
Многие JS-библиотеки созданы быть отгороженными и замкнутыми. Вы взаимодействуете с ними, вызывая их публичный API, но никогда не заглядываете во внутренности. Backbone.js не является такой библиотекой.

Так как она служит фундаментом вашего приложения, подразумевается что вы будете расширять и улучшать её под себя — весь исходный код аннотирован, чтобы облегчить это. Вы обнаружите, что там не так уж много всего, помимо функций ядра, и большинство из них может быть переопределено или улучшено, если вам нужно. Если вы поймаете себя на том, что добавляете методы в Backbone.Model.prototype, или создаёте свои собственные базовые субклассы, не беспокойтесь — так и было задумано.

Как Backbone соотносится с «традиционным» MVC?
Разные имплементации паттерна Model-View-Controller имеют тенденцию расходиться в определениях контроллера. Если это поможет — в Backbone класс представления может считаться чем-то вроде контроллера, диспетчиризуя события, которые идут от UI, а HTML-шаблон — настоящим представлением. Мы назвали его «View», так как он отвечает за логически выделенный кусок UI, ответственный за контент одного DOM-элемента.

Сравнивая общую структуру Backbone с серверным MVC-фреймворком, как Rails, получим примерно следующее:

  • Backbone.Model подобна моделям в Rails, минус методы класса. Оборачивает строчку данных в бизнес-логику.
  • Backbone.Collection — группа моделей на клиентской стороне, с сортировкой/фильтрацией/аггрегацией.
  • Backbone.Routerroutes.rb в Rails + экшены контроллера. Мапит адреса на функции.
  • Backbone.View — логически выделенный, готовый к повторному использованию кусочек интерфейса. Часто, но не всегда, связан с моделью.
  • Клиентские шаблоны — шаблоны *.html.erb из Rails, отрисовывающие кусочки HTML.

Привязка "this"
Вероятно, самая общая засада в JavaScript — это тот факт, что когда функция передается как коллбэк, её оригинальный контекст (this) теряется. С Backbone, имея дело с событиями и коллбэками, часто полезно полагаться на _.bind и _.bindAll из Underscore.js.

Назначая обработчики на события Backbone, можно передать опциональный третий параметр, чтобы указать контекст this, с которым обработчик будет потом вызван:

Работа Rails
Backbone.js изначально был извлечён из Rails-приложения; заставить модели на клиенте (в Backbone) корректно синхронизироваться с серверными (Rails) моделями не составляет никакого труда, но всё же есть несколько вещей, о которых следует знать.

По умолчанию, Rails версии 3.1 и ниже добавляет ещё одну обёртку в JSON-представлении моделей. Вы можете отключить это оборачивание, установив:

в конфигурации. Или переопределите parse таким образом, чтобы вытаскивать атрибуты моделей из обёртки. Похожим способом Backbone делает PUT и POST запросы с прямым JSON-представлением моделей, хотя Rails ожидает атрибуты завёрнутыми в пространство имён. Можно заставить контроллеры фильтровать атрибуты прямо из params, или переопределить метод toJSON в Backbone, добавив дополнительную обертку, которую ждёт Rails.

Цукерберг рекомендует:  Eclipse SWT обзор возможностей
Понравилась статья? Поделиться с друзьями:
Все языки программирования для начинающих