Российский Новый Университет
Опубликован: 25.01.2016 | Доступ: свободный | Студентов: 2234 / 161 | Длительность: 16:40:00
Лекция 6:

Улучшение пользовательского интерфейса с помощью Ajax

< Лекция 5 || Лекция 6: 1234 || Лекция 7 >

Манипуляция HTML-документами

Теперь, когда вам удобно манипулировать HTML-элементами, давайте посмотрим, как добавлять новые элементы или удалить существующие элементы. Чтобы вставить HTML-код перед элементом, используйте метод before(), а для вставки кода после элемента, используйте метод after().Обратите внимание, как методы jQuery хорошо именованы и их очень легко запомнить!

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

>>> $(".well span").before ("<strong>(</strong>")
>>> $(".well span").after ("<strong>)</strong>")

Вы можете передать любую строку, какую вы хотите, с методами before() или after(). Строка может содержать обычный текст, один или больше элементов HTML. Эти методы предоставляют очень гибкий способ для динамического добавления элементов HTML в документ HTML.

Если вы хотите удалить элемент, используйте метод remove(). Например:

$("#navbar").remove()

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

>>> $("#nav")

Результатом этого является следующим:

[]

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

Обход дерева документов

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

Для этого jQuery предоставляет несколько методов. Метод parent () возвращает родителя текущего выбранного элемента. Метод children () возвращает всех непосредственных дочерних элементов выбранного элемента. Наконец, метод find () возвращает всех потомков текущего выбранного элемента. Все эти методы принимают необязательную строку CSS селектора для ограничения элементов теми, которые соответствуют результату селектора. Например, $(".column").find("span") возвращает всех потомков <span> столбца aclass.

Если вы хотите получить доступ к отдельному элементу группы, используйте метод get (), который принимает индекс элемента в качестве параметра. Метод $("span").get(0), например, возвращает первый элемент <span> из выбранной группы.

Обработка событий

Далее мы изучим обработчики событий. Обработчик событий — это функция JavaScript, которая вызывается, когда происходит определенное событие, например, при нажатии кнопки или отправке формы. jQuery предоставляет большой набор методов для присоединения обработчиков к событиям; события, представляющие особый интерес в нашем приложении - щелчки мышью и отправка формы. Для обработки события нажатия на элемент, мы выбираем этот элемент и вызываем метод click(). Этот метод принимает в качестве параметра функцию обработчика событий. Давайте попробуем это в нашей консоли разработчика.

Откройте страницу профиля пользователя приложения и вставьте кнопку после твита:

>>> $(".well span").after("cbutton id=\"test-button\">Нажми!</ button>")

Обратите внимание, что нам пришлось опустить кавычки в строках переданных методу after().

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

>>> $("#test-button").click(function () { alert("Вы меня нажали!"); })

Теперь, когда вы нажмете на кнопку,появится окно сообщения.Как это работает?

Аргумент, который мы передали в методе click(), может выглядеть немного сложным, так что давайте рассмотрим его снова:

function () { alert("Вы меня нажали!"); }

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

>>> function handler{ alertC("Вы нажали меня!"); }
>>> $("#test-button").click(handler)

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

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

Отправка запросов AJAX

Прежде чем мы закончим этот раздел, давайте поговорим о AJAX-запросах. jQuery предоставляет много способов, чтобы отправлять запросы AJAX на сервер. Существует, например, метод load(), который принимает URL-адрес и загружает страницу по URL-адресу в выбранный элемент. Существуют также методы для отправки запросов GET или POST и получения результатов. Мы изучим эти методы более подробно при имплементации функций AJAX в наш проект.

Реализация поиска твитов

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

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

Так что прежде чем мы поработаем с AJAX давайте напишите простое представление, чтобы искать по названию закладки. Во-первых нам нужно создать форму поиска, поэтому откройте файл tweets/forms.py и добавьте в него следующий класс:

Сlass SearchForm(forms.Form):
    query = forms.CharField(label='Enter a keyword to search for',
  widget=forms.TextInput(attrs={'size': 32, 'class':'form-control search-query'}))

Как вы можете видеть, это довольно простой класс формы с только одним текстовым полем. Это поле будет использоваться пользователем для ввода ключевых слов поиска. Далее создадим представление для проведения поиска. Откройте файл tweets/views.py и введите следующий код в него:

