(устаревшее) Basis.js introduction
-
Upload
basisjs -
Category
Technology
-
view
1.299 -
download
0
Transcript of (устаревшее) Basis.js introduction
![Page 1: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/1.jpg)
basis.jsРоман Дворнов
март 2013
![Page 2: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/2.jpg)
basis.js
Это javascript фреймворк
для построения
single-page приложений
2
![Page 3: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/3.jpg)
Назначение• Для создания больших легковесных приложений
• Собственный дизайн компонент и их поведение
• Часто меняются требования
• В планах есть локализация и адаптивность
• Быстрое прототипирование
3
![Page 4: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/4.jpg)
Модули
• basis.js + 55 модулей (~352 kb, +gzip = ~100kb)
o работа с данными
o работа с сетью
o браузерные API
o организация интерфейса
o компоненты
o ...
4
![Page 5: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/5.jpg)
Модули
5
![Page 6: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/6.jpg)
Основные модули
core
6
![Page 7: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/7.jpg)
Основные модули
core event
6
![Page 8: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/8.jpg)
Основные модули
core event data
6
![Page 9: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/9.jpg)
Основные модули
core event data DOM
6
![Page 10: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/10.jpg)
Основные модули
core event data DOM UI
6
![Page 11: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/11.jpg)
Основные модули
core event data DOM UI
entity dataset
6
![Page 12: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/12.jpg)
Основные модули
core event data DOM UI
entity dataset components
6
![Page 13: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/13.jpg)
Основные модули
core event data DOM UI
entity dataset
net
components
6
![Page 14: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/14.jpg)
Основные модули
core event data DOM UI
entity dataset
net l10n
components
6
![Page 15: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/15.jpg)
Основные модули
core event data DOM UI
entity dataset
net routerl10n
components
6
![Page 16: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/16.jpg)
Core (basis.js)
• Утилитарные функции• Конструирование классов
• Ресурсы• Пространства имен (namespace)
7
![Page 17: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/17.jpg)
Ресурсы
• Основа модульности• Ресурс - это некоторый файл
• Загрузка по требованию (lazy)
• Являются частью программы
8
![Page 18: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/18.jpg)
Для чего нужны ресурсы
• Разбить большое на меньшие части• Контент разного типа в отдельных файлах
• Раннее связывание - поздняя инициализания
9
![Page 19: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/19.jpg)
var text = basis.resource('some/file.txt');var popup = basis.resource('popup.js');
function showText(){ alert(text()); // или alert(text.fetch());}...showText();...popup.fetch().show(...)
Пример
10
![Page 20: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/20.jpg)
var module = { exports: {}};var relResource = function(path){ return basis.resource('path/to/' + path);};
(function(exports, module, basis, global, __filename, __dirname, resource){ "use strict";
}).call(module, module.exports, module, basis, global, 'path/to/file.js', 'path/to', relResource);
return module.exports;
Javascript ресурсы
var SomeClass = basis.Class(null, { ...});module.exports = { whatever: 'you want to export', maybe: function(){ ... }, SomeClass: SomeClass};
path/to/file.js
11
![Page 21: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/21.jpg)
Приложение –
управление данными и
интерфейс для этого
12
![Page 22: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/22.jpg)
basis.ui.Node
Основа интерфейса
Наследует от классов потомком большую часть
функционала, которые вносят ту или иную функцию
–
это похоже на слоеный пирог
13
![Page 23: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/23.jpg)
basis.event – cобытия
+
события
=
basis.event.Emitter
14
![Page 24: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/24.jpg)
basis.data – состояние
basis.event.Emitter
+
состояние
=
basis.data.AbstractData
15
![Page 25: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/25.jpg)
basis.data.AbstractData
+
данные
=
basis.data.Object
basis.data – данные
16
![Page 26: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/26.jpg)
basis.data.AbstractData
+
данные
=
basis.data.Object
basis.data – данные
Скаляры
16
![Page 27: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/27.jpg)
basis.data.AbstractData
+
данные
=
basis.data.Object
basis.data – данные
НаборыСкаляры
16
![Page 28: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/28.jpg)
basis.data.Object
+
DOM
=
basis.dom.wrapper.Node
basis.dom.wrapper – DOM
17
![Page 29: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/29.jpg)
basis.ui – шаблон
basis.dom.wrapper.Node
+
шаблон
=
basis.ui.Node
18
![Page 30: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/30.jpg)
Функциональные слои
19
![Page 31: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/31.jpg)
Функциональные слои
+события = basis.event.Emmiter
19
![Page 32: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/32.jpg)
Функциональные слои
+события = basis.event.Emmiter
+состояние = basis.data.AbstractData
19
![Page 33: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/33.jpg)
Функциональные слои
+события = basis.event.Emmiter
+состояние = basis.data.AbstractData
+данные = basis.data.Object
19
![Page 34: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/34.jpg)
Функциональные слои
+события = basis.event.Emmiter
+состояние = basis.data.AbstractData
+данные = basis.data.Object
+DOM = basis.dom.wrapper.Node
19
![Page 35: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/35.jpg)
Функциональные слои
+события = basis.event.Emmiter
+состояние = basis.data.AbstractData
+данные = basis.data.Object
+DOM = basis.dom.wrapper.Node
+шаблон = basis.ui.Node
19
![Page 36: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/36.jpg)
basis.ui.Node• Это и view, и model, и controller – все
зависит от того как он используется, какая у
него логика
• Имеет все необходимое, для построения интерфейса
• Легко расширить или изменить поведение
20
![Page 37: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/37.jpg)
basis.require('basis.ui');
var node = new basis.ui.Node({
container: document.body,
template: 'Hello world'
});
Hello world
21
![Page 38: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/38.jpg)
Шаблоны• xhtml-like формат
• logic less – нет условных операторов, нет циклов
• Есть специальные вставки – биндинги
• Есть специальные теги, для подключения стилей, уточнений, включения других шаблонов etc
22
![Page 39: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/39.jpg)
Пример
<b:style src="block.css"/>
<div{element} class="block block_{disabled}">
<h2>{title}</h2>
<ul>
<!--{childNodesHere}-->
</ul>
</div>
23
![Page 40: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/40.jpg)
Взаимодействие
24
ОбъектШаблон
(DOM fragment)
binding
action
Javascript
![Page 41: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/41.jpg)
binding – данные для шаблонаvar Item = basis.Class(basis.ui.Node, { template: resource('template.tmpl'), binding: { selected: { events: 'select unselect', getter: function(node){ return node.selected; } }, name: 'data:' }});
25
template.tmpl
<li event-click="item_{selected}">
{name}
</li>
![Page 42: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/42.jpg)
var button = new basis.ui.Node({ template: resource('button.tmpl'), action: { run: function(event){ // event.type == 'click' } }});
button.tmpl<button event-click="run">click me</button>
action - обратная связь
26
![Page 43: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/43.jpg)
Жизнь без циклов в шаблонахbasis.require('basis.ui');
var list = new basis.ui.Node({ template: resource('template/list.tmpl'), childClass: { template: resource('template/item.tmpl'), binding: { name: 'name' // function(node){ return node.name } } }, childNodes: [ { name: 'foo' }, // конфиг для childClass { name: 'bar' } ]});
27
![Page 44: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/44.jpg)
Шаблоныlist.tmpl<b:style src="list.css" /><div class="list"> My list: <ul{childNodesElement} /></div>
item.tmpl<b:style src="item.css" /><li class="list-item"> {name}</li>
28
![Page 45: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/45.jpg)
Сортировкаbasis.require('basis.ui');
var list = new basis.ui.Node({ ... sorting: 'name'});...list.setSorting(function(node){ return node.data.age;}, true);
29
![Page 46: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/46.jpg)
Группировкаbasis.require('basis.ui');var list = new basis.ui.Node({ ... grouping: { groupGetter: function(node){ return node.value; }, childClass: { template: resource('template/group.tmpl'), binding: { title: 'title' } } }});...list.setGrouping(...);
30
![Page 47: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/47.jpg)
Резюме• Разделение логики и представления• Нет селекторов, нет css классов и id в коде
(почти)
• Не манипулируем DOM напрямую, хотя такая возможность есть (пока)
• Структуру интерфейса и компонент мы контролируем в javascript
• По тексту шаблона ясно где и что будет• Шаблоны и css храним отдельно от javascript
31
![Page 48: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/48.jpg)
Что это дает• Live update шаблонов и стилей без перезагрузки страницы
• Шаблоны не могут сломать приложение (только верстку) – в них нет кода
• Мы можем находить несоответсвия в шаблонах и стилях, применять оптимизации при сборке
• А еще мы можем реализовать темы
32
![Page 49: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/49.jpg)
Темы• Это набор шаблонов и стилей к ним• Можно сделать совсем разные look & feel интерфейсы, которые имееют общую кодовую базу (javascript)
• Могут дополнять друг друга, например, тема для iOS, может дополнять мобильную – нет необходимости определять все шаблоны
• Можно переключать на лету
33
![Page 50: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/50.jpg)
Live update – это круто
34
![Page 51: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/51.jpg)
Data-flow• Различные объекты объединяются в функциональные цепочки, описывая бизнес логику
• Управление через события и состояние
• Делегирование – механизм “соединения” basis.data.Object, в результате чего они начинают разделять данные и состояние
• Подписка – механизм тригирования необходимости синхронизации данных
35
![Page 52: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/52.jpg)
Работа с данными• basis.data.entity – типизированные данные, вычисляемые поля, обращение по индексу, пользовательские изменения
• basis.data.dataset – автоматические наборы: слияние (объединение, пересечение, разница), подмножество, вычитание, разбиение и др.
• basis.data.index – агрегатные функции для наборов, вычисление отношений к агрегатам
36
![Page 53: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/53.jpg)
basis.net.request({
url: '/api/something',
handler: {
success: function(sender, data){ ... },
failure: function(sender, error){ ... }
}
});
net
37
![Page 54: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/54.jpg)
basis.net.request({
url: '/api/something',
handler: {
success: function(sender, data){ ... },
failure: function(sender, error){ ... }
}
});
Но это не наш метод
net
37
![Page 55: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/55.jpg)
var service = new basis.net.service.Service({ // настройки сервиса});...var User = basis.Class(basis.data.Object, { ... save: service.createAction({ url: '/api/user', success: function(transport, data){ ... }, ... })});...var user = new User(...);user.save();
net - наш метод
38
![Page 56: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/56.jpg)
net - наш метод• Service
o общие настройки
o работа с сессией
o подпись запросов
o обработка ошибок
• Action
o синхронизируют свое состояние с данными
o описывают наиболее частые сценарии
o предотвращают конкурентные запросы
39
![Page 57: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/57.jpg)
// настройка
basis.l10n.setCultureList(['ru-RU', 'en-US']);
basis.l10n.setCulture('ru-RU');
// создание словаря
basis.l10n.createDictionary('dict.namespace', 'path/to/dicts', {
key: 'value'
});
Локализация
40
![Page 58: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/58.jpg)
• в коде:basis.l10n.token('some.dict.key').value
binding: { title: basis.l10n.token('some.dict.key')}
• в шаблонах*<span>{l10n:some.dict.key}</span>
* чаще токены задаются через binding
Локализация
41
![Page 59: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/59.jpg)
Компоненты• Они есть :)• Реализованы наиболее часто используемые компоненты: кнопки, закладки, дерево, таблицы, окна, попапы и т.д.
• Нет смысла много про них говорить, т.к. большая часть их функционала предоставляется basis.ui.Node
• В основном используются на этапе прототипирования
42
![Page 60: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/60.jpg)
Инструменты
• devpanel
• консольный инструмент
• Google Chrome plugin
43
![Page 61: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/61.jpg)
• достаточно добавить в проект basis.require('basis.devpanel');
• позволяет менять тему и язык• обеспечивает API для выбора шаблонов и токенов переводов, которые используются плагином
• обеспечивает синхронизацию ресурсов на клиенте
devpanel
44
![Page 62: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/62.jpg)
basisjs-tools
• Написан на javascript, работает под управлением node.js
• Установка npm install -g basisjs-tools
• В консоли становиться доступна команда basis
45
![Page 63: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/63.jpg)
basis create• быстрое создание приложения, модуля и др. по шаблону
• хорошее подспорье, особенно на этапе прототипирования
• Создание приложения с базовой структурой:basis create app appname
• пока мало возможностей и шаблонов, но мы планируем добавить шаблоны для большинства частых кейсов
46
![Page 64: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/64.jpg)
basis server• выполняет роль http сервера
• создает кеш ресурсов, минимизируя количество запросов
• мониторит изменение в файлах, и уведомляет клиент об изменениях
• умеет проксировать запросы
47
![Page 65: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/65.jpg)
• Нет деклараций и списков файлов• На вход получает лишь индексный html файл, который анализируется, извлекают ссылки на другие файлы, которые обрабатываются так же – и так пока не будут найдены все файлы
• Для анализа файлы парсятся в AST
• Перелинковывает, реструктурирует, применяет различные оптимизации
• Понимает простые проекты, но проекты на basisjs понимает больше
basis build
48
![Page 66: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/66.jpg)
Google Chrome plugin
49
![Page 67: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/67.jpg)
Google Chrome plugin
49
![Page 68: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/68.jpg)
Google Chrome plugin
49
![Page 69: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/69.jpg)
Google Chrome plugin
49
![Page 70: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/70.jpg)
Google Chrome plugin
49
![Page 71: (устаревшее) Basis.js introduction](https://reader034.fdocuments.in/reader034/viewer/2022052619/55640eaad8b42aa9518b599d/html5/thumbnails/71.jpg)
Ссылки
• http://github.com/basisjs – исходники
• http://basisjs.com – сайт
• http://basisjs.com/tour – интерактивный тур
• http://basisjs.com/demo – демонстрации
• http://basisjs.com/docs – автодокументация
50