nali 0.2.9 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +26 -31
- data/lib/client/javascripts/nali/collection.js.coffee +14 -5
- data/lib/client/javascripts/nali/connection.js.coffee +4 -4
- data/lib/client/javascripts/nali/form2js.min.js +1 -0
- data/lib/client/javascripts/nali/index.js +1 -0
- data/lib/client/javascripts/nali/model.js.coffee +30 -37
- data/lib/client/javascripts/nali/nali.js.coffee +1 -1
- data/lib/client/javascripts/nali/notice.js.coffee +5 -8
- data/lib/client/javascripts/nali/view.js.coffee +17 -22
- data/lib/generator/app/client/stylesheets/{notices → notice}/error.css.sass +0 -0
- data/lib/generator/app/client/stylesheets/{notices → notice}/info.css.sass +0 -0
- data/lib/generator/app/client/stylesheets/{notices → notice}/warning.css.sass +0 -0
- data/lib/nali/connection.rb +14 -15
- data/lib/nali/controller.rb +3 -3
- data/lib/nali/generator.rb +8 -0
- data/lib/nali/model.rb +6 -4
- data/lib/nali/version.rb +1 -1
- metadata +6 -5
data/README.md
CHANGED
@@ -1,31 +1,26 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
**Nali** - это фреймворк для разработки асинхронных веб приложений, включающий в себя веб-сервер и инструменты для создания как клиентской, так и серверной части. Серверная часть разрабатывается на языке **Ruby**, клиентская часть на **Coffeescript** (или Javascript), **Sass** (или
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
***bundle exec thin start***
|
28
|
-
|
29
|
-
6. Откройте браузер и перейдите по адресу `http://localhost:3000`
|
30
|
-
|
31
|
-
Вы увидите первую подготовленную страницу "Welcome to Nali"
|
1
|
+
## Добро пожаловать в Nali
|
2
|
+
|
3
|
+
**Nali** - это фреймворк для разработки асинхронных веб приложений, включающий в себя веб-сервер и инструменты для создания как клиентской, так и серверной части. Серверная часть разрабатывается на языке **Ruby**, клиентская часть на **Coffeescript** (или Javascript), **Sass** (или scss, css) и **Html** (или erb)
|
4
|
+
|
5
|
+
#### Документация
|
6
|
+
|
7
|
+
* [**Начало работы**](../../wiki/Начало-работы)
|
8
|
+
* [**Структура приложения**](../../wiki/Структура-приложения)
|
9
|
+
* **Основные компоненты**
|
10
|
+
* [Модель](../../wiki/Модель)
|
11
|
+
* [Вид](../../wiki/Вид)
|
12
|
+
* [Контроллер](../../wiki/Контроллер)
|
13
|
+
* [Коллекция](../../wiki/Коллекция)
|
14
|
+
* **Клиентская часть**
|
15
|
+
* [Базовый объект Nali](../../wiki/Nali)
|
16
|
+
* [Старт приложения](../../wiki/Nali.Application)
|
17
|
+
* [Система событий](../../wiki/Система-событий)
|
18
|
+
* [Модель уведомлений Notice](../../wiki/Nali.Notice)
|
19
|
+
* [Роутер](../../wiki/Nali.Router)
|
20
|
+
* [Соединение с сервером](../../wiki/Nali.Connection)
|
21
|
+
* [Работа с Cookie](../../wiki/Nali.Cookie)
|
22
|
+
* **Серверная часть**
|
23
|
+
* [Работа с клиентами](../../Работа с клиентами)
|
24
|
+
* [Маршрутизация](../../Маршрутизация)
|
25
|
+
* [Генератор](../../Генератор)
|
26
|
+
* [Rake задачи](../../Rake задачи)
|
@@ -7,20 +7,25 @@ Nali.extend Collection:
|
|
7
7
|
cloning: ->
|
8
8
|
@subscribeTo @Model, "create.#{ @model._name.lower() }", @onModelCreated
|
9
9
|
@subscribeTo @Model, "update.#{ @model._name.lower() }", @onModelUpdated
|
10
|
+
@subscribeTo @Model, "destroy.#{ @model._name.lower() }", @onModelDestroyed
|
10
11
|
@adaptations = apply: [], cancel: []
|
11
12
|
@ordering = {}
|
12
13
|
@adaptCollection()
|
13
|
-
@
|
14
|
+
@refilter()
|
15
|
+
@
|
16
|
+
|
17
|
+
refilter: ->
|
18
|
+
@model.each ( model ) => @add model if model.isCorrect( @filters ) and not ( model in @ )
|
14
19
|
@
|
15
20
|
|
16
21
|
new: ( model, filters ) ->
|
17
22
|
@clone model: model, filters: filters
|
18
23
|
|
19
|
-
onModelCreated: (
|
24
|
+
onModelCreated: ( model ) ->
|
20
25
|
@add model if not @freezed and model.isCorrect @filters
|
21
26
|
@
|
22
27
|
|
23
|
-
onModelUpdated: (
|
28
|
+
onModelUpdated: ( model ) ->
|
24
29
|
if model.written()
|
25
30
|
if model in @
|
26
31
|
if @freezed or model.isCorrect @filters
|
@@ -32,7 +37,7 @@ Nali.extend Collection:
|
|
32
37
|
@
|
33
38
|
|
34
39
|
onModelDestroyed: ( model ) ->
|
35
|
-
@remove model
|
40
|
+
@remove model if model in @ and not @freezed
|
36
41
|
@
|
37
42
|
|
38
43
|
adaptCollection: ->
|
@@ -57,7 +62,6 @@ Nali.extend Collection:
|
|
57
62
|
for model in [].concat models...
|
58
63
|
Array::push.call @, model
|
59
64
|
@adaptModel model
|
60
|
-
@subscribeTo model, 'destroy', @onModelDestroyed
|
61
65
|
@reorder()
|
62
66
|
@trigger 'update.length.add', model
|
63
67
|
@trigger 'update.length', 'add', model
|
@@ -100,6 +104,7 @@ Nali.extend Collection:
|
|
100
104
|
|
101
105
|
unfreeze: ->
|
102
106
|
@freezed = false
|
107
|
+
@refilter()
|
103
108
|
@
|
104
109
|
|
105
110
|
where: ( filters ) ->
|
@@ -156,6 +161,10 @@ Nali.extend Collection:
|
|
156
161
|
model.hide viewName
|
157
162
|
@
|
158
163
|
|
164
|
+
hide: ( viewName, delay ) ->
|
165
|
+
model.hide viewName, delay for model in @
|
166
|
+
@
|
167
|
+
|
159
168
|
prepareViewToShow: ( view ) ->
|
160
169
|
unless view in @::toShowViews
|
161
170
|
@::toShowViews.push view
|
@@ -53,11 +53,11 @@ Nali.extend Connection:
|
|
53
53
|
@Model.sync message.params
|
54
54
|
@
|
55
55
|
|
56
|
-
|
57
|
-
if model
|
56
|
+
callMethod: ( { model, method, params } ) ->
|
57
|
+
if model is 'Notice' then @Notice[ method ] params
|
58
|
+
else
|
58
59
|
[ model, id ] = model.split '.'
|
59
|
-
@Model.
|
60
|
-
else @Notice[ notice ] params
|
60
|
+
@Model.callStackAdd model: model, id: id, method: method, params: params
|
61
61
|
@
|
62
62
|
|
63
63
|
success: ( message ) ->
|
@@ -0,0 +1 @@
|
|
1
|
+
(function(e,t){if(typeof define==="function"&&define.amd){define(t)}else{e.form2js=t()}})(this,function(){"use strict";function e(e,r,i,s,o,u){u=u?true:false;if(typeof i=="undefined"||i==null)i=true;if(typeof r=="undefined"||r==null)r=".";if(arguments.length<5)o=false;e=typeof e=="string"?document.getElementById(e):e;var a=[],f,l=0;if(e.constructor==Array||typeof NodeList!="undefined"&&e.constructor==NodeList){while(f=e[l++]){a=a.concat(n(f,s,o,u))}}else{a=n(e,s,o,u)}return t(a,i,r)}function t(e,t,n){var r={},i={},s,o,u,a,f,l,c,h,p,d,v,m,g;for(s=0;s<e.length;s++){f=e[s].value;if(t&&(f===""||f===null))continue;m=e[s].name;g=m.split(n);l=[];c=r;h="";for(o=0;o<g.length;o++){v=g[o].split("][");if(v.length>1){for(u=0;u<v.length;u++){if(u==0){v[u]=v[u]+"]"}else if(u==v.length-1){v[u]="["+v[u]}else{v[u]="["+v[u]+"]"}d=v[u].match(/([a-z_]+)?\[([a-z_][a-z0-9_]+?)\]/i);if(d){for(a=1;a<d.length;a++){if(d[a])l.push(d[a])}}else{l.push(v[u])}}}else l=l.concat(v)}for(o=0;o<l.length;o++){v=l[o];if(v.indexOf("[]")>-1&&o==l.length-1){p=v.substr(0,v.indexOf("["));h+=p;if(!c[p])c[p]=[];c[p].push(f)}else if(v.indexOf("[")>-1){p=v.substr(0,v.indexOf("["));d=v.replace(/(^([a-z_]+)?\[)|(\]$)/gi,"");h+="_"+p+"_"+d;if(!i[h])i[h]={};if(p!=""&&!c[p])c[p]=[];if(o==l.length-1){if(p==""){c.push(f);i[h][d]=c[c.length-1]}else{c[p].push(f);i[h][d]=c[p][c[p].length-1]}}else{if(!i[h][d]){if(/^[0-9a-z_]+\[?/i.test(l[o+1]))c[p].push({});else c[p].push([]);i[h][d]=c[p][c[p].length-1]}}c=i[h][d]}else{h+=v;if(o<l.length-1){if(!c[v])c[v]={};c=c[v]}else{c[v]=f}}}}return r}function n(e,t,n,s){var o=i(e,t,n,s);return o.length>0?o:r(e,t,n,s)}function r(e,t,n,r){var s=[],o=e.firstChild;while(o){s=s.concat(i(o,t,n,r));o=o.nextSibling}return s}function i(e,t,n,i){if(e.disabled&&!i)return[];var u,a,f,l=s(e,n);u=t&&t(e);if(u&&u.name){f=[u]}else if(l!=""&&e.nodeName.match(/INPUT|TEXTAREA/i)){a=o(e,i);if(null===a){f=[]}else{f=[{name:l,value:a}]}}else if(l!=""&&e.nodeName.match(/SELECT/i)){a=o(e,i);f=[{name:l.replace(/\[\]$/,""),value:a}]}else{f=r(e,t,n,i)}return f}function s(e,t){if(e.name&&e.name!="")return e.name;else if(t&&e.id&&e.id!="")return e.id;else return""}function o(e,t){if(e.disabled&&!t)return null;switch(e.nodeName){case"INPUT":case"TEXTAREA":switch(e.type.toLowerCase()){case"radio":if(e.checked&&e.value==="false")return false;case"checkbox":if(e.checked&&e.value==="true")return true;if(!e.checked&&e.value==="true")return false;if(e.checked)return e.value;break;case"button":case"reset":case"submit":case"image":return"";break;default:return e.value;break}break;case"SELECT":return u(e);break;default:break}return null}function u(e){var t=e.multiple,n=[],r,i,s;if(!t)return e.value;for(r=e.getElementsByTagName("option"),i=0,s=r.length;i<s;i++){if(r[i].selected)n.push(r[i].value)}return n}return e})
|
@@ -14,7 +14,7 @@ Nali.extend Model:
|
|
14
14
|
tables: {}
|
15
15
|
attributes: {}
|
16
16
|
updated: 0
|
17
|
-
|
17
|
+
callStack: []
|
18
18
|
destroyed: false
|
19
19
|
|
20
20
|
adapt: ->
|
@@ -36,18 +36,18 @@ Nali.extend Model:
|
|
36
36
|
unless @[ hideMethod = 'hide' + shortCap ]? then @[ hideMethod ] = -> @hide short
|
37
37
|
@
|
38
38
|
|
39
|
-
|
40
|
-
# добавляет
|
41
|
-
@
|
42
|
-
@
|
39
|
+
callStackAdd: ( params ) ->
|
40
|
+
# добавляет задачу в очередь на выполнение, запускает выполнение очереди
|
41
|
+
@callStack.push params
|
42
|
+
@runStack()
|
43
43
|
@
|
44
44
|
|
45
|
-
|
46
|
-
# запускает выполнение
|
47
|
-
for item, index in @
|
45
|
+
runStack: ->
|
46
|
+
# запускает выполнение задач у существующих моделей
|
47
|
+
for item, index in @callStack[ 0.. ]
|
48
48
|
if model = @extensions[ item.model ].find item.id
|
49
|
-
model[ item.
|
50
|
-
@
|
49
|
+
model[ item.method ] item.params
|
50
|
+
@callStack.splice @callStack.indexOf( item ), 1
|
51
51
|
@
|
52
52
|
|
53
53
|
# работа с моделями
|
@@ -58,13 +58,6 @@ Nali.extend Model:
|
|
58
58
|
@setRelations()
|
59
59
|
@
|
60
60
|
|
61
|
-
force: ( params = {} ) ->
|
62
|
-
# создает новую модель с заданными атрибутами
|
63
|
-
attributes = @defaultAttributes()
|
64
|
-
attributes[ name ] = value for name, value of params
|
65
|
-
attributes[ name ] = @normalizeValue value for name, value of attributes
|
66
|
-
@clone( attributes: attributes ).accessing()
|
67
|
-
|
68
61
|
save: ( success, failure ) ->
|
69
62
|
# отправляет на сервер запрос на сохранение модели, вызывает success в случае успеха и failure при неудаче
|
70
63
|
if @isValid()
|
@@ -109,7 +102,7 @@ Nali.extend Model:
|
|
109
102
|
@table.push @
|
110
103
|
@onCreate?()
|
111
104
|
@Model.trigger "create.#{ @_name.lower() }", @
|
112
|
-
@Model.
|
105
|
+
@Model.runStack()
|
113
106
|
@
|
114
107
|
|
115
108
|
remove: ->
|
@@ -119,13 +112,16 @@ Nali.extend Model:
|
|
119
112
|
delete @table.index[ @id ]
|
120
113
|
@table.splice @table.indexOf( @ ), 1
|
121
114
|
@trigger 'destroy'
|
115
|
+
@Model.trigger "destroy.#{ @_name.lower() }", @
|
122
116
|
@onDestroy?()
|
123
117
|
@unsubscribeAll()
|
124
118
|
@
|
125
119
|
|
126
120
|
new: ( attributes ) ->
|
127
121
|
# создает модель, не сохраняя её на сервере
|
128
|
-
@
|
122
|
+
model = @clone( attributes: @defaultAttributes() ).accessing()
|
123
|
+
model[ name ] = @normalizeValue value for name, value of attributes
|
124
|
+
model
|
129
125
|
|
130
126
|
create: ( attributes, success, failure ) ->
|
131
127
|
# создает модель, и сохраняет её на сервере, вызывает success в случае успеха и failure при неудаче
|
@@ -136,7 +132,7 @@ Nali.extend Model:
|
|
136
132
|
if not updated or updated > @updated
|
137
133
|
@created = created if created
|
138
134
|
changed = []
|
139
|
-
changed.push name for name, value of attributes when @
|
135
|
+
changed.push name for name, value of attributes when @updateProperty name, value
|
140
136
|
if changed.length
|
141
137
|
@updated = updated if updated
|
142
138
|
@onUpdate? changed
|
@@ -144,8 +140,8 @@ Nali.extend Model:
|
|
144
140
|
@Model.trigger "update.#{ @_name.lower() }", @
|
145
141
|
@
|
146
142
|
|
147
|
-
|
148
|
-
# обновляет один атрибут модели, проверяя его валидность, генерирует событие update.
|
143
|
+
updateProperty: ( name, value ) ->
|
144
|
+
# обновляет один атрибут модели, проверяя его валидность, генерирует событие update.propertyName
|
149
145
|
value = @normalizeValue value
|
150
146
|
if @[ name ] isnt value and @isValidAttributeValue( name, value )
|
151
147
|
@[ name ] = value
|
@@ -172,12 +168,7 @@ Nali.extend Model:
|
|
172
168
|
|
173
169
|
where: ( filters ) ->
|
174
170
|
# возвращает коллекцию моделей соответствующих фильтру
|
175
|
-
|
176
|
-
if @forced and not collection.length
|
177
|
-
attributes = {}
|
178
|
-
attributes[ key ] = value for key, value of filters when typeof value in [ 'number', 'string' ]
|
179
|
-
collection.add @new attributes
|
180
|
-
collection
|
171
|
+
@Collection.new @, filters
|
181
172
|
|
182
173
|
all: ->
|
183
174
|
# возвращает коллекцию всех моделей
|
@@ -203,8 +194,8 @@ Nali.extend Model:
|
|
203
194
|
attributes = id: @guid()
|
204
195
|
for name, value of @attributes
|
205
196
|
if value instanceof Object
|
206
|
-
attributes[ name ] = if value.default? then value.default else null
|
207
|
-
else attributes[ name ] = value
|
197
|
+
attributes[ name ] = if value.default? then @normalizeValue value.default else null
|
198
|
+
else attributes[ name ] = @normalizeValue value
|
208
199
|
attributes
|
209
200
|
|
210
201
|
normalizeValue: ( value ) ->
|
@@ -333,8 +324,8 @@ Nali.extend Model:
|
|
333
324
|
@[ name ] = model.where correct: ->
|
334
325
|
return true for model in @[ through ] when model[ key ] is @
|
335
326
|
false
|
336
|
-
@[ name ].subscribeTo @[ through ], 'update.length.add', (
|
337
|
-
@[ name ].subscribeTo @[ through ], 'update.length.remove', (
|
327
|
+
@[ name ].subscribeTo @[ through ], 'update.length.add', ( model ) -> @add model[ key ]
|
328
|
+
@[ name ].subscribeTo @[ through ], 'update.length.remove', ( model ) -> @remove model[ key ]
|
338
329
|
@[ name ]
|
339
330
|
@
|
340
331
|
|
@@ -354,10 +345,10 @@ Nali.extend Model:
|
|
354
345
|
# функция возвращает объект вида при успехе либо null при неудаче
|
355
346
|
if ( view = @view( name ) )? then view.show insertTo else null
|
356
347
|
|
357
|
-
hide: ( name ) ->
|
348
|
+
hide: ( name, delay ) ->
|
358
349
|
# удаляет html-код вида со страницы
|
359
350
|
# функция возвращает объект вида при успехе либо null при неудаче
|
360
|
-
if ( view = @view( name ) )? then view.hide
|
351
|
+
if ( view = @view( name ) )? then view.hide delay else null
|
361
352
|
|
362
353
|
# валидации
|
363
354
|
|
@@ -390,12 +381,14 @@ Nali.extend Model:
|
|
390
381
|
|
391
382
|
isValidAttributeValue: ( name, value ) ->
|
392
383
|
# проверяет валидно ли значение для определенного атрибута модели, вызывается при проверке
|
393
|
-
# валидности модели, а также в методе
|
384
|
+
# валидности модели, а также в методе updateProperty() перед изменением значения атрибута, если значение
|
394
385
|
# валидно то вызов model.isValidAttributeValue( name, value )? вернет true, иначе false
|
395
386
|
for validation, tester of @validations when ( filter = @::attributes[ name ]?[ validation ] )?
|
396
387
|
unless tester.call @, value, filter
|
397
388
|
console.warn 'Attribute %s of model %O has not validate %s', name, @, validation
|
398
|
-
|
399
|
-
|
389
|
+
if notice = @::attributes[ name ].notice
|
390
|
+
for type, params of notice
|
391
|
+
if @Notice[ type ]? then @Notice[ type ] params
|
392
|
+
else console.warn 'Unknown Notice type "%s"', type
|
400
393
|
return false
|
401
394
|
true
|
@@ -2,19 +2,16 @@ Nali.Model.extend Notice:
|
|
2
2
|
|
3
3
|
initialize: ->
|
4
4
|
@::::expand Notice: @
|
5
|
+
@addMethods()
|
5
6
|
|
6
7
|
prepare: ( params ) ->
|
7
8
|
params = message: params if typeof params is 'string'
|
8
9
|
params
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
@new( @prepare params ).show 'warning'
|
15
|
-
|
16
|
-
error: ( params ) ->
|
17
|
-
@new( @prepare params ).show 'error'
|
11
|
+
addMethods: ->
|
12
|
+
for name of @views
|
13
|
+
do ( name ) =>
|
14
|
+
@[ name ] = ( params ) => @new( @prepare params ).show name
|
18
15
|
|
19
16
|
|
20
17
|
Nali.View.extend
|
@@ -28,7 +28,7 @@ Nali.extend View:
|
|
28
28
|
@subscribeTo source, event, @onSourceUpdated
|
29
29
|
|
30
30
|
insertTo: ->
|
31
|
-
if ( layout = @layout() )?.childOf? 'View' then layout.show().
|
31
|
+
if ( layout = @layout() )?.childOf? 'View' then layout.show().yield
|
32
32
|
else @Application.htmlContainer
|
33
33
|
|
34
34
|
draw: ->
|
@@ -45,6 +45,7 @@ Nali.extend View:
|
|
45
45
|
@subscribeTo @model, 'destroy', @onSourceDestroyed
|
46
46
|
@element.appendTo insertTo
|
47
47
|
setTimeout ( => @onShow() ), 5 if @onShow?
|
48
|
+
@trigger 'show'
|
48
49
|
@visible = true
|
49
50
|
@runModelCallback 'afterShow'
|
50
51
|
else
|
@@ -54,18 +55,19 @@ Nali.extend View:
|
|
54
55
|
hide: ( delay = 0 ) ->
|
55
56
|
if @visible
|
56
57
|
@runModelCallback 'beforeHide'
|
57
|
-
@hideDelay = delay if typeof( delay ) is 'number' and delay
|
58
58
|
@onHide?()
|
59
59
|
@trigger 'hide'
|
60
60
|
@runAssistants 'hide'
|
61
|
-
@hideElement
|
61
|
+
@hideElement delay or @hideDelay
|
62
62
|
@destroyObservation()
|
63
63
|
@visible = false
|
64
64
|
@runModelCallback 'afterHide'
|
65
65
|
@
|
66
66
|
|
67
|
-
hideElement: ->
|
68
|
-
if
|
67
|
+
hideElement: ( delay ) ->
|
68
|
+
if delay and typeof( delay ) is 'number'
|
69
|
+
setTimeout ( => @removeElement() ), delay
|
70
|
+
else @removeElement()
|
69
71
|
@
|
70
72
|
|
71
73
|
removeElement: ->
|
@@ -83,7 +85,7 @@ Nali.extend View:
|
|
83
85
|
|
84
86
|
runForm: ( event ) ->
|
85
87
|
event.preventDefault()
|
86
|
-
@runUrl event.currentTarget.getAttribute( 'action' ),
|
88
|
+
@runUrl event.currentTarget.getAttribute( 'action' ), form2js event.currentTarget, '.', false
|
87
89
|
@
|
88
90
|
|
89
91
|
runUrl: ( url, params ) ->
|
@@ -100,7 +102,7 @@ Nali.extend View:
|
|
100
102
|
|
101
103
|
parseUrlSegments: ( segments ) ->
|
102
104
|
params = []
|
103
|
-
for segment in segments
|
105
|
+
for segment in segments when segment isnt ''
|
104
106
|
[ name, value ] = segment.split ':'
|
105
107
|
if value
|
106
108
|
last = params[ params.length - 1 ]
|
@@ -109,17 +111,6 @@ Nali.extend View:
|
|
109
111
|
else params.push name
|
110
112
|
params
|
111
113
|
|
112
|
-
formToHash: ( form ) ->
|
113
|
-
params = {}
|
114
|
-
for element in form.elements
|
115
|
-
if name = element.name or element.id
|
116
|
-
property = ( keys = name.match /[^\[\]]+/g ).pop()
|
117
|
-
target = params
|
118
|
-
for key in keys
|
119
|
-
target = if target[ key ] instanceof Object then target[ key ] else target[ key ] = {}
|
120
|
-
target[ property ] = element.value
|
121
|
-
params
|
122
|
-
|
123
114
|
parseEvents: ->
|
124
115
|
@eventsMap = []
|
125
116
|
if @events
|
@@ -166,7 +157,6 @@ Nali.extend View:
|
|
166
157
|
if container = document.querySelector '#' + @_name.underscore()
|
167
158
|
@template = container.innerHTML.trim().replace( /\s+/g, ' ' )
|
168
159
|
.replace( /({\s*\+.+?\s*})/g, ' <assist>$1</assist>' )
|
169
|
-
.replace( /{\s*yield\s*}/g, '<div class="yield"></div>' )
|
170
160
|
unless RegExp( "^<[^>]+" + @_name ).test @template
|
171
161
|
@template = "<div class=\"#{ @_name }\">#{ @template }</div>"
|
172
162
|
@parseAssistants()
|
@@ -184,7 +174,9 @@ Nali.extend View:
|
|
184
174
|
|
185
175
|
scanAssistants: ( node, path = [] ) ->
|
186
176
|
if node.nodeType is 3
|
187
|
-
if
|
177
|
+
if /{\s*yield\s*}/.test( node.textContent.trim() ) and node.parentNode.childNodes.length is 1
|
178
|
+
@assistantsMap.push nodepath: path, type: 'Yield'
|
179
|
+
else if /^{\s*\w+ of @\w*\s*}$/.test( node.textContent.trim() ) and node.parentNode.childNodes.length is 1
|
188
180
|
@assistantsMap.push nodepath: path, type: 'Relation'
|
189
181
|
else if /{\s*.+?\s*}/.test node.textContent
|
190
182
|
@assistantsMap.push nodepath: path, type: 'Text'
|
@@ -238,7 +230,7 @@ Nali.extend View:
|
|
238
230
|
_node = @_ node
|
239
231
|
|
240
232
|
updateSource = ->
|
241
|
-
( params = {} )[ property ] = node.value
|
233
|
+
( params = {} )[ property ] = if node.type is 'checkbox' and !node.checked then null else node.value
|
242
234
|
source.update params
|
243
235
|
source.save() unless node.form?
|
244
236
|
|
@@ -251,7 +243,7 @@ Nali.extend View:
|
|
251
243
|
when node.type in [ 'checkbox', 'radio' ]
|
252
244
|
[
|
253
245
|
-> node.checked = source[ property ] + '' is node.value
|
254
|
-
-> _node.on 'change', => updateSource.call @ if node.checked is true
|
246
|
+
-> _node.on 'change', => updateSource.call @ if node.type is 'checkbox' or node.checked is true
|
255
247
|
]
|
256
248
|
when node.type is 'select-one'
|
257
249
|
[
|
@@ -268,6 +260,9 @@ Nali.extend View:
|
|
268
260
|
_node.off 'change'
|
269
261
|
@
|
270
262
|
|
263
|
+
addYieldAssistant: ( node ) ->
|
264
|
+
( @yield = node.parentNode ).removeChild node
|
265
|
+
|
271
266
|
addRelationAssistant: ( node ) ->
|
272
267
|
[ match, name, chain ] = node.textContent.match /{\s*(\w+) of @(\w*)\s*}/
|
273
268
|
( insertTo = node.parentNode ).removeChild node
|
File without changes
|
File without changes
|
File without changes
|
data/lib/nali/connection.rb
CHANGED
@@ -7,14 +7,16 @@ module EventMachine
|
|
7
7
|
@watches = {}
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
10
|
+
def storage
|
11
11
|
@storage ||= {}
|
12
|
-
|
12
|
+
end
|
13
|
+
|
14
|
+
def []( name = nil )
|
15
|
+
name ? ( storage[ name ] or nil ) : storage
|
13
16
|
end
|
14
17
|
|
15
|
-
def []=( name, value
|
16
|
-
|
17
|
-
@storage[ name ] = value
|
18
|
+
def []=( name, value )
|
19
|
+
storage[ name ] = value
|
18
20
|
end
|
19
21
|
|
20
22
|
def watches
|
@@ -56,16 +58,13 @@ module EventMachine
|
|
56
58
|
end
|
57
59
|
end
|
58
60
|
|
59
|
-
def
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
end
|
67
|
-
message[ :params ] = params
|
68
|
-
send_json message
|
61
|
+
def call_method( method, model, params = nil )
|
62
|
+
model = "#{ model.class.name }.#{ model.id }" if model.is_a?( ActiveRecord::Base )
|
63
|
+
send_json action: 'callMethod', model: model, method: method, params: params
|
64
|
+
end
|
65
|
+
|
66
|
+
def notice( method, params = nil )
|
67
|
+
call_method method, 'Notice', params
|
69
68
|
end
|
70
69
|
|
71
70
|
def info( params )
|
data/lib/nali/controller.rb
CHANGED
@@ -33,10 +33,10 @@ module Nali
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def save
|
36
|
-
params[ :id ].to_i.to_s == params[ :id ].to_s ?
|
36
|
+
params[ :id ].to_i.to_s == params[ :id ].to_s ? _update : _create
|
37
37
|
end
|
38
38
|
|
39
|
-
def
|
39
|
+
def _create
|
40
40
|
model = model_class.new params
|
41
41
|
model.access_action( :create, client ) do |options|
|
42
42
|
permit_params options
|
@@ -47,7 +47,7 @@ module Nali
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
def
|
50
|
+
def _update
|
51
51
|
if model = model_class.find_by_id( params[ :id ] )
|
52
52
|
model.access_action( :update, client ) do |options|
|
53
53
|
permit_params options
|
data/lib/nali/generator.rb
CHANGED
@@ -23,10 +23,16 @@ module Nali
|
|
23
23
|
dirs << File.join( target_path, 'db' )
|
24
24
|
dirs << File.join( target_path, 'db/migrate' )
|
25
25
|
dirs << File.join( target_path, 'lib' )
|
26
|
+
dirs << File.join( target_path, 'lib/client' )
|
27
|
+
dirs << File.join( target_path, 'lib/client/javascripts' )
|
28
|
+
dirs << File.join( target_path, 'lib/client/stylesheets' )
|
26
29
|
dirs << File.join( target_path, 'public' )
|
27
30
|
dirs << File.join( target_path, 'public/client' )
|
28
31
|
dirs << File.join( target_path, 'tmp' )
|
29
32
|
dirs << File.join( target_path, 'vendor' )
|
33
|
+
dirs << File.join( target_path, 'vendor/client' )
|
34
|
+
dirs << File.join( target_path, 'vendor/client/javascripts' )
|
35
|
+
dirs << File.join( target_path, 'vendor/client/stylesheets' )
|
30
36
|
dirs << File.join( target_path, 'config/initializers' )
|
31
37
|
dirs.each { |path| Dir.mkdir( path ) unless Dir.exists?( path ) }
|
32
38
|
puts "Application #{ name } created"
|
@@ -116,6 +122,8 @@ end"
|
|
116
122
|
|
117
123
|
helpers: {}
|
118
124
|
|
125
|
+
onDraw: ->
|
126
|
+
|
119
127
|
onShow: ->
|
120
128
|
|
121
129
|
onHide: ->"
|
data/lib/nali/model.rb
CHANGED
@@ -38,7 +38,9 @@ module Nali
|
|
38
38
|
relations << value
|
39
39
|
elsif value.is_a?( ActiveRecord::Base )
|
40
40
|
relations << value
|
41
|
-
|
41
|
+
if reflection = self.class.reflections[ option ] and reflection.macro == :belongs_to
|
42
|
+
params[ :attributes ][ option.to_s + '_id' ] = value.id
|
43
|
+
end
|
42
44
|
else
|
43
45
|
params[ :attributes ][ option ] = value
|
44
46
|
end
|
@@ -64,9 +66,9 @@ module Nali
|
|
64
66
|
watches.flatten.each { |client| client.watch self }
|
65
67
|
clients.each { |client| client.sync self if client.watch?( self ) }
|
66
68
|
end
|
67
|
-
|
68
|
-
def
|
69
|
-
clients.each { |client| client.
|
69
|
+
|
70
|
+
def call_method( name, params )
|
71
|
+
clients.each { |client| client.call_method self, name, params if client.watch?( self ) }
|
70
72
|
end
|
71
73
|
|
72
74
|
private
|
data/lib/nali/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nali
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-11-
|
12
|
+
date: 2014-11-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: thin
|
@@ -208,6 +208,7 @@ files:
|
|
208
208
|
- lib/client/javascripts/nali/collection.js.coffee
|
209
209
|
- lib/client/javascripts/nali/application.js.coffee
|
210
210
|
- lib/client/javascripts/nali/index.js
|
211
|
+
- lib/client/javascripts/nali/form2js.min.js
|
211
212
|
- lib/client/javascripts/nali/connection.js.coffee
|
212
213
|
- lib/nali.rb
|
213
214
|
- lib/nali/extensions.rb
|
@@ -230,10 +231,10 @@ files:
|
|
230
231
|
- lib/generator/app/client/templates/notice/warning.html
|
231
232
|
- lib/generator/app/client/templates/notice/info.html
|
232
233
|
- lib/generator/app/client/templates/home/index.html
|
234
|
+
- lib/generator/app/client/stylesheets/notice/info.css.sass
|
235
|
+
- lib/generator/app/client/stylesheets/notice/error.css.sass
|
236
|
+
- lib/generator/app/client/stylesheets/notice/warning.css.sass
|
233
237
|
- lib/generator/app/client/stylesheets/home/index.css.sass
|
234
|
-
- lib/generator/app/client/stylesheets/notices/info.css.sass
|
235
|
-
- lib/generator/app/client/stylesheets/notices/error.css.sass
|
236
|
-
- lib/generator/app/client/stylesheets/notices/warning.css.sass
|
237
238
|
- lib/generator/app/client/stylesheets/application.css.sass
|
238
239
|
- lib/generator/app/server/models/access.yml
|
239
240
|
- lib/generator/app/server/routes.rb
|