Элементы и стили (примеры)

Пример сайта: HTML разметка:

CSS:

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

подробнее

Akka Stream принцип работы и создание своих элементов

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

подробнее

Пример Instagram на JS

Небольшой аналог Instagram.

В процессе мы создадим несколько фильтров, которые будут применяться к фотографии в блоке .photo. Переключатели фильтров мы разместим в блоке .toggle-controls, а само переключение будет работать на JavaScript. Cначала подготовим разметку для нашего будущего фотоприложения.

Теперь давайте создадим первый набор фильтров для класса .walden. Набор фильтров применится к большой фото и к переключателю.

Давайте добавим заготовку для ещё одного переключателя. Класс для второго фильтра будет называться toaster.

Затем «отрепетируем» переключение фильтра без использования JavaScript. Для этого пока будем менять HTML-код вручную. При переключении фильтра происходит два события:

Первое. В переключателе класс active перемещается на текущий фильтр:

Второе. У блока с большим фото меняется класс текущего фильтра:

Мы «переключили» текущий фильтр, а чтобы увидеть его эффект, зададим его стили.

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

Всё готово для «оживления» интерфейса с помощью JavaScript. HTML-код Кекстаграма приведён в исходное состояние: фильтр ещё не выбран и к фото не применён.

Сначала включим фильтр toaster и применим его к фотографии. Для этого:

1. Найдём элемент списка с классом toaster и сохраним его в переменную control. var control = document.querySelector('li.toaster');

2. Найдём элемент с классом photo и сохраним его в переменную photovar photo = document.querySelector('.photo');

3. Теперь к элементу списка, хранящемуся в переменной control, добавим класс activecontrol.classList.add('active');

4. А к блоку большой фотографии, она уже в переменной photo, добавим класс toaster: photo.classList.add('toaster');

Теперь попробуйте повторить это сами. Обратите внимание, что при добавлении класса с помощью classList.add точка в начале строки не пишется.

На предыдущем шаге мы «включили» фильтр toaster из исходного состояния, а сейчас переключим его на walden. Для этого:

1. Снова найдём элемент списка с классом toaster, сохраним его в переменную toasterControl и удалим у него класс active, добавленный ранее: var toasterControl = document.querySelector('li.toaster'); toasterControl.classList.remove('active');

2. Найдём элемент списка с классом walden, сохраним его в переменную waldenControl и добавим ему класс active: var waldenControl = document.querySelector('li.walden'); waldenControl.classList.add('active');

3. Найдём элемент с классом photo и сохраним его в переменную photo. var photo = document.querySelector('.photo');

4. Удалим у фото класс toaster и добавим класс walden: photo.classList.remove('toaster'); photo.classList.add('walden');

Разберёмся подробнее в том коде, который мы написали. Вот один из фрагментов:

var toasterControl обозначает, что мы создаём переменную с именем toasterControl.

document – это специальная переменная, в которой хранится корневой элемент HTML-документа, будем называть его просто «документ». В нём хранятся все остальные теги.

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

Метод querySelector не всегда может найти элемент и тогда переменная остаётся пустой. Чтобы проверить, что в переменной есть элемент и с ним можно работать, используется условный оператор if.

У элементов, которые мы находим с помощью querySelector, есть свойство classList, в котором хранится список классов элемента.

Список классов можно изменять, удаляя или добавляя в него классы с помощью методов add и remove свойства classList.

Теперь немного отдохнём от JavaScript и создадим ещё один фильтр.

Вернёмся к JavaScript и немного улучшим наш код. Посмотрите эти строчки: var control = document.querySelector('li.toaster'); photo.classList.add('toaster');

Название фильтра toaster в коде повторяется два раза, Карл. Чтобы «переключить» фильтр, придётся поменять код в двух местах. А это лишняя работа!

Избавимся от дублирования. В начале кода создадим переменную с названием фильтра: var filterName = 'toaster'; В метод поиска элементов мы передаём строку li.toaster. Чтобы получить такую же строку из переменной, воспользуемся операцией «склеивания» строк: 'li.' + filterName // результат: 'li.toaster'

В коде для поиска переключателя заменим строку на выражение с переменной:

Внутри photo.classList.add находится такое же значение, как и в переменной, поэтому просто заменяем строку на переменную:

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

Функция создаётся выражением, начинающимся с ключевого слова function. Например, в этом коде мы создаём функцию для суммирования чисел c именем sum:

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

Обернём наш код для переключения фильтров в функцию toggleFilter, у которой будет один параметр — filterName. А затем вызовем функцию с разными названиями фильтра в качестве параметра.

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

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

Если же вызвать созданную функцию несколько раз подряд с разными параметрами: toggleFilter('toaster'); toggleFilter('kelvin'); То активными станут сразу несколько переключателей, а к фотографии применятся несколько фильтров одновременно.

У HTML-элементов есть возможность создавать специальные атрибуты, в которых можно хранить вспомогательную информацию и легко передавать её в JavaScript. Такие атрибуты начинаются с префикса data-.

При этом data-атрибуты валидны и никак не влияют на отображение элементов в браузере.

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

Чтобы с помощью JavaScript считать значение data-атрибутов, нужно использовать свойство dataset. Пример:

