Twitter Flight
Цитркоп Алексей. Разработчик 7bits.
Надо писать JavaScript
формы
таблицы
таблицы с пагинацией
лоадеры
графики
3
Проблемы
Спагетти код
4
Спагетти код
1 var fnGetSearchForm;
2 var fnGetSearchFormQuery;
3 var fnGetSearcheable;
4 var searcheableSelector;
5 var paginatableSelector;
6 var pagingContainerSelector;
7 var fnGetPaginatable;
8 var fnGetPaginatableContainer;
9 var fnGetPagingInfo;
10 var sortableSelector;
11 var sortableContainerSelector;
12 var fnGetSortingOrder;
13 var fnGetSortableContainer;
14 var fnGetSortableElementsNotBoth;
15 var fnInsertTableRows;
16 var fnGetMetaFieldsCodes;
17 var fnAddColumnsHtml;
18 var sortColumnCode = 'data-sort-code';
19 var tableSelector = '[data-table="true"]';
20 var tableWithMarkableRowsSelector = '[data-
table-with-markable-rows="true"]';
21 var sortableColumnSelector =
sortableContainerSelector + ' thead ' +
sortableSelector;
22 var rowSelectedClass = 'selected-row';
23 var dataRowMarkerAttr = 'data-row-
marker="true"';
24 var checkboxRowMarkerSelector = '[' +
dataRowMarkerAttr + ']';
25 var dataMetaFieldCode = 'data-meta-field-code';
26 var dataFromMetaField = 'data-from';
27 var dataToMetaField = 'data-to';
28 var dataPrimaryMetaField = 'data-primary';
29 var toggleAllInPageSelector = '[data-check-
type="toggle-all-in-page"]:first';
30 var dataTableFilterRowAttributes = 'data-filter-
row-attributes';
31 var dataFilterUrl = 'data-filter-url';
32 var dataTableFilterAdditionalRequestParams =
'data-filter-additional-request-params';
33 var dataTableFilterResponseJsonPart = 'data-
filter-response-json-part';
34 var dataTableRawObjectCode = 'data-object-raw-
code';
35 var mainTable = '[data-main-table="true"]';
36 var searchFormSelector = '[data-search-
component="form"]:first';
37 var editButtonSelector = '.edit-set-btn:first';
38 var dataObjectId = 'data-object-id';
39 ….
5
Решение № 1.
Свой велосипед
придумать правила
рассказать команде
рассказать новичку
написать документацию
написать свой framework
6
Angular
модный
большое комьюнити
много функций
Решение № 2.
7
Angular
используем малый процент функционала
навязывание своей архитектуры
кто-то замечает тормоза
гадит в шаблоны
боль с подлючением jquery плагинов
для single page
8
с Angular
.form-group.row.ng-cloak{:'ng-class' => "(portfolioForm.desired_return.$error.invalid ||
errors.desired_return[0] || portfolioForm.desired_return.$error.min ||
portfolioForm.desired_return.$error.max) ? 'has-error' : ''", 'ng-if' => "portfolio.algorithm
== 'algorithm_name'"}
%label.control-label.col-xs-12.col-sm-3.no-padding-right{:for => "form-field-2"}
Desired return:
.col-xs-12.col-sm-9
.clearfix
%input{'integer-validation' => "", :max => '99', :min => '1', :'required' => "", :type =>
"number", :id => "form-field-2", :class => "col-xs-4 col-sm-2", :step => "any", :'ng-model' =>
'portfolio.desired_return', :'name' => 'desired_return'}
%span.help-button{:popover => "{}", :'data-rel' => "popover", :'data-trigger' => "hover",
:'data-placement' => "right", :'data-content' => "help text", :title => "", :'data-original-
title' => '' }?
9
без Angular
.form-group.row.js-field-wrap.js-desired-return-wrap
%label.control-label.col-xs-12.col-sm-3.no-padding-right{:for => "form-field-2"}
Desired return:
.col-xs-12.col-sm-9
.clearfix
%input{ :type => "text", :id => "form-field-2", :class => "col-xs-4 col-sm-2", :'name' =>
'desired_return'}
%span.help-button{:popover => "{}", :'data-rel' => "popover", :'data-trigger' => "hover",
:'data-placement'=>"right", :'data-content' => "help text", :title=> "", :'data-original-title'
=>'' }?
.help-inline-block.col-xs-12.col-sm-reset.js-field-error.js-desired_return-error-wrap
10
Решение № 3.
Twitter Flight
легкий ( 5кб )
не навязывает свою архитектуру
низкий порог вхождения
event-based
11
Философия
компоненты
миксины
12
Компоненты
независимы
общаются исключительно событиями
набор атрибутов
набор функций
13
1 window.formComponentUI = flight.component(
2 function() {
3 this.defaultAttrs({
4 errorFieldSelector: '.js-field-error'
5 });
6 this.showErrors = function(formErrors) {
7 var that = this;
8 for (var name in formErrors) {
9 that.$node.find('.js-' + name + '-error').html(formErrors[name]);
10 }
11 };
12 this.hideErrors = function() {
13 this.select('errorFieldSelector').empty();
14 };
15 this.after('initialize', function() {
16 this.on('submit-done', this.hideErrors);
17 this.on('submit-form', this.hideErrors);
18 this.on('submit-error', function(e, v){
19 this.showErrors(v);
20 });
21 });
22 })
Компоненты
14
1 window.formComponents = flight.component(
2 window.loaderMixin,
3 window.showErrorsMixin,
4 window.formMixin,
5
6 function() {
7 this.after('initialize', function() {
8 this.on("form-load-data", this.showLoader);
9 this.on("form-load-data-done", this.hideLoader);
10 this.on("form-load-data-error", this.showErrors)
11 this.on("show-errors-done", this.hideLoader)
12 });
13 });
Компоненты
15
1 $(function() {
2 window.formComponentData.attachTo('.js-form');
3 window.formComponentUI.attachTo('.js-form');
4 window.relaodPageFormComponentUI.attachTo('.js-form-reload-page');
5 window.popupWindowComponentUI.attachTo('.js-popup-window');
6 window.messageInsteadFormComponentUI.attachTo('.js-show-message');
7 });
Компоненты
16
Миксины
утилитные методы
расширение компонентов
17
1 window.loadTableMixin = function() {
2 this.defaultAttrs({
3 tableSelector: '.table',
4 });
5
6 this.getPageTableData = function(url) {
7 var that = this;
8 $.getJSON(url, function(data) {
9 that.trigger('table-data-load-done', data);
10 });
11 };
12 };
Миксины
18
Файлы
до: после:
19
Выводы
подходит для стандартных задач
нет четких правил
низкий порог вхождения
20
flightjs.github.io
github.com/flightjs/flight
Спасибо за внимание

Стажировка-2015. Разработка. Занятие 14. Twitter Flight

  • 2.
    Twitter Flight Цитркоп Алексей.Разработчик 7bits.
  • 3.
    Надо писать JavaScript формы таблицы таблицыс пагинацией лоадеры графики 3
  • 4.
  • 5.
    Спагетти код 1 varfnGetSearchForm; 2 var fnGetSearchFormQuery; 3 var fnGetSearcheable; 4 var searcheableSelector; 5 var paginatableSelector; 6 var pagingContainerSelector; 7 var fnGetPaginatable; 8 var fnGetPaginatableContainer; 9 var fnGetPagingInfo; 10 var sortableSelector; 11 var sortableContainerSelector; 12 var fnGetSortingOrder; 13 var fnGetSortableContainer; 14 var fnGetSortableElementsNotBoth; 15 var fnInsertTableRows; 16 var fnGetMetaFieldsCodes; 17 var fnAddColumnsHtml; 18 var sortColumnCode = 'data-sort-code'; 19 var tableSelector = '[data-table="true"]'; 20 var tableWithMarkableRowsSelector = '[data- table-with-markable-rows="true"]'; 21 var sortableColumnSelector = sortableContainerSelector + ' thead ' + sortableSelector; 22 var rowSelectedClass = 'selected-row'; 23 var dataRowMarkerAttr = 'data-row- marker="true"'; 24 var checkboxRowMarkerSelector = '[' + dataRowMarkerAttr + ']'; 25 var dataMetaFieldCode = 'data-meta-field-code'; 26 var dataFromMetaField = 'data-from'; 27 var dataToMetaField = 'data-to'; 28 var dataPrimaryMetaField = 'data-primary'; 29 var toggleAllInPageSelector = '[data-check- type="toggle-all-in-page"]:first'; 30 var dataTableFilterRowAttributes = 'data-filter- row-attributes'; 31 var dataFilterUrl = 'data-filter-url'; 32 var dataTableFilterAdditionalRequestParams = 'data-filter-additional-request-params'; 33 var dataTableFilterResponseJsonPart = 'data- filter-response-json-part'; 34 var dataTableRawObjectCode = 'data-object-raw- code'; 35 var mainTable = '[data-main-table="true"]'; 36 var searchFormSelector = '[data-search- component="form"]:first'; 37 var editButtonSelector = '.edit-set-btn:first'; 38 var dataObjectId = 'data-object-id'; 39 …. 5
  • 6.
    Решение № 1. Свойвелосипед придумать правила рассказать команде рассказать новичку написать документацию написать свой framework 6
  • 7.
  • 8.
    Angular используем малый процентфункционала навязывание своей архитектуры кто-то замечает тормоза гадит в шаблоны боль с подлючением jquery плагинов для single page 8
  • 9.
    с Angular .form-group.row.ng-cloak{:'ng-class' =>"(portfolioForm.desired_return.$error.invalid || errors.desired_return[0] || portfolioForm.desired_return.$error.min || portfolioForm.desired_return.$error.max) ? 'has-error' : ''", 'ng-if' => "portfolio.algorithm == 'algorithm_name'"} %label.control-label.col-xs-12.col-sm-3.no-padding-right{:for => "form-field-2"} Desired return: .col-xs-12.col-sm-9 .clearfix %input{'integer-validation' => "", :max => '99', :min => '1', :'required' => "", :type => "number", :id => "form-field-2", :class => "col-xs-4 col-sm-2", :step => "any", :'ng-model' => 'portfolio.desired_return', :'name' => 'desired_return'} %span.help-button{:popover => "{}", :'data-rel' => "popover", :'data-trigger' => "hover", :'data-placement' => "right", :'data-content' => "help text", :title => "", :'data-original- title' => '' }? 9
  • 10.
    без Angular .form-group.row.js-field-wrap.js-desired-return-wrap %label.control-label.col-xs-12.col-sm-3.no-padding-right{:for =>"form-field-2"} Desired return: .col-xs-12.col-sm-9 .clearfix %input{ :type => "text", :id => "form-field-2", :class => "col-xs-4 col-sm-2", :'name' => 'desired_return'} %span.help-button{:popover => "{}", :'data-rel' => "popover", :'data-trigger' => "hover", :'data-placement'=>"right", :'data-content' => "help text", :title=> "", :'data-original-title' =>'' }? .help-inline-block.col-xs-12.col-sm-reset.js-field-error.js-desired_return-error-wrap 10
  • 11.
    Решение № 3. TwitterFlight легкий ( 5кб ) не навязывает свою архитектуру низкий порог вхождения event-based 11
  • 12.
  • 13.
  • 14.
    1 window.formComponentUI =flight.component( 2 function() { 3 this.defaultAttrs({ 4 errorFieldSelector: '.js-field-error' 5 }); 6 this.showErrors = function(formErrors) { 7 var that = this; 8 for (var name in formErrors) { 9 that.$node.find('.js-' + name + '-error').html(formErrors[name]); 10 } 11 }; 12 this.hideErrors = function() { 13 this.select('errorFieldSelector').empty(); 14 }; 15 this.after('initialize', function() { 16 this.on('submit-done', this.hideErrors); 17 this.on('submit-form', this.hideErrors); 18 this.on('submit-error', function(e, v){ 19 this.showErrors(v); 20 }); 21 }); 22 }) Компоненты 14
  • 15.
    1 window.formComponents =flight.component( 2 window.loaderMixin, 3 window.showErrorsMixin, 4 window.formMixin, 5 6 function() { 7 this.after('initialize', function() { 8 this.on("form-load-data", this.showLoader); 9 this.on("form-load-data-done", this.hideLoader); 10 this.on("form-load-data-error", this.showErrors) 11 this.on("show-errors-done", this.hideLoader) 12 }); 13 }); Компоненты 15
  • 16.
    1 $(function() { 2window.formComponentData.attachTo('.js-form'); 3 window.formComponentUI.attachTo('.js-form'); 4 window.relaodPageFormComponentUI.attachTo('.js-form-reload-page'); 5 window.popupWindowComponentUI.attachTo('.js-popup-window'); 6 window.messageInsteadFormComponentUI.attachTo('.js-show-message'); 7 }); Компоненты 16
  • 17.
  • 18.
    1 window.loadTableMixin =function() { 2 this.defaultAttrs({ 3 tableSelector: '.table', 4 }); 5 6 this.getPageTableData = function(url) { 7 var that = this; 8 $.getJSON(url, function(data) { 9 that.trigger('table-data-load-done', data); 10 }); 11 }; 12 }; Миксины 18
  • 19.
  • 20.
    Выводы подходит для стандартныхзадач нет четких правил низкий порог вхождения 20
  • 21.