class Search(View):
    """Search all tweets with query /search/?query=<query> URL"""
    def get(self, request):
        form = SearchForm()
        params = dict()
        params["search"] = form
        return render(request, 'search.html', params)

    def post(self, request):
        form = SearchForm(request.POST)
        if form.is_valid():
            query = form.cleaned_data['query']
            tweets = Tweet.objects.filter(text__icontains=query)
            context = Context({"query": query, "tweets": tweets})
            return_str = render_to_string('partials/_tweet_search.html', context)
            return HttpResponse(json.dumps(return_str), content_type="application/json")
        else:
            HttpResponseRedirect("/search")

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

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

Метод post() является тем методом где происходит волшебство. Когда мы отображаем результаты поиска, это просто макета отображения с формой поиска, так что если вы взглянете на новый файл, который мы создали, под названием search.html, вы можете увидеть следующее:

{% extends "base.html" %} 
{% load staticfiles %}
{% block content %}

<div class="row clearfix">
        <div class="col-md-6 col-md-offset-3 column">
            <form id="search-form" action="" method="post">{% csrf_token %}
            <div class="input-group input-group-sm">
                    {{ search.query.errors }}
                    {{ search.query }}
                  <span class="input-group-btn">
                    <button class="btn btn-search" type="submit">search</button>
                  </span>
            </div><!-- /input-group -->
          </form>
        </div>
		<div class="col-md-12 column tweets">
		</div>
	</div>
{% endblock %}
{% block js %}
    <script src="{% static 'js/search.js' %}"></script>
{% endblock %}

Если вы посмотрите внимательно, вы увидите, что мы включили новый раздел раздела с именем {% block js %}. Концепция, используемая здесь, является такой же, как и {% block content %}, то есть, то что объявляется здесь, будет передаваться в файл base.html. Взяв это на заметку, посмотрим на измененный файл base.html. Мы увидим следующее:

{% load staticfiles %}
<html>
  <head>
    <link href="{% static 'css/bootstrap.min.css' %}"
          rel="stylesheet" media="screen">
    {% block css %}
    {% endblock %}
  </head>
  <body>
<nav class="navbar navbar-default" role="navigation">
 <a class="navbar-brand" href="#">MyTweets</a>
    {% block navbar %}
    {% endblock %}
</nav>
  <div class="container">
    {% block content %}
    {% endblock %}
</div>
<nav class="navbar navbar-default navbar-fixed-bottom" role="navigation">
     <p class="navbar-text navbar-right">Footer </p>
</nav>
<script src="{% static 'js/jquery-2.1.1.min.js' %}"></script>
<script src="{% static 'js/bootstrap.min.js' %}"></script>
<script src="{% static 'js/base.js' %}"></script>
    {% block js %}
    {% endblock %}
 </body>
</html>

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

{% block css %}
{% endblock %}
{% block js %}
{% endblock %}

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

Теперь, возвращаясь к нашей функции поиска AJAX, вы увидите, что этот файл search.html, аналогичен файлу tweet.html.

Для функции поиска мы создадим новый URL-адрес, который нам нужно добавить к файлу urls.py следующим образом:

url(r'^search/$', Search.as_view())

urls.py

from django.conf.urls import patterns, include, url
from django.contrib import admin
from tweet.views import Index, Profile, PostTweet, HashTagCloud, Search

admin.autodiscover()

urlpatterns = patterns('',
    url(r'^$', Index.as_view()),
    url(r'^user/(\w+)/$', Profile.as_view()),
    url(r'^admin/', include(admin.site.urls)),
    url(r'^user/(\w+)/post/$', PostTweet.as_view()),
    url(r'^hashTag/(\w+)/$', HashTagCloud.as_view()),
    url(r'^search/$', Search.as_view()),
)
< Лекция 5 || Лекция 6: 1234 || Лекция 7 >
Константин Боталов
Константин Боталов

Вроде легкие вопросы и ответы знаю правильные, но система считает иначе и правильные ответысчитает неправильными. Приходится выполнть по несколько раз. Это я не правильно делаю или тест так составлен?

Владимир Филипенко
Владимир Филипенко

Листинг показывает в 4-ой лекции, что установлен Django 1.8.4. Тут же далее в этой лекции указаны настройки, которые воспринимает Django 1.7 и младше.