', {
56 | 'href': gitbook.state.basePath + '/' + res.url,
57 | 'text': res.title
58 | });
59 |
60 | var content = res.body.trim();
61 | if (content.length > MAX_DESCRIPTION_SIZE) {
62 | content = content.slice(0, MAX_DESCRIPTION_SIZE).trim()+'...';
63 | }
64 | var $content = $('').html(content);
65 |
66 | $link.appendTo($title);
67 | $title.appendTo($li);
68 | $content.appendTo($li);
69 | $li.appendTo($searchList);
70 | });
71 | }
72 |
73 | function launchSearch(q) {
74 | // Add class for loading
75 | $body.addClass('with-search');
76 | $body.addClass('search-loading');
77 |
78 | // Launch search query
79 | throttle(gitbook.search.query(q, 0, MAX_RESULTS)
80 | .then(function(results) {
81 | displayResults(results);
82 | })
83 | .always(function() {
84 | $body.removeClass('search-loading');
85 | }), 1000);
86 | }
87 |
88 | function closeSearch() {
89 | $body.removeClass('with-search');
90 | $bookSearchResults.removeClass('open');
91 | }
92 |
93 | function launchSearchFromQueryString() {
94 | var q = getParameterByName('q');
95 | if (q && q.length > 0) {
96 | // Update search input
97 | $searchInput.val(q);
98 |
99 | // Launch search
100 | launchSearch(q);
101 | }
102 | }
103 |
104 | function bindSearch() {
105 | // Bind DOM
106 | $searchInput = $('#book-search-input input');
107 | $bookSearchResults = $('#book-search-results');
108 | $searchList = $bookSearchResults.find('.search-results-list');
109 | $searchTitle = $bookSearchResults.find('.search-results-title');
110 | $searchResultsCount = $searchTitle.find('.search-results-count');
111 | $searchQuery = $searchTitle.find('.search-query');
112 |
113 | // Launch query based on input content
114 | function handleUpdate() {
115 | var q = $searchInput.val();
116 |
117 | if (q.length == 0) {
118 | closeSearch();
119 | }
120 | else {
121 | launchSearch(q);
122 | }
123 | }
124 |
125 | // Detect true content change in search input
126 | // Workaround for IE < 9
127 | var propertyChangeUnbound = false;
128 | $searchInput.on('propertychange', function(e) {
129 | if (e.originalEvent.propertyName == 'value') {
130 | handleUpdate();
131 | }
132 | });
133 |
134 | // HTML5 (IE9 & others)
135 | $searchInput.on('input', function(e) {
136 | // Unbind propertychange event for IE9+
137 | if (!propertyChangeUnbound) {
138 | $(this).unbind('propertychange');
139 | propertyChangeUnbound = true;
140 | }
141 |
142 | handleUpdate();
143 | });
144 |
145 | // Push to history on blur
146 | $searchInput.on('blur', function(e) {
147 | // Update history state
148 | if (usePushState) {
149 | var uri = updateQueryString('q', $(this).val());
150 | history.pushState({ path: uri }, null, uri);
151 | }
152 | });
153 | }
154 |
155 | gitbook.events.on('page.change', function() {
156 | bindSearch();
157 | closeSearch();
158 |
159 | // Launch search based on query parameter
160 | if (gitbook.search.isInitialized()) {
161 | launchSearchFromQueryString();
162 | }
163 | });
164 |
165 | gitbook.events.on('search.ready', function() {
166 | bindSearch();
167 |
168 | // Launch search from query param at start
169 | launchSearchFromQueryString();
170 | });
171 |
172 | function getParameterByName(name) {
173 | var url = window.location.href;
174 | name = name.replace(/[\[\]]/g, '\\$&');
175 | var regex = new RegExp('[?&]' + name + '(=([^]*)|&|#|$)', 'i'),
176 | results = regex.exec(url);
177 | if (!results) return null;
178 | if (!results[2]) return '';
179 | return decodeURIComponent(results[2].replace(/\+/g, ' '));
180 | }
181 |
182 | function updateQueryString(key, value) {
183 | value = encodeURIComponent(value);
184 |
185 | var url = window.location.href;
186 | var re = new RegExp('([?&])' + key + '=.*?(&|#|$)(.*)', 'gi'),
187 | hash;
188 |
189 | if (re.test(url)) {
190 | if (typeof value !== 'undefined' && value !== null)
191 | return url.replace(re, '$1' + key + '=' + value + '$2$3');
192 | else {
193 | hash = url.split('#');
194 | url = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, '');
195 | if (typeof hash[1] !== 'undefined' && hash[1] !== null)
196 | url += '#' + hash[1];
197 | return url;
198 | }
199 | }
200 | else {
201 | if (typeof value !== 'undefined' && value !== null) {
202 | var separator = url.indexOf('?') !== -1 ? '&' : '?';
203 | hash = url.split('#');
204 | url = hash[0] + separator + key + '=' + value;
205 | if (typeof hash[1] !== 'undefined' && hash[1] !== null)
206 | url += '#' + hash[1];
207 | return url;
208 | }
209 | else
210 | return url;
211 | }
212 | }
213 | });
214 |
--------------------------------------------------------------------------------
/docs/gitbook/gitbook-plugin-sharing/buttons.js:
--------------------------------------------------------------------------------
1 | require(['gitbook', 'jquery'], function(gitbook, $) {
2 | var SITES = {
3 | 'facebook': {
4 | 'label': 'Facebook',
5 | 'icon': 'fa fa-facebook',
6 | 'onClick': function(e) {
7 | e.preventDefault();
8 | window.open('http://www.facebook.com/sharer/sharer.php?s=100&p[url]='+encodeURIComponent(location.href));
9 | }
10 | },
11 | 'twitter': {
12 | 'label': 'Twitter',
13 | 'icon': 'fa fa-twitter',
14 | 'onClick': function(e) {
15 | e.preventDefault();
16 | window.open('http://twitter.com/home?status='+encodeURIComponent(document.title+' '+location.href));
17 | }
18 | },
19 | 'google': {
20 | 'label': 'Google+',
21 | 'icon': 'fa fa-google-plus',
22 | 'onClick': function(e) {
23 | e.preventDefault();
24 | window.open('https://plus.google.com/share?url='+encodeURIComponent(location.href));
25 | }
26 | },
27 | 'weibo': {
28 | 'label': 'Weibo',
29 | 'icon': 'fa fa-weibo',
30 | 'onClick': function(e) {
31 | e.preventDefault();
32 | window.open('http://service.weibo.com/share/share.php?content=utf-8&url='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title));
33 | }
34 | },
35 | 'instapaper': {
36 | 'label': 'Instapaper',
37 | 'icon': 'fa fa-instapaper',
38 | 'onClick': function(e) {
39 | e.preventDefault();
40 | window.open('http://www.instapaper.com/text?u='+encodeURIComponent(location.href));
41 | }
42 | },
43 | 'vk': {
44 | 'label': 'VK',
45 | 'icon': 'fa fa-vk',
46 | 'onClick': function(e) {
47 | e.preventDefault();
48 | window.open('http://vkontakte.ru/share.php?url='+encodeURIComponent(location.href));
49 | }
50 | }
51 | };
52 |
53 |
54 |
55 | gitbook.events.bind('start', function(e, config) {
56 | var opts = config.sharing;
57 |
58 | // Create dropdown menu
59 | var menu = $.map(opts.all, function(id) {
60 | var site = SITES[id];
61 |
62 | return {
63 | text: site.label,
64 | onClick: site.onClick
65 | };
66 | });
67 |
68 | // Create main button with dropdown
69 | if (menu.length > 0) {
70 | gitbook.toolbar.createButton({
71 | icon: 'fa fa-share-alt',
72 | label: 'Share',
73 | position: 'right',
74 | dropdown: [menu]
75 | });
76 | }
77 |
78 | // Direct actions to share
79 | $.each(SITES, function(sideId, site) {
80 | if (!opts[sideId]) return;
81 |
82 | gitbook.toolbar.createButton({
83 | icon: site.icon,
84 | label: site.text,
85 | position: 'right',
86 | onClick: site.onClick
87 | });
88 | });
89 | });
90 | });
91 |
--------------------------------------------------------------------------------
/docs/gitbook/images/apple-touch-icon-precomposed-152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cam-inc/riotx/387b5d0beb0cc4b69b19aa6f1a3634d773613709/docs/gitbook/images/apple-touch-icon-precomposed-152.png
--------------------------------------------------------------------------------
/docs/gitbook/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cam-inc/riotx/387b5d0beb0cc4b69b19aa6f1a3634d773613709/docs/gitbook/images/favicon.ico
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Choose a language · Riotx
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
Choose a language
52 |
53 |
54 |
55 | -
56 | English
57 |
58 |
59 | -
60 | 日本語
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/docs/ja/CATEGORY.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | カテゴリ · Riotx
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 | カテゴリ
375 | Riotxをカテゴリごとに紹介します。
376 |
383 | Riotxを利用するには、上記の理解が必要です。
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
results matching ""
393 |
394 |
395 |
396 |
397 |
398 |
No results matching ""
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
--------------------------------------------------------------------------------
/gitbook/LANGS.md:
--------------------------------------------------------------------------------
1 | * [English](en/)
2 | * [日本語](ja/)
3 |
4 |
5 |
--------------------------------------------------------------------------------
/gitbook/book.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Riotx",
3 | "gitbook": ">3.0.0",
4 | "plugins": ["github", "mermaid-gb3", "codepen"],
5 | "pluginsConfig": {
6 | "github": {
7 | "url": "https://github.com/cam-inc/riotx/"
8 | }
9 | },
10 | "links": {
11 | "sharing": {
12 | "facebook": false,
13 | "twitter": false
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/gitbook/en/0_x_1_x_DOCUMENTS.md:
--------------------------------------------------------------------------------
1 | # riotx
2 |
3 | Centralized State Management for riot.js
4 |
5 | A Simplistic Central Event Controller / Dispatcher For RiotJS, Inspired By [vuex](https://github.com/vuejs/vuex) Architecture Pattern.
6 |
7 | Riotx is a state management pattern + library for riot.js applications.
8 |
9 | 
10 |
11 | # Install
12 |
13 | ```
14 | $ npm install --save riotx
15 | ```
16 |
17 | # Example
18 |
19 | # index.html
20 |
21 | ```js
22 |
23 | Name: { name }
24 |
25 |
41 |
42 | ```
43 |
44 | ## index.js
45 |
46 | ```js
47 | let store = new riotx.Store({
48 | state: {
49 | name: "",
50 | },
51 | actions: {
52 | name: (context, name) => {
53 | return Promise
54 | .resolve()
55 | .then(() => {
56 | context.commit('name', {name});
57 | });
58 | }
59 | },
60 | mutations: {
61 | name: (context, obj) => {
62 | context.state.name = obj.name;
63 | return ['name'];
64 | }
65 | },
66 | getters: {
67 | name: context => {
68 | return context.state.name;
69 | }
70 | },
71 | plugins: [ /** ... */ ]
72 | });
73 |
74 | riotx.add(store);
75 |
76 | ```
77 |
78 | > More example to `./test`
79 |
80 | # Demo
81 |
82 | | Sample | Codepen |
83 | | :--: | :--: |
84 | | Increment(counter) |(https://codepen.io/fkei/pen/ybmNqN)|
85 |
86 | # Descriptions
87 |
88 | ## Riot(View) Components
89 |
90 | Custom tag of `riot.js`.
91 |
92 | > Inside a component, you can access `riotx` through `this.riotx`.
93 |
94 | ## Actions
95 |
96 | Logics and asynchronous processing like calling API should be implemented in Actions.
97 |
98 | Actions are entrypoints for riotx.
99 |
100 | ## Mutations
101 |
102 | `Mutations` mutate data in `State`.
103 |
104 | `mutations` are the only way to update `State`.
105 |
106 | You may need to trigger `change event` at the end of mutation.
107 |
108 | ## State
109 |
110 | Manages data.
111 |
112 | It is allowed to access `State` but you should always update `State` through `Mutations`.
113 |
114 | > Using `getter` you can get filtered data.
115 |
116 |
117 | ## Getters
118 |
119 | You can get filtered data of `State`.
120 |
121 | It is not allowed to mutate `State` through `Getters`.
122 |
123 |
124 |
125 | # API
126 |
127 | ## RiotX
128 |
129 | ### version: string
130 |
131 | returns Version number.
132 |
133 | ### setChangeBindName(name): riotX
134 |
135 | change the function name that is used to bind listeners for store change events.(default is `riotxChange`)
136 |
137 | ### add(store): Riotx
138 |
139 | register a store.
140 |
141 | registering multiple stores is allowed.
142 |
143 | @see `Store.name`
144 |
145 | ### get(name='@'): Store
146 |
147 | returns a store.
148 |
149 | ### debug(flag): Riotx
150 |
151 | returns the state of debugging mode. active or not.
152 |
153 | ### reset(): Riotx
154 |
155 | reset data.
156 |
157 | ### size(): int
158 |
159 | returns the total number of stores.
160 |
161 | # Store
162 |
163 | ### constructor(setting): Riotx
164 |
165 | a store setting.
166 |
167 | ```
168 | setting
169 | {
170 | name: string key(default='@', optional)
171 | actions: object key=string, value=function
172 | mutations: object key=string, value=function
173 | getters: object key=string, value=function
174 | }
175 | ```
176 |
177 | ### action(name, parameter...): Promise
178 |
179 | executes an action.
180 |
181 | ### getter(name, parameter...): ...
182 |
183 | executes a getter.
184 |
185 | ### riotxChange(name, parameter...): null
186 |
187 | starts listening to change events.
188 |
189 | # Develop
190 |
191 | ## Pre
192 |
193 | ```
194 | $ npm install .
195 | ```
196 |
197 | ## Launch Develop/Debug Environment.
198 |
199 | ```
200 | $ npm run karma-dev
201 | ```
202 |
203 | # npm target
204 |
205 | ## Test (karma/mocha)
206 |
207 | ```
208 | $ npm test
209 | ```
210 |
211 | > `Chrome` on Machine. custom to `test/karma/karma.conf.js`
212 |
213 | ## Test (require.js)
214 |
215 | [Read more](test/requirejs)
216 |
217 | ## Test (browserify)
218 |
219 | [Read more](test/browserify)
220 |
221 | ## Build and minify
222 |
223 | ```
224 | $ npm run build
225 | ```
226 |
227 | ## Watch
228 |
229 | ```
230 | $ npm run watch
231 | ```
232 |
233 | ## ESLint
234 |
235 | ```
236 | $ npm run lint
237 | ```
238 |
--------------------------------------------------------------------------------
/gitbook/en/README.md:
--------------------------------------------------------------------------------
1 | {% include "./SUMMARY.md" %}
2 |
--------------------------------------------------------------------------------
/gitbook/en/SUMMARY.md:
--------------------------------------------------------------------------------
1 | # 目次
2 |
3 | # Riotx
4 |
5 | - [Installation](../ja/INSTALLATION.md)
6 | - [Riotx introduce](../ja/INTRODUCE.md)
7 | - [Category](../ja/CATEGORY.md)
8 | - [State](../ja/STATE.md)
9 | - [Getters](../ja/GETTERS.md)
10 | - [Mutations](../ja/MUTATIONS.md)
11 | - [Actions](../ja/ACTIONS.md)
12 | - [Stores](../ja/STORES.md)
13 | - [Riotx](../ja/RIOTX.md)
14 | - [Plugins](../ja/PLUGINS.md)
15 | - [Testing](../ja/TESTING.md)
16 | - [API reference](../ja/APIS.md)
17 | - [Release notes](RELEASENOTES.md)
18 | - [Develop](DEVELOPS.md)
19 | - [0.x, 1.x documents](0_x_1_x_DOCUMENTS.md)
20 |
21 |
22 |
--------------------------------------------------------------------------------
/gitbook/ja/0_x_1_x_DOCUMENTS.md:
--------------------------------------------------------------------------------
1 | # riotx
2 |
3 | Centralized State Management for riot.js
4 |
5 | Riotxは、riot.jsアプリケーション用の状態管理パターン+ライブラリです。
6 |
7 | 
8 |
9 | # Install
10 |
11 | ```
12 | $ npm install --save riotx
13 | ```
14 |
15 | # Example
16 |
17 | # index.html
18 |
19 | ```html
20 |
21 | Name: { name }
22 |
23 |
39 |
40 | ```
41 |
42 | ## index.js
43 |
44 | ```js
45 | let store = new riotx.Store({
46 | state: {
47 | name: "",
48 | },
49 | actions: {
50 | name: (context, name) => {
51 | return Promise
52 | .resolve()
53 | .then(() => {
54 | context.commit('name', {name});
55 | });
56 | }
57 | },
58 | mutations: {
59 | name: (context, obj) => {
60 | context.state.name = obj.name;
61 | return ['name'];
62 | }
63 | },
64 | getters: {
65 | name: context => {
66 | return context.state.name;
67 | }
68 | },
69 | plugins: [ /** ... */ ]
70 | });
71 |
72 | riotx.add(store);
73 |
74 | ```
75 |
76 | > More example to `./test`
77 |
78 | # Demo
79 |
80 | | Sample | Codepen |
81 | | :--: | :--: |
82 | | Increment(counter) |(https://codepen.io/fkei/pen/ybmNqN)|
83 |
84 | # Descriptions
85 |
86 | ## Riot(View) Components
87 |
88 | `riot.js` のカスタムタグです。
89 |
90 | > Component内では、`this.riotx` で `riotx` にアクセス可能です。
91 |
92 |
93 | ## Actions
94 |
95 | API通信などの非同期処理、各種ロジックはActionに実装します。
96 |
97 | riotxの処理は、Actionを起点に始めてください。
98 |
99 |
100 | ## Mutations
101 |
102 | Actionで、行った処理を元に、`State` を更新します。
103 |
104 | `State`の更新は、`mutation` でのみ行われます。
105 |
106 | 処理の後に、`change event` を発火することができます。
107 |
108 | ## State
109 |
110 | 状態(データ)を管理します。
111 |
112 | 参照することは可能ですが、更新は `Mutations` からのみ行ってください。
113 |
114 | > フィルター取得は `getter` で行うことが可能です。
115 |
116 |
117 | ## Getters
118 |
119 | `State` の情報を加工して取得することができます。
120 |
121 | `State` の書き換えはできません。
122 |
123 | # API
124 |
125 | ## RiotX
126 |
127 | ### version: string
128 |
129 | Version取得
130 |
131 | ### setChangeBindName(name): riotX
132 |
133 | ストア監視用の関数名を設定します。(デフォルトは`riotxChange`)
134 |
135 | ### add(store): Riotx
136 |
137 | ストア登録
138 |
139 | 複数ストアを登録することができます。
140 |
141 | @see `Store.name`
142 |
143 | ### get(name='@'): Store
144 |
145 | ストア取得
146 |
147 | ### debug(flag): Riotx
148 |
149 | デバッグフラグ
150 |
151 | ### reset(): Riotx
152 |
153 | データリセット
154 |
155 | ### size(): int
156 |
157 | 管理ストア総数
158 |
159 | # Store
160 |
161 | ### constructor(setting): Riotx
162 |
163 | ストア定義
164 |
165 | ```
166 | setting
167 | {
168 | name: string key(default='@', optional)
169 | actions: object key=string, value=function
170 | mutations: object key=string, value=function
171 | getters: object key=string, value=function
172 | }
173 | ```
174 |
175 | ### action(name, parameter...): Promise
176 |
177 | アクションを実行
178 |
179 | ### getter(name, parameter...): ...
180 |
181 | ゲッターを実行
182 |
183 | ### riotxChange(name, parameter...): null
184 |
185 | チェンジイベント監視を開始
186 |
187 | # Develop
188 |
189 | ## Pre
190 |
191 | ```
192 | $ npm install .
193 | ```
194 |
195 | ## 開発/デバッグ環境の起動
196 |
197 | ```
198 | $ npm run karma-dev
199 | ```
200 |
201 | # npm target
202 |
203 | ## Test (karma/mocha)
204 |
205 | ```
206 | $ npm test
207 | ```
208 |
209 | > `Chrome` on Machine. custom to `test/karma/karma.conf.js`
210 |
211 | ## Test (require.js)
212 |
213 | [Read more](test/requirejs)
214 |
215 | ## Test (browserify)
216 |
217 | [Read more](test/browserify)
218 |
219 | ## Build and minify
220 |
221 | ```
222 | $ npm run build
223 | ```
224 |
225 | ## Watch
226 |
227 | ```
228 | $ npm run watch
229 | ```
230 |
231 | ## ESLint
232 |
233 | ```
234 | $ npm run lint
235 | ```
236 |
--------------------------------------------------------------------------------
/gitbook/ja/ACTIONS.md:
--------------------------------------------------------------------------------
1 | # アクション
2 |
3 | アクションは、ミューテーションへ渡すデータを作成するために存在しています。
4 |
5 | ## 原則
6 |
7 | - アクションは、ステートの変更を行いません。
8 | - アクションは、非同期処理を含むことが可能です。 (promise)
9 | - 非同期のAPI通信などに利用してください。
10 |
11 | ## 定義
12 |
13 | ```mermaid
14 | graph LR
15 | subgraph Riotx
16 | subgraph Store
17 | Actions((Actions)) -- Commit -->Mutations((Mutations))
18 | end
19 | end
20 | subgraph External Service
21 | Actions-. "RESTful (async)" .->API(Backend API)
22 | end
23 | subgraph Riot
24 | CustomTag(CustomTag)-- "Dispatch (promise)" -->Actions
25 | end
26 | ```
27 |
28 |
29 | `nameAction` が呼び出し名、関数が実際に実行されるコードになります。
30 |
31 | **[API リファレンス](APIS.md) を参照してください。**
32 |
33 | ```js
34 | const store = new riotx.Store({
35 | state: {
36 | name: {
37 | lastName: 'yamada',
38 | firstName: 'taro'
39 | },
40 | },
41 | actions: {
42 | nameAction: (context/**, data */) => { // <--
43 | return Promise
44 | .resolve()
45 | .then(() => {
46 | const lastName = 'http request .... async';
47 | });
48 | .then(() => {
49 | context.commit('nameMutation', {lastName: lastName});
50 | });
51 | }
52 | },
53 | mutations: {
54 | nameMutation: (context, data) => {
55 | context.state.name.lastName = data.lastName;
56 | return ['nameChangeMutation', /** ... */];
57 | }
58 | }
59 | })
60 | ```
61 |
--------------------------------------------------------------------------------
/gitbook/ja/APIS.md:
--------------------------------------------------------------------------------
1 | # API リファレンス
2 |
3 | ## riotx.Store
4 |
5 | ``` js
6 | import riotx from 'riotx'
7 |
8 | const store = new riotx.Store({ ...options })
9 | ```
10 |
11 | ### riotx.Store constructor
12 |
13 | - **state**
14 | - Type: `Object`
15 | ステートオブジェクト
16 | [詳細](STATE.md)
17 |
18 | - **mutations**
19 |
20 | - Type: `{ [String: name]: Function (context, data) return Array[String] }`
21 | - Description: [ストア](STORES.md)に[ミューテーション](MUTATIONS.md)を登録
22 | - [詳細](MUTATIONS.md)
23 |
24 | - Arguments
25 | - `context`
26 | - Type: `Object`
27 | - Description: Riotxが提供するコンテキスト情報
28 | - `context.state`
29 | - Type: `Object`
30 | - Description: [ステート](STATE.md)情報
31 | - `context.getter`
32 | - Type: `Function`
33 | - Description: `store.getter` ショートカット
34 | `getter`関数をつかって、[ミューテーション](MUTATIONS.md)で必要なデータを取得することができる
35 | - `data`
36 | - Type: `Object`
37 | - Description: [ミューテーション](MUTATIONS.md)に渡したいデータ
38 | - Return
39 | - Type: `Array`
40 | - Description: [ステート](STATE.md)の変更を通知するトリガー名を配列で返却
41 | トリガーはコミット完了後に自動で発火
42 |
43 | - **actions**
44 |
45 | - Type: `{ [String: name]: Function (Object: context, Object: data) return Promise }`
46 | - Description: [ストア](STORES.md)に[アクション](ACTIONS.md)を登録
47 | - [詳細](ACTIONS.md)
48 | - Arguments
49 | - `context`
50 | - Type: `Object`
51 | - Description: Riotxが提供するコンテキスト情報
52 | - `context.commit`
53 | - Type: `Function`
54 | - Description: [ミューテーション](MUTATIONS.md)に依頼
55 | - `context.getter`
56 | - Type: `Function`
57 | - Description: `store.getter` ショートカット
58 | `getter`関数をつかって、[アクション](ACTIONS.md)で必要なデータを取得することができる
59 | - `data`
60 | - Type: `Object`
61 | - Description: [アクション](ACTIONS.md)に渡したいデータ
62 | - Return
63 | - Type: `Promise`
64 | - Description: 連続してのアクション操作や例外処理に使える
65 |
66 | - **getters**
67 |
68 | - Type: `{ [String: name]: Function (Object: context, Object: data) return * }`
69 | - Description: ストアにゲッターを登録
70 | - [詳細](GETTERS.md)
71 | - Arguments
72 | - `context`
73 | - Type: `Object`
74 | - Description: Riotxが提供するコンテキスト情報
75 | - `context.state`
76 | - Type: `Object`
77 | - Description: [ステート](STATE.md)情報
78 | - `context.getter`
79 | - Type: `Function`
80 | - Description: `store.getter` ショートカット
81 | `getter`関数をつかって、[ゲッター](GETTERS.md)で必要なデータを取得
82 | - `data`
83 | - Type: `Object`
84 | - Description: [ゲッター](GETTERS.md)に渡したいデータ
85 | - Return
86 | - Type: `*`
87 | - Description: フィルターした結果を返却
88 |
89 | - **plugins**
90 |
91 | - Type: `Array[Function (riotx.Store: store)]`
92 | - Description: [プラグイン](PLUGINS.md)関数の配列は、[ストア](STORES.md)生成時に適用
93 | - [詳細](PLUGINS.md)
94 | - Arguments
95 | - `store`
96 | - Type: `riotx.Store`
97 | - Description: [ストア](STORES.md)情報
98 |
99 | ### riotx.Store properties
100 |
101 | - **name** [詳細](STORES.md)
102 |
103 | - Type: `String`
104 | - Default: `@`
105 | - Description: [ストア](STORE.md)名 を指定
106 | 複数の[ステート](STATE.md)を1つの[ストア](STORES.md)で管理する場合に使用
107 |
108 | - **state** [詳細](STATE.md)
109 | - Type: `Object`
110 | - Description: [ステート](STATE.md)情報
111 | [厳格モード](RIOTX.md)を使用すると、操作することができなる。
112 |
113 | ### riotx.Store methods
114 |
115 | - **reset**
116 | - Type: `Function`
117 | - Description: [ストア](STORES.md)をリセット
118 | 内部の参照をすべて切断したりなど、メモリ解放の手助けを行う
119 | [厳格モード](RIOTX.md)を使用すると、操作することができなくなります。
120 |
121 | - **getter** [詳細](GETTERS.md)
122 | - Type: `Function (String: name, Object: data) return *`
123 | - Description: getterを呼び出します。
124 |
125 | - Arguments
126 | - `name`
127 | - Type: `String`
128 | - Description: [ゲッター](GETTERS.md)名
129 | - `data`
130 | - Type: `Object`
131 | - Description: [ゲッター](GETTERS.md)に渡したいデータ
132 |
133 | - **commit** [詳細](ACTIONS.md)
134 | - Type: `Function (String: name, Object: data) return Array[String]`
135 | - Description: [ミューテーション](MUTATIONS.md)を呼び出す
136 | - **重要** [アクション](ACTIONS.md)経由での操作が望ましいです。
137 |
138 | - Arguments
139 | - `name`
140 | - Type: `String`
141 | - Description: [ミューテーション](MUTATIONS.md)名
142 | - `data`
143 | - Type: `Object`
144 | - Description: [ミューテーション](MUTATIONS.md)に渡したいデータ
145 |
146 | - **action** [詳細](ACTIONS.md)
147 | - Type: `Function (String: name, Object: data) return Promise`
148 | - Description: [アクション](ACTIONS.md)を呼び出す
149 |
150 | - Arguments
151 | - `name`
152 | - Type: `String`
153 | - Description: [アクション](MUTATIONS.md)名
154 | - `data`
155 | - Type: `Object`
156 | - Description: [アクション](MUTATIONS.md)に渡したいデータ
157 |
158 | - **change** [詳細](STATE.md)
159 | - Type: `String: name, Function (state, store)`
160 | - Description: [ステート](STATE.md)の変更監視を行う
161 |
162 | - Arguments
163 | - `name`
164 | - Type: `String`
165 | - Description: トリガー名 [ステート](STATE.md) - 変更を監視して取得 を参照
166 | - `Function`
167 | - Type: `Function`
168 | - Description: 指定したトリガーが発火した際に呼ばれる
169 | - `state`
170 | - Type: `Object`
171 | - Description: [ステート](STATE.md)情報
172 | - `store`
173 | - Type: `riotx.Store`
174 | - Description: riotx.Store 情報
175 |
176 | ## riotx
177 |
178 | ``` js
179 | import riotx from 'riotx'
180 | ```
181 |
182 | ### riotx properties
183 |
184 | - **version**
185 |
186 | - Type: `String`
187 | - Description: Riotxのバージョン情報
188 |
189 | - **Store**
190 |
191 | - Type: `Class`
192 | - Description: riotx.Store クラス
193 |
194 | - **stores**
195 |
196 | - Type: `{ [String: name]: riotx.Store }`
197 | - Description: riotxが管理している [ストア](STORES.md) データ
198 |
199 | ### riotx methods
200 |
201 | - **setChangeBindName** [詳細](RIOTX.md)
202 |
203 | - Type: `Function (String: name)`
204 | - Default: `riotxChange`
205 | - Description: riotカスタムタグでの、[ステート](STATE.md)の変更監視の関数名を設定
206 | - TIPS: riotカスタムタグで、`this.change` を拡張していない場合は、`change`に変更するとriotx.Store.changeと同じになり実装が楽になります。
207 |
208 | - **add**
209 |
210 | - Type: `Function (riotx.Store: store)`
211 | - Description: [ストア](STORES.md) 登録
212 | [プラグイン](PLUGINS.md) のロードは、このタイミングで行われます。
213 |
214 | - **get**
215 |
216 | - Type: `Function (String: name) return riotx.Store`
217 | - Description: [ストア](STORES.md) 取得
218 |
219 | - Arguments
220 | - `name`
221 | - Type: `String`
222 | - Default: `@`
223 | - Description: [ストア](STORES.md) 名
224 |
225 | - **debug**
226 |
227 | - Type: `Boolean`
228 | - Default: `false`
229 | - Description: `riotx` のデバッグログをコンソールに出力
230 |
231 | - **strict** [詳細](RIOTX.md) `Experimental`
232 |
233 | - Type: `Boolean`
234 | - Default: `false`
235 | - Description: 厳格モードで動作
236 |
237 | - **logger**
238 |
239 | - Type: `Function (type, ...args)`
240 | - Default: `_output`
241 | - Description: ログ出力関数を上書きできます。
242 |
243 | - **reset**
244 |
245 | - Type: `Function`
246 | - Description: `riotx.stores`で管理しているすべての[ストア](STORES.md)をリセット
247 |
248 | - **size**
249 |
250 | - Type: `int`
251 | - Description: `riotx.stores`で管理しているすべての[ストア](STORES.md)の件数を取得
252 |
--------------------------------------------------------------------------------
/gitbook/ja/CATEGORY.md:
--------------------------------------------------------------------------------
1 | # カテゴリ
2 |
3 | Riotxをカテゴリごとに紹介します。
4 |
5 | - [ステート](STATE.md)
6 | - [ゲッター](GETTERS.md)
7 | - [ミューテーション](MUTATIONS.md)
8 | - [アクション](ACTIONS.md)
9 | - [ストア](STORES.md)
10 |
11 | Riotxを利用するには、上記の理解が必要です。
12 |
--------------------------------------------------------------------------------
/gitbook/ja/DEMOS.md:
--------------------------------------------------------------------------------
1 | # デモ - サンプル
2 |
3 | ## [カウンターアプリ - https://codepen.io/fkei/pen/ybmNqN](https://codepen.io/fkei/pen/ybmNqN)
4 |
5 | > ブラウザ付属の`Developer Tools - Console Panel`で、実行順番が確認できます。
6 |
7 | [](codepen://Lingyucoder/ybmNqN?theme=0)
8 |
--------------------------------------------------------------------------------
/gitbook/ja/DEVELOPS.md:
--------------------------------------------------------------------------------
1 | # 開発者向け
2 |
3 | ## ブラウザテスト (Karma)
4 |
5 | `Chrome` on Machine. custom to `test/karma/karma.conf.js`
6 |
7 | ```sh
8 | npm run karma
9 | ```
10 |
11 | ### デバッグモード
12 |
13 | ```sh
14 | npm run karma-dev
15 | ```
16 |
17 | ## Nodeテスト (Mocha/Chai)
18 |
19 | ```sh
20 | npm run mocha
21 | ```
22 |
23 | ### デバッグモード
24 |
25 | ```sh
26 | npm run mocha-dev
27 | ```
28 |
29 | ## まとめてテスト (karma/mocha)
30 |
31 | ```sh
32 | npm test
33 | ```
34 |
35 | ## ビルド
36 |
37 | ```sh
38 | npm run build
39 | ```
40 |
41 | ## ソースの変更監視からの自動ビルド
42 |
43 | ```sh
44 | npm run watch
45 | ```
46 |
47 | ## ESLint
48 |
49 | ```sh
50 | npm run lint
51 | ```
52 |
53 | ## ドキュメントビルド
54 |
55 | ```sh
56 | npm run docs-build
57 | ```
58 |
59 | ### ドキュメントビルド & serve
60 |
61 | ```sh
62 | npm run docs
63 | ```
64 |
65 | > Local Server(gitbook): [http://localhost:4000](http://localhost:4000)
66 |
67 | ## その他
68 |
69 | `package.json` を見てください。
70 |
--------------------------------------------------------------------------------
/gitbook/ja/GETTERS.md:
--------------------------------------------------------------------------------
1 | # ゲッター
2 |
3 | ステートをフィルターして取得します。
4 |
5 | 小さいステートであれば、フィルターする必要はありませんが、ある程度大きくなるとフィルターを使う必要が出てくると思います。
6 |
7 | また、ゲッターを使用しておくと、同じフィルターの使い回しができるので再利用性が高まります。
8 |
9 | ## 定義
10 |
11 | ```mermaid
12 | graph LR
13 | Getters((Getters))-- Filter -->State
14 | ```
15 |
16 | `fullNameGetter` が呼び出し名、関数が実際に実行されるコードになります。
17 |
18 | **[API リファレンス](APIS.md) を参照してください。**
19 |
20 | ```js
21 |
22 | const store = new riotx.Store({
23 | state: {
24 | name: {
25 | lastName: 'yamada',
26 | firstName: 'taro'
27 | }
28 | }
29 | getters: { // <--
30 | fullNameGetter: (context, data) => {
31 | return `${context.state.name.lastName} ${context.state.name.firstName} ${data.suffix}`; // 'yamada taro ⭐️'
32 | }
33 | }
34 | })
35 | ```
36 |
37 | ## 操作
38 |
39 | ゲッター内の処理は自由です、`rx`、`lodash`などをつかってもいいですし、サンプルのように、文字列連結だけをするだけも構いません。
40 |
41 |
42 | ```js
43 | store.getter('fullNameGetter', {suffix: '⭐️'})
44 | ```
45 |
46 | > 第2引数の `data` は省略可能です。
47 |
--------------------------------------------------------------------------------
/gitbook/ja/INSTALLATION.md:
--------------------------------------------------------------------------------
1 | # インストール
2 |
3 |
4 | ## ダウンロード, CDN
5 |
6 | [https://github.com/cam-inc/riotx/tree/develop/dist](https://github.com/cam-inc/riotx/tree/develop/dist) もしくは、下記の unpkg.com を利用してください。
7 |
8 |
9 |
10 | > 重要 : unpkgは、無料のベストエフォートサービスです。稼働時間やサポートを保証していません。 [https://unpkg.com](https://unpkg.com)
11 |
12 | - 非圧縮版
13 | - [https://unpkg.com/riotx/dist/riotx.js](https://unpkg.com/riotx/dist/riotx.js)
14 | - 圧縮版
15 | - [https://unpkg.com/riotx/dist/riotx.min.js](https://unpkg.com/riotx/dist/riotx.min.js)
16 | - バージョン指定
17 | - [https://unpkg.com/riotx@1.0.0/dist/riotx.js](https://unpkg.com/riotx@1.0.0/dist/riotx.js)
18 |
19 |
20 | ## NPM
21 |
22 |
23 | **[Webpack](https://webpack.js.org/)**, **[Rollup](https://github.com/rollup/rollup)** はこちらを使用してください。
24 |
25 | ```
26 | $ npm install --save riotx
27 | ```
28 |
29 | > [https://www.npmjs.com/package/riotx](https://www.npmjs.com/package/riotx)
30 |
31 | ## Browserify
32 |
33 | [Browserify](http://browserify.org/)
34 |
35 | テストサンプルを見てください。シンプルな組み込みコードがあります。
36 |
37 | [https://github.com/cam-inc/riotx/tree/develop/test/browserify](https://github.com/cam-inc/riotx/tree/develop/test/browserify)
38 |
39 | ## RequireJS
40 |
41 | [RequireJS](http://requirejs.org/)
42 |
43 | テストサンプルを見てください。シンプルな組み込みコードがあります。
44 |
45 | [https://github.com/cam-inc/riotx/tree/develop/test/requirejs](https://github.com/cam-inc/riotx/tree/develop/test/requirejs)
46 |
47 |
48 | ## Bower
49 |
50 | [Bower](https://bower.io/)
51 |
52 |
53 | テストサンプルを見てください。シンプルな組み込みコードがあります。
54 |
55 | [https://github.com/cam-inc/riotx/tree/develop/test/requirejs](https://github.com/cam-inc/riotx/tree/develop/test/requirejs)
56 |
57 |
58 | ## ソースからビルド
59 |
60 | ```
61 | $ git clone https://github.com/cam-inc/riotx.git
62 | $ npm install
63 | $ npm run build
64 |
65 | ---
66 |
67 | 出力ファイル
68 | dist/
69 | ├── amd.riotx+riot.js
70 | ├── amd.riotx+riot.min.js
71 | ├── amd.riotx.js
72 | ├── amd.riotx.min.js
73 | ├── riotx+riot.js
74 | ├── riotx+riot.min.js
75 | ├── riotx.js
76 | └── riotx.min.js
77 | lib/
78 | └── index.js
79 | index.js
80 | ```
81 |
--------------------------------------------------------------------------------
/gitbook/ja/INTRODUCE.md:
--------------------------------------------------------------------------------
1 | # Riotx 紹介
2 |
3 | Riotxは、riot.jsアプリケーション用の状態管理パターン+ライブラリです。
4 |
5 | Riot.jsは、View フレームワークであり、状態管理機構を持ちません、そこで VueになぞりVuexのような Riotx を開発しました。
6 |
7 | ## コンセプト
8 |
9 | 明確に、Store, Actions, Mutations, State, Getters の役割を決め、それに準拠することで、開発を加速させる手助けをします。
10 |
11 | Riotは非常にシンプルです、その思想を受け継ぎ重量級な機能をつけません。
12 |
13 | > Riotxは、Vuex, Flux, Redux などに影響を受けながら開発されています。
14 |
15 | ## アーキテクチャ
16 |
17 | ```mermaid
18 | graph LR
19 | subgraph Riotx
20 | subgraph Store
21 | Actions((Actions)) -- Commit --> Mutations
22 | Mutations((Mutations))-- Mutates-->State
23 | Getters((Getters))-- Filter -->State
24 | Plugins((Plugins))-- Mutations after hook -->Mutations
25 | end
26 | end
27 | subgraph External Service
28 | Actions-. "RESTful (async)" .->API(Backend API)
29 | end
30 | subgraph Riot
31 | CustomTag(CustomTag)-- "Dispatch (promise)" -->Actions
32 | CustomTag(CustomTag)-- Get state -->Getters
33 | State((State))-- Change events -->CustomTag
34 | end
35 | ```
36 |
37 | ## サンプル Webアプリケーション
38 |
39 | これは、Riotxの基本機能を実装したサンプルアプリで、非常にシンプルにプログラミングされています。
40 |
41 | Riotxの、基本機能を実際のコードで確認してみてください。
42 |
43 | [カウンターアプリ - https://codepen.io/fkei/pen/ybmNqN](https://codepen.io/fkei/pen/ybmNqN)
44 |
45 | > ブラウザ付属の`Developer Tools - Console Panel`で、実行順番が確認できます。
46 |
47 | [](codepen://Lingyucoder/ybmNqN?theme=0)
48 |
--------------------------------------------------------------------------------
/gitbook/ja/MUTATIONS.md:
--------------------------------------------------------------------------------
1 | # ミューテーション
2 |
3 | [ステート](STATE.md)を変更出来る唯一の方法は、ミューテーションをコミットすることです。
4 |
5 | **重要** ミューテーション以外からのステートの変更は、Riotxを使う理由を著しく低下させます。
6 | 例外は、[プラグイン](PLUGINS.md)だけです。
7 |
8 | ## 定義
9 |
10 | ```mermaid
11 | graph LR
12 | Actions((Actions))-- commit -->Mutations((Mutations))
13 | Mutations((Mutations))-- mutates -->State((State))
14 | ```
15 |
16 | `nameMutation` が呼び出し名、関数が実際に実行されるコードになります。
17 |
18 | **[API リファレンス](APIS.md) を参照してください。**
19 |
20 | ```js
21 | const store = new riotx.Store({
22 | state: {
23 | name: {
24 | lastName: 'yamada',
25 | firstName: 'taro'
26 | }
27 | }
28 | mutations: {
29 | nameMutation: (context, data) => { // <--
30 | context.state.name.lastName = data.lastName;
31 | return ['nameChangeMutation', /** ... */];
32 | }
33 | }
34 | })
35 | ```
36 |
37 | ## トリガーとは
38 |
39 | [ステート - 変更を監視して取得](STATE.md)を参照ください。
40 |
--------------------------------------------------------------------------------
/gitbook/ja/PLUGINS.md:
--------------------------------------------------------------------------------
1 | # プラグイン
2 |
3 | [ミューテーション](MUTATIONS.md) をフックする機能をプラグインとして提供します。
4 |
5 | [ステート](STATE.md)の上書きなどが可能です。
6 |
7 | **重要** Riotxの機能を破壊することも可能ですので注意してください。
8 |
9 | ## 定義
10 |
11 | ```mermaid
12 | graph LR
13 | subgraph Riotx
14 | subgraph Store
15 | Mutations((Mutations))-- Mutates -->State
16 | Mutations((Mutations))-- Mutations after hook -->Plugins((Plugins))
17 | Plugins((Plugins))-- Override mutates -->State
18 | end
19 | end
20 | ```
21 |
22 | **[API リファレンス](APIS.md) を参照してください。**
23 |
24 | ### store.change 関数
25 |
26 | #### 第一引数
27 |
28 | 実行された[ミューテーション](MUTATIONS.md)の名前です。
29 |
30 | #### 第二引数
31 |
32 | 実行された[ミューテーション](MUTATIONS.md)が返却した、トリガー名のリストです。
33 |
34 | #### 第三引数
35 |
36 | 実行された[ミューテーション](MUTATIONS.md)の引数にある`context`と同一です。
37 |
38 | #### 第四引数
39 |
40 | [ステート](STATE.md)を変更するのに必要なデータを受け取ります。
41 |
42 | ```js
43 | const store = new riotx.Store({
44 | state: {
45 | name: {
46 | lastName: 'yamada',
47 | firstName: 'taro'
48 | }
49 | },
50 | mutations: {
51 | nameMutation: (context, data) => {
52 | context.state.name.lastName = data.lastName;
53 | return ['nameChangeMutation', /** ... */];
54 | }
55 | },
56 | plugins: [ // <--
57 | store => {
58 | store.change('riotx:mutations:after', (name, targets, context, data) => {
59 | if (name === 'nameMutation' && targets.includes('nameChangeMutation')) {
60 | // Direct
61 | context.state.name.lastName = `Override ${context.state.lastName}`;
62 | //
63 | // or
64 | //
65 | // Mutation
66 | store.mutation('nameMutation', {
67 | lastName: `Override ${context.state.lastName}`;
68 | })
69 | }
70 | });
71 | },
72 | ]
73 | })
74 | ```
75 |
76 | ## フック
77 |
78 | フックの種類
79 |
80 | ### [ミューテーション](MUTATIONS.md)完了タイミング
81 |
82 | `riotx:mutations:after`
83 |
84 | ```js
85 | store.change('riotx:mutations:after', (name, targets, context, data) => {
86 | // ...
87 | });
88 | ```
89 |
90 | ## プラグインの実行順番
91 |
92 | 配列のはじめから順次逐次実行されます。
93 |
--------------------------------------------------------------------------------
/gitbook/ja/README.md:
--------------------------------------------------------------------------------
1 | {% include "./SUMMARY.md" %}
2 |
--------------------------------------------------------------------------------
/gitbook/ja/RELEASENOTES.md:
--------------------------------------------------------------------------------
1 | # リリースノート
2 |
3 | Github Release [https://github.com/cam-inc/riotx/releases](https://github.com/cam-inc/riotx/releases)
4 |
5 | # 2.0.0
6 |
7 | - [変更] ObjectAssignを除去
8 | - [変更] riotx.reset()で、Store.reset()を呼び出す
9 | - [追加] Store.reset() 内部の参照をすべて切断します
10 | - [変更] `action`,`mutation`,`getter`の呼び出し引数を統一
11 | - [追加] 厳格モード
12 | - [追加] プラグイン機能
13 | - [変更] 依存ライブラリを最新版にアップデート
14 | - [追加] テストコードの拡充
15 |
--------------------------------------------------------------------------------
/gitbook/ja/RIOTX.md:
--------------------------------------------------------------------------------
1 | # Riotx
2 |
3 | ロードすると、[riotx](https://github.com/cam-inc/riotx)は、グローバルにシングルトンで存在します。
4 |
5 | ## 依存
6 |
7 | ```mermaid
8 | graph LR
9 | riotx-- deps -->riot
10 | ```
11 |
12 | Riotxは、
13 | [riot](https://github.com/riot/riot) の、`mixin`, `observable` に依存しています。
14 |
15 | ## 設定
16 |
17 | Riotxには設定があります。
18 |
19 | ### デバッグ
20 |
21 | `console.log` に、デバッグログが出力されます。
22 |
23 | `default : false`
24 |
25 | ```js
26 | riotx.debug(true);
27 | ```
28 |
29 | ### [riot](https://github.com/riot/riot) カスタムタグ バインド名
30 |
31 | [riot](https://github.com/riot/riot)のカスタムタグに、変更監視関数をバインディングする名前です。
32 |
33 | `default : riotxChange`
34 |
35 | ```js
36 | riotx.changeBindName('change');
37 | ```
38 |
39 | ```html
40 |
41 | Hello
42 |
54 | ```
55 |
56 | ### 厳格モード
57 |
58 | 直接[ステート](STATE.md)を取得、設定できなくします。
59 |
60 | `default : false`
61 |
62 | > [プラグイン](PLUGINS.md) での直接変更は可能です。
63 |
64 | ### logger
65 |
66 | `riotx`が出力するログ関数を上書きすることが可能
67 |
68 | 既存のコードは、`src/index.js#_output`関数です。上書きを行う場合はこちらのコードを参考にしてください。
69 |
70 | > IMPORTANT : 上書きを行うとログ出力されなくなります。上書きしたコードでログ出力も実装スルのが望ましいです。
71 |
72 | ```js
73 | riotx.logger((type, ...args) => {
74 | // Override code...
75 | });
76 | ```
77 |
78 |
--------------------------------------------------------------------------------
/gitbook/ja/STATE.md:
--------------------------------------------------------------------------------
1 | # ステート
2 |
3 | アプリケーションの状態(データ)を管理します。
4 |
5 | ## 定義
6 |
7 | 作成するのは、ただの `Object` です。
8 |
9 | > 初期値 `state: {}` でも構いません。
10 |
11 |
12 | ```js
13 | const store = new riotx.Store({
14 | state: {}
15 | })
16 | // or
17 | const store = new riotx.Store({
18 | state: {
19 | name: {
20 | lastName: 'yamada',
21 | firstName: 'taro'
22 | }
23 | },
24 | mutations: {
25 | nameMutation: context => {
26 | context.state.name.lastName = 'tanaka';
27 | return ['nameChangeMutation'];
28 | }
29 | }
30 | })
31 | ```
32 |
33 | ## 操作
34 |
35 | ステートの操作には、ルールがあります。
36 |
37 | ### 追加、編集、削除
38 |
39 | ```mermaid
40 | graph LR
41 | Actions((Actions))-- commit -->Mutations
42 | Mutations((Mutations))-- Mutates-->State
43 | ```
44 |
45 | [アクション](ACTIONS.md) -> [ミューテーション](MUTATIONS.md) を経由して操作する必要があります。
46 |
47 | > 直接[ミューテーション](MUTATIONS.md)から操作ことも可能ですが、[アクション](ACTIONS.md)経由を推奨しています。
48 |
49 | ### 取得
50 |
51 | ```mermaid
52 | graph LR
53 | Getters((Getters))-- Filter -->State
54 | ```
55 |
56 | [ゲッター](GETTERS.md) を経由して操作する必要があります。
57 |
58 | ### 変更を監視して取得
59 |
60 | ```mermaid
61 | graph LR
62 | Getters((Getters))-- Filter -->State
63 | State-- "Change events (trigger)" --> CustomTag((Custom Tag))
64 | State-- "Change events (trigger)" --> Store((Store))
65 | ```
66 |
67 |
68 | ```html
69 |
82 | ```
83 |
--------------------------------------------------------------------------------
/gitbook/ja/STORES.md:
--------------------------------------------------------------------------------
1 | # Store
2 |
3 | ストアは、[ステート](STATE.md), [ゲッター](GETTERS.md), [ミューテーション](MUTATIONS.md), [アクション](ACTIONS.md) を持ちます。
4 |
5 | ```mermaid
6 | graph LR
7 | subgraph riotx.Store
8 | Actions((Actions)) -- Commit --> Mutations
9 | Mutations((Mutations))-- Mutates-->State
10 | Getters((Getters))-- Filter -->State
11 | end
12 | ```
13 |
14 | ## 定義
15 |
16 | ### 登録
17 |
18 | ```js
19 |
20 | const store = new riotx.Store({
21 | state: {}
22 | })
23 |
24 | riotx.add(store);
25 |
26 | /////////
27 |
28 | // 取得
29 | const store = riotx.get(/** @ */);
30 | ```
31 |
32 | ### 複数ストア
33 |
34 | ```mermaid
35 | graph TB
36 | subgraph Riotx
37 | main(("Store (main)"))
38 | sub(("Store (sub)"))
39 | etc0[" "]
40 | etc1[" "]
41 | etc2[" "]
42 | end
43 | ```
44 |
45 | 複数のストア持つことが可能です。
46 |
47 | `name` のデフォルトは`@`です。
48 |
49 | ```js
50 |
51 | const main = new riotx.Store({
52 | name: 'main'
53 | state: {}
54 | })
55 | const sub = new riotx.Store({
56 | name: 'sub'
57 | state: {}
58 | })
59 |
60 | riotx.add(main);
61 | riotx.add(sub);
62 |
63 | /////////
64 |
65 | // 取得
66 | const main = riotx.get('main');
67 | const sub = riotx.get('sub');
68 | ```
69 |
70 |
--------------------------------------------------------------------------------
/gitbook/ja/SUMMARY.md:
--------------------------------------------------------------------------------
1 | # 目次
2 |
3 | ## Riotx
4 |
5 | - [インストール](INSTALLATION.md)
6 | - [Riotx 紹介](INTRODUCE.md)
7 | - [カテゴリ](CATEGORY.md)
8 | - [ステート](STATE.md)
9 | - [ゲッター](GETTERS.md)
10 | - [ミューテーション](MUTATIONS.md)
11 | - [アクション](ACTIONS.md)
12 | - [ストア](STORES.md)
13 | - [Riotx](RIOTX.md)
14 | - [プラグイン](PLUGINS.md)
15 | - [テスト](TESTING.md)
16 | - [API リファレンス](APIS.md)
17 | - [リリースノート](RELEASENOTES.md)
18 | - [開発者向け](DEVELOPS.md)
19 | - [デモ - サンプル](DEMOS.md)
20 | - [0.x, 1.x ドキュメント](0_x_1_x_DOCUMENTS.md)
21 |
--------------------------------------------------------------------------------
/gitbook/ja/TESTING.md:
--------------------------------------------------------------------------------
1 | # テスト
2 |
3 | すべてのテストが、どのスコープからでも可能です。
4 |
5 |
6 | ```mermaid
7 | graph LR
8 | subgraph Riotx
9 | subgraph Store
10 | Actions((Actions)) -- Commit --> Mutations
11 | Mutations((Mutations))-- Mutates-->State
12 | Getters((Getters))-- Filter -->State
13 | Plugins((Plugins))-- Mutations after hook -->Mutations
14 | end
15 | end
16 | subgraph Testing
17 | BroserNodeJS("Browser/NodeJS") -. mocha .->Actions
18 | BroserNodeJS("Browser/NodeJS") -. mocha .->Mutations
19 | BroserNodeJS("Browser/NodeJS") -. mocha .->State
20 | BroserNodeJS("Browser/NodeJS") -. mocha .->Getters
21 | end
22 | ```
23 |
24 | ## サンプル
25 |
26 | Riotxのテストコードが参考になります。
27 |
28 | [テストコード](https://github.com/cam-inc/riotx/tree/develop/test)
29 |
30 | ## おすすめのテストツール
31 |
32 | Riotx 開発チームは、[Karma](https://github.com/karma-runner/karma), [Mocha](https://github.com/mochajs/mocha), [Chai](https://github.com/chaijs/chai), [power-assert](https://github.com/power-assert-js/power-assert) を使ってテストを行っています。
33 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "riotx",
3 | "version": "2.0.3",
4 | "description": "Centralized State Management for riot.js",
5 | "main": "index.js",
6 | "jsnext:main": "lib/index.js",
7 | "module": "lib/index.js",
8 | "modules.root": "lib",
9 | "directories": {
10 | "lib": "lib"
11 | },
12 | "scripts": {
13 | "test": "npm run build && npm run karma && npm run mocha",
14 | "build": "npm run lint && npm run rollup && npm run minify",
15 | "rollup": "node rollup.js",
16 | "watch": "chokidar src/* -c 'npm run build'",
17 | "minify": "npm run uglify && npm run uglify-amd && npm run uglify-bundle && npm run uglify-amd-bundle",
18 | "lint": "eslint ./src/**/* ./test/spec/* ./test/browserify/index.js ./test/karma/spec.js",
19 | "karma": "karma start test/karma/karma.conf.js",
20 | "karma-dev": "DEBUG=1 karma start test/karma/karma.conf.js",
21 | "mocha": "mocha test/spec/*.js",
22 | "mocha-dev": "npm run rollup; mocha test/spec/*.js",
23 | "uglify": "uglifyjs dist/riotx.js --comments --mangle -o dist/riotx.min.js",
24 | "uglify-bundle": "uglifyjs dist/riotx+riot.js --comments --mangle -o dist/riotx+riot.min.js",
25 | "uglify-amd": "uglifyjs dist/amd.riotx.js --comments --mangle -o dist/amd.riotx.min.js",
26 | "uglify-amd-bundle": "uglifyjs dist/amd.riotx+riot.js --comments --mangle -o dist/amd.riotx+riot.min.js",
27 | "docs": "gitbook install gitbook && gitbook serve gitbook",
28 | "docs-build": "gitbook build gitbook docs",
29 | "ncu": "ncu"
30 | },
31 | "repository": {
32 | "type": "git",
33 | "url": "git+https://github.com/cam-inc/riotx.git"
34 | },
35 | "keywords": [
36 | "riot"
37 | ],
38 | "author": "CA Mobile, Inc.",
39 | "license": "MIT",
40 | "bugs": {
41 | "url": "https://github.com/cam-inc/riotx/issues"
42 | },
43 | "homepage": "https://github.com/cam-inc/riotx#readme",
44 | "devDependencies": {
45 | "chokidar": "^2.0.0",
46 | "chokidar-cli": "^1.2.0",
47 | "eslint": "^4.19.1",
48 | "gitbook-cli": "^2.3.2",
49 | "gitbook-plugin-codepen": "^0.1.2",
50 | "gitbook-plugin-github": "^3.0.0",
51 | "gitbook-plugin-mermaid-gb3": "^2.1.0",
52 | "karma": "^2.0.0",
53 | "karma-chrome-launcher": "^2.2.0",
54 | "karma-coverage": "^1.1.1",
55 | "karma-firefox-launcher": "^1.1.0",
56 | "karma-mocha": "^1.3.0",
57 | "karma-mocha-reporter": "^2.2.5",
58 | "karma-power-assert": "^1.0.0",
59 | "karma-riot": "^2.0.0",
60 | "karma-rollup-plugin": "^0.2.4",
61 | "karma-rollup-preprocessor": "^5.1.1",
62 | "karma-safari-launcher": "^1.0.0",
63 | "mocha": "^5.0.5",
64 | "npm-check-updates": "^2.14.1",
65 | "power-assert": "^1.4.4",
66 | "riot": "^3.9.0",
67 | "rollup": "^0.57.1",
68 | "rollup-plugin-alias": "^1.4.0",
69 | "rollup-plugin-buble": "^0.19.2",
70 | "rollup-plugin-commonjs": "^9.1.0",
71 | "rollup-plugin-node-resolve": "^3.3.0",
72 | "rollup-plugin-riot": "^2.0.0",
73 | "slash": "^1.0.0",
74 | "uglify-js": "^3.3.16"
75 | },
76 | "dependencies": {
77 | "mout": "^1.1.0",
78 | "promise-polyfill": "^7.0.2"
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/rollup.js:
--------------------------------------------------------------------------------
1 | /* global */
2 | /* eslint-env node, mocha */
3 | const
4 | rollup = require('rollup'),
5 | buble = require('rollup-plugin-buble'),
6 | alias = require('rollup-plugin-alias'),
7 | riot = require('rollup-plugin-riot'), // eslint-disable-line
8 | nodeResolve = require('rollup-plugin-node-resolve'),
9 | commonjs = require('rollup-plugin-commonjs'),
10 | banner = require('./rollup.vars').banner,
11 | banner_bundle = require('./rollup.vars').banner_bundle, // eslint-disable-line
12 | intro = require('./rollup.vars').intro;
13 |
14 | let namedExports = {
15 | 'node_modules/mout/array.js': [ 'forEach' ],
16 | 'node_modules/mout/object.js': [ 'keys' ],
17 | };
18 |
19 | // @see https://rollupjs.org/guide/en#javascript-api
20 |
21 | // iife/amd (riot.js bundle)
22 | async function buildIifeAmdBundle() {
23 | // create a bundle
24 | const bundle = await rollup.rollup({
25 | input: 'src/index.js',
26 | plugins: [
27 | alias({
28 | 'riot': 'node_modules/riot/lib/riot.js', // eslint-disable-line
29 | 'riot-tmpl': 'node_modules/riot-tmpl/dist/es6.tmpl.js',
30 | 'riot-observable': 'node_modules/riot-observable/dist/es6.observable.js',
31 | }),
32 | nodeResolve({
33 | jsnext: true,
34 | main: true,
35 | browser: true
36 | }),
37 | commonjs({
38 | include: 'node_modules/**',
39 | namedExports: namedExports,
40 | }),
41 | buble()
42 | ]
43 | });
44 | await bundle.write({
45 | format: 'iife',
46 | name: 'riotx',
47 | banner: banner_bundle,
48 | intro: intro,
49 | file: 'dist/riotx+riot.js',
50 | sourcemap: true
51 | });
52 |
53 | await bundle.write({
54 | format: 'amd',
55 | banner: banner_bundle,
56 | intro: intro,
57 | file: 'dist/amd.riotx+riot.js',
58 | sourcemap: true
59 | });
60 |
61 | }
62 |
63 | buildIifeAmdBundle();
64 |
65 |
66 | // iife/amd (riot.js not bundle)
67 | async function buildIifeAmd() {
68 | // create a bundle
69 | const bundle = await rollup.rollup({
70 | input: 'src/index.js',
71 | external: ['riot'],
72 | plugins: [
73 | nodeResolve({
74 | jsnext: true,
75 | main: true,
76 | browser: true
77 | }),
78 | commonjs({
79 | include: 'node_modules/**',
80 | namedExports: namedExports
81 | }),
82 | buble()
83 | ]
84 | });
85 | await bundle.write({
86 | format: 'iife',
87 | name: 'riotx',
88 | globals: {
89 | riot: 'riot'
90 | },
91 | banner: banner,
92 | intro: intro,
93 | file: 'dist/riotx.js',
94 | sourcemap: true
95 | });
96 | await bundle.write({
97 | format: 'amd',
98 | banner: banner,
99 | intro: intro,
100 | file: 'dist/amd.riotx.js',
101 | sourcemap: true
102 | });
103 | }
104 |
105 | buildIifeAmd();
106 |
107 | // es/cjs
108 | async function buildEsCjs() {
109 | // create a bundle
110 | const bundle = await rollup.rollup({
111 | input: 'src/index.js',
112 | external: ['riot'],
113 | plugins: [
114 | nodeResolve({
115 | jsnext: true,
116 | main: true,
117 | browser: true
118 | }),
119 | commonjs({
120 | include: 'node_modules/**',
121 | namedExports: namedExports
122 | }),
123 | buble()
124 | ]
125 | });
126 | await bundle.write({
127 | format: 'es',
128 | banner: banner,
129 | intro: intro,
130 | file: 'lib/index.js'
131 | });
132 | await bundle.write({
133 | format: 'cjs',
134 | banner: banner,
135 | intro: intro,
136 | file: 'index.js'
137 | });
138 | }
139 |
140 | buildEsCjs();
141 |
--------------------------------------------------------------------------------
/rollup.vars.js:
--------------------------------------------------------------------------------
1 | const package = require('./package.json');
2 |
3 | const
4 | banner = '/* riotx version ' + package.version + ' */',
5 | banner_bundle = '/* riotx version ' + package.version + ', riot version ' + package.devDependencies.riot + ' */',
6 | intro = 'var VERSION = "' + package.version + '";';
7 |
8 | module.exports = {
9 | banner: banner,
10 | banner_bundle: banner_bundle,
11 | intro: intro,
12 | };
13 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | /*global VERSION*/
2 |
3 | import forEach from 'mout/array/forEach';
4 | import forOwn from 'mout/object/forOwn';
5 | import keys from 'mout/object/keys';
6 | import isFunction from 'mout/lang/isFunction';
7 | import isObject from 'mout/lang/isObject';
8 | import Promise from 'promise-polyfill';
9 | import riot from 'riot';
10 |
11 |
12 | /**
13 | * console output
14 | *
15 | * @param {String} type level
16 | * @param {*} args output messages
17 | */
18 | const _output = (type, ...args) => {
19 | args.unshift('[riotx]');
20 | try {
21 | console.log.apply(console, args); // eslint-disable-line
22 | } catch (e) {
23 | console.log(args); // eslint-disable-line
24 | }
25 | };
26 |
27 | /**
28 | * settings for riotx
29 | * @type {{debug: boolean, default: string}}
30 | */
31 | const settings = {
32 | debug: false,
33 | default: '@',
34 | changeBindName: 'riotxChange',
35 | strict: false,
36 | logger: {
37 | output: _output,
38 | }
39 | };
40 |
41 | /**
42 | * console debug output
43 | * @param {*} args
44 | */
45 | const debug = (...args) => {
46 | if (!settings.debug) {
47 | return;
48 | }
49 | args.unshift('DEBUG');
50 | settings.logger.output.apply(null, args);
51 | };
52 |
53 | /**
54 | * console error output
55 | * @param {*} message
56 | */
57 | const error = message => {
58 | const err = new Error(`[riotx] ${message}`);
59 | settings.logger.output.apply(null, ['ERROR', err]);
60 | throw err;
61 | };
62 |
63 | /**
64 | * @class Store
65 | */
66 | class Store {
67 |
68 | /**
69 | * Creates an instance of Store.
70 | * @param {Object} _store { name: 'Store Name', state: { default state data }, actions: { functions... } mutations: { functions... }, getters: { functions... }, plugins: { functions... } }
71 | * @memberof Store
72 | */
73 | constructor(_store) {
74 | /**
75 | * name of the store.
76 | * @type {String}
77 | * @memberof Store
78 | */
79 | this.name = _store.name;
80 | if (!this.name) {
81 | this.name = settings.default;
82 | debug(`Default store name. name=${this.name}`);
83 | }
84 |
85 | /**
86 | * a object that represents full application state.
87 | * @memberof Store
88 | * @type {Object}
89 | */
90 | this._state = _store.state;
91 | Object.defineProperty(this, 'state', {
92 | get: () => {
93 | if (settings.strict) {
94 | error('[strict] Direct access get error.');
95 | }
96 | return this._state;
97 | },
98 | set: state => {
99 |
100 | if (settings.strict) {
101 | error(`[strict] Direct access set error. ${state}`);
102 | }
103 | this._state = state;
104 | }
105 | });
106 |
107 | /**
108 | * functions to mutate application state.
109 | * @memberof Store
110 | * @type {Object}
111 | */
112 | this._actions = _store.actions;
113 |
114 | /**
115 | * mutaions.
116 | * mutaion = a function which mutates the state.
117 | * all mutation functions take two parameters which are `state` and `obj`.
118 | * @memberof Store
119 | * @type {Object}
120 | */
121 | this._mutations = _store.mutations;
122 |
123 | /**
124 | * functions to get data from states.
125 | * @memberof Store
126 | * @type {Object}
127 | */
128 | this._getters = _store.getters;
129 |
130 | /**
131 | * functions to plugins.
132 | * @memberof Store
133 | * @type {Array}
134 | */
135 | this._plugins = _store.plugins;
136 |
137 | riot.observable(this);
138 |
139 | // Load plugins.
140 | forEach(this._plugins, p => {
141 | if (!isFunction(p)) {
142 | error('[plugin] The plugin is not a function.');
143 | }
144 | p.apply(null, [this]);
145 | });
146 |
147 | }
148 |
149 | /**
150 | * Reset store instance.
151 | * @memberof Store
152 | */
153 | reset() {
154 | this.name = null;
155 | this._state = null;
156 | this._actions = null;
157 | this._mutations = null;
158 | this._getters = null;
159 | this._plugins = null;
160 | this.off('*');
161 | }
162 |
163 | /**
164 | * Getter state
165 | * @param {String} name
166 | * @param {Object} data
167 | * @memberof Store
168 | * @returns {*}
169 | */
170 | getter(name, data) {
171 | if (data && !isObject(data)) {
172 | error(`[getter]', 'The getter data is not object type. name=${name} data=${data}`);
173 | }
174 | const context = {
175 | state: this._state
176 | };
177 | const fn = this._getters[name];
178 | if (!fn || typeof fn !== 'function') {
179 | error(`[getter]', 'The getter is not a function. name=${name} data=${data}`);
180 | }
181 | debug('[getter]', name, data);
182 | return fn.apply(null, [context, data]);
183 | }
184 |
185 | /**
186 | * Commit mutation.
187 | * only actions are allowed to execute this function.
188 | * @param {String} name mutation name
189 | * @param {Object} data
190 | * @memberof Store
191 | */
192 | commit(name, data) {
193 | if (data && !isObject(data)) {
194 | error(`[mutation]', 'The mutation data is not object type. name=${name} data=${data}`);
195 | }
196 | const context = {
197 | getter: (name, data) => {
198 | return this.getter.apply(this, [name, data]);
199 | },
200 | state: this._state
201 | };
202 |
203 | const fn = this._mutations[name];
204 | if (!fn || typeof fn !== 'function') {
205 | error(`[mutation]', 'The mutation is not a function. name=${name} data=${data}`);
206 | }
207 |
208 | debug('[mutation(before)]', name, this._state, data);
209 | const triggers = fn.apply(null, [context, data]);
210 | debug('[mutation(after)]', name, this._state, data);
211 |
212 | // Plugins
213 | this.trigger('riotx:mutations:after', name, triggers, context, data);
214 |
215 | forEach(triggers, v => {
216 | // this.trigger(v, null, this.state, this);
217 | this.trigger(v, this._state, this);
218 | });
219 | }
220 |
221 | /**
222 | * emit action.
223 | * only ui components are allowed to execute this function.
224 | * @param {Stting} name action name
225 | * @param {Object} data parameter's to action
226 | * @memberof Store
227 | * @return {Promise}
228 | */
229 | action(name, data) {
230 | if (data && !isObject(data)) {
231 | error(`[action]', 'The action data is not object type. name=${name} data=${data}`);
232 | }
233 | const context = {
234 | getter: (name, data) => {
235 | return this.getter.apply(this, [name, data]);
236 | },
237 | //state: this._state,
238 | commit: (name, data) => {
239 | this.commit(name, data);
240 | }
241 | };
242 |
243 | const fn = this._actions[name];
244 | if (!fn || typeof fn !== 'function') {
245 | error(`[action] The action is not a function. name=${name} data=${data}`);
246 | }
247 |
248 | debug('[action]', name, data);
249 | return Promise
250 | .resolve()
251 | .then(() => fn.apply(null, [context, data]));
252 | }
253 |
254 | /**
255 | * shorthand for `store.on('event', () => {})`.
256 | * @param {...*} args
257 | * @memberof Store
258 | */
259 | change(...args) {
260 | this.on(...args);
261 | }
262 |
263 | }
264 |
265 | /**
266 | * @class RiotX
267 | */
268 | class RiotX {
269 |
270 | /**
271 | * Creates an instance of RiotX.
272 | * @memberof RiotX
273 | */
274 | constructor() {
275 | this.version = VERSION || '';
276 |
277 | /**
278 | * constructor of RiotX.Store.
279 | * @type {RiotX.Store}
280 | */
281 | this.Store = Store;
282 |
283 | /**
284 | * instances of RiotX.Store.
285 | * @type {Object}
286 | */
287 | this.stores = {};
288 |
289 | // add and keep event listener for store changes.
290 | // through this function the event listeners will be unbinded automatically.
291 | const riotxChange = function (store, evtName, handler, ...args) {
292 | this._riotx_change_handlers.push({
293 | store,
294 | evtName,
295 | handler
296 | });
297 | args.unshift(handler);
298 | args.unshift(evtName);
299 | store.change(...args);
300 | };
301 |
302 | // register a mixin globally.
303 | riot.mixin({
304 | // intendedly use `function`.
305 | // switch the context of `this` from `riotx` to `riot tag instance`.
306 | init: function () {
307 | // the context of `this` will be equal to riot tag instant.
308 | this.on('unmount', () => {
309 | this.off('*');
310 | forEach(this._riotx_change_handlers, obj => {
311 | obj.store.off(obj.evtName, obj.handler);
312 | });
313 | delete this.riotx;
314 | delete this._riotx_change_handlers;
315 | delete this[settings.changeBindName];
316 | });
317 |
318 | if (settings.debug) {
319 | this.on('*', eventName => {
320 | debug('[riot.mixin]', eventName, this);
321 | });
322 | }
323 |
324 | this._riotx_change_handlers = [];
325 |
326 | // let users set the name.
327 | this[settings.changeBindName] = riotxChange;
328 | },
329 | // give each riot instance the ability to access the globally defined singleton RiotX instance.
330 | riotx: this
331 | });
332 | }
333 |
334 | /**
335 | * Add a store instance
336 | * @param {RiotX.Store} store instance of RiotX.Store
337 | * @memberof RiotX
338 | * @returns {RiotX}
339 | */
340 | add(store) {
341 | if (this.stores[store.name]) {
342 | error(`[store.add] The store instance named \`${store.name}\` already exists.`);
343 | }
344 |
345 | this.stores[store.name] = store;
346 | return this;
347 | }
348 |
349 | /**
350 | * Get store instance
351 | * @param {String} name store name
352 | * @memberof RiotX
353 | * @returns {RiotX.Store} store instance
354 | */
355 | get(name = settings.default) {
356 | return this.stores[name];
357 | }
358 |
359 | /**
360 | * Set debug flag
361 | * @param {boolean} flag
362 | * @memberof RiotX
363 | * @returns {RiotX}
364 | */
365 | debug(flag) {
366 | settings.debug = !!flag;
367 | return this;
368 | }
369 |
370 | /**
371 | * Set function name to bind store change event.
372 | * @param {String} name
373 | * @memberof RiotX
374 | * @returns {RiotX}
375 | */
376 | setChangeBindName(name) {
377 | settings.changeBindName = name;
378 | return this;
379 | }
380 |
381 | /**
382 | * Directly changing the state property from outside will occur an exception.
383 | * You can change it through “mutations”, or you can get it via “getters”.
384 | * @param {boolean} flag
385 | * @memberof RiotX
386 | * @returns {RiotX}
387 | */
388 | strict(flag) {
389 | settings.strict = !!flag;
390 | return this;
391 | }
392 |
393 | /**
394 | *
395 | *
396 | * @param {Function} fn @see function _output
397 | * @returns Riotx
398 | * @memberof RiotX
399 | */
400 | logger(fn) {
401 | settings.logger.output = fn;
402 | return this;
403 | }
404 |
405 | /**
406 | * Reset all store instances at once.
407 | * @memberof RiotX
408 | * @returns {RiotX} instance
409 | */
410 | reset() {
411 | forOwn(this.stores || {}, store => {
412 | store.reset();
413 | });
414 | this.stores = {};
415 | return this;
416 | }
417 |
418 | /**
419 | * Store's count
420 | * @memberof RiotX
421 | * @returns {int} size
422 | */
423 | size() {
424 | return keys(this.stores).length;
425 | }
426 |
427 | }
428 |
429 | export default new RiotX();
430 |
--------------------------------------------------------------------------------
/test/browserify/.gitignore:
--------------------------------------------------------------------------------
1 | bundle.js
2 |
--------------------------------------------------------------------------------
/test/browserify/README.md:
--------------------------------------------------------------------------------
1 | Browserify
2 |
3 | Operation test in Browserify environment.
4 |
5 | # QuickStart
6 |
7 |
8 | ## build
9 |
10 | ```
11 | $ npm install .
12 | $ npm run build
13 | ```
14 |
15 | ## Operation
16 |
17 | Activate the browser and check the operation.
18 |
19 | ```
20 | $ open index.html; # browser display output 'Successful' or 'Failure'.
21 | ```
22 |
--------------------------------------------------------------------------------
/test/browserify/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | riotx - browserify
6 |
7 |
8 |
9 |
10 | ...
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/test/browserify/index.js:
--------------------------------------------------------------------------------
1 | /*global window, require, document*/
2 | var riot = require('riot');
3 | var riotx = require('riotx');
4 |
5 | // debug browser.
6 | if (window) {
7 | window.riot = riot;
8 | window.riotx = riotx;
9 | }
10 |
11 | if (riot && riotx) {
12 | document.getElementById('result').innerText ='Successful';
13 | } else {
14 | document.getElementById('result').innerText ='Failure';
15 | }
16 |
--------------------------------------------------------------------------------
/test/browserify/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "riotx-test",
3 | "private": true,
4 | "devDependencies": {
5 | "chokidar-cli": "^1.2.0",
6 | "browserify": "^15.2.0",
7 | "riot": "*",
8 | "riotx": "../../"
9 | },
10 | "scripts": {
11 | "watch": "chokidar index.js -c 'npm run build'",
12 | "build": "browserify index.js -o bundle.js"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/test/karma/karma.conf.js:
--------------------------------------------------------------------------------
1 | /* eslint-env node, mocha */
2 |
3 | const
4 | buble = require('rollup-plugin-buble'),
5 | nodeResolve = require('rollup-plugin-node-resolve'),
6 | commonjs = require('rollup-plugin-commonjs'),
7 | banner = require('../../rollup.vars').banner,
8 | intro = require('../../rollup.vars').intro;
9 |
10 | var debug = !!process.env.DEBUG;
11 |
12 |
13 | let namedExports = {
14 | 'node_modules/mout/array.js': [ 'forEach' ],
15 | 'node_modules/mout/object.js': [ 'keys' ],
16 | };
17 |
18 |
19 | module.exports = config => {
20 | config.set({
21 | autoWatch: true,
22 | // client: { captureConsole: false },
23 | browsers: [
24 | 'Chrome',
25 | //'Firefox',
26 | //'Safari'
27 | ],
28 | browserConsoleLogOptions: {
29 | level: 'error',
30 | format: '%b %T: %m',
31 | terminal: false
32 | },
33 | colors: true,
34 | files: [
35 | '../../node_modules/riot/riot.js',
36 | '../../src/index.js',
37 | '../spec/index.js',
38 | 'spec.js',
39 | 'spec.tag',
40 | ],
41 | frameworks: ['mocha', 'power-assert', 'riot'],
42 | logLevel: config.LOG_DEBUG,
43 | //logLevel: config.LOG_ERROR,
44 | plugins: [
45 | //'karma-rollup-plugin',
46 | 'karma-rollup-preprocessor',
47 | 'karma-mocha',
48 | 'karma-mocha-reporter',
49 | 'karma-power-assert',
50 | 'karma-chrome-launcher',
51 | 'karma-firefox-launcher',
52 | 'karma-safari-launcher',
53 | 'karma-coverage',
54 | 'karma-riot'
55 | ],
56 | preprocessors: {
57 | '../../src/index.js': ['rollup', 'coverage'],
58 | 'spec.js': ['rollup'],
59 | '../spec/index.js': ['rollup'],
60 | 'spec.tag': ['riot'],
61 | },
62 | reporters: ['mocha', 'coverage'],
63 | rollupPreprocessor: {
64 | // context: 'this',
65 | format: 'iife',
66 | moduleName: 'riotx',
67 | globals: {
68 | riot: 'riot'
69 | },
70 | banner: banner,
71 | intro: intro,
72 | external: ['riot'],
73 | plugins: [
74 | nodeResolve({
75 | jsnext: true,
76 | main: true,
77 | browser: true
78 | }),
79 | commonjs({
80 | include: 'node_modules/**',
81 | namedExports: namedExports
82 | }),
83 | buble()
84 | ],
85 | sourceMap: false // 'inline'
86 | },
87 | singleRun: !debug,
88 | });
89 | };
90 |
--------------------------------------------------------------------------------
/test/karma/spec.js:
--------------------------------------------------------------------------------
1 | /* global assert, riot, riotx */
2 | /* eslint-env browser, node */
3 |
4 | describe('browser-side specs', () => {
5 |
6 | it('mount spec.tag', () => {
7 | let html = document.createElement('spec');
8 | document.body.appendChild(html);
9 |
10 | var store = new riotx.Store({
11 | name: 'spec',
12 | state: {
13 | name: '',
14 | },
15 | actions: {
16 | name: (context, data) => {
17 | return Promise
18 | .resolve()
19 | .then(() => {
20 | context.commit('name', data);
21 | });
22 | }
23 | },
24 | mutations: {
25 | name: (context, data) => {
26 | context.state.name = data.name;
27 | return ['name'];
28 | }
29 | },
30 | getters: {
31 | name: context => {
32 | return context.state.name;
33 | }
34 | }
35 | });
36 |
37 | riotx.add(store);
38 |
39 |
40 | var tag = riot.mount('spec', {
41 | message: 'Welcome'
42 | })[0];
43 | assert(document.querySelector('spec > h1').textContent === 'Welcome');
44 |
45 | assert(!!tag.riotx);
46 | assert(tag.riotx.get('spec').name === 'spec');
47 |
48 | });
49 | });
50 |
--------------------------------------------------------------------------------
/test/karma/spec.tag:
--------------------------------------------------------------------------------
1 |
2 | { opts.message }
3 | Name: { name }
4 |
5 |
20 |
21 |
--------------------------------------------------------------------------------
/test/requirejs/README.md:
--------------------------------------------------------------------------------
1 | RequireJS
2 |
3 | Operation test in RequireJS environment.
4 |
5 | # QuickStart
6 |
7 | ```
8 | $
9 | $
10 | $
11 | ```
12 |
13 |
14 | ## build
15 |
16 | ```
17 | $ npm install -g bower
18 | $ bower install
19 | ```
20 |
21 | ## Operation
22 |
23 | Activate the browser and check the operation.
24 |
25 | ```
26 | $ open index.html; # The counter page is displayed in the browser
27 | ```
28 |
--------------------------------------------------------------------------------
/test/requirejs/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "riotx-test",
3 | "private": true,
4 | "dependencies": {
5 | "requirejs": "~2.1.20",
6 | "riot": "*"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/test/requirejs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | riotx on require.js
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
37 |
38 |
99 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/test/spec/index.js:
--------------------------------------------------------------------------------
1 | /* eslint-env browser, node */
2 |
3 | var riot;
4 | var riotx;
5 | var assert;
6 |
7 | if (typeof window === 'undefined') {
8 | riot = require('riot');
9 | riotx = require('../../index');
10 | assert = require('power-assert');
11 | var version = require('../../package.json').version;
12 | } else {
13 | riot = window.riot;
14 | riotx = window.riotx;
15 | assert = window.assert;
16 | }
17 |
18 |
19 | riotx.strict(true);
20 |
21 |
22 | if (typeof window === 'undefined') {
23 | describe('server-side specs', () => {
24 | it('version', () => {
25 | assert(riotx.version === version); // eslint-disable-line block-scoped-var
26 | });
27 | });
28 | }
29 |
30 | describe('client-side specs', () => {
31 | it('init', () => {
32 | assert(!!riot);
33 | assert(!!riotx);
34 | assert(riotx.version !== '');
35 | });
36 |
37 | it('reset riotx', done => {
38 | riotx.add(new riotx.Store({
39 | name: 'A',
40 | state: {},
41 | actions: {},
42 | mutations: {},
43 | getters: {}
44 | }));
45 | riotx.add(new riotx.Store({
46 | name: 'B',
47 | state: {},
48 | actions: {},
49 | mutations: {},
50 | getters: {}
51 | }));
52 |
53 | const storeA = riotx.get('A');
54 | let isCalled = false;
55 | storeA.on('evt', () => {
56 | isCalled = true;
57 | });
58 | assert(riotx.get('A').name === 'A');
59 | assert(riotx.get('B').name === 'B');
60 | assert(riotx.size() === 2);
61 | riotx.reset();
62 | assert(!riotx.get('A'));
63 | assert(!riotx.get('B'));
64 | assert(riotx.size() === 0);
65 | storeA.trigger('evt');
66 | setTimeout(() => {
67 | assert(!isCalled);
68 | done();
69 | }, 100);
70 | });
71 |
72 | it('mixin', () => {
73 | riot.tag('test-tag', '{ message }
');
74 | });
75 |
76 | it('basic new Store()', done => {
77 | riotx.reset();
78 | riotx.setChangeBindName('change');
79 |
80 | var store = new riotx.Store({
81 | state: {
82 | text: '',
83 | },
84 | actions: {
85 | testAction: context => {
86 | return Promise
87 | .resolve()
88 | .then(() => {
89 | context.commit('testMutation');
90 | });
91 | }
92 | },
93 | mutations: {
94 | testMutation: context => {
95 | context.state.test = true;
96 | return ['testChangeMutation'];
97 | }
98 | },
99 | getters: {
100 | testGetter: context => {
101 | return context.state.test;
102 | }
103 | }
104 | });
105 |
106 | riotx.add(store);
107 |
108 | riotx.strict(false);
109 | assert(riotx.get().name === '@');
110 | assert(!riotx.get().state.test);
111 | riotx.strict(true);
112 |
113 |
114 | riotx.get().change('testChangeMutation', (state, store) => {
115 | let res = store.getter('testGetter');
116 | assert(res);
117 | done();
118 | });
119 |
120 | riotx.get().action('testAction'); // fire!
121 | });
122 |
123 | it('add multi riotx.Store', () => {
124 | riotx.reset();
125 |
126 | riotx.add(new riotx.Store({
127 | name: 'a',
128 | state: {},
129 | actions: {},
130 | mutations: {},
131 | getters: {}
132 | }));
133 | try {
134 | riotx.add(new riotx.Store({
135 | name: 'a',
136 | state: {},
137 | actions: {},
138 | mutations: {},
139 | getters: {}
140 | }));
141 | assert(false);
142 | } catch (e) {
143 | assert(true);
144 | }
145 | riotx.add(new riotx.Store({
146 | name: 'b',
147 | state: {},
148 | actions: {},
149 | mutations: {},
150 | getters: {}
151 | }));
152 | assert(riotx.get('a').name === 'a');
153 | assert(riotx.get('b').name === 'b');
154 | assert(riotx.size() === 2);
155 | });
156 |
157 | it('strict mode', () => {
158 | riotx.reset();
159 | riotx.strict(true);
160 | riotx.add(new riotx.Store({
161 | name: 'test',
162 | state: {
163 | test: true
164 | },
165 | actions: {},
166 | mutations: {},
167 | getters: {}
168 | }));
169 | try {
170 | const state = riotx.stores.test.state;
171 | assert.fail(`strict mode not working. ${state}`);
172 | } catch (e) {
173 | assert.ok('strict mode is working.');
174 | }
175 | });
176 |
177 | it('plugins', done => {
178 | riotx.reset();
179 | riotx.strict(true);
180 |
181 | const store = new riotx.Store({
182 | state: {
183 | hello: 'Hello',
184 | },
185 | actions: {
186 | testAction: (context, data) => {
187 | return Promise
188 | .resolve()
189 | .then(() => {
190 | context.commit('testMutation', data);
191 | });
192 | }
193 | },
194 | mutations: {
195 | testMutation: (context, data) => {
196 | context.state.hello = `${context.state.hello} ${data.text}`;
197 | return ['testChangeMutation'];
198 | }
199 | },
200 | getters: {
201 | testGetter: context => {
202 | return context.state.hello;
203 | }
204 | },
205 | plugins: [
206 | store => {
207 | store.change('riotx:mutations:after', (name, targets, context, data) => { // eslint-disable-line no-unused-vars
208 | if (name === 'testMutation' && targets.includes('testChangeMutation')) {
209 | context.state.hello = `Override ${context.state.hello}`;
210 | }
211 | });
212 | },
213 | ]
214 | });
215 | riotx.add(store);
216 |
217 | store.change('testChangeMutation', (state, store) => {
218 | let res = store.getter('testGetter');
219 | assert.equal(res, 'Override Hello World');
220 | done();
221 | });
222 | const text = 'World';
223 | store.action('testAction', {
224 | text: text
225 | });
226 | });
227 |
228 | it('Checking plugin, action, mutation and getter definition (function)', () => {
229 | riotx.reset();
230 | riotx.strict(true);
231 |
232 | assert.throws(() => {
233 | new riotx.Store({
234 | state: {},
235 | actions: {},
236 | mutations: {},
237 | getters: {},
238 | plugins: [
239 | '...'
240 | ]
241 | });
242 | }, Error);
243 |
244 | const store = new riotx.Store({
245 | state: {},
246 | actions: {
247 | testAction: '...'
248 | },
249 | mutations: {
250 | testMutation: '...'
251 | },
252 | getters: {
253 | testGetter: '...'
254 | },
255 | plugins: []
256 | });
257 |
258 | riotx.add(store);
259 | assert.throws(() => store.action('testAction'), Error);
260 | assert.throws(() => store.commit('testMutation'), Error);
261 | assert.throws(() => store.getter('testGetter'), Error);
262 | assert.throws(() => store.action('empty'), Error);
263 | assert.throws(() => store.commit('empty'), Error);
264 | assert.throws(() => store.getter('empty'), Error);
265 |
266 | });
267 |
268 | it('Unify the arguments to Getter, Action Mutation and Plugin.', done => {
269 | riotx.reset();
270 | riotx.strict(true);
271 |
272 | const store = new riotx.Store({
273 | state: {
274 | text: 'Hello'
275 | },
276 | /**
277 | * - sayGetter/sayAppendSuffixGetter Getter name.
278 | * @param {Object} context Information provided by `riotx` to `Getter`.
279 | * - context.state Store.state object
280 | * @param {Object} data Data from this caller.
281 | */
282 | getters: {
283 | sayGetter: context => {
284 | return context.state.text;
285 | },
286 | sayAppendSuffixGetter: (context, data) => {
287 | return `${context.state.text} ${data.text}`;
288 | }
289 | },
290 | /**
291 | * - sayAction Action name.
292 | * @param {Object} context Information provided by `riotx` to `Action`.
293 | * - context.getter Store.getter shortcut
294 | * - context.commit Data to carry to Mutation.
295 | * @param {Object} data Data from this caller.
296 | */
297 | actions: {
298 | sayAction: (context, data) => {
299 | context.commit('sayMutation', data);
300 | }
301 | },
302 | /**
303 | * - sayMutation Mutation name.
304 | * @param {Object} context Information provided by `riotx` to `Mutation`.
305 | * - context.getter Store.getter shortcut
306 | * - context.state Store.state object
307 | * @param {Object} data Data from this caller. (from action)
308 | * @return {Array} The name of the subscriber who wants to let you catch fire.
309 | */
310 | mutations: {
311 | sayMutation: (context, data) => {
312 | const text = `${context.getter('sayGetter')} ${data.text}`;
313 | context.state.text = text;
314 | return ['sayChangeMutation'];
315 | }
316 | },
317 | plugins: [
318 | /**
319 | * @param {Object} store Store instance.
320 | */
321 | store => {
322 | /**
323 | * - plugin subscriber
324 | * @param {String} name It will be hooked after running all `mutations`.
325 | * Event name : `riotx:mutations:after`
326 | * @param {Array} triggers Subscriber list
327 | * @param {Object} context Information provided by `riotx` to `Mutation`.
328 | * - context.getter Store.getter shortcut
329 | * - context.state Store.state object
330 | */
331 | store.change('riotx:mutations:after', (name, targets, context, data) => { // eslint-disable-line no-unused-vars
332 | if (name === 'sayMutation' && targets.includes('sayChangeMutation')) {
333 | context.state.text = `Override ${context.state.text}`;
334 | }
335 | });
336 | },
337 | ]
338 | });
339 |
340 | riotx.add(store);
341 |
342 | store.change('sayChangeMutation', (state, store) => {
343 | const text = store.getter('sayAppendSuffixGetter', {
344 | text: ':)'
345 | });
346 | assert.equal(text, 'Override Hello World :)');
347 | assert(store);
348 | done();
349 | });
350 |
351 | store.action('sayAction', {
352 | text: 'World'
353 | });
354 | });
355 |
356 | it('execute functions with proper arguments and values.', done => {
357 | riotx.reset();
358 | riotx.strict(true);
359 | const store = new riotx.Store({
360 | name: 'sample',
361 | state: {
362 | text: 'A'
363 | },
364 | actions: {
365 | testAction: (context, data) => {
366 | directStoreAccessAndMutation();// eslint-disable-line no-use-before-define
367 | assert(!!context);
368 | assert(!!context.getter);
369 | assert(!!context.commit);
370 | assert(!!data);
371 | assert(data.text === ':)');
372 | const text = context.getter('testGetter', {
373 | text: ':('
374 | });
375 | assert(text === 'A');
376 | return Promise.resolve().then(() => {
377 | context.commit('testMutation', {
378 | text: 'B'
379 | });
380 | });
381 | }
382 | },
383 | mutations: {
384 | testMutation: (context, data) => {
385 | directStoreAccessAndMutation();// eslint-disable-line no-use-before-define
386 | assert(!!context);
387 | assert(!!context.getter);
388 | const currentText = context.getter('testGetter', {
389 | text: ':('
390 | });
391 | assert(currentText === 'A');
392 | assert(!!context.state);
393 | assert(data.text === 'B');
394 | context.state.text = data.text;
395 | return ['change'];
396 | }
397 | },
398 | getters: {
399 | testGetter: (context, data) => {
400 | directStoreAccessAndMutation();// eslint-disable-line no-use-before-define
401 | assert(!!context);
402 | assert(!!context.state);
403 | assert(context.state.text === 'A');
404 | assert(!!data);
405 | assert(data.text === ':(');
406 | return context.state.text;
407 | }
408 | },
409 | plugins: [store => {
410 | assert.throws(() => {
411 | store.state.text;// eslint-disable-line no-unused-expressions
412 | }, Error, 'direct access not allowed with strict mode on.');
413 | assert.throws(() => {
414 | store.state.text = ':(';
415 | }, Error, 'direct mutation not allowed with strict mode on.');
416 | store.change('riotx:mutations:after', (name, triggers, context, data) => {
417 | assert(name === 'testMutation');
418 | assert(triggers.length === 1);
419 | assert(triggers[0] === 'change');
420 | assert(!!context);
421 | assert(!!context.getter);
422 | assert(!!context.state);
423 | assert(!!data);
424 | assert(data.text === 'B');
425 | assert.doesNotThrow(() => {
426 | context.state.text;// eslint-disable-line no-unused-expressions
427 | }, 'plugin functions can access to state.');
428 | assert.doesNotThrow(() => {
429 | context.state.text2 = ':)';
430 | }, 'plugin functions can mutate state.');
431 | });
432 | }]
433 | });
434 | riotx.add(store);
435 | const directStoreAccessAndMutation = () => {
436 | assert.throws(() => {
437 | store.state.text;// eslint-disable-line no-unused-expressions
438 | }, Error, 'direct access not allowed with strict mode on.');
439 | assert.throws(() => {
440 | store.state.text = ':(';
441 | }, Error, 'direct mutation not allowed with strict mode on.');
442 | };
443 | directStoreAccessAndMutation();
444 | assert.doesNotThrow(() => {
445 | store.getter('testGetter', {
446 | text: ':('
447 | });
448 | }, 'should be able to get data via getter functions.');
449 | assert(store.getter('testGetter', {
450 | text: ':('
451 | }) === 'A');
452 | store.on('change', (state, store) => {
453 | assert(!!state);
454 | assert(!!store);
455 | assert(store.name === 'sample');
456 | assert(state.text === 'B');
457 | assert.throws(() => {
458 | store.state.text;// eslint-disable-line no-unused-expressions
459 | }, Error, 'direct access not allowed with strict mode on.');
460 | assert.throws(() => {
461 | store.state.text = ':(';
462 | }, Error, 'direct mutation not allowed with strict mode on.');
463 | done();
464 | });
465 | store.action('testAction', {
466 | text: ':)'
467 | });
468 | });
469 |
470 | });
471 |
--------------------------------------------------------------------------------