WEB start

Компьютеры. Интернет. Профессиональное обучение. 055-966-10-17

hit 
counter

Наши преимущества

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


Регистрация на сайте

WEB

  • Angular 6

    Angular

    Angular - это фреймворк, разработанный Google для создания клиентских (frontend WEB development) приложений. Прежде всего он предназначен для разработки SPA - проектов (Single Page Application), то есть одностраничных приложений. В этом плане Angular является наследником другого фреймворка AngularJS. В то же время Angular, начиная с версии 2, это не новая версия AngularJS, а принципиально новый фреймворк.

    Последняя версия Angular на момент написания - Angular 6. Официальный репозиторий фреймворка на гитхаб: https://github.com/angular/angular.

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

    Язык TypeScript - это надмножество языка ECMAScript 6 (также известной как ECMAScript 2015, ES2015), которое компилируется в обычный код на JavaScript (ES5) и широко поддерживается современными ОС.

    На настоящий момент браузеры не имеют встроенной поддержки ни TypeScript, ни ECMAScript 6, поэтому для публикации на сервеере код должен быть преобразован в код на JavaScript, поддерживаемый всеми браузерами.

    Установка Angular

    https://angular.io/guide/setup#windows

    NodeJS

    Установка

    NodeJS ( Node.js® - это среда выполнения для языка JavaScript, построенная на платформе JavaScript V8 для Chrome. https://nodejs.org/en/)

    Node.js позволяет запускать JavaScript-код вне браузера.

    Чтобы JavaScript код выполнился вне браузера (на backend), он должен быть интерпретирован и выполнен. Именно это и делает Node.js. Для этого он использует движок V8 VM от Google — ту же самую среду исполнения для JavaScript, которую использует браузер Google Chrome.

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

    Так, например, для 32 bit Windows нужен файл: node-v8.9.4-x86.msi . Программа установки NodeJS для Windows одной из опций предлагает поставить также и npn.

    Проверить версию

    node -v npm

    (npm - это менеджер пакетов для JavaScript и самый большой реестр программного обеспечения https://www.npmjs.com/)

    Если не поставили вместе с NodeJS, то скачать по ссылке https://nodejs.org/en/download/ и поставить дополнительно.

    Некоторые команды

    npm -v

    проверить версию

    p> npm list strong>

    получить перечень локально установленны пакетов

    npm list -g

    список глобально установленных пакетов

    Angular CLI

    Наиболее популярный инструмент для управления пректами Angular.

    https://cli.angular.io/

    На github:

    https://github.com/angular/angular-cli

    установить cli

    npm install -g @angular/cli

    удалить cli

    npm uninstall -g angular-cli

    npm cache clean

    npm cache clean --force

    проверить установленную версию

    ng --version

    Редактор кода

    Для редактирования проектов на Angular удобно пользоваться, например:

    Visual Studio Code

    Notepad++

    Новый проект

    Запустить консоль NodeJS

    Перейти в папку с проектами Angular и запустить создание нового - project1 командой:

    ng new project1

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

    cd project1

    CLI автоматически создаёт начальную структуру папок и файлов проекта.

    В папке ./src/app находятся, в частности:

    • app.component.ts - первый Angular - компонент, корневой, он называется app-root
    • app.module.ts - исполняемый модуль
    • app.component.css - стили
    • app.component.html - шаблон HTML для вывода в окно браузера

    Запустить проект

    ng serve

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

    ng serve --port 3000 --open

    Открыть запущенный проект в браузере

    http://localhost:4200 (или, соответственно http://localhost:3000)

    Редактировать проект

    Файлы запущенного проекта можно редактировать в любом редакторе кодов (например: Notepad++). При сохранении изменений проект автоматически перезапускается и в окне браузера сразу отражаются изменения.

    Отредактируем файл шаблона корневого компонента нашего приложения (), заменим его на:

    <h1> Название проекта: {{ title }}! </h1> <h2> Наш первый проект с Angular 5 </h2>

    Сгенерировать проект для публикации

    ng build --prod

    Проект для публикации (HTML, CSS, JavaScript) по умолчанию создастся в папке dist

    Все команды ng (Angular):

    Wiki https://github.com/angular/angular-cli/wiki

    PDF https://cli.angular.io/reference.pdf

    Angular компоненты (Components)

    Основной составляющий блок проекта на Angular - компонент.

    Создаём новый компонент (Angular component)

    Создаём компонент с именем comp1 в паке существующего проекта

    ng generate component comp1

    По завершении команды в папке app проекта добавилась папка нашего нового компонента - src/app/comp1.

    В файл app.module.ts добавилась строки описания нашего компонента: 

    import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { Comp1Component } from './comp1/comp1.component'; @NgModule({ declarations: [ AppComponent, Comp1Component ], imports: [ BrowserModule ], providers: [], bootstrap: [ AppComponent] }) export class AppModule { }

    По-умолчанию создался компонент с селектором: app-comp1. Используя этот селектор можно добавить новый компонент в наше приложение. Для этого в файле с шаблоном нашего приложения (app.component.html) добавим строки:

    Он примет вид:

    <div style="text-align:center"> <h1> Название проекта: {{ title }}! </h1> <H1> Наш первый проект с Angular 5 </H1> <app-comp1> </app-comp1>


    Шаблон нового компонента находится в его файле с именем:

    src\app\comp1\comp1.component.html

    Отредактируем его, вставив строки:

    <h2> Первый компонент! </h2>

    Запустить наше приложение с новым компонентом, проверить работу:

    ng serve


    Angular 5 web-start.top

    Структура компонента Angular

    Компонет состоит из 3-х секций:

    1. директива - import
    2. декоратор
    3. директива export

    Импортируем из библиотеки '@angular/core' необходимые модули:

    import { Component, OnInit } from '@angular/core';

    Некоторые компоненты могут содержать множество директив import

    Декоратор компонента позволяет менять некоторые свойства нашего компонента (метаданные).

    Приведённый ниже декоратор задаёт свойства компонента (selector, templateUrl, styleUrls).

    @Component({ selector: 'app-comp1', templateUrl: './comp1.component.html', styleUrls: ['./comp1.component.css'] })

    selector - имя тега, использование которого инициирует наш компонент.

    templateUrl - шаблон HTML (может быть именем файла или встроенным набором HTML - свойство template )

    styleUrls - листы стилей (список файлов или встроенный - inline набор описаний стилей - свойство styles )

    В директиве export описаны свойства и методы класса-компонента, которые будут доступны другим компонентам приложения

    export class Comp1Component implements OnInit { public title ; constructor() { } ngOnInit() { this.title = 'Первый компонент запущен.' } }  


    Файл компонента - программа на Typescript :

    import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-comp1', templateUrl: './comp1.component.html', styleUrls: ['./comp1.component.css'] }) export class Comp1Component implements OnInit { public title ; constructor() { } ngOnInit() { this.title = 'Первый компонент запущен.' } }


    Angular 5 web-start.top

    Шаблоны Angular (Angular templates)

    Создадим новый проект (app-my-first-component) и посмотрим, как работать с шаблонами и стилями.

    Встроенные и внешние шаблоны (inline & external Angular templates)

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

    Параметры template и style описывают встроенный шаблон (соответственно HTML и CSS ). Если необходимо использовать несколько строк для inline описаний, то вместо ограничителя строки - кавычка (') используется ограничитель строки - backtick (`) 

    Например

    template: '<h1>Inline HTML template</h1>',

    Или:

    import { Component} from '@angular/core'; @Component({ selector: 'app-my-first-component', template: ` <h1>Inline HTML template</h1> <hr> <h2> Встроенный HTML шаблон из трёх строк</h2> `, styles: ['h2 {color:red;}'] })

    При использовании встроенного многострочного шаблона ограничитель строки - кавычка (') нужно заменить на другой символ - ` (backtick symbol слева сверху на клавиатуре)

    Angular 5 web-start.top

    Интерполяция строк (использование динамических данных)

    (Angular string interpolation)

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


    {{ИМЯ_СВОЙСТВА}}


    Например, если в компоненте описано свойство title :

    export class FirstComponent{ title = 'Первый тест'; }

    То в шаблоне может быть использовано {{title}}:

    template : '<H1>{{title}}</H1>',

    Можно вставлять в шаблон свойства объекта (пример со встроенными - inline - стилями и шаблоном)

    import { Component} from '@angular/core'; @Component({ selector: 'app-my-first-component', template: ` <h1> Студент </h1> <h2> Имя: {{student.name}}</h2> <h2> Возраст: {{student.age}}</h2> <h2> Курс: {{student.course}}</h2>`, styles: ['h2 {color:red;}'] }) export class MyFirstComponent { // Описание класса student = { name: "Иванов", age: 22, course: "Angular" } }



     Подробнее - Angular components


    Структурные директивы (Angular Structural Directives)

    Структурные директивы отвечают за компоновку HTML - макета. Они формируют или изменяют структуру DOM, как правило, путем добавления, удаления или изменения элементов. 

    Директива ngFor

    Можно в объекте описать массив данных, тогда в шаблон можно вставлять элементы массива или, например, с помощью оператора ngFor пробегать по всему массиву в цикле.

    import { Component} from '@angular/core'; @Component({ selector: 'app-my-first-component', template: ` <h1> Студент </h1> <h2> Имя: {{students[0].name}}</h2> <h2> Возраст: {{students[0].age}}</h2> <h2> Курс: {{students[0].course}}</h2> `, styles: ['h2 {color:red;}'] }) export class MyFirstComponent { students = [ { name: "Иванов", age: 21, course: "'Angular 2'" }, { name: "Петров", age: 22, course: "'Angular 4'" }, { name: "Сидоров", age: 23, course: "'Angular 5'" }, ] }


    Angular 5 web-start.top

    Проход по массиву в цикле

    import { Component} from '@angular/core'; @Component({ selector: 'app-my-first-component', template: ` <h1> Студенты </h1> <ul> <li *ngFor="let item of students; let i = index"> {{i}} <b>{{students[i].name}}</b> {{students[i].age}} {{students[i].course}} </li> </ul> `, styles: ['h2 {color:red;}'] }) export class MyFirstComponent { students = [ { name: "Иванов", age: 21, course: "'Angular 2'" }, { name: "Петров", age: 22, course: "'Angular 4'" }, { name: "Сидоров", age: 23, course: "'Angular 5'" }, ] }



    Подробнее - Angular directives


  • Angular 6 component interaction

    Обмен данными между родительским и дочерним компонентом (Angular component interaction)

    @input


    @output


    Decorators


    Event emitter


    C помощью декораторов @Input, @Output и API EventEmitter можно обеспечить обмен данными между родительскими и дочерними компонентами.


    Декоратор @Input

    Дочерний компонент с помощью декоратора input может получать данные от родительского, а  с помощью декоратора output - посылать.


    Для получения данных от родительского компонента дочерним:

    - в дочернем компоненте создаём свойство, в которое данные будем получать, декорируем его с помощью декоратора @Input

    - в родительском компоненте создаём public - свойство, которое будем передавать

    - при вызове дочернего компонента через созданное нами свойство привязываем к свойству дочернего компонента данные из родительского.


    Родительский компонент:

    import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app'; public string1 = <string> 'Data from parent...'; }


    Шаблон родительского компонента - вызов дочернего:

    <h1>This is parent component:</h1> <hr> <app-inoutcomponent [inFromParent]='string1'></app-inoutcomponent>


    Дочерний компонент

    import { Component, OnInit, Input } from '@angular/core'; @Component({ selector: 'app-inoutcomponent', templateUrl: './inoutcomponent.component.html', styleUrls: ['./inoutcomponent.component.css'] }) export class InoutcomponentComponent implements OnInit { @Input() public inFromParent: string; constructor() { } ngOnInit() { } }


    Шаблон дочернего компонента 

    <h1>This is child component:</h1> <h3>{{inFromParent}}</h3>


    Результат



    Добавим в родительский компонент метод, который меняет это свойство. Привяжем его к событию click кнопки.

    import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app'; public string1 = <string> 'Data from parent...'; changeChildData() { this.string1 += ' Changed '; } }


    При каждом нажатии к строке будем приписывать текст: this.string1 += ' Changed ';


    Результат после 2-х кликов:



    Декоратор @Output и  EventEmitter 

    Передача данных от дочернего компонента к родительскому.

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


    У дочернего компонета создаём своё событие - outToParent (объект класса EventEmitter ), декорируя его декоратором @Output.

    Создадим в дочернем компоненте метод - sendToParent() . Его задача: передать событие родительскому объекту (метод emit()).

    Передано это событие будет через Angular объект - $event.

    Таким образом, созданное нами событие - outToParent произойдёт в тот момент, когда сработает sendToParent()и его (события) содержимое можно будет получить из $event.


    Дочерний компонент

    import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'app-inoutcomponent', templateUrl: './inoutcomponent.component.html', styleUrls: ['./inoutcomponent.component.css'] }) export class InoutcomponentComponent implements OnInit { @Input() public inFromParent: string; @Output() public outToParent = new EventEmitter(); constructor() { } ngOnInit() { } sendToParent() { this.outToParent.emit('Child sent this message to parent...'); } }


    Привяжем обработчик событий - click к кнопке в шаблоне дочернего компонента и по этому клику вызовем метод sentToParent, который в свою очередь включит событие outToParent:

    Шаблон дочернего компонента

    <h1>This is child component:</h1> <h3>{{inFromParent}}</h3> <br> <button (click)='sendToParent()'>Click to send data!</button> <br>


    Стиль дочернего компонента

    * {
    color: green;
    }



    Родительский компонент получает данные события методом, который мы в нём создали - getNessage()

    import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app'; public string1 = <string> 'Data from parent...'; public string2 = ''; changeChildData() { this.string1 += ' Changed '; } receiveFromChild(evnt){ this.string2 = evnt; } }



    Шаблон родительского компонента (outToParent - новое событие, которое мы создали)

    <h1>This is parent component:</h1> <button (click)='changeChildData()'>Change child data </button> <hr> <strong>{{string2}}</strong> <app-inoutcomponent (outToParent)='receiveFromChild($event)' [inFromParent]='string1'></app-inoutcomponent>


    До клика



    После клика



    Декоратор @Component, свойства - inputs, outputs


    Вместо использования декораторов свойств - @Input и @Outpur можно использовать свойства декоратора класса - @Component (inputs, outputs).


    import { Component, OnInit, EventEmitter } from '@angular/core'; // import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'app-inoutcomponent', templateUrl: './inoutcomponent.component.html', styleUrls: ['./inoutcomponent.component.css'], inputs: ['inFromParent'], outputs:['outToParent'] }) export class InoutcomponentComponent implements OnInit { // @Input() public inFromParent: string; inFromParent: string; // @Output() public outToParent = new EventEmitter(); outToParent = new EventEmitter(); constructor() { } ngOnInit() { } sendToParent() { this.outToParent.emit('Child sent this message to parent...'); } }


    Но Angular рекомендуют использовать @Input и @Output 

    https://angular.io/guide/styleguide#style-05-12)%20(use-output-property-decorator

    style 05-12






  • Angular 6 components

    Angular 5 компоненты (Angular components)

    Компонент - базовый элемент структуры Angular - приложения

    • создать компонент
    • зарегистрировать в модуле
    • добавить HTML elelement в шаблон

    Самый простой компонент - один файл:

    import { Component} from '@angular/core'; @Component({ selector: 'comp1', template: '<h1>Comp1Component</h1>' }) export class Comp1Component { }

    Регистрация в модуле

    app.module.ts

    import { Comp1Component } from './comp1/comp1.component';

    и

    @NgModule({ declarations: [ AppComponent, Comp1Component ],


    Дальше в шаблоне можно использовать тег <comp1>

    Создать компонент Angular 5

    Внутри папки app создать папку для компонента

    component2

    В этой папке создать TypeScript файл с описанием класса компонента

    component2.component.ts

    import {Component} from "@angular/core"; @Component ({ selector : 'app-test2', templateUrl: './test2.component.html', styleUrls: ['./test2.component.css'], }) export class Test2Component{ }


    Строка 

    import { Component} from '@angular/core';

    импортирует декоратор компонента из библиотеки Angular core

    Создать файлы шаблона и стиля компонента (test2.component.html и test2.component.css)

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

      (import { Test2Component } from './test2/test2.component';) 

    и зарегистрировать новый компонент в в секции declarations декоратора модуля - @NgModule 


    @NgModule({ declarations: [ AppComponent, Test2Component ], imports: [ BrowserModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }


    Добавить вызов нашего компонента в шаблон главного компонента приложения (app.component.html)

    <app-test2> </app-test2>

    Компоненты могут быть вложенными.

    Компонент можно использовать несколько раз.

    Например:

    <app-test2> </> <app-test1> </app-test1> <app-test1> </app-test1> </app-test2>

    Селектор компонента

    В декораторе компонента одно из свойств - селектор компонента.

    По этому свойству Angular определяет, в какое место шаблона компонент должен быть помещён.

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

    selector : 'app-test2-component',

    Место компонента в шаблоне в этом случае должно быть задано тегом:

    <app-test2> </app-test2>

    Но можно также использовать название атрибута тега

    selector : '[app-test2]',

    или название класса

    selector : '.app-test2]',

    Место компонента в шаблоне в этом случае может быть задано как :

    <div app-test2> </div>

    или

    <span class="app-test2"> </span>


  • Angular 6 data binding

    Angular 5 databinding

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

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

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

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

    • передача данных от шаблона в компонент (Angular string interpolation, property binding, class binding, style bynding, ngStyle, ngClass)
    • отслеживание событий, связвнных с DOM элементами шаблона (Angular Event Binding, $event)
    • двусторонний обмен данными между шаблоном и компонентом (Angular two-way data binding, ngModel)


    Интерполяция (Angular string interpolation)

    {{expression}}
    [target]="expression"
    bind-target="expression"

    Обработка событий в окне


    (target)="statement" on-target="statement"

    Можно использовать встроенный Angular объект - $event. Он автоматически привязывается к использующему его событию. Его свойства содержат свойства события и сыойства элемента, который это событие обработал

    Пример:

    import { Component} from '@angular/core'; @Component({ selector : 'app-comp2', template : ` <h1> $event properties - > to console </h1> <button class='btn' (click)='displEvntProp($event)'>Log $event properties</button> `, styles : [''] }) export class Comp2Component { constructor() { } displEvntProp(evnt){ console.log(evnt); } }


    event filter 

    Template variable

    #var1 = template reference variables in Angular

    Эта переменная будет содержать ссылку на DOM элемент

    <input type="text" (change)="true" #variable> {{ variable.value }} <my-component #variable [input]="'hello'"></my-component> {{ variable.input }} <form #variable="ngForm"> <!-- some more HTML... --> <button type="submit" [disabled]="variable.form.invalid">Submit!</button> </form>

    console.log($event) - вывести в консоль все его свойства, методы

    Event bubbling - отслежтванте события всеми родительскими элементами в пррядке иерархии

    $event.stopPropagation() - метод, который отменяет процесс event bubbling

    Пример:



    (String interpolation, property binding, custom variables)

    <div style="text-align:center"> <h1> Пример : {{ title }}! </h1> </div> <hr> <button id="myButton" #myBut1 type="submit" class="btn btn-default" [disabled]="buttonDisabled" [style.color]="buttonColor" (click)="myButClick($event)"> <i>{{buttonText}}</i> </button> <p style="color:blue" [innerHTML]="myBut1.innerText"></p> <p style="color:red">{{buttonText}} </p> <hr>



    import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'data binding test'; buttonDisabled = true; buttonText = "Ждите"; buttonColor = "red"; evntOut; constructor (){ setTimeout(()=>{ this.buttonDisabled = false; this.buttonText = "Вводите"; this.buttonColor = "green"; },5000); } myButClick (evnt){ this.buttonText = "Нажали уже!" ; this.buttonDisabled = true; this.evntOut = evnt; console.log(evnt); }; }




    Переменные шаблона

    Templaеу variable #var1 = template reference variables in Angular

    Эта переменная будет содержать ссылку на DOM элемент

    <input type="text" (change)="true" #variable> {{ variable.value }} <my-component #variable [input]="'hello'"></my-component> {{ variable.input }} <form #variable="ngForm"> <!-- some more HTML... --> <button type="submit" [disabled]="variable.form.invalid">Submit!</button> </form>

    Двусторонний обмен данными

    Директива ngModel  

    Содержится в модуле 


    [(target)]="expression"
    bindon-target="expression" <example-component [(message)]="title"></example-component> Name: <input type="text" [(ngModel)]="name" /> <div>{{name}}</div>


    Импортировать в app.module.ts

    import { FormsModule } from '@angular/forms'; // Importing forms module to this file

    и  

    imports: [ BrowserModule, FormsModule // Importing forms module to application module ],

    Angular обеспечивает простой способ обработки событий, связанныз с элементами DOM. 

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


    Двусторонняя привязка данных объединяет ввод и вывод в одном описании, используя директиву ngModel.

    <input [(ngModel)]="name" >

    Это эквивалентно:

    <input [ngModel]="name" (ngModelChange)="name=$event">



    Pipes

    Последовательное поточное динамическое форматирование данных


    BuiltIn pipes

    DatePipe, UpperCasePipe, LowerCasePipe, CurrencyPipe, PercentPipe.



    Custom pipes



  • Angular 6 directives (part1)

    Директивы (Angular directives)

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

    Angular 5 использует директивы, которые можно разделить на:

    • Компоненты (Angular  components)
    • Структурные директивы (Angular structural directives)
    • Директивы-атрибуты (Angular attribute directives)
    • Встроенные директивы (Angular built in directives)
    • Пользовательские директивы (Angular custom directives)


    Компоненты (Angular components)

    Тип директивы, который использует шаблон. Это наиболее часто используемый тип директив. Angular. Внутри такой директивы можно использовать другие директивы, типа: всроенные, пользовательские.

    Создать компонент

    ng generate component students

    Angular CLI создаст в папке ./src/app файлы компонента:

    • students.component.css
    • students.component.html
    • students.component.spec.ts
    • students.component.ts

    TypeScript код компонента - в файле: students.component.ts

    import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-students', templateUrl: './students.component.html', styleUrls: ['./students.component.css'] }) export class StudentsComponent implements OnInit { constructor() { } ngOnInit() { } }


    В файл app-modules.ts автоматически добавляются строки:

    import { StudentsComponent } from './students/students.component';

    и в секцию declaration:

    declarations: [ ..., StudentsComponent ]


    Структурные (Angular structural directives)

    Позволяют менять структуру DOM, добавляя, удаляя, изменяя элементы.

    Структурные директивы могут использоваться с HTML тегом <ng-template> или без него.

    Существуют три встроенных структурных директивы: NgIf, NgFor и NgSwitch.

    Структурные директивы - это тип директив, которыя изменяют структуру DOM. Тег <ng-template> можно использовать, чтобы определить элемент, который мы хотим вставить в DOM. Можно добавить имя директивы с помощью *,  чтобы пропустить определение <ng-template> и использовать в качестве шаблона директивы элемент, к которому она привязана .

    Изменим шаблон компонента:

    <h2> Компонент {{name}} работает </h2> <ng-template [ngIf]=" students.length > 0"> <h3>Список студентов:</h3> </ng-template> <ul> <ng-template ngFor let-student [ngForOf]="students" ; let-i="index"> <li>Номер: {{i+1}} Имя:{{student[0]}} Курс:{{student[2]}}</li> </ng-template> </ul> <hr> <ul *ngFor="let student of students; even as i" [ngSwitch]="i"> <li style="background-color:gray" *ngSwitchCase="true">Четный:{{i}} Курс:{{student[2]}}</li> <li style="background-color:lightGray" *ngSwitchCase="false">Четный:{{i}} Курс:{{student[2]}}</li> <i *ngSwitchDefault>{{i}} Курс:{{student[2]}}</i> </ul> <hr>


    Тег <ng-template>

    <ng-template [ngIf]='condition'> <p>I am the content to show</p> </ng-template>


    ngIf

    <div *ngIf="condition">...</div>
    <ng-template [ngIf]="condition"><div>...</div></ng-template>
    <div *ngIf="condition; then thenBlock else elseBlock"></div> <ng-template #thenBlock>...</ng-template> <ng-template #elseBlock>...</ng-template>
    <div *ngIf="condition as value; else elseBlock">{{value}}</div> <ng-template #elseBlock>...</ng-template>


    ngFor (ngForOf)

    Синтаксис:

    <li *ngFor="let item of items; index as i; trackBy: trackByFn">...</li>


    <ng-template ngFor let-item [ngForOf]="items" let-i="index" [ngForTrackBy]="trackByFn"> <li>...</li> </ng-template>


    <ng-container *ngFor = " let item of items; let i = index"> <li [innerHTML] = 'item'>...</li> </ng-container>


    Локальные переменные ngFor

    • index: number: индекс текущего элемента в итерации
    • first: boolean: ИСТИНА , если элемент - первый в итерации
    • last: boolean: ИСТИНА , если элемент - последний в итерации
    • even: boolean: ИСТИНА , если элемент имеет чётный индекс
    • odd: boolean: ИСТИНА , если элемент имеет нечётный индекс


    Пример:


    <ul>Список студентов: <ng-template ngFor let-student [ngForOf]="students" ; let-i="index"> <li>Номер: {{i+1}} Имя:{{student[0]}} Курс:{{student[2]}}</li> </ng-template> </ul>


     


    NgSwitch

    Используем в качестве переключателя внутреннюю переменную even цикла ngFor 

    <container-tag *ngFor="let student of students; even as i" [ngSwitch]="i"> <case1-tag style="background-color:gray" *ngSwitchCase="true">Четный:{{i}} Курс:{{student[2]}}</case1-tag> <case2-tag style="background-color:lightGray" *ngSwitchCase="false">Четный:{{i}} Курс:{{student[2]}}</case2-tag> <caseDefault-tag*ngSwitchDefault>{{i}} Курс:{{student[2]}}</caseDefault-tag> </container-tag>


    <ul *ngFor="let student of students; even as i" [ngSwitch]="i"> <li style="background-color:gray" *ngSwitchCase="true">Четный:{{i}} Курс:{{student[2]}}</li> <li style="background-color:lightGray" *ngSwitchCase="false">Четный:{{i}} Курс:{{student[2]}}</li> <i *ngSwitchDefault>{{i}} Курс:{{student[2]}}</i> </ul>



    Тег <ng-container>

    <ng-container *ngIf="lessons"> <div class="lesson" *ngFor="let lesson of lessons"> <div class="lesson-detail"> {{lesson | json}} </div> </div> </ng-container>




    Директивы-свойства (Angular 5 attribute directives)

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


    Встроенные директивы (Angular built in directives)

    Это, например, директивы:

    • NgIf
    • NgSwitch
    • NgStyle
    • NgClass

    Пользовательские директивы (Angular custom derectives)

    Создать директиву

    ng create directive my-dir1

    Простой пример1

    Отредактировать TypeScript - my-dir1.directive.ts

    import { Directive, ElementRef, Renderer2 } from '@angular/core'; @Directive({ selector: '[appMyDir1]' }) export class MyDir1Directive { constructor(myElement: ElementRef, myRenderer: Renderer2) { myRenderer.setStyle(myElement.nativeElement, 'box-shadow', '2px 2px 12px #ccc'); myRenderer.setStyle(myElement.nativeElement, 'padding', '10px 20px'); } }


    Шаблон

    <div style="text-align:center"> <h1> Welcome to {{ title }}! </h1> <hr> <span></span> <span appMyDir1>Test directive</span> </div>



    Класс ElementRef  обеспечивает доступ к объектам DOM

    Класс Renderer2 

    Класс Renderer2 представляет собой абстракцию, предоставляемую Angular в виде сервиса, который позволяет управлять элементами приложения без непосредственного доступа к DOM. Это рекомендуемый подход, потому что он упрощает разработку приложений, которые могут отображаться в средах, не имеющих доступа к DOM, например, на сервере, web-workers или на мобильном устройстве.

    Renderer2 часто используется в пользовательских директивах из-за того, что Angular директивы используются для модификации элементов. 

    Этот пример В этом примере мы создаем новый div и создаем текстовый узел. Затем мы помещаем текстовый узел в наш новый div и, наконец, наш div добавляется к элементу, на который ссылается наша директива:

    constructor(private renderer: Renderer2, private el: ElementRef) {} ngOnInit() { const div = this.renderer.createElement('div'); const text = this.renderer.createText('Hello world!'); this.renderer.appendChild(div, text); this.renderer.appendChild(this.el.nativeElement, div); }



  • Angular 6 directives (part2)

    Встроенные директивы Angular (Angular built-in directives)

    Примеры


    app.modules.ts


    import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { StudentsComponent } from './students/students.component'; @NgModule({ declarations: [ AppComponent, StudentsComponent ], imports: [ BrowserModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }



    StudentsComponent

    import { Component, OnInit } from '@angular/core'; import { StudentsInterface } from '../students-interface'; @Component({ selector: 'app-students', templateUrl: './students.component.html', styleUrls: ['./students.component.css'] }) export class StudentsComponent implements OnInit { students: StudentsInterface[]; constructor() { } ngOnInit() { this.students = [ { name: 'Anna', id: 1234567, age: 22, course: 'Angular' }, { name: 'Haim', id: 987654, age: 18, course: 'WEB' }, { name: 'Yossy', id: 456687456, age: 44, course: 'C' }, { name: 'Vasily', id: 1234567, age: 22, course: 'PHP' }, { name: 'Bob', id: 14312554, age: 37, course: 'Photoshop' }, { name: 'Bob', id: 657856784567, age: 37, course: 'WEB' }, ]; } }



    StudentsInterface

    export interface StudentsInterface { name: string; id?: number; age: number; course: string; }



    students.component.html


    <h1>Students</h1> <hr> <h2>Names -all</h2> <ng-container *ngFor='let student of students; let n = index;'> <p>{{n}} : {{student.name}}</p> </ng-container> <hr> <h2>WEB students</h2> <ul *ngFor='let stud of students'> <li *ngIf='stud.course === "WEB"'>{{stud.course}} -> {{stud.name}}</li> </ul> <hr> <h2>Colored list</h2> <ul *ngFor='let studnt of students'> <ng-container [ngSwitch]='studnt.course'> <div style='color:red' *ngSwitchCase='"WEB"'>Name: {{studnt.name}}, Age: {{studnt.age}}, Course: {{studnt.course}}, Id: {{studnt.id}}</div> <div style='color:green' *ngSwitchCase='"PHP"'>Name: {{studnt.name}}, Age: {{studnt.age}}, Course: {{studnt.course}}, Id: {{studnt.id}}</div> <div style='color:blue' *ngSwitchCase='"C"'>Name: {{studnt.name}}, Age: {{studnt.age}}, Course: {{studnt.course}}, Id: {{studnt.id}}</div> <div style='color:lightgray' *ngSwitchDefault>Name: {{studnt.name}}, Age: {{studnt.age}}, Course: {{studnt.course}}, Id: {{studnt.id}}</div> </ng-container> </ul>





  • Angular 6 directives (part3)


    Примеры Angular директив

    (Angular built in directives)



    <H1>Students</H1> <table> <tr> <th>N</th> <th>Name</th> <th>Age</th> <th>Course</th> </tr> <tr *ngFor='let student of students; let n = index'> <td>{{n+1}}</td> <td>Name: {{student['Name']}}</td> <td>Age: {{student['Age']}}</td> <td>Course: {{student['Course']}}</td> </tr> </table> <hr> <h1>WEB students</h1> <table> <tr> <th>N</th> <th>Name</th> <th>Age</th> <th>Course</th> </tr> <ng-container *ngFor='let item of students; let n = index'> <tr *ngIf="item['Course'] == 'WEB'"> <td>{{n+1}}</td> <td>Name: {{item['Name']}}</td> <td>Age: {{item['Age']}}</td> <td>Course: {{item['Course']}}</td> </tr> </ng-container> </table> <hr> <ng-container *ngFor='let student of students'> <div *ngIf="student['Age'] >= 20; then adult; else child">this is ignored</div> <ng-template #adult>Adult: {{student['Name'] + ' Age:' + student['Age'] }}<br></ng-template> <ng-template #child>Child: {{student['Name'] + ' Age:' + student['Age'] }}<br></ng-template> </ng-container> <hr> <ng-container *ngFor='let student of students; let n = index'> {{n + 1}} <ng-container [ngSwitch]='student["Course"]'> <div *ngSwitchCase='"WEB"' style='color:red'> WEB : {{student['Name']}}<br> </div> <div *ngSwitchCase='"PHP"' style='color:green'> PHP : {{student['Name']}}<br> </div> <div *ngSwitchCase='"C++"' style='color:blue'> C++ : {{student['Name']}}<br> </div> </ng-container> </ng-container>



    import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-students', templateUrl: './students.component.html', styleUrls: ['./students.component.css'] }) export class StudentsComponent implements OnInit { students = []; constructor() { } ngOnInit() { this.students = [ {'Name': 'Ivan', 'Age': '25', 'Course': 'WEB'}, {'Name': 'Haim', 'Age': '20', 'Course': 'PHP'}, {'Name': 'Kate', 'Age': '19', 'Course': 'C++'}, {'Name': 'Ivan', 'Age': '25', 'Course': 'WEB'}, {'Name': 'Haim', 'Age': '30', 'Course': 'PHP'}, {'Name': 'Kate', 'Age': '19', 'Course': 'C++'}, {'Name': 'Ivan', 'Age': '16', 'Course': 'WEB'}, {'Name': 'Haim', 'Age': '33', 'Course': 'PHP'}, {'Name': 'Kate', 'Age': '10', 'Course': 'C++'} ]; console.log(this.students); } }






  • Angular 6 HTTP запросы (part1)

    Angular HttpClient - работа с HTTP запросами



    Использование HttpClient


    Angular HttpClient - класс, который предоставляет пользователям удобный интерфейс для работы с HTTP запросами, он базируется на использовании XMLHttpRequest объекта браузера - .

    Для использования HttpClient API нужно импортировать модуль HttpClientModule (обычно - в app.module.ts):


    import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { HttpClientModule } from '@angular/common/http'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, HttpClientModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }



    После этого можно использовать HttpClient в классе Angular - приложений, импортируя HttpClient и подключая его через dependancy injection. Например, создав сервис, который будет отвечать за передачу данных но HTTP:


    import { Injectable } from '@angular/core'; import { HttpClient} from '@angular/common/http'; @Injectable({ providedIn: 'root' }) export class Http1Service { constructor(private myHttp: HttpClient) { } }


    Объект, созданный из HttpClient (в примере выше - myHttp), поддерживает методы:


    • get
    • post
    • put
    • delete
    • patch
    • head
    • jsonp


    Для тестирования приложения Angular, которое работает с HttpClient можно использовать, например:

    • Angular модуль:  HttpClientTestingModule, 
    • специальные online сервисы, типа: http://jsonplaceholder.typicode.com/ , https://www.jsontest.com/, 
    • nodeJs (Angular in-memory web API: npm i angular-in-memory-web-api@0.5.3 --save ).
    • Или любой другой WEB server, который будет обрабатывать HTTP запросы.


      Простой пример - get()

      Простой пример использования метода get() Http клиента - файл на локальном диске, который содержит данные в формате JSON.

      Создадим айл с именем: myData.json

      [ {"Name": "Bob", "Age": "23", "Course": "WEB"}, {"Name": "Anna", "Age": "33", "Course": "PHP"}, {"Name": "Yony", "Age": "27", "Course": "Angular"} ]

      Расположим его в папке src/assets/data

      Создадим компонент get-data

      import { Component, OnInit } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Component({ selector: 'app-get-data', templateUrl: './get-data.component.html', styleUrls: ['./get-data.component.css'] }) export class GetDataComponent implements OnInit { fileData: any; constructor(private myHttp: HttpClient) { } ngOnInit( ) { this.myHttp.get('assets/data/myData.json').subscribe( (reslt) => { console.log(this.fileData = reslt) }); } }


      this.myHttp - наш объект типа HttpClient

      this.myHttp.get('assets/data/myData.json') - метод get() этого объекта, который получает в качестве рапаметра - URL , где расположен источник данных в формате JSON

      Этот метод возвращает в качестве результата Angular объект типа Observable. Это - массив данных, элементв которого формируются асинхронно, динамически, в результате запроса.

      У этого объекта есть метод - subscribe(), который позволяет получать данные в формате JSON.

      Мы задали (в формате arrow - function) параметр этого меода - функцию с аргументом reslt, которая выполнится по эго окончании (call-back function). В переменную reslt subscribe поместит результат выполнения.

       this.myHttp.get('assets/data/myData.json').subscribe((reslt) => {console.log(reslt)});

      Этот результат можно запомнить в переменной класса и использовать в шаблоне компонента (при интерпретации данных в примере используется Angular pipe - json для форматирования данных ).

      Шаблон:

      {{fileData | json }}


      this.myHttp.get('assets/data/myData.json').subscribe((reslt) => {console.log(this.fileData = reslt)});


      Результат: 


      PHP - server side

      Далее , для тестирования используем на сервере PHP - программу (myAngularGetV2.php).

      Программа на PHP запущена локально (URL =  http://angularhttp/myAngularGetV2.php).

      Программа получает запрос от Angular и отвечает на него.

      Рассмотрим метод HttpClient.get().


      Код программы:

      <?php header('Access-Control-Allow-Origin: http://localhost:4200'); header('Content-type: application/json'); header('Access-Control-Allow-Methods: GET'); $outstr = ' [ {"Name": "Bob", "Age": "23", "Course": "WEB"}, {"Name": "Anna", "Age": "33", "Course": "PHP"}, {"Name": "Yony", "Age": "27", "Course": "Angular"} ] '; echo($outstr); ?>


      Эта программа получает запрос от Angular - приложения и отдаёт ему нужные данные (данные эти в нашем случае хранятся в переменной $outstr, в реальной жизни, скорее всего PHP берёт их из базы данных)

      Результат - такой же, как при чтении из файла на диске.


      Передача данных от Angular на сервер по get()

      Усложним немного запрос от Angular к серверу.

      Для этого в метод get() добавим ещё один допустимый параметр - params и передадим через него на сервер имя пользователя.

      Вызов get() примет вид:

      this.myHttp.get( myUrl, {params: { 'Name': 'Anna' }} ).subscribe( (reslt) => {console.log(this.fileData = reslt)} ); }

      Мы передаём теперь на сервер по методу get параметр Name со значением Anna

      Теперь сервер получает запрос с параметром. PHP - программа на сервере может этот запрос проанализиолвать и дать ответ в соответствии с этим параметром.

      В нашем случае заведём в программе массив данных - $students и в этом массиве найдём того, чьё имя соответствует параметру запроса.

      В ответ сервера (JSON ) вставим данные только найденного студента.


      PHP:

      <?php header('Access-Control-Allow-Origin: http://localhost:4200'); header('Content-type: application/json'); header('Access-Control-Allow-Methods: GET'); $stud = $_GET['Name']; $students = Array( Array("Name"=> "Bob", "Age"=> "23", "Course"=> "WEB"), Array("Name"=> "Anna", "Age"=> "33", "Course"=> "PHP"), Array("Name"=> "Yony", "Age"=> "27", "Course"=> "Angular"), ); foreach($students as $student){ if($student['Name'] == $stud){ $outstr = '[{ '; $outstr .= '"Name": "'; $outstr .= $student['Name']; $outstr .= '", "Age": "'; $outstr .= $student['Age']; $outstr .= '", "Course": "'; $outstr .= $student['Course']; $outstr .= '" }]'; } } echo($outstr); ?>


      В переменную $stud получили искомого студента

      В цикле foreach перебираем массив, ищем нужного.

      Если нашли - формируем строке $outstring ответ в формате JSON и командой echo отправляем ответ (до этого функциями header мы сформировали необходимый набор HTTP заголовков ).


      Компонент:

      import { Component, OnInit } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Component({ selector: 'app-get-data', templateUrl: './get-data.component.html', styleUrls: ['./get-data.component.css'] }) export class GetDataComponent implements OnInit { fileData: any; constructor(private myHttp: HttpClient) { } ngOnInit( ) { const: myUrl = 'http://angularhttp/myAngularGetV2.php'; this.myHttp.get( myUrl, {params: { 'Name': 'Anna' }} ).subscribe( (reslt) => {console.log(this.fileData = reslt)} ); } }


      Шаблон (используем Angular - pipe json для ворматирования данных):

      {{ getData | json }}


      Результат



  • Angular 6 HTTP запросы (part2)

    Структура проекта

    my-post.service.ts - сервис, который обменивается данными с сервером

    my-post-interface.ts - структура данных 

    my-post.component.ts - компонент, который этот сервис использует


    Сервис (Injectable )

    import { Injectable, OnInit } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { MyPostInterface } from './my-post-interface'; @Injectable({ providedIn: 'root' }) export class MyPostService { myData = []; myUrl = 'http://angularhttp/myAngularPostV4.php'; constructor(private myHttp: HttpClient) { } sendRequest() { this.myHttp.post(this.myUrl, {observe: 'body', responseType: 'json'}) .subscribe({ next: data => console.log('Request N: ' , this.myData.push(data)), error: err => console.error('Error: ' + err), complete: () => console.log('Complete'),}); return this.myData; } }


    Интерфейс

    export interface MyDataInterface { id: number; name: string; title: string; msg: string; }


    Компонент

    import { Component, OnInit } from '@angular/core'; import { MyPostService } from '../my-post.service'; @Component({ selector: 'app-my-post', templateUrl: './my-post.component.html', styleUrls: ['./my-post.component.css'] }) export class MyPostComponent implements OnInit { myDataArray = []; constructor(private connectToServer: MyPostService) { } ngOnInit() { } getData() { this.myDataArray = this.connectToServer.sendRequest(); } }


    app-module

    import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { HttpClientModule } from '@angular/common/http' import { MyPostService } from './my-post.service'; import { MyPostComponent } from './my-post/my-post.component'; @NgModule({ declarations: [ AppComponent, MyPostComponent ], imports: [ BrowserModule, HttpClientModule ], providers: [MyPostService], bootstrap: [AppComponent] }) export class AppModule { }


    Шаблон компонента


    import { Component, OnInit } from '@angular/core'; import { MyPostService } from '../my-post.service'; @Component({ selector: 'app-my-post', templateUrl: './my-post.component.html', styleUrls: ['./my-post.component.css'] }) export class MyPostComponent implements OnInit { myDataArray = []; constructor(private connectToServer: MyPostService) { } ngOnInit() { } getData() { this.myDataArray = this.connectToServer.sendRequest(); } }


    Стили компонента


    TABLE { border-collapse: collapse; width: 100%; } TABLE TH { color: red; font-size: 1.2rem; } TABLE TH, TABLE TD { border: 1px solid lightgray; padding: 5px; } .testbutton { color: #14396A; text-shadow: 1px 1px 0px #7CACDE; box-shadow: 1px 1px 1px #BEE2F9; padding: 10px 25px; border-radius: 10px; border: 2px solid #3866A3; background: #63B8EE; background: linear-gradient(to bottom, #63B8EE, #468CCF); } .testbutton:hover { color: #F00; background: #468CCF; background: linear-gradient(to bottom, #468CCF, #63B8EE); }



    Результат - до запроса к серверу



    После запроса


    Поиск данных на сервере

    Пошлём серверу имя пользователя (Anna), чтобы получить полную информации о нём

    Сервис

    import { Injectable, OnInit } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { MyPostInterface } from './my-post-interface'; @Injectable({ providedIn: 'root' }) export class MyPostService { constructor(private myHttp: HttpClient) { } sendRequest() { const myUrl = 'http://angularhttp/myAngularPostV4.php'; let myData = []; this.myHttp.post(myUrl, {observe: 'body', responseType: 'json'}) .subscribe({ next: data => console.log('Server requested: ' , myData.push(data)), error: err => console.error('Error: ' + err), complete: () => console.log('Complete'),}); return myData; } getUserData() { const myUrl = 'http://angularhttp/myAngularPostV5.php'; const myHeaders = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); let myData = []; this.myHttp.post(myUrl, {name : 'Anna'}, {headers: myHeaders, observe: 'body', responseType: 'json'}) .subscribe({ next: data => console.log('Server requested: ' , myData.push(data)), error: err => console.error('Error: ' + err), complete: () => console.log('Complete'),}); return myData; } }



    Компонент

    import { Component, OnInit } from '@angular/core'; import { MyPostService } from '../my-post.service'; @Component({ selector: 'app-my-post', templateUrl: './my-post.component.html', styleUrls: ['./my-post.component.css'] }) export class MyPostComponent implements OnInit { allUsers = []; foundUser = []; constructor(private connectToServer: MyPostService) { } ngOnInit() { } getAllData() { this.allUsers = this.connectToServer.sendRequest(); } getUserData() { this.foundUser = this.connectToServer.getUserData(); } }



    Шаблон компонента

    <h1>POST test component</h1> <hr> <button class='testbutton' (click)='getAllData()'>Request all data from server</button> <table> <tr> <th>ID</th> <th>Name</th> <th>Position</th> <th>Remarks</th> </tr> <tr *ngFor='let str of allUsers[0]'> <td>{{str['id']}}</td> <td>{{str['name']}}</td> <td>{{str['title']}}</td> <td>{{str['msg']}}</td> </tr> </table> <hr> <button class='testbutton' (click)='getUserData()'>Get user data</button> <table> <tr> <th>ID</th> <th>Name</th> <th>Position</th> <th>Remarks</th> </tr> <tr *ngFor='let str of foundUser[0]'> <td>{{str['id']}}</td> <td>{{str['name']}}</td> <td>{{str['title']}}</td> <td>{{str['msg']}}</td> </tr> </table> <hr>



    app.module.ts
    import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { HttpClientModule } from '@angular/common/http' import { MyPostService } from './my-post.service'; import { MyPostComponent } from './my-post/my-post.component'; @NgModule({ declarations: [ AppComponent, MyPostComponent ], imports: [ BrowserModule, HttpClientModule ], providers: [MyPostService], bootstrap: [AppComponent] }) export class AppModule { }


    Результат 



    Server side

    Используется  Apache на локальном компьютере. Адрес сервера: http://angularhttp/ Запросы обрабатывает PHP - программа myAngularPostV4.php.

    Формат данных и способ их интерпретации зависит от HTTP заголовков (руфвукы), которые выставлены и в Angular 

    const myHeaders = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');

    и 

    {observe: 'body', responseType: 'json'}

    и в PHP

    header('Content-type: application/x-www-form-urlencoded; charset=UTF-8');

    PHP должен интерпретировать то, что посылает Angular через метод subscribe() объекта Observable. Если при посылке меняем формат, то и в PHP его надо менять.


    Программа PHP получает запрос от Angular и в ответ посылает строку с данными (в формате JSON) - myAngularPostV4.php

    <?php header('Access-Control-Allow-Origin: http://localhost:4200'); header('Content-type: application/json'); header("Access-Control-Allow-Headers: *"); header('Access-Control-Allow-Methods: POST'); $outstr = '[{ "id" : 1000, "name" : "Anna", "title" : "Manager", "msg" : "Sales department" }, { "id" : 1001, "name" : "Bob", "title" : "Technician", "msg" : "Server support team" }, { "id" : 1002, "name" : "Alex", "title" : "WEB developer", "msg" : "Corporate web development team" } ]'; echo($outstr); ?>



    Эхо - тест (получили запрос - отдали то, что получили) - myAngularPostV3.php

    <?php header('Access-Control-Allow-Origin: http://localhost:4200'); header('Content-type: application/json'); header("Access-Control-Allow-Headers: *"); header('Access-Control-Allow-Methods: POST'); $_POST = json_decode(file_get_contents('php://input'), true); $id = $_POST['id']; $name = $_POST['name']; $title = $_POST['title']; $msg = $_POST['msg']; $outstr = '[{ '; $outstr .= '"id": "'; $outstr .= $id; $outstr .= '", "name": "'; $outstr .= $name; $outstr .= '", "title": "'; $outstr .= $title; $outstr .= '", "msg":"'; $outstr .= $msg; $outstr .= '" }]'; echo($outstr); ?>


    Найти пользователя по имени (myAngularPostV5.php)


    <?php //if($_SERVER['HTTP_ORIGIN'] == "http://localhost:4200") header('Access-Control-Allow-Origin: http://localhost:4200'); header("Access-Control-Allow-Headers: *"); header('Content-type: application/x-www-form-urlencoded; charset=UTF-8'); header('Access-Control-Allow-Methods: POST'); $data = json_decode(file_get_contents("php://input")); $name = $data->name; $users = Array(); $users[] = Array ("id"=> 1111, "name"=> "Bob", "title"=> "Manager", "msg"=> "CEO"); $users[] = Array("id"=> 222, "name"=> "Nik", "title"=> "Sales", "msg"=> "Corporate sales dept"); $users[] = Array("id"=> 4444, "name"=> "Anna", "title"=> "Technician", "msg"=> "Network support team"); $users[] = Array("id"=> 5, "name"=> "Haim", "title"=> "HR", "msg"=> "Human resource"); $users[] = Array("id"=> 76, "name"=> "Ronald", "title"=> "CA", "msg"=> "Accounting") ; foreach($users as $key => $user){ if($user['name'] == $name){ $outstr = '[{ '; $outstr .= '"id": "'; $outstr .= $user['id']; $outstr .= '", "name": "'; $outstr .= $user['name']; $outstr .= '", "title": "'; $outstr .= $user['title']; $outstr .= '", "msg": "'; $outstr .= $user['msg']; $outstr .= '" }]'; } } error_log( $outstr); echo($outstr); ?>



    Асинхронный поиск по мере ввода имени

    В этом примере в окне браузера (в поле INPUT ) вводится имя сотрудника. По мере ввода (событие - keyup ) имя пересылается по POST серверу и проверяется PHP программой на сервере. Если PHP не нашёл сотрудника по имени (ищем в массиве сотрудников), он выдаёт сообщение (также в формате JSON)  

    Сервис


    import { Injectable, OnInit } from '@angular/core'; import { HttpClient, HttpHeaders} from '@angular/common/http'; import { MyPostInterface } from './my-post-interface'; import { PostOptionsInterface } from './post-options-interface'; @Injectable({ providedIn: 'root' }) export class MyPostService { constructor(private myHttp: HttpClient) { } sendRequest() { const myUrl = 'http://angularhttp/myAngularPostV4.php'; let myData = []; this.myHttp.post(myUrl, {observe: 'body', responseType: 'json'}) .subscribe({ next: data => console.log('Server request: ' , myData.push(data)), error: err => console.error('Error: ' + err), complete: () => console.log('Complete'),}); return myData; } getSingleUser() { const myUrl = 'http://angularhttp/myAngularPostV5.php'; const myHeaders = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); let myData = []; this.myHttp.post(myUrl, {name : 'Anna'}, {headers: myHeaders, observe: 'body', responseType: 'json'}) .subscribe({ next: data => console.log('Server request: ' , myData.push(data)), error: err => console.error('Error: ' + err), complete: () => console.log('Complete'),}); return myData; } findUser(userName){ const httpHdr = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); const postUrl = 'http://angularhttp/myAngularPostV6.php'; const postBody = {name : userName}; let myData = []; this.myHttp.post(postUrl, postBody, { headers: httpHdr, observe: 'body', responseType: 'json' }) .subscribe({ next: data => console.log('Server requested: ' , myData.push(data)), error: err => console.error('Error: ' + err), complete: () => console.log('Complete'),}); return myData; } }


    Компонент


    import { Component, OnInit } from '@angular/core'; import { MyPostService } from '../my-post.service'; @Component({ selector: 'app-my-post', templateUrl: './my-post.component.html', styleUrls: ['./my-post.component.css'] }) export class MyPostComponent implements OnInit { allUsers = []; singleUser = []; foundUser = []; constructor(private connectToServer: MyPostService) { } ngOnInit() { } getAllData() { this.allUsers = this.connectToServer.sendRequest(); } getSingleUser() { this.singleUser = this.connectToServer.getSingleUser(); } findUser(evnt){ console.log(evnt.target.value); this.foundUser = this.connectToServer.findUser(evnt.target.value); } removeHint(evnt){ evnt.target.value = ''; evnt.target.select(); } }


    HTML - шаблон компонента


    <h1>POST test component</h1> <hr> <button class='testbutton' (click)='getAllData()'>Request all users data from server</button> <table> <tr> <th>ID</th> <th>Name</th> <th>Position</th> <th>Remarks</th> </tr> <tr *ngFor='let str of allUsers[0]'> <td>{{str['id']}}</td> <td>{{str['name']}}</td> <td>{{str['title']}}</td> <td>{{str['msg']}}</td> </tr> </table> <hr> <button class='testbutton' (click)='getSingleUser()'>Get data of user: Anna</button> <table> <tr> <th>ID</th> <th>Name</th> <th>Position</th> <th>Remarks</th> </tr> <tr *ngFor='let str of singleUser[0]'> <td>{{str['id']}}</td> <td>{{str['name']}}</td> <td>{{str['title']}}</td> <td>{{str['msg']}}</td> </tr> </table> <hr> <input type='text' (keyup)='findUser($event)' (mouseenter)='removeHint($event); ' name='' value='Type case-sensitive user name here...'> <table> <tr> <th>ID</th> <th>Name</th> <th>Position</th> <th>Remarks</th> </tr> <tr *ngFor='let str of foundUser[0]'> <td colspan=4 *ngIf="str['id'] == 0; else found">{{str['name']}} {{str['title']}} {{str['msg']}}</td> <ng-template #found> <td>{{str['id']}}</td> <td>{{str['name']}}</td> <td>{{str['title']}}</td> <td>{{str['msg']}}</td> </ng-template> </tr> </table> <hr>



    CSS - стили компонента



    BUTTON, INPUT { margin: 10px 0px; } INPUT { width: 98.5%; padding: 5px; background-color: #EFEFEF; } TABLE { border-collapse: collapse; width: 100%; } TABLE TH { color: red; font-size: 1.2rem; } TABLE TH, TABLE TD { border: 1px solid lightgray; padding: 5px; } .testbutton { color: #FFF; text-shadow: 1px 1px 0px #7CACDE; box-shadow: 1px 1px 1px #BEE2F9; padding: 10px 25px; border-radius: 10px; border: 2px solid #3866A3; background: #63B8EE; background: linear-gradient(to bottom, #63B8EE, #468CCF); } .testbutton:hover { color: #F00; background: #468CCF; background: linear-gradient(to bottom, #468CCF, #63B8EE); }



    app.module.ts


    import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { HttpClientModule } from '@angular/common/http' import { MyPostService } from './my-post.service'; import { MyPostComponent } from './my-post/my-post.component'; @NgModule({ declarations: [ AppComponent, MyPostComponent ], imports: [ BrowserModule, HttpClientModule ], providers: [MyPostService], bootstrap: [AppComponent] }) export class AppModule { }




    Интерфес - структура данных: my-post-interface.ts

    export interface MyPostInterface { id: number; name: string; title: string; msg: string; }



    Server side: PHP - ищет сотрудника по имени (http://angularhttp/myAngularPostV6.php)

    <?php // if($_SERVER['HTTP_ORIGIN'] == "http://localhost:4200") header('Access-Control-Allow-Origin: http://localhost:4200'); header('Content-type: application/x-www-form-urlencoded; charset=UTF-8'); header('Access-Control-Allow-Methods: POST'); $data = json_decode(file_get_contents("php://input")); $name = $data->name; $users = []; $users[] = ["id"=> 1111, "name"=> "Bob", "title"=> "Manager", "msg"=> "CEO"]; $users[] = ["id"=> 222, "name"=> "Nik", "title"=> "Sales", "msg"=> "Corporate sales dept"]; $users[] = ["id"=> 4444, "name"=> "Anna", "title"=> "Technician", "msg"=> "Network support team"]; $users[] = ["id"=> 5, "name"=> "Haim", "title"=> "HR", "msg"=> "Human resource"]; $users[] = ["id"=> 76, "name"=> "Ronald", "title"=> "CA", "msg"=> "Accounting"] ; $outstr = '[{ "id":"00000", "name":"User", "title":"not", "msg":"found" }]'; foreach($users as $key => $user){ if($user['name'] == $name){ $outstr = '[{ '; $outstr .= '"id": '; $outstr .= $user['id']; $outstr .= ', "name": "'; $outstr .= $user['name']; $outstr .= '", "title": "'; $outstr .= $user['title']; $outstr .= '", "msg": "'; $outstr .= $user['msg']; $outstr .= '" }]'; } } error_log($name); error_log( $outstr); echo($outstr); ?>


    Server side: PHP выводит всех сотрудников ((http://angularhttp/myAngularPostV4.php))


    <?php header('Access-Control-Allow-Origin: http://localhost:4200'); header('Content-type: application/x-www-form-urlencoded; charset=UTF-8'); header("Access-Control-Allow-Headers: *"); header('Access-Control-Allow-Methods: POST'); $users = []; $users[] = ["id"=> 1111, "name"=> "Bob", "title"=> "Manager", "msg"=> "CEO"]; $users[] = ["id"=> 222, "name"=> "Nik", "title"=> "Sales", "msg"=> "Corporate sales dept"]; $users[] = ["id"=> 4444, "name"=> "Anna", "title"=> "Technician", "msg"=> "Network support team"]; $users[] = ["id"=> 5, "name"=> "Haim", "title"=> "HR", "msg"=> "Human resource"]; $users[] = ["id"=> 76, "name"=> "Ronald", "title"=> "CA", "msg"=> "Accounting"] ; $outstr = json_encode($users, JSON_PRETTY_PRINT); echo($outstr); ?>


    Результат - вывели всех сотрудников




    Результат при начале набора в поле ввода




    Результат - нашлось имя



    PHP - error log (при каждом событии keyup PHP получает имя и пишет для отладки в error log полученное имя и строку для отправки в Angular ):

    [01-Jun-2018 15:43:53 UTC] R [01-Jun-2018 15:43:53 UTC] [{ "id":"00000", "name":"User", "title":"not", "msg":"found" }] [01-Jun-2018 15:43:53 UTC] R [01-Jun-2018 15:43:53 UTC] [{ "id":"00000", "name":"User", "title":"not", "msg":"found" }] [01-Jun-2018 15:43:54 UTC] Ron [01-Jun-2018 15:43:54 UTC] [{ "id":"00000", "name":"User", "title":"not", "msg":"found" }] [01-Jun-2018 15:43:54 UTC] Ron [01-Jun-2018 15:43:54 UTC] [{ "id":"00000", "name":"User", "title":"not", "msg":"found" }] [01-Jun-2018 15:43:54 UTC] Rona [01-Jun-2018 15:43:54 UTC] [{ "id":"00000", "name":"User", "title":"not", "msg":"found" }] [01-Jun-2018 15:43:55 UTC] Ronal [01-Jun-2018 15:43:55 UTC] [{ "id":"00000", "name":"User", "title":"not", "msg":"found" }] [01-Jun-2018 15:43:55 UTC] Ronald [01-Jun-2018 15:43:55 UTC] [{ "id": 76, "name": "Ronald", "title": "CA", "msg": "Accounting" }]









  • Angular 6 routing

    Angular - навигация по сайту (Angular routing)

    При помощи  Routing - модуля Angular позволяет организовать привычную навигацию по страничкам сайта:

    • если ввести в адресной строке браузера IRI нужной странички, то она откроется
    • если кликнуть по ссылке на нужную страничку сайта (меню сайта, другие внутренние ссылки) , то Angular откроет её в окне браузера
    • если пользоваться кнопками браузера НАЗАД, ВПЕРЁД, то мы будем перемещаться по истории посещённых страничек сайта.

    Сконфигурируем сайт, который будет состоять из: одной главной странички - home, страничек  About, Contacts и специальной странички, которая будет открываться в том случае, если посетитель сайта пытается перейти на несуществующую страничку - NotFound.

    Для этого:

    • генерируем новый проект с опцией - routing (ng new routing-test1 --routing) в дополнение к стандарной конфигурации проекта появится модуль app-routing.module.ts
    • генерируем модуль с названием header для меню сайта
    • генерируем модули для каждой нужной странички сайта (home, about, contacts, notFound)
    • проверяем наличие тега <base href="/"> в файле index.html, что обязательно для работы router 
    • конфигурируем router - модуль (ссылки и их привязки к компонентам)
    • конфигурируем шаблон сайта в модуле app.component

    Angular создаёт app-routing.module.ts

    import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; const routes: Routes = []; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }


    Генерируем нужные компоненты:

    ng g c not-found

    ng g c contacts

    ng g c home

    ng g c header

    ng g c about


    Все компоненты и Router импортированы в app.module - проверяем:

    import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { HomeComponent } from './home/home.component'; import { HeaderComponent } from './header/header.component'; import { AboutComponent } from './about/about.component'; import { ContactsComponent } from './contacts/contacts.component'; import { NotFoundComponent } from './not-found/not-found.component'; @NgModule({ declarations: [ AppComponent, HomeComponent, HeaderComponent, AboutComponent, ContactsComponent, NotFoundComponent ], imports: [ BrowserModule, AppRoutingModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }


    Конфигурируем - app.component

    import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { }


    Его HTML шаблон:

    <div id='wrapper'> <app-header></app-header> <router-outlet></router-outlet> </div>

    Через него определяем место (placeholder ) в окне браузера для компонента-меню (<app-header></app-header>)

    И для меняющихся компонентов-страничек ( <router-outlet></router-outlet>)

    Его стили:

    #wrapper { display: grid; grid-template-rows: auto auto; grid-template-columns: 1fr; }


    Компоненты страничек практически ничем, в нашем примере, друг от друга не отличаются (только текстом в HTML).

    import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-about', templateUrl: './about.component.html', styleUrls: ['./about.component.css'] }) export class AboutComponent implements OnInit { constructor() { } ngOnInit() { } }


    HTML

    <h1>About Us</h1>


    Компонент header - это меню сайта (он показывает кнопки меню и привязывает их к тем путям URI , которые мы задали в раутере, он появляется на каждой страничке):

    import { Component} from '@angular/core'; @Component({ selector: 'app-header', templateUrl: './header.component.html', styleUrls: ['./header.component.css'] }) export class HeaderComponent { constructor() { } }


    HTML

    Директивы routerLink привязывают тег A к пути, который задан в модуле Router (константа routes )

    Директивы routerLinkActive присваивают элементам A класс стилей myActive в тот момент, когда ссылка активна.

    <div id='navBlock'> <a class='menuItem' routerLink='/home' routerLinkActive="myActive">Home</a> <a class='menuItem' routerLink='/about' routerLinkActive="myActive">About</a> <a class='menuItem' [routerLink]="['/contacts']" routerLinkActive="myActive">Contacts</a> </div>


    Стили

    Селектор  .menuItem[class*='myActive'] описывает стиль для активной ссылки. Класс myActive она получает по директиве routerLinkActive

    #navBlock { display: grid; grid-template-columns: repeat(3, minmax(auto, 300px)); grid-template-rows: 1fr; justify-content: center; align-content: space-between; border-bottom: 1px solid #aaa; } .menuItem { display: inline-block; text-align: center; padding: 10px 0px; margin: 10px; border: 1px solid #FFF; font-weight: bold; font-size: 1.2re; border-radius: 5px; box-shadow: 0px 2px 5px 1px rgba(100, 100, 100, 0.294); } .menuItem:hover { border-color: red; box-shadow: 0px 5px 10px 3px rgba(100, 100, 100, 0.294); } .menuItem[class*='myActive'] { color: red ! important; } .menuItem:visited { color: blue; } A { text-decoration: none; }




    Конфигурируем router.

    Конфигурируем в константе routes массив ссылок. Каждый элемент массива - путь и компонент, который к этому пути привязан.

    Элемент массива {path: '', redirectTo: '/home', pathMatch: 'full'} переадресовывает ссылки в корень сайта на страничку home

    Элемент массива {path: '**', component: NotFoundComponent} переадресовывает все странички, путь к которым не соответствует фильтрам пути в предыдущих элементах, на страничку NotFound 

    import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { AboutComponent } from './about/about.component'; import { ContactsComponent } from './contacts/contacts.component'; import { HomeComponent } from './home/home.component'; import { NotFoundComponent } from './not-found/not-found.component'; const routes: Routes = [ {path: '', redirectTo: '/home', pathMatch: 'full'}, {path: 'home', component: HomeComponent}, {path: 'about', component: AboutComponent}, {path: 'contacts', component: ContactsComponent}, {path: '**', component: NotFoundComponent} ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }



    Результат :





  • Angular 6 service

    Angular Service


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

    Генерируем сервис, пользуясь Angular CLI

    ng g service my-serv1

    Получаем его шаблон:  

    import { Injectable } from '@angular/core'; @Injectable() export class MyServ1Service { constructor() { } }


    Импортируем его в app.module.ts, чтобы он был доступен всем компонентам проекта

    import { MyServ1Service } from './my-serv1.service';

    Регистрируем его там же в providers, чтобы можно было его использовать во всех дочерних компонентов через Angular Dependancy Injection

    providers: [ MyServ1Service ],

     


    import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { BsDropdownModule } from 'ngx-bootstrap/dropdown'; import { CollapseModule } from 'ngx-bootstrap/collapse'; import { PopoverModule } from 'ngx-bootstrap/popover'; import { AppComponent } from './app.component'; import { Comp1Component } from './comp1/comp1.component'; import { MyServ1Service } from './my-serv1.service'; @NgModule({ declarations: [ AppComponent, Comp1Component ], imports: [ PopoverModule.forRoot(), CollapseModule.forRoot(), BsDropdownModule.forRoot(), BrowserModule ], providers: [ MyServ1Service ], bootstrap: [AppComponent] }) export class AppModule { }




    Добавляем метод getSomething():  

    import { Injectable } from '@angular/core'; @Injectable() export class MyServ1Service { constructor() { } getSomething(){ return "222222222"; } }



    Используем в компоненте - без Dependancy injection (не рекомендуется)

    import {MyServ1Service} from '../my-serv1.service' ; import { Component} from '@angular/core'; @Component({ selector: 'comp1', template: ` <h1>Comp1Component</h1> {{courses}} ` }) export class Comp1Component { courses; constructor (){ let servData = new MyServ1Service(); this.courses = servData.getSomething(); } }



    Используем в компоненте через Dependency injection (в этом случае constructor (service: MyServ1Service) создаёт внутри класса переменную с именем service , которая является объектом (instance) класса MyServ1Service )

    import {MyServ1Service} from '../my-serv1.service' ; import { Component} from '@angular/core'; @Component({ selector: 'comp1', template: ` <h1>Comp1Component</h1> {{courses}} ` }) export class Comp1Component { courses; constructor (service: MyServ1Service){ this.courses = service.getSomething(); } }


    И в app.module.ts добавляем импорт 

    import { MyServ1Service } from './my-serv1.service';

    и 

    providers: [ MyServ1Service ],


    весь файл 

    import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { BsDropdownModule } from 'ngx-bootstrap/dropdown'; import { CollapseModule } from 'ngx-bootstrap/collapse'; import { PopoverModule } from 'ngx-bootstrap/popover'; import { AppComponent } from './app.component'; import { Comp1Component } from './comp1/comp1.component'; import { MyServ1Service } from './my-serv1.service'; @NgModule({ declarations: [ AppComponent, Comp1Component ], imports: [ PopoverModule.forRoot(), CollapseModule.forRoot(), BsDropdownModule.forRoot(), BrowserModule ], providers: [ MyServ1Service ], bootstrap: [AppComponent] }) export class AppModule { }






  • API WEB - уведомлений (Notifications)

    WEB - уведомления (Notifications)

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

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

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

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

    Запрос разрешения

    Notification.requestPermission()

    Проверить статус разрешения

    Notification.permission

    Создание уведомления

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

    var notification = new Notification('Need support', {
    body: 'Call us...'
    });

    Методы, свойства и события

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

    • body: Строка, используемая для дальнейшего уточнения цели уведомления.
    • lang: Указывает язык уведомления. Его значение должно соответствовать стандарту BCP 47. Примеры действительных строк - en-US и it-IT.
    • dir: Определяет направление текста сообщения. Его значение может быть автоматически означающим, что направление основано на настройках браузера, ltr, чтобы указать направление слева направо (для европейских языков) или rtl, чтобы указать направление справа налево (для некоторых азиатских языков).
    • tag: Строка, которая используется как идентификатор, который можно использовать для извлечения, замены или удаления уведомления.
    • icon: Указывает URL-адрес изображения, которое будет использоваться в качестве значка уведомления.

    Чтобы создать экземпляр объекта Notification, мы должны написать инструкцию следующим образом:

    var note = new Notification('Need support', {
    body: 'Call us...'
    });

    Настройки доступны как свойства для чтения экземпляра объекта notification.

    Кроме того, объект Notification предоставляет свойство, называемое разрешением (permission). Разрешение содержит строку, представляющую текущей статус разрешения на отображение уведомлений.

    Его значение может быть одним из следующих:

    • denied, что означает, что пользователь отклонил уведомления
    • granted, что означает, что пользователь дал разрешение
    • default, что означает, что выбор пользователя неизвестен

    Этот API предоставляет два метода: requestPermission() и close(). Как следует из названия, первый используется для запроса разрешения на показ уведомлений пользователю, в то время как последний программно закрывает уведомление.

    requestPermission () - это метод объекта Notification, который принимает необязательный параметр - callback функцию, которая выполняется, когда пользователь принимает или отклоняет разрешение. Выбор пользователя передается в эту функцию в качестве параметра, и значение может быть: granted, denied, default.

    close () является методом, который не принимает никаких параметров.

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

    • onclick: вызывается, когда пользователь нажимает на уведомление.
    • onclose: вызывается, как только пользователь или броузер закрывает уведомление.
    • onerror: вызывается, если с уведомлением возникает ошибка.
    • onshow: вызывается, когда отображается уведомление.

    Пример использования этих событий.

    var note = new Notification('Need support', {
    body: 'Call us...'
    });
    note.onshow = function () {
    console.log ("Отображено уведомление");
    };

  • CMS

    Современные системы управление контентом (CMS)

    Понятие CMS. Преимущества и недостатки

    Аббревиатура CMS расшифровывается как «Content Management System» (Система управления контентом). Сайт, построеннвй на CMS, строится из набора стандартных елементов. При использовании CMS задача разработчика складывается из необходимости выбрать нужную CMS (в зависим от целей и функционала сайта) и сконфигурировать свой сайт из готовых блоков этой CMS.

    Большинство современных сайтов строится именно на CMS, а не пишутся программистами "с нуля".


    Понятия: FrontEnd - BackEnd, Design - Content

    Большинство CMS сегодня написаны на языке PHP и обычно используют базу банных MySQL (большинство современных CMS позволяют использовать разные БД).

    Сайт, построенный на базе CMS состоит из 2-х частей:

    • сайт для администратора (панель управления)
    • сайт для пользователя.

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

    • дизайн сайта (тема, шаблон)
    • контент сайта (статьи, публикации, навигация,...)

    В контексте CMS используются следующие соглашения-термины (вне CMS эти термины имеют другое значение):

    • FrontEnd - видимая часть сайта, доступная посетителям
    • BackEnd - панель управления сайтом, досткпная администратору
    • Template (Theme) - дизайн сайта
    • Content - материалы, документы на сайте

    Обзор CMS

    Наиболее популярны при создании сайтов такие CMS как WordPress, Joomla, Droopal.

    У каждой из них - своя структура, свои особенност.

    Для создания сайтов электронной коммерции часто используются такие целевые CMS как OpenCart, Magento, OsCommerceи др..

    Подробнее

    WordPress Joomla OpenCart


    Рабочее место разработчика

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

    На сервере хостинга для установки используется его интерфейс, на локальном компьютере - локальный WEB сервер.


    Установка WAMP на локальный компьютер






    Установка WordPress на локальный компьютер

     






  • CMS WordPress

    Построение сайта на CMS WordPress

    • Установка WordPress.
    • Сайт (FrontEnd) и панель управления (BackEnd).
    • Основные настройки сайта (general, writing, reading, discussion, media, permalinks )
    • Контент сайта.
      • Категории.
      • Статьи.
      • Страницы.
    • Плагины.
    • Внешний вид сайта.
      • Шаблоны (темы) сайта.
      • Виджеты.
      • Меню.
    • Управление пользователями.
    • Дополнительные инструменты.
    • Популярные плагины.

    WordPress - это система управления контентом (CMS) с открытым исходным кодом, которая позволяет пользователям создавать динамические веб-сайты. WordPress - самая популярная система ведения блогов в Интернете. Современные версии WordPress позволяют реализовывать не только  блоги, но и сайты с другой функциональностью.

    Как и другие CMS, WordPress  наряду с лицевой, видимой для посетителя частью сайта (FrontEnd) поддерживает интерфейс  панели управления сайтом (BackEnd), который доступен только администратору сайта.

    Изучение WordPress требует знания основ интернет-технологий, HTML, CSS.

    Для установки WordPress необходим WEB – сервер с поддержкой PHP (WAMP –Windows, LAMP-Linux, XAMP-Multi-platform, MAMP-Mac) и база данных MySQL.

    Сайт, построенный на CMS WordPress, позволяет настраивать, менять,  обновлять все его компоненты (дизайн сайта, дополнительные компоненты, публикации на сайте),  используя панель управления (BackEnd).

    Как и в других CMS, в WordPress можно сравнительно легко менять внешний вид сайта, не теряя при этом контент. Внешний вид сайта определяется установленной темой (шаблоном) и независим от его содержания.

    После установки WordPress по умолчанию панель управления находится по адресу:

    ИМЯ_САЙТА/wp-admin


    Основные характеристики WordPress

    Управление пользователями - позволяет управлять пользовательской информацией, такой как изменение роли пользователей (subscriber,  contributor,  author,  editor или administrator), создавать или удалять пользователя, изменять пароль и информацию о пользователе. Основная роль менеджера пользователей – авторизация пользователей, управление правами доступа.

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

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

    Расширения (плагины) - предоставляют дополнительные функции в соответствии с задачами  сайта.

    Оптимизация для поисковых систем (SEO) - предоставляет несколько инструментов для оптимизации сайта с точки зрения поисковых систем.

    Многоязычность - позволяет переводить весь контент на язык, предпочитаемый пользователем.


    Основные настройки сайта на WordPress

    General Settings - общие настройки WordPress используется для установки основных параметров конфигурации сайта.

    Writing Settings - определяют режим публикации материалов на сайте.

    Reading Settings - параметры показа сайта. Эти параметры используются для настройки параметров главной страницы сайта (FrontPage)

    Discussion Settings - настройки параметров блога.

    Media Settings - настройки работы с изображениями.

    Permalink Settings - настройки ссылок, параметры для SEF (Search Engine Friendly) URL's.


    Внешний вид сайта

    В основе внешнего вида сайта на WordPress лежит тема, или шаблон (theme, template). У каждого шаблона есть определённые параметры, он определяет расположение на экране контента, элементов навигацтт, графических элементов и тд. . По умолчанию WordPress предлагает на выбор несколько шаблонов, большое количество шаблонов можно найти в интернет, они могут быть как платными так и бесплатными, можно создавать шаблоны самостоятельно или генерировать при помощи специальных программ (например - Artiisteer).

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


    Контент сайта

    Статьи (Posts), страницы (Pages), меню (Menu).

    Основные 2 типа контента для сайта на WordPress - посты (или статьи) и страницы.

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

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

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

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


    Плагины (Plugins)

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


    Виджеты (Widgets)

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

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


    Управление пользователями (Users )

    Каждый пользователь (user) имеет свою собственную роль в WordPress. Роли - это права доступа, предоставляемые конкретному пользователю для использования ресурсов сайта на WordPress. 

    Роли могут быть назначенв только пользователем с правом доступа - Администратором.

    Администратор (Administrator) - имеет все права. Администратор может делать все, что угодно на сайте WordPress, например: создавать других администраторов, пользователей и удалять их.

    Редактор (Editor) - имеет доступ ко всем записям, страницам, комментариям, категориям, тегам и ссылкам. Он может создавать, публиковать, редактировать или удалять любые сообщения или страницы.

    Автор (Author) - может писать статьи (посты), загружать фотографии, редактировать и публиковать свои сообщения.

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

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

    Посетитель (Viewer) - может просматривать сообщения, посетители не могут редактировать, но могут комментировать сообщения.





  • CSS

  • CSS - Макет. Колонки

    Несколько примеров, используя разные CSS свойства


    HTML

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Multicolumns</title> <style> div{ background-color: #EEE; } #colTest1{ columns: 2; } #colTest2{ columns: 3; column-rule: 1px dotted red; } #colTest3{ width: 100%; display: flex; flex-flow: row; } .col1{ margin: 20px; } #colTest4 { display: grid; grid-template-columns: 200px 1fr 300px; } #colTest4 .col1:last-child{ grid-column: 1 / 4; } </style> </head> <body> <h1>Используя CSS свойство columns</h1> <p id="colTest1"> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Assumenda maxime aspernatur aliquam repellendus tenetur eum expedita minima labore, error ex magni, qui alias reprehenderit, perferendis cumque dolor nihil veniam molestiae. Lorem ipsum dolor sit amet consectetur, adipisicing elit. Ad atque expedita, minima ipsum facilis commodi cum eos dolor quae odit. Voluptatem aperiam veniam, illo adipisci fugiat facere consequatur expedita assumenda?Lorem ipsum dolor, sit amet consectetur adipisicing elit. Debitis quod ex aut consequuntur dolorem et laborum error quidem iure nulla a, vel distinctio pariatur repellendus aliquid hic illum recusandae placeat?Lorem ipsum dolor sit amet consectetur adipisicing elit. Alias veniam nisi cum. Culpa sit architecto ipsa optio sed nemo hic, laborum atque nihil quos velit suscipit obcaecati numquam amet vero! Lorem ipsum dolor, sit amet consectetur adipisicing elit. Vero quas adipisci placeat quibusdam aliquam ratione mollitia alias totam libero dolores cum, modi animi vitae? Dolorem corrupti accusantium odit quaerat maxime. Lorem ipsum dolor sit amet consectetur adipisicing elit. In iusto explicabo recusandae consectetur eos, temporibus laudantium hic eligendi pariatur similique soluta maxime ipsum tenetur, accusamus facilis dolores quae vel mollitia! </p> <p id="colTest2"> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Assumenda maxime aspernatur aliquam repellendus tenetur eum expedita minima labore, error ex magni, qui alias reprehenderit, perferendis cumque dolor nihil veniam molestiae. Lorem ipsum dolor sit amet consectetur, adipisicing elit. Ad atque expedita, minima ipsum facilis commodi cum eos dolor quae odit. Voluptatem aperiam veniam, illo adipisci fugiat facere consequatur expedita assumenda?Lorem ipsum dolor, sit amet consectetur adipisicing elit. Debitis quod ex aut consequuntur dolorem et laborum error quidem iure nulla a, vel distinctio pariatur repellendus aliquid hic illum recusandae placeat?Lorem ipsum dolor sit amet consectetur adipisicing elit. Alias veniam nisi cum. Culpa sit architecto ipsa optio sed nemo hic, laborum atque nihil quos velit suscipit obcaecati numquam amet vero! Lorem ipsum dolor, sit amet consectetur adipisicing elit. Vero quas adipisci placeat quibusdam aliquam ratione mollitia alias totam libero dolores cum, modi animi vitae? Dolorem corrupti accusantium odit quaerat maxime. Lorem ipsum dolor sit amet consectetur adipisicing elit. In iusto explicabo recusandae consectetur eos, temporibus laudantium hic eligendi pariatur similique soluta maxime ipsum tenetur, accusamus facilis dolores quae vel mollitia! </p> <hr> <h1>Используя CSS FLEX</h1> <div id="colTest3"> <p class="col1"> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Enim dicta, laborum dolor soluta tenetur voluptatem quibusdam nihil nisi molestiae ut magnam dolores similique facere odit ab fuga quasi. Exercitationem, consequatur? Lorem ipsum dolor sit amet consectetur, adipisicing elit. Accusamus qui odit animi quo delectus? Ea neque est nam! Quasi blanditiis rerum odit consectetur inventore totam! Sequi labore asperiores officia tenetur. Lorem ipsum, dolor sit amet consectetur adipisicing elit. Nobis nulla sit aliquid beatae perferendis ullam alias necessitatibus aliquam qui expedita molestiae at, nisi laudantium ab dignissimos dolores accusamus porro? Ullam. </p> <p class="col1"> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Enim dicta, laborum dolor soluta tenetur voluptatem quibusdam nihil nisi molestiae ut magnam dolores similique facere odit ab fuga quasi. Exercitationem, consequatur? Lorem ipsum dolor sit amet consectetur, adipisicing elit. Accusamus qui odit animi quo delectus? Ea neque est nam! Quasi blanditiis rerum odit consectetur inventore totam! Sequi labore asperiores officia tenetur. Lorem ipsum, dolor sit amet consectetur adipisicing elit. Nobis nulla sit aliquid beatae perferendis ullam alias necessitatibus aliquam qui expedita molestiae at, nisi laudantium ab dignissimos dolores accusamus porro? Ullam. </p> </div> <hr> <h1>Используя CSS GRID</h1> <div id="colTest4"> <p class="col1"> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Enim dicta, laborum dolor soluta tenetur voluptatem quibusdam nihil nisi molestiae ut magnam dolores similique facere odit ab fuga quasi. Exercitationem, consequatur? Lorem ipsum dolor sit amet consectetur, adipisicing elit. Accusamus qui odit animi quo delectus? Ea neque est nam! Quasi blanditiis rerum odit consectetur inventore totam! Sequi labore asperiores officia tenetur. Lorem ipsum, dolor sit amet consectetur adipisicing elit. Nobis nulla sit aliquid beatae perferendis ullam alias necessitatibus aliquam qui expedita molestiae at, nisi laudantium ab dignissimos dolores accusamus porro? Ullam. </p> <p class="col1"> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Enim dicta, laborum dolor soluta tenetur voluptatem quibusdam nihil nisi molestiae ut magnam dolores similique facere odit ab fuga quasi. Exercitationem, consequatur? Lorem ipsum dolor sit amet consectetur, adipisicing elit. Accusamus qui odit animi quo delectus? Ea neque est nam! Quasi blanditiis rerum odit consectetur inventore totam! Sequi labore asperiores officia tenetur. Lorem ipsum, dolor sit amet consectetur adipisicing elit. Nobis nulla sit aliquid beatae perferendis ullam alias necessitatibus aliquam qui expedita molestiae at, nisi laudantium ab dignissimos dolores accusamus porro? Ullam. </p> <p class="col1"> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Enim dicta, laborum dolor soluta tenetur voluptatem quibusdam nihil nisi molestiae ut magnam dolores similique facere odit ab fuga quasi. Exercitationem, consequatur? Lorem ipsum dolor sit amet consectetur, adipisicing elit. Accusamus qui odit animi quo delectus? Ea neque est nam! Quasi blanditiis rerum odit consectetur inventore totam! Sequi labore asperiores officia tenetur. Lorem ipsum, dolor sit amet consectetur adipisicing elit. Nobis nulla sit aliquid beatae perferendis ullam alias necessitatibus aliquam qui expedita molestiae at, nisi laudantium ab dignissimos dolores accusamus porro? Ullam. </p> <p class="col1"> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Enim dicta, laborum dolor soluta tenetur voluptatem quibusdam nihil nisi molestiae ut magnam dolores similique facere odit ab fuga quasi. Exercitationem, consequatur? Lorem ipsum dolor sit amet consectetur, adipisicing elit. Accusamus qui odit animi quo delectus? Ea neque est nam! Quasi blanditiis rerum odit consectetur inventore totam! Sequi labore asperiores officia tenetur. Lorem ipsum, dolor sit amet consectetur adipisicing elit. Nobis nulla sit aliquid beatae perferendis ullam alias necessitatibus aliquam qui expedita molestiae at, nisi laudantium ab dignissimos dolores accusamus porro? Ullam. </p> </div> </body> </html>







  • CSS clipping, shapes

    CSS clipping


    • clip-path
    • shape-outside
    • mask-border
    • mask
    • mask-clip
    • -webkit-background-clip: text


    Клипы

    Клип (clip-path) позволяет менять форму HTML элемента. Форму можно создать  как: circle, ellipse, polygon, SVG - image.

    circle( [<shape-radius>]? [at <position>]? )

    ellipse( [<shape-radius>{2}]? [at <position>]? )

    polygon( [<fill-rule>,]? [<shape-arg> <shape-arg>]# )


    shape-radius - радиус, для эллипса задаются 2 радиуса

    position - две координаты центра - смещения от левой границы и от верхней границы блока

    fill-rule - способ заливки внутренней области многоугольника

    shape-arg - массив координат вершин многоугольника


    Простой клип

    CSS:

    #clipTest { display: inline-block; padding: 10px; margin: 20px; height: 300px; width: 200px; background-color: blue; clip-path: circle(150px at 0px 0px); color: #fff; font-size: 1.5rem; font-weight: bold; }


    HTML


    <div id="clipTest">Clip test</div>





    Текст и клип

    Текст, располагающийся вокруг области клипа в форме окружности. Клип-окружность создаёт свойство   

    clip-path: circle(100px at 0px 0px) 

    Область, которая "вырезана" из блока с текстом, создаёт свойство

    shape-outside: circle(110px at 0px 0px)

    Свойство 

    float: left

    для клипа обязательно для того, чтобы текст "обтекал" клип.


    <!DOCTYPE html> <head> <style> #shapeOutsideTest1 { display: inline-block; position: relative; height: 300px; width: 300px; position: relative; border: 1px solid red; padding: 10px; } #shapeOutsideTest1 > #shape1-1 { float: left; height: 100%; width: 100%; background-color: blue; shape-outside: circle(110px at 0px 0px); -webkit-clip-path: circle(100px at 0px 0px); clip-path: circle(100px at 0px 0px); } </style> </head> <body> <div id="shapeOutsideTest1"> <div id="shape1-1"></div> Lorem ipsum dolor sit amet consectetur adipisicing elit. Maiores id, ad illo ea iste totam, consectetur ab praesentium repudiandae iusto perferendis consequuntur, recusandae suscipit fugit dolorum impedit? Blanditiis, pariatur quae. Lorem ipsum dolor sit amet consectetur adipisicing elit. Aut consequuntur provident eum illo doloremque ducimus alias molestiae quo illum eveniet, debitis saepe ex, recusandae magni veniam esse! Excepturi, ratione tenetur! </div> </body> </html>




    Два клипа и текст

    Два клипа в форме многоугольников и текст между ними.

    Один клип - слева () , второй клип - справа ()

    <!DOCTYPE html> <head> <style> #shapeOutsideTest2 { display: inline-block; height: 400px; width: 400px; border: 1px solid gray; padding: 10px; } #shapeOutsideTest2 #shape2-1 { float: left; width: 50%; height: 100%; margin-right: 10px; background-color: red; clip-path: polygon(0% 0%, 38% 0, 54% 50%, 38% 100%, 0% 100%); shape-outside: polygon(0% 0%, 38% 0, 54% 50%, 38% 100%, 0% 100%); } #shapeOutsideTest2 #shape2-2 { float: right; width: 45%; height: 100%; background-color: green; shape-outside: polygon(100% 0, 0 100%, 100% 100%); clip-path: polygon(100% 0, 0 100%, 100% 100%); } </style> </head> <body> <div id="shapeOutsideTest2"> <div id="shape2-1"></div> <div id="shape2-2"></div> <div id="shape2Text"> Lorem ipsum dolor sit amet consectetur adipisicing elit. Maiores id, ad illo ea iste totam, consectetur ab praesentium repudiandae iusto perferendis consequuntur, recusandae suscipit fugit dolorum impedit? Blanditiis, pariatur quae. Lorem ipsum dolor sit amet consectetur adipisicing elit. Aut consequuntur provident eum illo doloremque ducimus alias molestiae quo illum eveniet, debitis saepe ex, recusandae magni veniam esse! Excepturi, ratione tenetur!Aut consequuntur provident eum illo doloremque ducimus alias molestiae quo illum eveniet, debitis saepe ex! </div> </div> </body> </html>





    <!DOCTYPE html> <head> <style> #shapeOutsideTest3 { display: inline-block; border: 1px solid #157cca; width: 300px; height: 300px; } #shapeOutsideTest3 .leftTriangle { width: 40%; height: 100%; background-color: #157cca; margin: 0 20px 0 0; float: left; clip-path: polygon(0 0, 0 100%, 50% 0); shape-outside: polygon(0 0, 0 100%, 50% 0); } #shapeOutsideTest3 .rightTriangle { width: 40%; height: 100%; background-color: #157cca; float: right; clip-path: polygon(100% 0, 50% 100%, 100% 100%); shape-outside: polygon(100% 0, 50% 100%, 100% 100%); } </style> </head> <body> <div id="shapeOutsideTest3"> <div class="leftTriangle"></div> <div class="rightTriangle"></div> Lorem isum dolor sit amet consectetur adipisicing elit. Beatae aspernatur aut molestias, expedita ipsa quae deserunt, non, magni recusandae dolor blanditiis asperiores ex itaque accusantium alias. Voluptas quis corrupti ducimus. Lorem ipsum dolor, sit amet consectetur adipisicing elit. Magni nihil repellendus soluta doloribus, totam sunt aliquam facere a maxime itaque, cupiditate deleniti molestias nostrum eos ipsum, ex rerum. Minus, perspiciatis. </div> </body> </html>



    Картинка - в фоне клипа

    Картинка - background-image: url(../images/image.jpg);

    Многоугольник - клип (clip-path: polygon(30% 0, 50% 50%, 30% 100%, 0% 100%, 0 50%, 0% 0%))


    <!DOCTYPE html> <head> <style> #wrapper4 { width: 320px; height: 300px; display: inline-block; margin: 20px; } #wrapper4 #clip4 { float: left; width: 100%; height: 100%; margin-right: 30px; background-image: url(../images/image.jpg); background-size: auto 100%; shape-outside: polygon(30% 0, 50% 50%, 30% 100%, 0% 100%, 0 50%, 0% 0%); -webkit-clip-path: polygon(30% 0, 50% 50%, 30% 100%, 0% 100%, 0 50%, 0% 0%); clip-path: polygon(30% 0, 50% 50%, 30% 100%, 0% 100%, 0 50%, 0% 0%); } #wrapper4 p { color: #0099ff; } </style> </head> <body> <div id="wrapper4"> <div id="clip4"></div> Lorem ipsum dolor sit amet consectetur adipisicing elit. Maxime obcaecati voluptatum inventore facilis eum illum corporis, dolor possimus repellendus tenetur rerum aliquid sint aliquam! Nostrum amet id accusamus delectus ad. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quidem voluptate eveniet sit molestiae enim? Necessitatibus voluptas delectus cupiditate error, iste sapiente earum perspiciatis sint voluptatem, debitis impedit porro assumenda nulla! </div> </div> </body> </html>



    Клип - текст

    -webkit-background-clip: text;

    Фоновая картинка вставлена в клип-текст. Цвет текста задан с прозрачностью.

     

    <!DOCTYPE html> <head> <style> #wrapper5 { display: inline-block; border: 1px solid blue; text-align: center; background-image: url("../images/coffee-writing-computer-blogging-34676.jpg"); background-size: auto 100%; background-position: center; -webkit-background-clip: text; color: #74000077; padding: 20px; font-family: Arial, Helvetica, sans-serif; font-weight: bolder; font-size: 200px; } </style> </head> <body> <div id="wrapper5"> TEST </div> </body> </html>







  • CSS векторная графика (SVG)

    Масштабируемая векторная графика (SVG)

    SVG (Scalable Vector Graphics) - это язык разметки, построенный на основе XML и предназначенный для описания двумерной векторной графики. SVG – это графическое расширение для языка HTML. То, что HTML  делает с текстом, SVG делает с графикой.

    SVG похож на фирменную технологию Adobe Flash, но это - текстовый открытый веб-стандарт вместо закрытого двоичного формата. Он разработан для работы с другими веб-стандартами, такими как CSS, DOM и SMIL.

    Изображение в формате SVG - это текстовый файл. Этот файл создаётся в формате XML. Поэтому изображения в этом формате можно создавать в текстовом редакторе. 

    Часто удобнее создавать такие изображения, использую специальные программы (например - INKSCAPE ) или экспортируя из популярных графических программ (например - Adobe Photoshop).

     

    Графические элементы, созданные в формате SVG, можно вставить в HTML страничку разными способами:

     

     

     

    • используя теги img, embed, iframe, object (для вставки изображения из отдельного файла)
    • в любой HTML тег в качестве фона
    • используя тег svg (описание изображения непосредственно в документе)

     

     

     

    Синтаксис описания SVG

    Теги <svg>, <g>, <defs>

     

    Пример


    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>SVG 1</title>
    <style>
    SVG {
    height :300px;
    width :300px;
    border :1px solid black;
    }
    </style>
    </head>
    <body>
    <svg >
    <line x1="0" y1="0" x2="300" y2="300" stroke-width="10" stroke="rgb(255,0,0)"/>
    </svg>
    <svg>
    <polyline points="0,0 100,0 100,100 200,100 200,200 300,200 300,300" fill="rgb(255,0,0)" stroke-width="2" stroke="rgb(0,0,255)"/>
    </svg>
    <svg>
    <rect width="300" height="300" fill="rgb(0,0,255)" stroke-width="1" stroke="rgb(0,255,0)"/>
    <rect width="200" height="200" fill="rgb(255,0,0)" stroke-width="1" stroke="rgb(0,255,0)"/>
    <rect width="100" height="100" fill="rgb(0,255,0)" stroke-width="1" stroke="rgb(0,255,0)"/>
    </svg>
    <svg>
    <circle cx="150" cy="150" r="150" fill="rgb(255,255,0)" stroke-width="0" />
    <circle cx="150" cy="150" r="100" fill="rgb(0,0,255)" stroke-width="0" />
    </svg>
    <svg>
    <ellipse cx="150" cy="150" rx="150" ry="50" fill="rgb(0,0,255)" stroke-width="1" stroke="rgb(0,255,0)"/>
    </svg>
    <svg>
    <polygon points="0,100 100,100 100,50 300,150 100,250 100,200 0,200" fill="rgb(255,255,0)" stroke-width="1" stroke="rgb(255,0,0)" />
    </svg>
    </body>
    </html>

     

    Результат 

     

    Базовые формы изображений SVG 

    Линия - прямая <line>

    Тег рисует прямую линию. Использует параметры:

    x1, y1 - координаты начала

    x2, y2 - координаты конца

    stroke-width - толщина линии

    stroke - цвет линии

     

    Линия - ломаная  <polyline>

    Тег рисует ломаную линию. Использует параметры:

    points - массив координат узлов линии

    fill - цвет заливки

    stroke-width - толщина линии

    stroke - цвет линии

     

    Прямоугольник <rect>

    Тег рисует прямоугольник. Использует параметры:

    x, y - координаты прямоугольника 

    width - ширина

    height - высота

    fill - цвет заливки

    stroke-width - толщина линии обводки

    stroke - цвет линии обводки

     

    Круг <circle>

    Тег рисует круг. Использует параметры:

    cx, cy - координаты центра

    r - радиус

    fill - цвет заливки

    stroke-width - толщина линии обводки

    stroke - цвет линии обводки

     

     

    Эллипс <ellipse>

    Тег рисует элипс. Использует параметры:

    cx, cy - координаты центра

    rx - ширина

    ry - высота

    fill - цвет заливки

    stroke-width - толщина линии обводки

    stroke - цвет линии обводки

     

    Многоугольник <polygon>

    Тег рисует многоугольник. Использует параметры:

    points - массив координат углов

    fill - цвет заливки

    stroke-width - толщина линии обводки

    stroke - цвет линии обводки

     

    Путь <path>

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

    Атрибут d тегв <path> задаёт набор команд рисования:

    M - переместить курсор в точку (Move)

    L - нарисовать отрезок прямой (Line)

    A - нарисовать дугу (Arc)

    Q - кривая Безье (Quadratic Bezier Curves)

    C - кривая Безье (Cubic Bezier Curves)

    Z - замкнуть путь 

     

    Например:

    <path d="M100,100
    L150,100
    a50,25 0 0,0 150,100
    q50,-50 70,-170
    Z"
    style="stroke: #006666; fill: none;"/>

     

     

     

    Команды, используемые при рисовании линии пути (path)

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

    Команда Параметры Имя Описание
    M x,y moveto Перемещает карандаш в точку с абсолютными координатами x,y без рисования
    m x,y moveto Перемещает карандаш на x точек по горизонтали и на y - по вертикали, без рисования
     
    L x,y lineto Рисует строку из текущего местоположения пера в указанную точку x, y.
    l x,y lineto Рисует прямую от текущего положения до точки x,y относительно текущего положения
     
    H x horizontal lineto Draws a horizontal line to the point defined by 
    (specified x, pens current y).
    h x horizontal lineto Draws a horizontal line to the point defined by 
    (pens current x + specified x, pens current y). The x is relative to the current pens x position.
     
    V y vertical lineto Draws a vertical line to the point defined by 
    (pens current x, specified y).
    v y vertical lineto Draws a vertical line to the point defined by 
    (pens current x, pens current y + specified y). The y is relative to the pens current y-position.
     
    C x1,y1 x2,y2 x,y curveto Draws a cubic Bezier curve from current pen point to x,y. x1,y1 and x2,y2 are start and end control points of the curve, controlling how it bends.
    c x1,y1 x2,y2 x,y curveto Same as C, but interprets coordinates relative to current pen point.
     
    S x2,y2 x,y shorthand / 
    smooth curveto
    Draws a cubic Bezier curve from current pen point to x,y. x2,y2 is the end control point. The start control point is is assumed to be the same as the end control point of the previous curve.
    s x2,y2 x,y shorthand / 
    smooth curveto
    Same as S, but interprets coordinates relative to current pen point.
     
    Q x1,y1 x,y quadratic Bezier curveto Draws a quadratic Bezier curve from current pen point to x,y. x1,y1 is the control point controlling how the curve bends.
    q x1,y1 x,y quadratic Bezier curveto Same as Q, but interprets coordinates relative to current pen point.
     
    T x,y shorthand / smooth quadratic Bezier curveto Draws a quadratic Bezier curve from current pen point to x,y. The control point is assumed to be the same as the last control point used.
    t x,y shorthand / smooth quadratic Bezier curveto Same as T, but interprets coordinates relative to current pen point.
     
    A rx,ry 
    x-axis-rotation 
    large-arc-flag,
    sweepflag 
    x,y
    elliptical arc Draws an elliptical arc from the current point to the point x,y. rx and ry are the elliptical radius in x and y direction.
    The x-rotation determines how much the arc is to be rotated around the x-axis. It only seems to have an effect when rx and ry have different values.
    The large-arc-flag doesn't seem to be used (can be either 0 or 1). Neither value (0 or 1) changes the arc. 
    The sweep-flag determines the direction to draw the arc in.
    a rx,ry 
    x-axis-rotation 
    large-arc-flag,
    sweepflag 
    x,y
    elliptical arc Same as A, but interprets coordinates relative to current pen point.
     
    Z   closepath Closes the path by drawing a line from current point to first point.
    z   closepath Closes the path by drawing a line from current point to first point.
     

     

     

    Текст

     

    <text x="20" y="40" style="fill: #000000; stroke: none; font-size: 48px;"> Fill only </text> <text x="20" y="100" style="fill: none; stroke: #000000; font-size: 48px;"> Stroke only </text> <text x="20" y="150" style="fill: #999999; stroke: #000000; font-size: 48px;"> Fill and stroke </text>

     

     

     

    Оператор - switch

    Этот оператор позволяет использовать разные изображения, в зависимости от языка.

     

     

    <switch>
    <g systemLanguage="en-UK">
    <text x="10" y="20">UK English</text>
    </g>
    <g systemLanguage="en">
    <text x="10" y="20">English</text>
    </g>
    <g systemLanguage="es">
    <text x="10" y="20">Spanish</text>
    </g>
    </switch>

     

     SVG система координат

    В SVG отсчёт координат (точка с координатами х=0, y=0) начинается из левого верхнего угла. Ось y - направление сверху вниз. Ось x - направление слева направо.

     

    Единицы измерения

    Единица измерения указывается после значения. Например:  10cm или 125mm.

    Если единицы измерения не указаны, то имеются в виду пиксели - pixels (px).

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

    Единица Описание
    em Высота букв шрифта по умолчанию.
    ex Высота символа - x
    px Пиксели
    pt Пойнты (1 / 72 дюйма - inch)
    pc Picas (1 / 6 дюйма)
    cm Centimeters
    mm Миллиметры
    in Дюймы

    Единицы, установленные в элементе <svg> для  атрибутов width и height, влияют только на элемент <svg> (viewport - область просмотра).

    Формы, находящиеся  внутри элемента <svg> должны иметь свои собственные единицы.

    Если единицы измерения не указаны, то по умолчанию используются пиксели.

     

    Размеры форм, размер области их размещения

    Область, в которую выводятся SVG - формы, определяется тегом <svg>. Эта область - ViewPort определяется параметрами тега <svg> - width, height и параметром viewPort. 

    Если параметра viewBox в теге svg нет, то width и height определяют абсолютные размерый этой области.

    Это - абсолютные размеры области видимости форм. И параметры размеров самих форм, которые выводятся на экран тоже абсолютные (x, y, r, cx, cy,... ).

    Например, если задано в теге svg  height :500 и width :200, то на экране выделится для вывода изображений область шириной 200 и высотой 500 пикселей. Если в ней определено: 

    <rect   width=50 height=70 fill ="#0b0" stroke-width="1" stroke="#050" />

    то внутри области будет нарисован прямоугольник шириной 50 рикселей и высотой - 100.

    Параметр viewBox пропорционально меняет размеры всех элементов. Эта область имеет координаты (x, y ) и размеры (ширину, высоту).  Например: viewBox="0 0 50 20". Если для нашего примера задать такой viewBox, то реальные размеры всех элементов увеличется по горизонтали на коэффициент 500/50, а по вертикали - на коэффициент 200/20. То есть реальные размеры прясоугольника будут - 500 на 700 пикселей, а размер вилимой области - 5000 на 2000 пикселей.

     

     

    Применение стилей к SVG 

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

    Примеры:

     

    <svg> <rect x="203" width="200" height="200" style="fill:red; stroke:black; stroke-width:3;"/> </svg>

     

    <style type="text/css" media="screen"> rect { fill: green; stroke: black; stroke-width: 3; } rect:hover { fill: green; } </style>

     

     

    <link rel="stylesheet" type="text/css" href="/style.css">

     

     

    <?xml-stylesheet type="text/css" href="/style.css"?>

     

     

    Назначение стилей для всех сгруппированных элементов

    <g style="fill:blue; stroke:black; stroke-width:3; fill-opacity: 0.5;"> <rect x="200" width="200" height="200"/> <circle cx="120" cy="100" r="100"/> </g>

     

     

    Анимация SVGs при помощи CSS

    <svg> <rect x="10" y="10" height="110" width="110" style="stroke:#ff0000; fill: #0000ff"> <animateTransform attributeName="transform" begin="0s" dur="20s" type="rotate" from="0 60 60" to="360 60 60" repeatCount="indefinite" /> </rect> </svg>

     

     

     

     

    <rect x="0" y="0" width="30" height="15" style="stroke: #ff0000; fill: none;"> <animateMotion path="M10,50 q60,50 100,0 q60,-50 100,0" begin="0s" dur="10s" repeatCount="indefinite" rotate="auto" /> </rect>

     

     

     

    Пример: таймер


    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>SVG Javascript test1</title>
    <script>
    var x2, y2, grad, clockFace, secCounter, arrLength// Declare globals
    function drawTimer(){
    // Init counter
    x2=0, y2 = 0, grad = -90, clockFace = 400, secCounter = 0, arrLength = 180

    document.getElementById("myTimer").style.width = clockFace + "px";
    document.getElementById("myTimer").style.height = clockFace + "px";
    document.getElementById("myTimer").style.border = "4px solid red";
    document.getElementById("myTimer").style.backgroundColor = "#FFDDDD";
    document.getElementById("myTimer").style.borderRadius = "30%";
    x1 = clockFace/2;
    y1 = clockFace/2;
    x2 = arrLength;
    y2 = 0;
    rad = grad * (Math.PI / 180);
    x2 = x1 + Math.cos(rad)*arrLength;
    y2 = y1 + Math.sin(rad)*arrLength;
    console.log("x1 = " + x1 + ", y1 = " + y1 + ", x2 = " + x2 + ", y2 = " + y2);
    // Draw Line
    document.getElementById("arrow").setAttribute("x1",x1);
    document.getElementById("arrow").setAttribute("y1",y1);
    document.getElementById("arrow").setAttribute("x2",x2);
    document.getElementById("arrow").setAttribute("y2",y2);
    document.getElementById("arrow").setAttribute("stroke-width",2);
    document.getElementById("arrow").setAttribute("stroke","#FF0000");
    // Draw arrow end point
    document.getElementById("arrowEnd").setAttribute("cx",x2);
    document.getElementById("arrowEnd").setAttribute("cy",y2);
    document.getElementById("arrowEnd").setAttribute("r",4);
    document.getElementById("arrowEnd").setAttribute("fill","#FF0000");

    document.getElementById("arrowEnd").setAttribute("stroke-width",0);

    // Draw arrow start point
    document.getElementById("arrowStart").setAttribute("cx",x1);
    document.getElementById("arrowStart").setAttribute("cy",y1);
    document.getElementById("arrowStart").setAttribute("r",15);
    document.getElementById("arrowStart").setAttribute("fill","none");
    document.getElementById("arrowStart").setAttribute("stroke","#F00");
    document.getElementById("arrowStart").setAttribute("stroke-width",2);

    // draw numbers
    document.getElementById("out2").setAttribute("x",x1);
    document.getElementById("out2").setAttribute("y",y1);
    document.getElementById("out2").setAttribute("fill","#FFBBBB");
    document.getElementById("out2").setAttribute("font-size",arrLength);


    }

    function arrowStep(){
    // Move arrow once
    grad += 1;
    secCounter += 1;
    rad = grad * (Math.PI / 180);
    x2 = x1 + Math.cos(rad)*arrLength;
    y2 = y1 + Math.sin(rad)*arrLength;
    document.getElementById("arrow").setAttribute("x2",x2);
    document.getElementById("arrow").setAttribute("y2",y2);
    console.log("x1 = " + x1 + ", y1 = " + y1 + ", x2 = " + x2 + ", y2 = " + y2 + ", angle (degrees) = " + grad);
    console.log(secCounter);
    // Draw arrow top point

    document.getElementById("arrowEnd").setAttribute("cx",x2);
    document.getElementById("arrowEnd").setAttribute("cy",y2);
    document.getElementById("arrowEnd").setAttribute("r",4);
    document.getElementById("arrowEnd").setAttribute("fill","#FF0000");
    document.getElementById("arrowEnd").setAttribute("stroke-width",0);
    document.getElementById("out2").innerHTML = secCounter;
    }
    </script>
    </head>
    <body onload="drawTimer()">
    <svg id="myTimer">
    <text id = "out2" x="" y="" fill="" font-size="" alignment-baseline="middle" text-anchor="middle">0</text>
    <line id="arrow" x1="" y1="" x2="" y2="" stroke-width="" stroke=""/>
    <circle id="arrowStart" cx="" cy="" r="" fill="" stroke-width="" />
    <circle id="arrowEnd" cx="" cy="" r="" fill="" stroke-width="" />
    </svg>

    <button onclick = "arrowStep();">Go one step</button>
    <button onclick = "int1 = setInterval(arrowStep,1000);">Start timer</button>
    <button onclick = "clearInterval(int1);">Stop timer</button>
    <button onclick = "drawTimer();">Reset counter</button>

    </body>
    </html>

     

     

    Результат

     

  • CSS3 адаптивные блоки (Flex Box Model)

    CSS3 адаптивные блоки (Flexible Box Model)

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

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

    Вместо терминологии block и inline элементов flexbox исользует термины: главная и перпендикулярная оси (main axis и cross axis).

    Контейнер (container)

    Родительский элемент, в котором содержатся все остальные flexible - элементы. Flex - контейнер определяется с использованием значений flex или inline-flex свойства display.

    Элемент (item)

    Каждый дочерний элемент flex - контейнера становится flex - элементом.

    Оси (axis)

    Каждый flexbox макет использует две оси. Главная и перепендикулярная. Flex - элементы следуют один за другим вдоль главной оси (main-axis).

    • flex-direction - это свойство, которое задаёт главную ось
    • justify-content - задаёт размещение flex-элементов в текущей строке главной оси
    • align-items - задаёт размещение flex-элементов в текущей строке перпендикулярной оси
    • align-self - определяет, как единичный flex-элемент выравнивается вдоль перпендикулярной оси, переопределяя значения, заданные в align-items

    Направления (directions)

    Границы flex- контейнера ( main start/main end и cross start/cross end ) определяют задают начальные и конечные точки для перемещений flex-элементов внутри контейнера.

    • Свойство order присваивает элементы порядковым группам и определяет, какие элементы появляются первыми.
    • Свойство flex-flow сокращает описание свойств flex-direction и flex-wrap для размещения flex-элементов.

    Строки (lines)

    Элементы Flex могут быть размещены либо на одной строке, либо на нескольких строках в соответствии с свойством flex-wrap, которое управляет направлением поперечной оси и направлением, в котором формируются новые строки.

    Размеры (dimensions)

    Для flex-элементов свойства width и height задают размеры.

    Свойство flex сокращает описание свойств flex-grow, flex-shrink, flex-basis для описаниия адаптивных размеров flex-элементов.

    CSS3 Flexbox свойства

     

    Свойство Описание Значения Пример
    display Тип flex-контейнера flex
      inline-flex
    display:flex;
    display: -webkit-flex;
     
    flex-direction Определяет направление размещения flex-элементов внутри flex-контейнера flex-direction flex-direction: row-reverse;
    -webkit-flex-direction: row-reverse;
    justify-content Выравнивает горизонтально элементы flex в случае, если они не занимают всё пространство по главной оси. flex-start
      flex-end
      center
      space-between
      space-around
      initial
      inherit
    div {
    -webkit-justify-content: space-around; 
    justify-content: space-around;
    }
    align-items Свойство align-items указывает выравнивание по умолчанию для элементов внутри flex-контейнера.
    Можно использовать свойство align-self для каждого элемента, чтобы переопределить свойство align-items.
    stretch
      center
      flex-start
      flex-end
      baseline
      initial
      inherit;
    div {
    -webkit-align-items: center; 
    align-items: center;
    }
    flex-wrap Указывает, должны ли flex-элементы переноситься на другую строку, если им недостаточно места в одной строке nowrap
      wrap
      wrap-reverse
      initial
      inherit
    div {
    -webkit-flex-wrap: wrap; 
    flex-wrap: wrap;
    }
    align-content Модифицирует поведение свойства flex-wrap. Похоже на align-items, но вместо выравнивания flex-элементов  выравнивает строки stretch
      center
      flex-start
      flex-end
      space-between
      space-around
    i  nitial
      inherit
    div {
    -webkit-align-content: center;
    align-content: center;
    }
    flex-flow Сокращение для свойств flex-direction и flex-wrap flex-flow: flex-direction flex-wrap|initial|inherit; div {
    -webkit-flex-flow: row-reverse wrap; 
    flex-flow: row-reverse wrap;
    }
    order Задаёт порядок следования flexible элементов относительно остальных внутри одного контейнера number
      initial
      inherit
    -webkit-order: 2;
      order: 2;
    align-self Используется для  flex-элементов. Переопределяет свойство контейнера align-items  auto
    stretch
    center
    flex-start
    flex-end
    baseline
    initial
    inherit
    div {
    -webkit-align-self: center; 
    align-self: center;
    }
    flex Задаёт длину  flex-элемента по отношению к остальным внутри того же контейнера flex-grow flex-shrink flex-basis auto|initial|inherit div {
    -webkit-flex: 1; 
    -ms-flex: 1; 
    flex: 1;
    }
    flex-grow Указывает, насколько элемент будет увеличиваться относительно остальных элементов внутри одного и того же контейнера    
    flex-shrink Свойство определяет, как элемент будет уменьшаться относительно остальных гибких элементов внутри одного контейнера    
    flex-basis Свойство задает начальную длину flex-элемента   div:nth-of-type(2) {
    -webkit-flex-basis: 80px; 
    flex-basis: 80px;
    }
           

     

     

     

  • DOM - обработка событий (Events)

    DOM - обработка событий (Events)

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

    События могут генерироваться как пользователем (например: перемещение мышки) так и системой (например: законцилась анимация )

    События могут быть разных типов, например:

    • нажатия клавиш мыши, перемещение курсора
    • нажатие клавиш клавиатуры
    • изменение размеров окна браузеа (закрытие окна)
    • загрузка страницы в окно
    • заполнение формы
    • воспроизведение видео
    • возникновение ошибок.

    Реакция на события описывается через бработчики событий (events listeners или event handlers).

    Браузер постоянно отслеживает все события, при его возникновении (event firing) он ищет назначенную этому событию фукцию-обработчик события и запускает её (если она найдена).

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

    Типы событий

    События, связанные с мышью (mouse events)

    Событие Описание DOM
    onclick Клик левой кнопкой мыши 2
    oncontextmenu Клик правой кнопкой мышки 3
    ondblclick Два клика подряд левой кнопкой 2
    onmousedown Нажатие левой кнопки мышки 2
    onmouseenter Курсор попал на элемент 2
    onmouseleave Курсор ушёл с элемента 2
    onmousemove Курсор переместился, находясь над элементом 2
    onmouseover Курсор находится над элементом или его дочерними элементами 2
    onmouseout Курсор ушёл с области самого элемента или одного из его дочерних элементов 2
    onmouseup Отпускание левой кнопки мышки 2

    События клавиатуры (keyboard events)

    Событие Описание DOM
    onkeydown Нажатие кнопки клавиатурв 2
    onkeypress Нажатие и отпускание кнопки клавиатуры 2
    onkeyup Отпускание кнопки клавиатуры 2

    События объекта frame (frame/window events)

    Собвтие Описание DOM
    onabort Загрузка документа в фрейм прервана 2
    onbeforeunload Начало загрузки документа в фрейм 2
    onerror Ошибка загрузки файла в фрейм 2
    onhashchange Изменился параметр anchor фрейма 3
    onload Загрузка документа в фрейм 2
    onpageshow Событие происходит, когда пользователь переходит на веб-страницу 3
    onpagehide Событие происходит, когда пользователь уходит с веб-страницы 3
    onresize Событие возникает, когда размер окна документа изменяется 2
    onscroll Событие происходит при прокрутке элемента 2
    onunload Событие происходит после выгрузки страницы (для <body>) 2

    События, связанные с формой (form events)

    Событие Описание DOM
    onblur Событие происходит, когда элемент теряет фокус 2
    onchange Событие происходит, когда изменилось содержимое элемента формы (для <input>, <keygen>, <select> и <textarea>) 2
    onfocus Событие возникает, когда элемент получает фокус 2
    onfocusin Событие возникает, когда элемент собирается получить фокус 2
    onfocusout Событие происходит, когда элемент теряет фокус 2
    oninput Событие возникает, когда элемент получает пользовательский ввод 3
    oninvalid Событие oninvalid происходит, когда элемент <input> недопустим. 3
    onreset Событие происходит, когда форма сбрасывается 2
    onsearch Событие возникает, когда пользователь что-то пишет в поле поиска (для <input = "search">) 3
    onselect Событие происходит после выбора пользователем текста (для <input> и <textarea>) 2
    onsubmit Событие происходит при отправке формы 2

    События drag/drop

    Событие Описание DOM
    ondrag Событие возникает, когда элемент перетаскивается 3
    ondragend Событие происходит, когда пользователь закончил перетаскивание элемента 3
    ondragenter Событие возникает, когда элемент перетаскивания входит в целевую точку  3
    ondragleave Событие происходит, когда элемент перетаскивания оставляет целевую точку 3
    ondragover Событие происходит, когда элемент перетаскивания находится над целевой точкой перетаскивания 3
    ondragstart Событие возникает, когда пользователь начинает перетаскивать элемент 3
    ondrop Событие происходит, когда перетаскиваемый элемент выбрасывается в целевой точке 3

    Clipboard - события

    Событие Описание DOM
    oncopy Событие происходит, когда пользователь копирует содержимое элемента
    oncut Событие происходит, когда пользователь вырезает содержимое элемента
    onpaste Событие возникает, когда пользователь вставляет некоторый контент в элемент

    Print - события

    Событие Описание DOM
    onafterprint Событие происходит, когда страница начала печать, или если диалоговое окно печати закрывается 3
    onbeforeprint Событие происходит, когда страница будет напечатана 3

    Media - события

    Событие Описание DOM
    onabort The event occurs when the loading of a media is aborted 3
    oncanplay The event occurs when the browser can start playing the media (when it has buffered enough to begin) 3
    oncanplaythrough The event occurs when the browser can play through the media without stopping for buffering 3
    ondurationchange The event occurs when the duration of the media is changed 3
    onemptied The event occurs when something bad happens and the media file is suddenly unavailable (like unexpectedly disconnects) 3
    onended The event occurs when the media has reach the end (useful for messages like "thanks for listening") 3
    onerror The event occurs when an error occurred during the loading of a media file 3
    onloadeddata The event occurs when media data is loaded 3
    onloadedmetadata The event occurs when meta data (like dimensions and duration) are loaded 3
    onloadstart The event occurs when the browser starts looking for the specified media 3
    onpause The event occurs when the media is paused either by the user or programmatically 3
    onplay The event occurs when the media has been started or is no longer paused 3
    onplaying The event occurs when the media is playing after having been paused or stopped for buffering 3
    onprogress The event occurs when the browser is in the process of getting the media data (downloading the media) 3
    onratechange The event occurs when the playing speed of the media is changed 3
    onseeked The event occurs when the user is finished moving/skipping to a new position in the media 3
    onseeking The event occurs when the user starts moving/skipping to a new position in the media 3
    onstalled The event occurs when the browser is trying to get media data, but data is not available 3
    onsuspend The event occurs when the browser is intentionally not getting media data 3
    ontimeupdate The event occurs when the playing position has changed (like when the user fast forwards to a different point in the media) 3
    onvolumechange The event occurs when the volume of the media has changed (includes setting the volume to "mute") 3
    onwaiting The event occurs when the media has paused but is expected to resume (like when the media pauses to buffer more data) 3

    Animation - события

    Событие Описание DOM
    animationend The event occurs when a CSS animation has completed 3
    animationiteration The event occurs when a CSS animation is repeated 3
    animationstart The event occurs when a CSS animation has started 3

    Transition - события

    Событие Описание DOM
    transitionend The event occurs when a CSS transition has completed 3

    Server-Sent - события

    Событие Описание DOM
    onerror The event occurs when an error occurs with the event source
    onmessage The event occurs when a message is received through the event source
    onopen The event occurs when a connection with the event source is opened

    Другие события

    Событие Описание DOM
    onmessage The event occurs when a message is received through or from an object (WebSocket, Web Worker, Event Source or a child frame or a parent window) 3
    onmousewheel Deprecated. Use the onwheel event instead
    ononline The event occurs when the browser starts to work online 3
    onoffline The event occurs when the browser starts to work offline 3
    onpopstate The event occurs when the window's history changes 3
    onshow The event occurs when a <menu> element is shown as a context menu 3
    onstorage The event occurs when a Web Storage area is updated 3
    ontoggle The event occurs when the user opens or closes the <details> element 3
    onwheel The event occurs when the mouse wheel rolls up or down over an element 3

    Touch - события

    Событие Описание DOM
    ontouchcancel The event occurs when the touch is interrupted
    ontouchend The event occurs when a finger is removed from a touch screen
    ontouchmove The event occurs when a finger is dragged across the screen
    ontouchstart The event occurs when a finger is placed on a touch screen

    Объект event

    Когда происходит событие, браузер создает объект 'event', помещает в него детали события и передает его в качестве аргумента обработчику.

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

    function myFunc2(evnt){ console.log('Event: ', evnt); }

    ELEMENT.addEventListener('click', myFunc2);


    Константы

    Константа Описание DOM
    CAPTURING_PHASE The current event phase is the capture phase (1) 1
    AT_TARGET The current event is in the target phase, i.e. it is being evaluated at the event target (2) 2
    BUBBLING_PHASE The current event phase is the bubbling phase (3) 3

    Свойства

    Свойство Описание DOM
    bubbles Returns whether or not a specific event is a bubbling event 2
    cancelable Returns whether or not an event can have its default action prevented 2
    currentTarget Returns the element whose event listeners triggered the event 2
    defaultPrevented Returns whether or not the preventDefault() method was called for the event 3
    eventPhase Returns which phase of the event flow is currently being evaluated 2
    isTrusted Returns whether or not an event is trusted 3
    target Returns the element that triggered the event 2
    timeStamp Returns the time (in milliseconds relative to the epoch) at which the event was created 2
    type Returns the name of the event 2
    view Returns a reference to the Window object where the event occured 2

    Методы

    Метод Описание DOM
    preventDefault() Cancels the event if it is cancelable, meaning that the default action that belongs to the event will not occur 2
    stopImmediatePropagation() Prevents other listeners of the same event from being called 3
    stopPropagation() Prevents further propagation of an event during event flow 2

    Объект - MouseEvent

    Свойство Описание DOM
    altKey Возвращает, была ли нажата клавиша «ALT» при запуске события мыши 2
    button Возвращает, какая кнопка мыши была нажата при запуске события мыши 2
    buttons Возвращает, какие кнопки мыши были нажаты при запуске события мыши 3
    clientX Возвращает горизонтальную координату указателя мыши относительно текущего окна, когда событие мыши было запущено 2
    clientY Возвращает вертикальную координату указателя мыши относительно текущего окна, когда событие мыши было запущено 2
    ctrlKey Возвращает, была ли нажата клавиша CTRL при запуске события мыши 2
    detail Возвращает число, указывающее, сколько раз щелкнули мышь 2
    metaKey Возвращает, была ли нажата клавиша «META» при срабатывании события 2
    pageX Возвращает горизонтальную координату указателя мыши относительно документа, когда событие мыши было запущено
    pageY Возвращает вертикальную координату указателя мыши относительно документа, когда событие мыши было запущено
    relatedTarget Возвращает элемент, связанный с элементом, вызвавшим событие мыши 2
    screenX Возвращает горизонтальную координату указателя мыши относительно экрана, когда событие было вызвано 2
    screenY Возвращает вертикальную координату указателя мыши относительно экрана, когда событие было инициировано 2
    shiftKey Возвращает, была ли нажата клавиша «SHIFT» при срабатывании события 2
    which Возвращает, какая кнопка мыши была нажата при запуске события мыши 2

    Объект - KeyboardEvent

    Свойство Описание DOM
    altKey Возвращает, была ли нажата клавиша «ALT» при срабатывании  события 2
    ctrlKey Возвращает, была ли нажата клавиша CTRL при срабатывании события клавиатуры 2
    charCode Возвращает код символа Юникода клавиши, которая вызвала событие onkeypress 2
    key Возвращает для нажатой клавиши её значение  3
    location Возвращает местоположение ключа на клавиатуре или устройстве 3
    metaKey Возвращает, была ли нажата клавиша «meta» при запуске  события 2
    shiftKey Возвращает, была ли нажата клавиша «SHIFT» при срабатывании  события 2
    which Возвращает код символа Юникода ключа, вызвавшего событие onkeypress, или код ключа Unicode ключа, вызвавшего событие onkeydown или onkeyup 2

    HashChangeEvent - объект

    Property Описание DOM
    newURL Returns the URL of the document, after the hash has been changed
    oldURL Returns the URL of the document, before the hash was changed

    PageTransitionEvent - объект

    Property Описание DOM
    persisted Returns whether the webpage was cached by the browser

    FocusEvent - объект

    Property Описание DOM
    relatedTarget Returns the element related to the element that triggered the event 3

    AnimationEvent - объект

    Property Описание DOM
    animationName Returns the name of the animation
    elapsedTime Returns the number of seconds an animation has been running

    TransitionEvent - объект

    Property Описание DOM
    propertyName Returns the name of the CSS property associated with the transition
    elapsedTime Returns the number of seconds a transition has been running

    WheelEvent - объект

    Property Описание DOM
    deltaX Returns the horizontal scroll amount of a mouse wheel (x-axis) 3
    deltaY Returns the vertical scroll amount of a mouse wheel (y-axis) 3
    deltaZ Returns the scroll amount of a mouse wheel for the z-axis 3
    deltaMode Returns a number that represents the unit of measurements for delta values (pixels, lines or pages) 3

     

    Регистрация обработчика событий

    Зарегистриовать обработчик событий можно разными способами.

    Присвоить значение специальному атрибуту (onclick, onkeypress, onmouseenter,...) при описании HTMl тега. Например:

    <button id='myButton1' onclick="alert('My event!');">Press me</button>

    Можно его изменить с помощью соответствующего свойства объекта element:

    document.getElementById('myButton1').onclick = 'alert("New action")'

    Можно использовать метод объекта element - addEventListener(event, listener). Например:

    document.getElementById('myButton1').addEventListener('click', click2); function click2(){ alert('Listener 1 - click2()'); }

    или

    document.getElementById('myButton1').addEventListener('click', () => { alert ('Listener 1!!'); });

    Если в этом примере  ипользовать оба способа, то к элементу id=myButton1 , к событию click будут привязаны сразу 2 обработчика.


    Удаление обработчика событий

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

    Привязать обработчик к элементу 

    <button id="myButton1" onclick='alert("Event listener connected")'>Click me</button>

    или

    document.getElementById('myButton1').onclick='alert("Event listener connected")';

    Удалить его

    document.getElementById('myButton1').onclick='';

    Можно использовать метод элемента removeEventListener(событие, имя_обработчика)

    Привязать

    function myFunc2(){ alert("Listener myFunc2() response"); } document.getElementById('myButton1').addEventListener('click', myFunc2);

    Удалить

    document.getElementById('myButton1').removeEventListener('click', myFunc2);


    Удалить все обработчики событий у элемента можно, например, клонировав элемент (метод cloneNode()) , при этом обработчики событий не клонируются. 

    function removeAllEventListeners(elmntID){ var oldElement = document.getElementById(elmntID); var newElement = oldElement.cloneNode(true); oldElement.parentNode.replaceChild(newElement, oldElement); // cleanup out1 out1.innerHTML = ''; }



    Events bubbling, capturing

    event.target - элемент, который инициировал событие.

    event.currentTarget - текущий элемент, обрабатывающий событие.

    event bubbling (event propagation) - обработка события, котоое инициировал элемент, всеми его родительскими элементами (снизу вверх или от дочернего элемента).

    event capturing - 

    event.eventPhase - фаза обработки события (capturing=1, bubbling=3)

    Стандартные события DOM проходят фазы обработки событий (event.eventPhase):

    Константа Значение Описание
    Event.NONE 0 Ни одно событие не обрабатывается
    Event.CAPTURING_PHASE 1 Событие передаётся через объекты-предки целевого элемента (event.target). Этот процесс начинается с объекта Window, затем - Document, затем HTMLHtmlElement и т. д. через элементы до тех пор, пока не будет достигнут непоседственно родительский элемент. Обработчики событий, зарегистрированные для Capturing (при вызове EventTarget.addEventListener (EVENT, HANDLER, useCapture)), запускаются на этом этапе.
    Event.AT_TARGET 2 Событие достигло целевого элемента. В это время вызываются обработчики событий, зарегистрированные для этой фазы. Если Event.bubbles принимает значение false, обработка события завершается после завершения этой фазы.
    Event.BUBBLING_PHASE 3 Событие распространяется к предкам целевого элемента, в обратном порядке, начиная с его непосредственного родителя, и в конечном итоге достигает объекта Window. Этот процесс называется bubbling происходит только в том случае, если Event.bubbles принимает значение true. Обработчики событий, зарегистрированные для этой фазы, запускаются в это время.
    • Capturing phase - событие переходит к элементу
    • Target phase - событие достигло целевого элемента
    • Bubbling phase - событие "поднимается" от элемента