Сортировка и фильтрация таблицы с помощью Angular

angular
image-957

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

7661

Простое приложение

Наше приложение позволит нам:

  • Вывести таблицу данных (ng-repeat)
  • Сортировать по возрастанию или по убыванию колонки (orderBy)
  • Фильтр с помощью поля поиска (filter)

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

Настройки

Что мы будем использовать?

Bootstrap and Font Awesome для стилизации нашего приложение, и конечно же AngularJS. У нас будет два файла:

- index.html
- app.js

Вот код app.js:

angular.module('sortApp', [])
.controller('mainController', function($scope) {
  $scope.sortType     = 'name'; // значение сортировки по умолчанию
  $scope.sortReverse  = false;  // обратная сортировка
  $scope.searchFish   = '';     // значение поиска по умолчанию
  // список
  $scope.sushi = [
    { name: 'Cali Roll', fish: 'Crab', tastiness: 2 },
    { name: 'Philly', fish: 'Tuna', tastiness: 4 },
    { name: 'Tiger', fish: 'Eel', tastiness: 7 },
    { name: 'Rainbow', fish: 'Variety', tastiness: 6 }
  ];

Тут у нас приложение sortApp и его контроллер mainController. Инициализируем три переменные: sortType, sortReverse, searchFish. Так же мы создали объект список суш. Теперь используем этот модуль в нашем HTML шаблоне:

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Angular Sort and Filter</title>
    <!-- CSS -->
    <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootswatch/3.2.0/sandstone/bootstrap.min.css">
    <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css">
    <style>
        body { padding-top:50px; }
    </style>
    <!-- JS -->
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <script src="app.js"></script>
</head>
<body>
<div class="container" ng-app="sortApp" ng-controller="mainController">
  <div class="alert alert-info">
    <p>Sort Type: {{ sortType }}</p>
    <p>Sort Reverse: {{ sortReverse }}</p>
    <p>Search Query: {{ searchFish }}</p>
  </div>
  <table class="table table-bordered table-striped">
    <thead>
      <tr>
        <td>
            Sushi Roll
        </td>
        <td>
          Fish Type
        </td>
        <td>
          Taste Level
        </td>
      </tr>
    </thead>
    <tbody>
      <tr ng-repeat="roll in sushi">
        <td>{{ roll.name }}</td>
        <td>{{ roll.fish }}</td>
        <td>{{ roll.tastiness }}</td>
      </tr>
    </tbody>
  </table>
</div>
</body>
</html>

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

43b4-Z6AOUg
image-958

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

Сортировка таблицы

Мы будем достигать этой сортировки используя две переменные, которые мы создали ранее ($scope.sortType и $scope.sortReverse). Мы также будем использовать Angular фильтр orderBy. В принципе, используя сочетание переменных sortType и sortReverse к orderBy в нашем ng-repeat таблица будет от сортирована.

<!-- index.html -->
...
    <tr ng-repeat="roll in sushi | orderBy:sortType:sortReverse">
...

Это все, что нужно, чтобы изменить порядок сортировки нашего ng-repeat. Если вы обновите страницу, то увидите, что список отсортирован по называют в обычном порядке. Если вы измените в модуле параметры по умолчанию на $scope.sortType = 'fish' или $scope.sortReverse = true; то и сортировка изменится, сортировка будет теперь по полю fish и в обратном порядке.

Создание кликабельных заголовков таблицы

Мы добавим ссылки в наши заголовки таблицы. Давайте посмотрим на thead тег нашего сайта и используем ng-click, чтобы настроить переменную sortType:

...
    <thead>
      <tr>
        <td>
          <a href="#" ng-click="sortType = 'name'">
            Sushi Roll
            <span ng-show="sortType == 'name'" class="fa fa-caret-down"></span>
          </a>
        </td>
        <td>
          <a href="#" ng-click="sortType = 'fish'">
          <span ng-show="sortType == 'fish'" class="fa fa-caret-down"></span>
          Fish Type
          </a>
        </td>
        <td>
          <a href="#" ng-click="sortType = 'tastiness'">
          <span ng-show="sortType == 'tastiness'" class="fa fa-caret-down"></span>
          Taste Level
          </a>
        </td>
      </tr>
    </thead>
...

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

Изменение порядка сортировки

Следующим шагом будет добавление возможности изменять направление сортировки, так что бы пользователи могли сортировать таблицу по возрастанию или по убыванию. У фильтра orderBy есть третий параметр reverse. Мы просто должны передать true или false, чтобы изменить порядок сортировки. Сейчас значение false, так как мы инциализировали переменную $scope.sortReverse. Мы добавим возможность менять направление сортировки:

...
    <a href="#" ng-click="sortType = 'name'; sortReverse = !sortReverse">
...

Теперь, если вы кликните по заголовку, вы увидите изменение порядка сортировки. Давайте добавим знак направления сортировки, для большей наглядности. Мы добавим иконки вверх и вниз, а затем использовать ngShow и ngHide, чтобы показать и скрыть их. Вот как будет выглядеть одна из ссылок:

...
    <td>
      <a href="#" ng-click="sortType = 'name'; sortReverse = !sortReverse">
        Sushi Roll
        <span ng-show="sortType == 'name' && !sortReverse" class="fa fa-caret-down"></span>
        <span ng-show="sortType == 'name' && sortReverse" class="fa fa-caret-up"></span>
      </a>
    </td>
...

Фильтрация таблицы

Фильтрация данных в ng-repeat довольно легко, так как у Angular есть модуль фильтра. Есть только две вещи, которые мы должны сделать здесь: создать форму и применить переменную формы в ng-repeat. Давайте создадим форму:

  <form>
    <div class="form-group">
      <div class="input-group">
        <div class="input-group-addon"><i class="fa fa-search"></i></div>
        <input type="text" class="form-control" placeholder="Search da Fish" ng-model="searchFish">
      </div>
    </div>
  </form>

Это обычная Bootstrap форма. Основное тут это ng-model="searchFish" нашего input. searchFish мы будем использовать при фильтрации:

<!-- index.html -->
...
    <tr ng-repeat="roll in sushi | orderBy:sortType:sortReverse | filter:searchFish">
...

Так наш фильтр будет применен к таблице. Вы также заметите, что orderBy и filter будет работать вместе.

7661

Вывод.

Используя встроенные инструменты Angular, такие как ngRepeat, OrderBy, filter, ngClick и ngShow, мы смогли создать функциональную и быструю таблицу данных. Это один из примеров, когда Angular помогает в создании некоторой функциональности в приложения без лишних затрат.

11 классных шрифтов иконок для ваших проектов

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

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

Это очень важные и ключевые преимущества.

Как использовать иконки шрифтов

Все, что вам нужно сделать, это загрузить CSS файл, и все уже готово!

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

<!-- подключаем css файл -->
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<!-- используем шрифт иконок с помощью классов -->
<i class="ti-fire"></i>
<span class="ti-user"></span>

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

FontAwesome

fontawesoek-905x500[1]
image-934

Themify Icons

themifyicons-905x500[1]
image-935

Foundation Icons

foundation-iconfonts-905x500[1]
image-936

Ionicons

ionicons-905x500[1]
image-937

Octicons

octicons-905x500[1]
image-938

Linecons

linecons-905x500[1]
image-939

Open Iconic

openiconic-905x500[1]
image-940

Entypo

entypo-905x500[1]
image-941

JustVector

justvectoricons-905x500[1]
image-942

SVG Icons

svgfonts-905x500[1]
image-943

Payment Icons

paymentfonticons-905x500[1]
image-944

Вывод.

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

CSS эффекты нажатия

Набор эффектов нажатия мыши, или сенсорных взаимодействий. Эффекты сделано с CSS-анимацией в основном на псевдо-элементах.

Демо / Исходники

ClickEffect[1]
image-925

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

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

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

IE10, похоже, не поддерживает animationend на псевдо-элементах.

Для демонстрации мы используем значки шрифта Awesome и вызываем эффект на кнопке:

<button class="cbutton cbutton--effect-boris">
	<i class="cbutton__icon fa fa-fw fa-play"></i>
	<span class="cbutton__text">Play</span>
</button>

Кнопки имеют следующий общий стиль:

.cbutton {
	position: relative;
	display: inline-block;
	margin: 1em;
	padding: 0;
	border: none;
	background: none;
	color: #286aab;
	font-size: 1.4em;
	transition: color 0.7s;
}
.cbutton.cbutton--click,
.cbutton:focus {
	outline: none;
	color: #3c8ddc;
}
.cbutton__icon {
	display: block;
}
.cbutton__text {
	position: absolute;
	opacity: 0;
	pointer-events: none;
}
.cbutton::after {
	content: '';
	position: absolute;
	top: 50%;
	left: 50%;
	margin: -35px 0 0 -35px;
	width: 70px;
	height: 70px;
	border-radius: 50%;
	opacity: 0;
	pointer-events: none;
}

При добавлении класса с помощью JavaScript мы вызываем анимацию:

/* Effect Boris */
.cbutton--effect-boris::after {
	background: rgba(111,148,182,0.1);
}
.cbutton--effect-boris.cbutton--click::after {
	animation: anim-effect-boris 0.3s forwards;
}
@keyframes anim-effect-boris {
	0% {
		transform: scale3d(0.3, 0.3, 1);
	}
	25%, 50% {
		opacity: 1;
	}
	100% {
		opacity: 0;
		transform: scale3d(1.2, 1.2, 1);
	}
}

Вот один из эффектов:

ClickEffect[1]
image-926

Для эффекта «Stana», мы используем переход на SVG clipPath, так что работает он только в Chrome на данный момент.

ClickEffect2[1]
image-927

Надеемся, вам понравится эти эффекты.

Демо / Исходники

Продвинутые концепции Flask

flask
image-888

Введение — приложение, которое можно масштабировать.

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

Существует два тесно связанных понятий связанных с масштабированием — как влияет на приложение увеличение числа пользователей и как влияет на разработку приложения увеличение числа программистов. Эти проблемы являются центральными в разработке программного обеспечения. Центральные вопросы: Как мы эффективно будем работать в командах 20 разработчиков, 40 разработчиков, или даже тысячи? И как нам справиться с максимальной нагрузки на нашей системе?

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

Масштабирование кодовой базы

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

Есть некоторые идеи которые можно использовать при проектировании  кода:

  1. Модульность
  2. Слабосвязанный код лучше, чем тесно связанный (обычно)
  3. Используйте комментарии
  4. Повторно используйте код, как можно чаще
  5. Пишете код, который является как можно более общим
  6. Тестируйте так часто, как это возможно, и на уровне модуля и на уровень системы
  7. Дайте себе достаточно времени, чтобы добиться своей цели, и затем останьтесь в рамках бюджета
  8. Сотрудничество является крайне важным

Следует отметить, что все из перечисленных выше пунктов, не будут рассмотрены в этой статье; Пункты 6 — 8 будет в значительной степени игнорироваться.

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

  1. Сервер для обслуживания страниц. — конкретно
  2. База данных для хранения данных пользователей. — конкретно
  3. Способ входа активных пользователей, и взаимодействия с ними. — расплывчато
  4. Система управления контентом для администратора сайта, для обновления сайта. — конкретно
  5. Способ взаимодействовать с сообществом которое мы разрабатываем. — расплывчато
  6. RSS фиды — конкретно
  7. Способ централизованного управления нашей социальной наличием. — конкретно
  8. Поддержка видео контента. — конкретно

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

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

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

  1. Таблица базы данных регистрации пользователей в нашей системе.
  2. Функция или набор функций, которые необходимо работы с пользователями.

Способ взаимодействовать с сообществом которое мы разрабатываем. Можно разделить на:

  1. Форум для обсуждения тем
  2. Раздел комментарий после каждого поста в блоге.
  3. Обратная связь и контакты для связи с администрацией сайта

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

Что мы получаем с Flask

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

База данных — Flask поставляется с SQLite, но есть и много других вариантов.

Вход пользователей? Мы должны создать эту функциональность в нашем приложении.

То, что мы должны написать:

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

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

RSS — мы создадим это в его собственном разделе приложения.

Почтовый клиент — мы должны создать тоже с нуля.

Имея свой дизайн настроен, как правило, сэкономить время. В этом примере, зная доска объявлений и CMS потребуется некоторое повторное использование кода, необходимо сохранить какое-то время.

Blue prints (эскизы)

Так что мы идем вперед и создаем пять раздельных приложений, и код будет повторятся в каких то местах? Конечно нет! Эскизы позволяют создать одно большое приложение, работающее с несколькими приложениями одновременно. Благодаря этому увеличивается модульность приложения и в целом облегчит разработку. Это также делают ваш код более отказоустойчивым. Это означает, что когда часть вашего кода не работает, будет легче найти причину, и у вас будете меньше ошибок (потому что у вас есть куча небольших приложений вместо одного очень большого).

Настройка нашего проекта

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

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

Структура каталога:

run.py
/slavery_website/
    __init__.py
    blog/
        __init__.py
        static/
        templates/
        views.py
        models.py
    cms/
        __init__.py
        static/
        templates/
        views.py
        models.py
    email_client/
        __init__.py
        static/
        templates/
        views.py
        models.py
    feeder/
        __init__.py
        static/
        templates/
        views.py
        models.py
    logger/
        __init__.py
        static/
        templates/
        views.py
        models.py
    message_board/
        __init__.py
        static/
        templates/
        views.py
        models.py

Некоторые из views.py файлов

cms/views.py

from flask import Blueprint, render_template
from models import *
cms = Blueprint("cms",__name__,template_folder='templates')
@cms.route("/add",methods=["GET","POST"])
def add():
    return render_template("admin.html")
@cms.route("/remove",methods=["GET","POST"])
def remove():
    return render_template("admin.html")
@cms.route("/view_entries",methods=["GET","POST"])
def view_entries():
    entries = get_entries()
    return render_template("entries.html",entries=entries)

logger/views.py

from flask import Blueprint, render_template
from models import *
logger = Blueprint('logger',__name__,template_folder="templates")
@logger.route("/analytics/page_views",methods=["GET","POST"])
def page_views():
    pages = get_page_views()
    return render_template("viewer.html",pages=pages)
@logger.route("/analytics/button_press", methods=["GET","POST"])
def button_press():
    buttons = get_button_press()
    return render_template("viewer.html",buttons=buttons)
**Some functions snipped**

slavery_website/init.py:

from flask import Flask
from cms.views import cms
from logger.views import logger
app = Flask(__name__)
app.register_blueprint(cms, url_prefix='/admin')
app.register_blueprint(logger,url_prefix='/analytics')

Основы AngularJS (шпаргалка) Часть 1

angular[1]
image-885

Настройка и установка

Устанавливать будем с помощью bower, так как ним очень удобно устанавливать дополнения для angular. Настройка каталога для .bowerrc (настройка не обязательная, я использую для смены стандартной директории установки компонентов)

{
  "directory": "components/",
  "analytics": false,
  "timeout": 120000,
  "registry": {
    "search": [
      "http://localhost:8000",
      "https://bower.herokuapp.com"
    ]
  }
}

Инициализация bower и установка angular с сохранением в конфигурации

bower init
bower install angular --save

Подключаем к шаблону.

<html ng-app>
 <head>
 </head>
 <body>
   //основная часть с директивами angular
   <script src="/путь/до/angular.js"></script>
   <script src="/путь/до/script.js"></script>
   </body>
</html>

Обертка

{{ 'Привет' }}
{{ 'Привет' + myVar }}
{{ 3 + 5 }}
<input type="text" ng-model="data.message">
<h1>{{ data.message }}</h1>

Контроллер

Добавляем в шаблоне директивы ng-app и ng-controller

<html ng-app="myApp">
 <head>
 </head>
 <body ng-controlle="FirstCtrl">
   <input type="text" ng=model="data.message">
   <h1>{{ data.message }}</h1>
   <script src="/путь/до/angular.js"></script>
   <script src="/путь/до/main.js"></script>
   </body>
</html>

main.js

var app = angular.module('myApp', [])
app.controller('FirstCctrl', function($scope){
   $scope.data = {message:'Hello'}
});

Обмен данными между контроллерами

Создаем два контроллера FirstCtrl и SecondCtrl.

<html ng-app="myApp">
 <head>
 </head>
 <body>
	<div ng-controller="FirstCtrl">
	    <h1>{{ data.message }}</h1>
	</div>
	<div ng-controller="SecondCtrl">
	    <h1>{{ data.message }}</h1>
	</div>
   <script src="/путь/до/angular.js"></script>
   <script src="/путь/до/main.js"></script>
   </body>
</html>

main.js

var app = angular.module('myApp', []);
app.factory('Data', function(){
	return {message: 'Message'}
});
app.controller('FirstCtrl', function ($scope, Data){
	$scope.data = Data
});
app.controller('SecondCtrl', function($scope, Data){
	$scope.data = Data
});

Добавление методов в scope

Добавим новый метод reversedMessage() (он будет переворачивать текст)

<html ng-app="myApp">
 <head>
 </head>
 <body>
	<div ng-controller="FirstCtrl">
	    <h1>{{ data.message }}</h1>
            <h3>{{ reversedMessage() }}</h3>
	</div>
   <script src="/путь/до/angular.js"></script>
   <script src="/путь/до/main.js"></script>
   </body>
</html>

main.js

var app = angular.module('myApp', []);
app.controller('FirstCtrl', function ($scope){
	$scope.data = {message: 'Привет'};
	$scope.reversedMessage = function(){
            return $scope.data.message.split("").reverse().join("");
	}
});

Фильтр

Добавим фильтр reverse который будет делать то же самое что и предыдущий метод

<html ng-app="myApp">
 <head>
 </head>
 <body>
	<div ng-controller="FirstCtrl">
	    <h1>{{ data.message }}</h1>
            <h3>{{ data.message|reverse }}</h3>
	</div>
   <script src="/путь/до/angular.js"></script>
   <script src="/путь/до/main.js"></script>
   </body>
</html>

main.js

var app = angular.module('myApp', []);
app.filter('reverse', function(Data){
	return function(text){
		return text.split("").reverse().join("") + " " + Data.message;
	}
});
app.controller('FirstCtrl', function ($scope){
	$scope.data = {message:'Текст'};
});

ngFiltr

В main.js создадим объект Avengers

var app = angular.module('myApp', []);
app.factory('Avengers', function () {
    var Avengers = {};
    Avengers.cast = [
        {
            name: 'Roma',
            character: 'Rdfvbbdf'
        },
        {
            name: 'Sasha',
            character: 'SDFSDffsdfsd'
        },
        {
            name: 'Tanya',
            character: 'Sdfvds'
        }
    ];
    return Avengers;
});
app.controller('AvengersCtrl', function($scope, Avengers){
    $scope.avengers = Avengers;
});

Выводим в таблице все значения и фильтруем их с помощью search.

<html ng-app="myApp">
 <head>
 </head>
 <body>
        <div ng-controller="AvengersCtrl">
            <input type="text" ng-model="search"/>
            <table>
                <tr ng-repeat="actor in avengers.cast | filter: search">
                    <td>{{ actor.name }}</td>
                    <td>{{ actor.character }}</td>
                </tr>
            </table>
        </div>
   <script src="/путь/до/angular.js"></script>
   <script src="/путь/до/main.js"></script>
   </body>
</html>

Так же можно фильтровать только по name(ng-model="search.name"), по character(ng-model="search.character") или по обоим сразу(ng-model=»search.$»)

Встроенные фильтры

В main.js без изменений

var app = angular.module('myApp', []);
app.factory('Avengers', function () {
    var Avengers = {};
    Avengers.cast = [
        {
            name: 'Roma',
            character: 'Rdfvbbdf'
        },
        {
            name: 'Sasha',
            character: 'SDFSDffsdfsd'
        },
        {
            name: 'Tanya',
            character: 'Sdfvds'
        }
    ];
    return Avengers;
});
app.controller('AvengersCtrl', function($scope, Avengers){
    $scope.avengers = Avengers;
});

Выводим в таблице все значения и фильтруем их с помощью search.

<html ng-app="myApp">
 <head>
 </head>
 <body>
        <div ng-controller="AvengersCtrl">
            <input type="text" ng-model="search"/>
            <table>
                <tr ng-repeat="actor in avengers.cast | orderBy: 'name'">
                    <td>{{ actor.name }}</td>
                    <td>{{ actor.character }}</td>
                </tr>
            </table>
        </div>
   <script src="/путь/до/angular.js"></script>
   <script src="/путь/до/main.js"></script>
   </body>
</html>

Отсортирует по полю name. Возможные варианты:

orderBy: 'name' сортировка по полю name
orderBy: '-name' обратная сортировка по полю name
limitTo:5 первые пять элементов
limitTo:5 последние пять элементов
orderBy: 'name' | limitTo:5 | filter:search несколько фильтров одновременно

Вывод относительного времени в Angular

angular
image-906

Вывод относительного времени стало популярным в последние несколько лет. Это можно увидеть в социальных сетях, таких как Twitter, Facebook и vk.

Например, вместо того, чтобы отображать время записи, как 8:12, время будет отображаться как 3 часа назад.

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

Пакеты

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

Пакет, который поможет нам отображать относительное время — angular-moment. Этот пакет использует библиотеку MomentJS. Если вы не использовали библиотеку раньше, посмотрите ее; она может помочь со всеми видами скриптов, в которых вам приходится работать с датой и временем в JavaScript.

Установка

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

Все, что мы должны сделать, это добавить следующие строки в нашем проекте:

<!-- подключаем angular -->
<script src='//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js'>
<!-- загрузка momentJS (необходим для angular-moment) -->
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.9.0/moment.min.js"></script>
<!-- загрузка angular-moment -->
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-moment/0.9.0/angular-moment.min.js"></script>
<!-- подключаем языковой файл vjventjs, нужен для русского языка -->
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.9.0/locales.js"></script>

Модель

А нас будет следующий код модуля:

// создание angular приложения
angular.module('timeApp', ['angularMoment'])
// создание angular контроллера
.controller('mainController', function() {
  // связь контроллера с vm (вид-модель)
  var vm = this;
  //устанавливаем русский язык
  moment.locale('ru');
  // создание новой временной переменной с текущей датой
  vm.time = new Date();
});

Мы создали новую переменную времени с использованием new Date(). Вы можете передать дату и время в Date(), чтобы конвертировать ее в объект даты. Наши данные и Angular приложение готово, теперь перейдем к HTML разметке, чтобы увидеть, как мы можем вывести переменную vm.time для наших пользователей.

Вид

Мы должны применить Angular модуль (timeApp) и контроллер (mainController) в нашем приложении:

<!-- добавим наше приложение(модуль) и контроллер-->
<div class="container" ng-app="timeApp" ng-controller="mainController as main">
  <div class="jumbotron">
    <p>Время: {{ main.time }}</p>
  </div>
</div>

7661

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

Методы использования этого пакета

Относительное время — Директива

<time am-time-ago="main.time"></time>

Директива am-time-ago будет автоматически обновлять значение времени. Когда вы первый раз увидите ее, вы увидите несколько секунд назад. Если вы подождете, вы увидите 3 минут назад и тд.

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

Формат даты — Фильтр

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

<time>{{ main.time | amDateFormat: 'dddd, MMMM Do YYYY, h:mm a' }}</time>

Календарный Формат — Фильтр

Третий способ, которым вы можете использовать это календарный формат.

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

<time>{{ main.time | amCalendar }}</time>

Хорошая практика

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

Хорошей практикой при использовании относительного времени, использование title в ваших тегах, так что пользователь имели возможность видеть точное время при наведении мыши.

<time title="{{ main.time | amDateFormat: 'dddd, MMMM Do YYYY, h:mm a' }}">{{ main.time | amCalendar }}</time>

Демо

7661

Вывод

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

ООП и Python

За и против использования ООП в Python. Как решить нужно ли помещать код в класс или функций достаточно. Как применять классические принципы ООП к Python.

Защита маршрутов в AngularJS

angular
image-879

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

var loginRequired = function($location, $q) {
    var deferred = $q.defer();
    if(! userIsAuthenticated()) {
        deferred.reject()
        $location.path('/login');
    } else {
        deferred.resolve()
    }
    return deferred.promise;
}

И добавьте эту функцию, в маршруты которые требуется проверка подлинности

app.config(['$locationProvider', '$routeProvider',
    function($location, $routeProvider) {
        $routeProvider.
            when('/todos', {
                templateUrl: '/js/templates/todos/index.html',
                controller: 'TodoCtrl',
                resolve: { loginRequired: loginRequired }
            });
    }
]);

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

var redirectIfAuthenticated = function(route) {
    return function($location, $q) {
        var deferred = $q.defer();
        if (userIsAuthenticated()) {
            deferred.reject()
            $location.path(route);
        } else {
            deferred.resolve()
        }
        return deferred.promise;
    }
}
app.config(['$locationProvider', '$routeProvider',
    function($location, $routeProvider) {
        $routeProvider.
            when('/login', {
                templateUrl: '/js/templates/login.html',
                controller: 'UserCtrl',
                resolve: { redirectIfAuthenticated: redirectIfAuthenticated('/todos') }
            }).
            when('/todos', {
                templateUrl: '/js/templates/todos/index.html',
                controller: 'TodoCtrl',
                resolve: { loginRequired: loginRequired }
            });
    }
]);

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

Использование React.js для рисования SVG

reactjs-logo-thumb
image-869

Масштабируемая векторная графика (Scalable Vector Graphics — SVG) являются отличным способом, чтобы включить векторную графики на веб-странице. Они легкие, на основе XML, и поддерживаются почти всеми современными браузерами. Так как они на основе XML, они состоят из разметки, и могут(в теории, по крайней мере) создавать все то, что может создавать корректные XML-разметки. Это включает в себя и JavaScript библиотеку, пользовательского интерфейса, React.js.

Введение

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

var SVGComponent = React.createClass({
    render: function() {
        return this.transferPropsTo(
            <svg>{this.props.children}</svg>
        );
    }
});
React.renderComponent(
    <SVGComponent height="50" width="50" />,
    document.getElementById('svg_mount_example')
);

Так мы получили svg элемент 50 на 50, он находится ниже, можете посмотреть его через «Просмотр кода элемента»

Это обычный пустой SVG элемент.

Основные формы

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

var Rectangle = React.createClass({
    render: function() {
        return this.transferPropsTo(
            <rect>{this.props.children}</rect>
        );
    }
});
React.renderComponent(
    <SVGComponent height="100" width="100">
        <Rectangle height="50" width="50" x="25" y="25" />
    </SVGComponent>,
    document.getElementById('svg_rectangle')
);

Круги

var Circle = React.createClass({
    render: function() {
        return this.transferPropsTo(
            <circle>{this.props.children}</circle>
        );
    }
});
React.renderComponent(
    <SVGComponent height="100" width="100">
        <Circle cx="50" cy="50" r="25" />
    </SVGComponent>,
    document.getElementById('svg_circle')
);

Эллипсы

var Ellipse = React.createClass({
    render: function() {
        return this.transferPropsTo(
            <ellipse>{this.props.children}</ellipse>
        );
    }
});
React.renderComponent(
    <SVGComponent height="100" width="100">
        <Ellipse cx="50" cy="50" rx="25" ry="15" />
    </SVGComponent>,
    document.getElementById('svg_ellipse')
);

Работа с цветами

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

Два наиболее полезных параметров SVG цвета являются:

      fill: интерьер цвет формы
      stroke: цвет линии, образующей наружную форму

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

React.renderComponent(
    <SVGComponent height="100" width="230">
        <Circle
            cx="50" cy="50" r="25"
            fill="mediumorchid" />
        <Circle
            cx="125" cy="50" r="25"
            fill="#ff0099" />
        <Circle
            cx="200" cy="50" r="25"
            fill="none"
            stroke="crimson" />
    </SVGComponent>,
    document.getElementById('svg_colors')
);

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

Линии

Прямые линии

var Line = React.createClass({
    render: function() {
        return this.transferPropsTo(
            <line>{this.props.children}</line>
        );
    }
});
React.renderComponent(
    <SVGComponent height="100" width="100">
        <Line x1="25" y1="25" x2="75" y2="75"
            strokeWidth="5"
            stroke="orange" />
    </SVGComponent>,
    document.getElementById('svg_straight_line')
);

Ломанные линии

var Polyline = React.createClass({
    render: function() {
        return this.transferPropsTo(
            <polyline>{this.props.children}</polyline>
        );
    }
});
React.renderComponent(
    <SVGComponent height="100" width="100">
        <Polyline
            points="25,25 25,75 50,75 50,50 75,25"
            strokeWidth="5"
            stroke="orange"
            fill="none" />
    </SVGComponent>,
    document.getElementById('svg_polyline')
);