В свойстве dataset HTML-элемента хранятся все значения его data-атрибутов. Обратиться к ним можно по названию data-атрибута, удалив из названия приставку data-.

Добавлять содержимое в HTML-элемент через JavaScript можно с помощью свойства innerHTML:

Присвоенная свойству innerHTML строка заменяет всё содержимое HTML-элемента. В этой строке можно использовать любой HTML-код.

Если нужно совершить несколько однотипных действий, то можно использовать цикл for. Вот его синтаксис:

Ранее мы использовали метод querySelector, который возвращает только один элемент: первый элемент, соответствующий селектору.

Другой метод querySelectorAll возвращает все элементы, соответствующие селектору.

С помощью for удобно перебирать найденные элементы:

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

Лучше найти все переключатели внутри списка и перебрать их с помощью цикла. И внутри цикла задавать название каждому переключателю.

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

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

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

На предыдущем шаге мы уже находили все переключатели и сохраняли их в переменную controls: var controls = document.querySelectorAll('.toggle-controls li'); Теперь мы можем использовать эту переменную внутри функции — добавить в начало функции ещё один цикл, который пройдётся по всем переключателям и удалит у них класс.

Ошибку с выделением активного переключателя исправили. Осталась вторая ошибка: фильтр на большой фотографии применяется неправильно. Причина — лишние классы фильтров у большой фотографии. Вот что происходит с HTML, когда функция переключения вызывается несколько раз: <div class="photo walden toaster kelvin"></div>

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

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

И ещё одна важная деталь. Переменная photo теперь используется в самом начале функции, поэтому мы вынесем строчку поиска переменной из функции в самый верх кода: var controls = document.querySelectorAll('.toggle-controls li'); var photo = document.querySelector('.photo');

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

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

Для этого нам нужно научиться отслеживать и обрабатывать события, которые происходят на веб-странице. Для этого в JavaScript, существует метод addEventListener:

В этом фрагменте кода мы сделали следующее:

  1. Нашли элемент списка и у него вызвали метод addEventListener.
  2. Указали отслеживать событие click или «щелчок мыши».
  3. Для щелчков указали функцию-обработчик без названия, внутри которой вызвали функцию переключения фильтров.

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

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

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

А чтобы сократить код в цикле, создадим новую функцию:

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

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

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

1. Изменим обработчик внутри clickControl:

2. Изменим параметр у toggleFilter, теперь это не строка, а элемент:

3. В toggleFilter передаётся переключатель и искать его уже не надо, удаляем лишний код

4. Название фильтра для фото теперь берём из data-атрибута переключателя:

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

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

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

Чтобы изменить CSS-свойство элемента в скрипте, нужно обратиться к свойству styleэлемента. Например: var element = document.querySelector('.photo-original'); element.style.width = '10px';

В этом коде элементу задаётся ширина 10px.

С помощью element.style можно и получать, и изменять значения свойств.

Но названия свойств в JavaScript не всегда совпадают с их названиями в CSS. Например, CSS-свойство left совпадает с style.left, но CSS-свойство baсkground-color уже отличается: style.backgroundColor.

Результат:

HTML:

CSS:

JS script:

JS separator:

Просто пример:

HTML:

CSS:
JS:

Создание форм из моделей¶

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

подробнее

Наборы форм Formsets

Класс BaseFormSet¶Набор форм – это уровень абстракции для работы с несколькими формами на одной странице. Это может быть лучше по сравнению с сеткой данных. Допустим, у вас есть следующая форма:

Вы можете разрешить пользователю создавать несколько статей одновременно. Чтобы создать набор форм из ArticleForm, вы должны сделать:

Теперь…

подробнее

Django Forms

HTML-формы HTML форма – это набор элементов внутри <form> … </ form>, которые позволяют посетителю выполнять такие действия, как ввод текста, выбор параметров или управление объектами и т. д., а затем отправлять эту информацию обратно на сервер. Некоторые из этих элементов интерфейса формы – поля ввода текста или флажки –…

подробнее

Python волшебные методы “__getattr__”, “__getattribute__” и другие

За обращение к атрибутам метода отвечают методы класса (это протокол обращения к атрибутам): __getattribute__ __getattr__ __setattr__ __delattr__ Первые два метода отвечают за доступ к атрибутам по чтению. При этом отдельный метод __getattr__ позволяет перехватывать доступ только к не существующим атрибутам.  При этом можно считать, что при доступе на чтение к…

подробнее

Как создать нового пользователя и настроить права доступа в MySQL

Начнем с создания нового пользователя из консоли MySQL:

К сожалению, на данном этапе пользователь “newuser” не имеет прав делать что-либо с базами данных. На самом деле, даже если если пользователь “newuser” попробует залогиниться (с паролем “password”), он не попадет в консоль MySQL. Таким образом, первое, что нам необходимо сделать,…

подробнее

reset the MySQL root password

Залогинится по SSH. Для доступа нужен уровень привилегий root.  Остановить  MySQL при помощи команды Linux : For CentOS and Fedora, type:

For Debian and Ubuntu, type:

Запустите MySQL с  —skip-grant-tables опцией:

Не забудьте символ (&)  в конце команды. Что позволит перевести сервер в фоновый режим, а вам…

подробнее