nali 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +19 -14
- data/lib/client/javascripts/nali/application.js.coffee +59 -0
- data/lib/client/javascripts/nali/collection.js.coffee +188 -0
- data/lib/{assets → client}/javascripts/nali/connection.js.coffee +32 -32
- data/lib/{assets → client}/javascripts/nali/controller.js.coffee +28 -30
- data/lib/{assets → client}/javascripts/nali/cookie.js.coffee +5 -5
- data/lib/client/javascripts/nali/deferred.js.coffee +16 -0
- data/lib/client/javascripts/nali/extensions.js.coffee +18 -0
- data/lib/{assets → client}/javascripts/nali/index.js +2 -1
- data/lib/{assets → client}/javascripts/nali/jbone.min.js +1 -1
- data/lib/{assets → client}/javascripts/nali/model.js.coffee +208 -118
- data/lib/{assets → client}/javascripts/nali/nali.js.coffee +32 -32
- data/lib/client/javascripts/nali/notice.js.coffee +29 -0
- data/lib/{assets → client}/javascripts/nali/router.js.coffee +20 -22
- data/lib/{assets → client}/javascripts/nali/view.js.coffee +63 -60
- data/lib/generator/Gemfile +8 -8
- data/lib/generator/app/{assets → client}/javascripts/application.js.coffee +1 -1
- data/lib/generator/app/{assets → client}/javascripts/controllers/homes.js.coffee +4 -4
- data/lib/generator/app/client/javascripts/models/home.js.coffee +5 -0
- data/lib/generator/app/client/javascripts/views/home/index.js.coffee +9 -0
- data/lib/generator/app/{assets → client}/stylesheets/application.css.sass +1 -1
- data/lib/generator/app/{assets → client}/stylesheets/home/index.css.sass +5 -5
- data/lib/generator/app/{assets → client}/stylesheets/notices/error.css.sass +1 -1
- data/lib/generator/app/{assets → client}/stylesheets/notices/info.css.sass +1 -1
- data/lib/generator/app/{assets → client}/stylesheets/notices/warning.css.sass +1 -1
- data/lib/generator/app/{templates → client/templates}/application.html.erb +1 -1
- data/lib/generator/app/{templates → client/templates}/home/index.html +1 -1
- data/lib/generator/app/client/templates/notice/error.html +1 -0
- data/lib/generator/app/client/templates/notice/info.html +1 -0
- data/lib/generator/app/client/templates/notice/warning.html +1 -0
- data/lib/generator/app/server/clients.rb +15 -0
- data/lib/generator/app/{controllers → server/controllers}/application_controller.rb +2 -2
- data/lib/generator/app/{models → server/models}/access.yml +0 -0
- data/lib/generator/{config → app/server}/routes.rb +3 -3
- data/lib/generator/config/environments/development.rb +2 -2
- data/lib/generator/config/environments/production.rb +4 -4
- data/lib/generator/config/environments/test.rb +5 -5
- data/lib/nali/application.rb +24 -23
- data/lib/nali/connection.rb +14 -31
- data/lib/nali/controller.rb +36 -16
- data/lib/nali/generator.rb +38 -23
- data/lib/nali/helpers.rb +3 -3
- data/lib/nali/model.rb +36 -22
- data/lib/nali/tasks.rb +16 -25
- data/lib/nali/version.rb +2 -2
- metadata +85 -86
- data/lib/assets/javascripts/nali/application.js.coffee +0 -28
- data/lib/assets/javascripts/nali/collection.js.coffee +0 -150
- data/lib/assets/javascripts/nali/extensions.js.coffee +0 -19
- data/lib/assets/javascripts/nali/notice.js.coffee +0 -14
- data/lib/generator/app/assets/javascripts/models/home.js.coffee +0 -3
- data/lib/generator/app/assets/javascripts/views/home/index.js.coffee +0 -1
- data/lib/generator/app/templates/notice/error.html +0 -1
- data/lib/generator/app/templates/notice/info.html +0 -1
- data/lib/generator/app/templates/notice/warning.html +0 -1
- data/lib/generator/config/clients.rb +0 -19
- data/lib/generator/config/environments/development.rb~ +0 -32
- data/lib/generator/config/environments/production.rb~ +0 -80
@@ -1,13 +1,13 @@
|
|
1
1
|
Nali.extend Cookie:
|
2
|
-
|
2
|
+
|
3
3
|
set: ( name, value, options = {} ) ->
|
4
4
|
set = "#{ name }=#{ escape( value ) }"
|
5
5
|
if options.live? and typeof options.live is 'number'
|
6
6
|
date = new Date
|
7
|
-
date.setDate date.getDate() + options.live
|
8
|
-
date.setMinutes date.getMinutes() - date.getTimezoneOffset()
|
7
|
+
date.setDate date.getDate() + options.live
|
8
|
+
date.setMinutes date.getMinutes() - date.getTimezoneOffset()
|
9
9
|
set += "; expires=#{ date.toUTCString() }"
|
10
|
-
set += '; domain=' + escape options.domain if options.domain?
|
10
|
+
set += '; domain=' + escape options.domain if options.domain?
|
11
11
|
set += '; path=' + if options.path? then escape options.path else '/'
|
12
12
|
set += '; secure' if options.secure?
|
13
13
|
document.cookie = set
|
@@ -18,4 +18,4 @@ Nali.extend Cookie:
|
|
18
18
|
if get then unescape( get[2] ) else null
|
19
19
|
|
20
20
|
remove: ( name ) ->
|
21
|
-
@set name, '', live: -1
|
21
|
+
@set name, '', live: -1
|
@@ -0,0 +1,16 @@
|
|
1
|
+
Nali.extend Deferred:
|
2
|
+
|
3
|
+
new: ( callback ) ->
|
4
|
+
obj = Object.create @
|
5
|
+
obj.defer = callback
|
6
|
+
obj.awaits = []
|
7
|
+
obj.results = []
|
8
|
+
obj
|
9
|
+
|
10
|
+
await: ( callback ) ->
|
11
|
+
wrapper = ( args... ) =>
|
12
|
+
@results.push callback args...
|
13
|
+
@awaits.splice @awaits.indexOf( wrapper ), 1
|
14
|
+
@defer @results unless @awaits.length
|
15
|
+
@awaits.push wrapper
|
16
|
+
wrapper
|
@@ -0,0 +1,18 @@
|
|
1
|
+
String::upper = ->
|
2
|
+
"#{ @toUpperCase() }"
|
3
|
+
|
4
|
+
String::lower = ->
|
5
|
+
"#{ @toLowerCase() }"
|
6
|
+
|
7
|
+
String::capitalize = ->
|
8
|
+
@charAt(0).upper() + @slice(1)
|
9
|
+
|
10
|
+
String::uncapitalize = ->
|
11
|
+
@charAt(0).lower() + @slice(1)
|
12
|
+
|
13
|
+
String::camel = ->
|
14
|
+
@replace /(_[^_]+)/g, ( match ) -> match[ 1.. ].capitalize()
|
15
|
+
|
16
|
+
String::underscore = ->
|
17
|
+
str = @replace /([A-Z])/g, ( match ) -> '_' + match.lower()
|
18
|
+
if str[ 0...1 ] is '_' then str[ 1.. ] else str
|
@@ -1,10 +1,11 @@
|
|
1
1
|
//= require ./jbone.min
|
2
2
|
//= require ./extensions
|
3
3
|
//= require ./nali
|
4
|
+
//= require ./deferred
|
4
5
|
//= require ./application
|
5
6
|
//= require ./connection
|
6
7
|
//= require ./router
|
7
8
|
//= require ./view
|
8
9
|
//= require ./model
|
9
10
|
//= require ./collection
|
10
|
-
//= require_tree .
|
11
|
+
//= require_tree .
|
@@ -7,4 +7,4 @@
|
|
7
7
|
* Released under the MIT license.
|
8
8
|
*/
|
9
9
|
|
10
|
-
!function(a){function b(b){var c=b.length,d=typeof b;return o(d)||b===a?!1:1===b.nodeType&&c?!0:p(d)||0===c||"number"==typeof c&&c>0&&c-1 in b}function c(a,b){var c,d;this.originalEvent=a,d=function(a,b){this[a]="preventDefault"===a?function(){return this.defaultPrevented=!0,b[a]()}:o(b[a])?function(){return b[a]()}:b[a]};for(c in a)(a[c]||"function"==typeof a[c])&&d.call(this,c,a);q.extend(this,b)}var d,e=a.$,f=a.jBone,g=/^<(\w+)\s*\/?>$/,h=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,i=[].slice,j=[].splice,k=Object.keys,l=document,m=function(a){return"string"==typeof a},n=function(a){return a instanceof Object},o=function(a){var b={};return a&&"[object Function]"===b.toString.call(a)},p=function(a){return Array.isArray(a)},q=function(a,b){return new d.init(a,b)};q.noConflict=function(){return a.$=e,a.jBone=f,q},d=q.fn=q.prototype={init:function(a,b){var c,d,e,f;if(!a)return this;if(m(a)){if(d=g.exec(a))return this[0]=l.createElement(d[1]),this.length=1,n(b)&&this.attr(b),this;if((d=h.exec(a))&&d[1]){for(f=l.createDocumentFragment(),e=l.createElement("div"),e.innerHTML=a;e.lastChild;)f.appendChild(e.firstChild);return c=i.call(f.childNodes),q.merge(this,c)}if(q.isElement(b))return q(b).find(a);try{return c=l.querySelectorAll(a),q.merge(this,c)}catch(j){return this}}return a.nodeType?(this[0]=a,this.length=1,this):o(a)?a():a instanceof q?a:q.makeArray(a,this)},pop:[].pop,push:[].push,reverse:[].reverse,shift:[].shift,sort:[].sort,splice:[].splice,slice:[].slice,indexOf:[].indexOf,forEach:[].forEach,unshift:[].unshift,concat:[].concat,join:[].join,every:[].every,some:[].some,filter:[].filter,map:[].map,reduce:[].reduce,reduceRight:[].reduceRight,length:0},d.constructor=q,d.init.prototype=d,q.setId=function(b){var c=b.jid;b===a?c="window":void 0===b.jid&&(b.jid=c=++q._cache.jid),q._cache.events[c]||(q._cache.events[c]={})},q.getData=function(b){b=b instanceof q?b[0]:b;var c=b===a?"window":b.jid;return{jid:c,events:q._cache.events[c]}},q.isElement=function(a){return a&&a instanceof q||a instanceof HTMLElement||m(a)},q._cache={events:{},jid:0},q.merge=function(a,b){for(var c=b.length,d=a.length,e=0;c>e;)a[d++]=b[e++];return a.length=d,a},q.contains=function(a,b){var c;return a.reverse().some(function(a){return a.contains(b)?c=a:void 0}),c},q.extend=function(a){var b,c,d,e;return j.call(arguments,1).forEach(function(f){if(f)for(b=k(f),c=b.length,d=0,e=a;c>d;d++)e[b[d]]=f[b[d]]}),a},q.makeArray=function(a,c){var d=c||[];return null!==a&&(b(a)?q.merge(d,m(a)?[a]:a):d.push(a)),d},q.Event=function(a,b){var c,d;return a.type&&!b&&(b=a,a=a.type),c=a.split(".").splice(1).join("."),d=a.split(".")[0],a=l.createEvent("Event"),a.initEvent(d,!0,!0),q.extend(a,{namespace:c,isDefaultPrevented:function(){return a.defaultPrevented}},b)},d.on=function(a){var b,d,e,f,g,h,i,j,k=arguments,l=this.length,m=0;for(2===k.length?b=k[1]:(d=k[1],b=k[2]),j=function(j){q.setId(j),g=q.getData(j).events,a.split(" ").forEach(function(a){h=a.split(".")[0],e=a.split(".").splice(1).join("."),g[h]=g[h]||[],f=function(a){a.namespace&&a.namespace!==e||(i=null,d?(~q(j).find(d).indexOf(a.target)||(i=q.contains(q(j).find(d),a.target)))&&(i=i||a.target,a=new c(a,{currentTarget:i}),b.call(i,a)):b.call(j,a))},g[h].push({namespace:e,fn:f,originfn:b}),j.addEventListener&&j.addEventListener(h,f,!1)})};l>m;m++)j(this[m]);return this},d.one=function(a){var b,c,d,e=arguments,f=0,g=this.length;for(2===e.length?b=e[1]:(c=e[1],b=e[2]),d=function(d){a.split(" ").forEach(function(a){var e=function(c){q(d).off(a,e),b.call(d,c)};c?q(d).on(a,c,e):q(d).on(a,e)})};g>f;f++)d(this[f]);return this},d.trigger=function(a){var b,c=[],d=0,e=this.length;if(!a)return this;for(m(a)?c=a.split(" ").map(function(a){return q.Event(a)}):(a=a instanceof Event?a:q.Event(a),c=[a]),b=function(a){c.forEach(function(b){b.type&&a.dispatchEvent&&a.dispatchEvent(b)})};e>d;d++)b(this[d]);return this},d.off=function(a,b){var c,d,e,f,g=0,h=this.length,i=function(a,c,d,e,f){var g;(b&&f.originfn===b||!b)&&(g=f.fn),a[c][d].fn===g&&(e.removeEventListener(c,g),q._cache.events[q.getData(e).jid][c].splice(d,1))};for(e=function(b){var e,g,h;return(c=q.getData(b).events)?!a&&c?k(c).forEach(function(a){for(g=c[a],e=g.length;e--;)i(c,a,e,b,g[e])}):void a.split(" ").forEach(function(a){if(f=a.split(".")[0],d=a.split(".").splice(1).join("."),c[f])for(g=c[f],e=g.length;e--;)h=g[e],(!d||d&&h.namespace===d)&&i(c,f,e,b,h);else d&&k(c).forEach(function(a){for(g=c[a],e=g.length;e--;)h=g[e],h.namespace.split(".")[0]===d.split(".")[0]&&i(c,a,e,b,h)})}):void 0};h>g;g++)e(this[g]);return this},d.find=function(a){for(var b=[],c=0,d=this.length,e=function(c){o(c.querySelectorAll)&&[].forEach.call(c.querySelectorAll(a),function(a){b.push(a)})};d>c;c++)e(this[c]);return q(b)},d.get=function(a){return this[a]},d.eq=function(a){return q(this[a])},d.parent=function(){for(var a,b=[],c=0,d=this.length;d>c;c++)!~b.indexOf(a=this[c].parentElement)&&a&&b.push(a);return q(b)},d.toArray=function(){return i.call(this)},d.is=function(){var a=arguments;return this.some(function(b){return b.tagName.toLowerCase()===a[0]})},d.has=function(){var a=arguments;return this.some(function(b){return b.querySelectorAll(a[0]).length})},d.attr=function(a,b){var c,d=arguments,e=0,f=this.length;if(m(a)&&1===d.length)return this[0]&&this[0].getAttribute(a);for(2===d.length?c=function(c){c.setAttribute(a,b)}:n(a)&&(c=function(b){k(a).forEach(function(c){b.setAttribute(c,a[c])})});f>e;e++)c(this[e]);return this},d.val=function(a){var b=0,c=this.length;if(0===arguments.length)return this[0]&&this[0].value;for(;c>b;b++)this[b].value=a;return this},d.css=function(b,c){var d,e=arguments,f=0,g=this.length;if(m(b)&&1===e.length)return this[0]&&a.getComputedStyle(this[0])[b];for(2===e.length?d=function(a){a.style[b]=c}:n(b)&&(d=function(a){k(b).forEach(function(c){a.style[c]=b[c]})});g>f;f++)d(this[f]);return this},d.data=function(a,b){var c,d=arguments,e={},f=0,g=this.length,h=function(a,b,c){n(c)?(a.jdata=a.jdata||{},a.jdata[b]=c):a.dataset[b]=c},i=function(a){return"true"===a?!0:"false"===a?!1:a};if(0===d.length)return this[0].jdata&&(e=this[0].jdata),k(this[0].dataset).forEach(function(a){e[a]=i(this[0].dataset[a])},this),e;if(1===d.length&&m(a))return this[0]&&i(this[0].dataset[a]||this[0].jdata&&this[0].jdata[a]);for(1===d.length&&n(a)?c=function(b){k(a).forEach(function(c){h(b,c,a[c])})}:2===d.length&&(c=function(c){h(c,a,b)});g>f;f++)c(this[f]);return this},d.removeData=function(a){for(var b,c,d=0,e=this.length;e>d;d++)if(b=this[d].jdata,c=this[d].dataset,a)b&&b[a]&&delete b[a],delete c[a];else{for(a in b)delete b[a];for(a in c)delete c[a]}return this},d.html=function(a){var b,c=arguments;return 1===c.length&&void 0!==a?this.empty().append(a):0===c.length&&(b=this[0])?b.innerHTML:this},d.append=function(a){var b,c=0,d=this.length;for(m(a)&&h.exec(a)?a=q(a):n(a)||(a=document.createTextNode(a)),a=a instanceof q?a:q(a),b=function(b,c){a.forEach(function(a){b.appendChild(c?a.cloneNode():a)})};d>c;c++)b(this[c],c);return this},d.appendTo=function(a){return q(a).append(this),this},d.empty=function(){for(var a,b=0,c=this.length;c>b;b++)for(a=this[b];a.lastChild;)a.removeChild(a.lastChild);return this},d.remove=function(){var a,b=0,c=this.length;for(this.off();c>b;b++)a=this[b],delete a.jdata,a.parentNode&&a.parentNode.removeChild(a);return this},"object"==typeof module&&module&&"object"==typeof module.exports?module.exports=q:"function"==typeof define&&define.amd?(define(function(){return q}),a.jBone=a.$=q):"object"==typeof a&&"object"==typeof a.document&&(a.jBone=a.$=q)}(window);
|
10
|
+
!function(a){function b(b){var c=b.length,d=typeof b;return o(d)||b===a?!1:1===b.nodeType&&c?!0:p(d)||0===c||"number"==typeof c&&c>0&&c-1 in b}function c(a,b){var c,d;this.originalEvent=a,d=function(a,b){this[a]="preventDefault"===a?function(){return this.defaultPrevented=!0,b[a]()}:o(b[a])?function(){return b[a]()}:b[a]};for(c in a)(a[c]||"function"==typeof a[c])&&d.call(this,c,a);q.extend(this,b)}var d,e=a.$,f=a.jBone,g=/^<(\w+)\s*\/?>$/,h=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,i=[].slice,j=[].splice,k=Object.keys,l=document,m=function(a){return"string"==typeof a},n=function(a){return a instanceof Object},o=function(a){var b={};return a&&"[object Function]"===b.toString.call(a)},p=function(a){return Array.isArray(a)},q=function(a,b){return new d.init(a,b)};q.noConflict=function(){return a.$=e,a.jBone=f,q},d=q.fn=q.prototype={init:function(a,b){var c,d,e,f;if(!a)return this;if(m(a)){if(d=g.exec(a))return this[0]=l.createElement(d[1]),this.length=1,n(b)&&this.attr(b),this;if((d=h.exec(a))&&d[1]){for(f=l.createDocumentFragment(),e=l.createElement("div"),e.innerHTML=a;e.lastChild;)f.appendChild(e.firstChild);return c=i.call(f.childNodes),q.merge(this,c)}if(q.isElement(b))return q(b).find(a);try{return c=l.querySelectorAll(a),q.merge(this,c)}catch(j){return this}}return a.nodeType?(this[0]=a,this.length=1,this):o(a)?a():a instanceof q?a:q.makeArray(a,this)},pop:[].pop,push:[].push,reverse:[].reverse,shift:[].shift,sort:[].sort,splice:[].splice,slice:[].slice,indexOf:[].indexOf,forEach:[].forEach,unshift:[].unshift,concat:[].concat,join:[].join,every:[].every,some:[].some,filter:[].filter,map:[].map,reduce:[].reduce,reduceRight:[].reduceRight,length:0},d.constructor=q,d.init.prototype=d,q.setId=function(b){var c=b.jid;b===a?c="window":void 0===b.jid&&(b.jid=c=++q._cache.jid),q._cache.events[c]||(q._cache.events[c]={})},q.getData=function(b){b=b instanceof q?b[0]:b;var c=b===a?"window":b.jid;return{jid:c,events:q._cache.events[c]}},q.isElement=function(a){return a&&a instanceof q||a instanceof HTMLElement||m(a)},q._cache={events:{},jid:0},q.merge=function(a,b){for(var c=b.length,d=a.length,e=0;c>e;)a[d++]=b[e++];return a.length=d,a},q.contains=function(a,b){var c;return a.reverse().some(function(a){return a.contains(b)?c=a:void 0}),c},q.extend=function(a){var b,c,d,e;return j.call(arguments,1).forEach(function(f){if(f)for(b=k(f),c=b.length,d=0,e=a;c>d;d++)e[b[d]]=f[b[d]]}),a},q.makeArray=function(a,c){var d=c||[];return null!==a&&(b(a)?q.merge(d,m(a)?[a]:a):d.push(a)),d},q.Event=function(a,b){var c,d;return a.type&&!b&&(b=a,a=a.type),c=a.split(".").splice(1).join("."),d=a.split(".")[0],a=l.createEvent("Event"),a.initEvent(d,!0,!0),q.extend(a,{namespace:c,isDefaultPrevented:function(){return a.defaultPrevented}},b)},d.on=function(a){var b,d,e,f,g,h,i,j,k=arguments,l=this.length,m=0;for(2===k.length?b=k[1]:(d=k[1],b=k[2]),j=function(j){q.setId(j),g=q.getData(j).events,a.split(" ").forEach(function(a){h=a.split(".")[0],e=a.split(".").splice(1).join("."),g[h]=g[h]||[],f=function(a){a.namespace&&a.namespace!==e||(i=null,d?(~q(j).find(d).indexOf(a.target)||(i=q.contains(q(j).find(d),a.target)))&&(i=i||a.target,a=new c(a,{currentTarget:i}),b.call(i,a)):b.call(j,a))},g[h].push({namespace:e,fn:f,originfn:b}),j.addEventListener&&j.addEventListener(h,f,!1)})};l>m;m++)j(this[m]);return this},d.one=function(a){var b,c,d,e=arguments,f=0,g=this.length;for(2===e.length?b=e[1]:(c=e[1],b=e[2]),d=function(d){a.split(" ").forEach(function(a){var e=function(c){q(d).off(a,e),b.call(d,c)};c?q(d).on(a,c,e):q(d).on(a,e)})};g>f;f++)d(this[f]);return this},d.trigger=function(a){var b,c=[],d=0,e=this.length;if(!a)return this;for(m(a)?c=a.split(" ").map(function(a){return q.Event(a)}):(a=a instanceof Event?a:q.Event(a),c=[a]),b=function(a){c.forEach(function(b){b.type&&a.dispatchEvent&&a.dispatchEvent(b)})};e>d;d++)b(this[d]);return this},d.off=function(a,b){var c,d,e,f,g=0,h=this.length,i=function(a,c,d,e,f){var g;(b&&f.originfn===b||!b)&&(g=f.fn),a[c][d].fn===g&&(e.removeEventListener(c,g),q._cache.events[q.getData(e).jid][c].splice(d,1))};for(e=function(b){var e,g,h;return(c=q.getData(b).events)?!a&&c?k(c).forEach(function(a){for(g=c[a],e=g.length;e--;)i(c,a,e,b,g[e])}):void a.split(" ").forEach(function(a){if(f=a.split(".")[0],d=a.split(".").splice(1).join("."),c[f])for(g=c[f],e=g.length;e--;)h=g[e],(!d||d&&h.namespace===d)&&i(c,f,e,b,h);else d&&k(c).forEach(function(a){for(g=c[a],e=g.length;e--;)h=g[e],h.namespace.split(".")[0]===d.split(".")[0]&&i(c,a,e,b,h)})}):void 0};h>g;g++)e(this[g]);return this},d.find=function(a){for(var b=[],c=0,d=this.length,e=function(c){o(c.querySelectorAll)&&[].forEach.call(c.querySelectorAll(a),function(a){b.push(a)})};d>c;c++)e(this[c]);return q(b)},d.get=function(a){return this[a]},d.eq=function(a){return q(this[a])},d.parent=function(){for(var a,b=[],c=0,d=this.length;d>c;c++)!~b.indexOf(a=this[c].parentElement)&&a&&b.push(a);return q(b)},d.toArray=function(){return i.call(this)},d.is=function(){var a=arguments;return this.some(function(b){return b.tagName.toLowerCase()===a[0]})},d.has=function(){var a=arguments;return this.some(function(b){return b.querySelectorAll(a[0]).length})},d.attr=function(a,b){var c,d=arguments,e=0,f=this.length;if(m(a)&&1===d.length)return this[0]&&this[0].getAttribute(a);for(2===d.length?c=function(c){c.setAttribute(a,b)}:n(a)&&(c=function(b){k(a).forEach(function(c){b.setAttribute(c,a[c])})});f>e;e++)c(this[e]);return this},d.val=function(a){var b=0,c=this.length;if(0===arguments.length)return this[0]&&this[0].value;for(;c>b;b++)this[b].value=a;return this},d.css=function(b,c){var d,e=arguments,f=0,g=this.length;if(m(b)&&1===e.length)return this[0]&&a.getComputedStyle(this[0])[b];for(2===e.length?d=function(a){a.style[b]=c}:n(b)&&(d=function(a){k(b).forEach(function(c){a.style[c]=b[c]})});g>f;f++)d(this[f]);return this},d.data=function(a,b){var c,d=arguments,e={},f=0,g=this.length,h=function(a,b,c){n(c)?(a.jdata=a.jdata||{},a.jdata[b]=c):a.dataset[b]=c},i=function(a){return"true"===a?!0:"false"===a?!1:a};if(0===d.length)return this[0].jdata&&(e=this[0].jdata),k(this[0].dataset).forEach(function(a){e[a]=i(this[0].dataset[a])},this),e;if(1===d.length&&m(a))return this[0]&&i(this[0].dataset[a]||this[0].jdata&&this[0].jdata[a]);for(1===d.length&&n(a)?c=function(b){k(a).forEach(function(c){h(b,c,a[c])})}:2===d.length&&(c=function(c){h(c,a,b)});g>f;f++)c(this[f]);return this},d.removeData=function(a){for(var b,c,d=0,e=this.length;e>d;d++)if(b=this[d].jdata,c=this[d].dataset,a)b&&b[a]&&delete b[a],delete c[a];else{for(a in b)delete b[a];for(a in c)delete c[a]}return this},d.html=function(a){var b,c=arguments;return 1===c.length&&void 0!==a?this.empty().append(a):0===c.length&&(b=this[0])?b.innerHTML:this},d.append=function(a){var b,c=0,d=this.length;for(m(a)&&h.exec(a)?a=q(a):n(a)||(a=document.createTextNode(a)),a=a instanceof q?a:q(a),b=function(b,c){a.forEach(function(a){b.appendChild(c?a.cloneNode():a)})};d>c;c++)b(this[c],c);return this},d.appendTo=function(a){return q(a).append(this),this},d.empty=function(){for(var a,b=0,c=this.length;c>b;b++)for(a=this[b];a.lastChild;)a.removeChild(a.lastChild);return this},d.remove=function(){var a,b=0,c=this.length;for(this.off();c>b;b++)a=this[b],delete a.jdata,a.parentNode&&a.parentNode.removeChild(a);return this},"object"==typeof module&&module&&"object"==typeof module.exports?module.exports=q:"function"==typeof define&&define.amd?(define(function(){return q}),a.jBone=a.$=q):"object"==typeof a&&"object"==typeof a.document&&(a.jBone=a.$=q)}(window);
|
@@ -1,22 +1,24 @@
|
|
1
1
|
Nali.extend Model:
|
2
|
-
|
2
|
+
|
3
3
|
extension: ->
|
4
4
|
if @_name isnt 'Model'
|
5
5
|
@table = @tables[ @_name ] ?= []
|
6
6
|
@table.index = {}
|
7
|
+
@parseRelations()
|
7
8
|
@adapt()
|
8
9
|
@
|
9
|
-
|
10
|
+
|
10
11
|
cloning: ->
|
11
12
|
@views = {}
|
12
|
-
|
13
|
+
|
13
14
|
tables: {}
|
14
15
|
hasOne: []
|
15
16
|
hasMany: []
|
16
17
|
attributes: {}
|
17
18
|
updated: 0
|
18
19
|
noticesWait: []
|
19
|
-
|
20
|
+
destroyed: false
|
21
|
+
|
20
22
|
adapt: ->
|
21
23
|
for name, method of @ when /^_\w+/.test name
|
22
24
|
do ( name, method ) =>
|
@@ -24,7 +26,7 @@ Nali.extend Model:
|
|
24
26
|
@[ name[ 1.. ] ] = ( args... ) -> @[ name ] args...
|
25
27
|
@adaptViews()
|
26
28
|
@
|
27
|
-
|
29
|
+
|
28
30
|
adaptViews: ->
|
29
31
|
@views = {}
|
30
32
|
for name, view of @View.extensions when name.indexOf( @_name ) >= 0
|
@@ -35,13 +37,13 @@ Nali.extend Model:
|
|
35
37
|
@show short
|
36
38
|
@
|
37
39
|
@
|
38
|
-
|
40
|
+
|
39
41
|
notice: ( params ) ->
|
40
42
|
# добавляет уведомление в очередь на выполнение, запускает выполнение очереди
|
41
43
|
@noticesWait.push params
|
42
44
|
@runNotices()
|
43
45
|
@
|
44
|
-
|
46
|
+
|
45
47
|
runNotices: ->
|
46
48
|
# запускает выполнение уведомлений на существующих моделях
|
47
49
|
for item, index in @noticesWait[ 0.. ]
|
@@ -49,131 +51,154 @@ Nali.extend Model:
|
|
49
51
|
model[ item.notice ] item.params
|
50
52
|
@noticesWait.splice @noticesWait.indexOf( item ), 1
|
51
53
|
@
|
52
|
-
|
54
|
+
|
53
55
|
# работа с моделями
|
54
|
-
|
56
|
+
|
55
57
|
accessing: ->
|
56
58
|
# устанавливает геттеры доступа к атрибутам и связям
|
57
59
|
@access @attributes
|
58
60
|
@setRelations()
|
59
61
|
@
|
60
|
-
|
62
|
+
|
61
63
|
force: ( params = {} ) ->
|
62
64
|
# создает новую модель с заданными атрибутами
|
63
|
-
attributes
|
65
|
+
attributes = @defaultAttributes()
|
64
66
|
attributes[ name ] = value for name, value of params
|
65
67
|
attributes[ name ] = @normalizeValue value for name, value of attributes
|
66
68
|
@clone( attributes: attributes ).accessing()
|
67
|
-
|
69
|
+
|
68
70
|
save: ( success, failure ) ->
|
69
71
|
# отправляет на сервер запрос на сохранение модели, вызывает success в случае успеха и failure при неудаче
|
70
72
|
if @isValid()
|
71
|
-
@query "#{ @_name.
|
73
|
+
@query "#{ @_name.lower() }s.save", @attributes,
|
72
74
|
( { attributes, created, updated } ) =>
|
73
75
|
@update( attributes, updated, created ).write()
|
74
76
|
success? @
|
75
77
|
else failure? @
|
76
78
|
@
|
77
|
-
|
79
|
+
|
78
80
|
sync: ( { _name, attributes, created, updated, destroyed } ) ->
|
79
81
|
# синхронизирует пришедшую с сервера модель с локальной, либо создает новую
|
80
|
-
if model = @extensions[ _name ].find attributes.id
|
82
|
+
if model = @extensions[ _name ].find attributes.id
|
81
83
|
if destroyed then model.remove()
|
82
84
|
else model.update attributes, updated, created
|
83
85
|
else
|
84
|
-
model = @extensions[ _name ].
|
86
|
+
model = @extensions[ _name ].new attributes
|
85
87
|
model.updated = updated
|
86
88
|
model.created = created
|
87
89
|
model.write()
|
88
90
|
@
|
89
|
-
|
90
|
-
select: (
|
91
|
-
# отправляет на сервер запрос на выборку моделей
|
92
|
-
|
93
|
-
|
91
|
+
|
92
|
+
select: ( options ) ->
|
93
|
+
# отправляет на сервер запрос на выборку моделей
|
94
|
+
obj = {}
|
95
|
+
if typeof options is 'object'
|
96
|
+
obj.selector = Object.keys( options )[0]
|
97
|
+
obj.params = options[ obj.selector ]
|
98
|
+
else
|
99
|
+
obj.selector = options
|
100
|
+
obj.params = {}
|
101
|
+
@query @_name.lower() + 's.select', obj
|
102
|
+
@
|
103
|
+
|
104
|
+
written: ->
|
105
|
+
@ in @table
|
106
|
+
|
94
107
|
write: ->
|
95
|
-
# добавляет модель
|
96
|
-
|
97
|
-
|
98
|
-
@table.
|
108
|
+
# добавляет модель в локальную таблицу, генерирует событие create
|
109
|
+
@table.index[ @id ] = @ if @id and not @table.index[ @id ]
|
110
|
+
unless @written()
|
111
|
+
@table.push @
|
99
112
|
@onCreate?()
|
100
|
-
@Model.trigger "create.#{ @_name.
|
113
|
+
@Model.trigger "create.#{ @_name.lower() }", @
|
101
114
|
@Model.runNotices()
|
102
115
|
@
|
103
|
-
|
116
|
+
|
104
117
|
remove: ->
|
105
|
-
# удаляет модель из
|
106
|
-
if @
|
118
|
+
# удаляет модель из локальной таблицы, генерирует событие destroy
|
119
|
+
if @written()
|
120
|
+
@destroyed = true
|
107
121
|
delete @table.index[ @id ]
|
108
|
-
@table.splice @table.indexOf( @ ), 1
|
109
|
-
@trigger 'destroy'
|
122
|
+
@table.splice @table.indexOf( @ ), 1
|
123
|
+
@trigger 'destroy'
|
110
124
|
@onDestroy?()
|
111
125
|
@unsubscribeAll()
|
112
|
-
@
|
126
|
+
@
|
113
127
|
|
114
|
-
|
128
|
+
new: ( attributes ) ->
|
115
129
|
# создает модель, не сохраняя её на сервере
|
116
130
|
@force attributes
|
117
|
-
|
131
|
+
|
118
132
|
create: ( attributes, success, failure ) ->
|
119
133
|
# создает модель, и сохраняет её на сервере, вызывает success в случае успеха и failure при неудаче
|
120
|
-
@
|
121
|
-
|
134
|
+
@new( attributes ).save success, failure
|
135
|
+
|
122
136
|
update: ( attributes, updated = 0, created = 0 ) ->
|
123
137
|
# обновляет атрибуты модели, проверяя их валидность, генерирует событие update
|
124
138
|
if not updated or updated > @updated
|
125
139
|
@created = created if created
|
126
140
|
changed = []
|
127
|
-
changed.push name for name, value of attributes when @
|
141
|
+
changed.push name for name, value of attributes when @updateAttribute name, value
|
128
142
|
if changed.length
|
129
143
|
@updated = updated if updated
|
130
144
|
@onUpdate? changed
|
131
|
-
@trigger 'update',
|
145
|
+
@trigger 'update', changed
|
146
|
+
@Model.trigger "update.#{ @_name.lower() }", @
|
132
147
|
@
|
133
|
-
|
134
|
-
|
135
|
-
# обновляет один атрибут модели, проверяя его валидность, генерирует событие update.
|
148
|
+
|
149
|
+
updateAttribute: ( name, value ) ->
|
150
|
+
# обновляет один атрибут модели, проверяя его валидность, генерирует событие update.attributeName
|
136
151
|
value = @normalizeValue value
|
137
152
|
if @attributes[ name ] isnt value and @isValidAttributeValue( name, value )
|
138
153
|
@attributes[ name ] = value
|
139
154
|
@[ 'onUpdate' + name.capitalize() ]?()
|
140
|
-
@trigger "update.#{ name }"
|
155
|
+
@trigger "update.#{ name }"
|
141
156
|
true
|
142
157
|
else false
|
143
|
-
|
158
|
+
|
144
159
|
destroy: ( success, failure ) ->
|
145
160
|
# отправляет на сервер запрос на удаление модели, вызывает success в случае успеха и failure при неудаче
|
146
|
-
@query @_name.
|
147
|
-
|
161
|
+
@query @_name.lower() + 's.destroy', @attributes, success, failure
|
162
|
+
@
|
163
|
+
|
148
164
|
# поиск моделей
|
149
|
-
|
165
|
+
|
150
166
|
find: ( id ) ->
|
151
167
|
# находит модель по её id используя индекс
|
152
168
|
@table.index[ id ]
|
153
|
-
|
169
|
+
|
154
170
|
where: ( filters ) ->
|
155
|
-
#
|
156
|
-
|
157
|
-
collection = @Collection.clone model: @, filters: filters
|
171
|
+
# возвращает коллекцию моделей соответствующих фильтру
|
172
|
+
collection = @Collection.new @, filters
|
158
173
|
collection.add model for model in @table when model.isCorrect filters
|
159
174
|
if @forced and not collection.length
|
160
175
|
attributes = {}
|
161
176
|
attributes[ key ] = value for key, value of filters when typeof value in [ 'number', 'string' ]
|
162
|
-
collection.add @
|
163
|
-
|
164
|
-
|
165
|
-
|
177
|
+
collection.add @new attributes
|
178
|
+
collection
|
179
|
+
|
180
|
+
all: ->
|
181
|
+
@where id: /./
|
182
|
+
|
166
183
|
# работа с аттрибутами
|
167
|
-
|
168
|
-
|
184
|
+
|
185
|
+
guid: ->
|
186
|
+
# генерирует случайный идентификатор
|
187
|
+
date = new Date().getTime()
|
188
|
+
'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace /[xy]/g, ( sub ) ->
|
189
|
+
rand = ( date + Math.random() * 16 ) % 16 | 0
|
190
|
+
date = Math.floor date / 16
|
191
|
+
( if sub is 'x' then rand else ( rand & 0x7 | 0x8 ) ).toString 16
|
192
|
+
|
193
|
+
defaultAttributes: ->
|
169
194
|
# возвращает объект аттрибутов по умолчанию
|
170
|
-
attributes = id:
|
195
|
+
attributes = id: @guid()
|
171
196
|
for name, value of @attributes
|
172
|
-
if value instanceof Object
|
197
|
+
if value instanceof Object
|
173
198
|
attributes[ name ] = if value.default? then value.default else null
|
174
199
|
else attributes[ name ] = value
|
175
200
|
attributes
|
176
|
-
|
201
|
+
|
177
202
|
normalizeValue: ( value ) ->
|
178
203
|
# приводит значения к нормальному виду, если в строке только числа - преобразуется к числу
|
179
204
|
# т.е. строка '123' становится числом 123, '123.5' становится 123.5, а '123abc' остается строкой
|
@@ -184,11 +209,12 @@ Nali.extend Model:
|
|
184
209
|
|
185
210
|
isCorrect: ( filters = {} ) ->
|
186
211
|
# проверяет соответствие аттрибутов модели определенному набору фильтров, возвращает true либо false
|
212
|
+
return filters.call @ if typeof filters is 'function'
|
187
213
|
return false unless Object.keys( filters ).length
|
188
214
|
return false for name, filter of filters when not @isCorrectAttribute @attributes[ name ], filter
|
189
215
|
return true
|
190
|
-
|
191
|
-
isCorrectAttribute: ( attribute, filter ) ->
|
216
|
+
|
217
|
+
isCorrectAttribute: ( attribute, filter ) ->
|
192
218
|
# проверяет соответствие аттрибута модели определенному фильтру, возвращает true либо false
|
193
219
|
return false unless attribute
|
194
220
|
if filter instanceof RegExp
|
@@ -199,69 +225,132 @@ Nali.extend Model:
|
|
199
225
|
+ attribute is filter
|
200
226
|
else if filter instanceof Array
|
201
227
|
'' + attribute in filter or + attribute in filter
|
202
|
-
else false
|
203
|
-
|
204
|
-
# работа со связями
|
205
|
-
|
228
|
+
else false
|
229
|
+
|
230
|
+
# работа со связями
|
231
|
+
|
232
|
+
parseRelations: ( type, options ) ->
|
233
|
+
# производит разбор связей
|
234
|
+
@relations = {}
|
235
|
+
for type in [ 'belongsTo', 'hasOne', 'hasMany' ]
|
236
|
+
for options in [].concat( @[ type ] ) when @[ type ]?
|
237
|
+
params = @[ 'parse' + type.capitalize() ] @parseInitialRelationParams options
|
238
|
+
section = type + if params.through? then 'Through' else ''
|
239
|
+
( @relations[ section ] ?= [] ).push params
|
240
|
+
@
|
241
|
+
|
242
|
+
parseInitialRelationParams: ( options ) ->
|
243
|
+
# дает начальные параметры настроек связи
|
244
|
+
if typeof options is 'object'
|
245
|
+
params = name: Object.keys( options )[0]
|
246
|
+
params.through = through if through = options[ params.name ].through
|
247
|
+
params.key = key if key = options[ params.name ].key
|
248
|
+
params.model = @Model.extensions[ model.capitalize() ] if model = options[ params.name ].model
|
249
|
+
else
|
250
|
+
params = name: options
|
251
|
+
params
|
252
|
+
|
253
|
+
parseBelongsTo: ( params ) ->
|
254
|
+
# производит разбор связей belongsTo
|
255
|
+
params.model ?= @Model.extensions[ params.name.capitalize() ]
|
256
|
+
params.key ?= params.name.lower() + '_id'
|
257
|
+
params
|
258
|
+
|
259
|
+
parseHasOne: ( params ) ->
|
260
|
+
# производит разбор связей hasOne
|
261
|
+
params.model ?= @Model.extensions[ params.name.capitalize() ]
|
262
|
+
params.key ?= ( if params.through then params.name else @_name + '_id' ).lower()
|
263
|
+
params
|
264
|
+
|
265
|
+
parseHasMany: ( params ) ->
|
266
|
+
# производит разбор связей hasMany
|
267
|
+
params.model ?= @Model.extensions[ params.name[ ...-1 ].capitalize() ]
|
268
|
+
params.key ?= ( if params.through then params.name[ ...-1 ] else @_name + '_id' ).lower()
|
269
|
+
params
|
270
|
+
|
206
271
|
setRelations: ->
|
207
|
-
#
|
208
|
-
@
|
209
|
-
@
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
272
|
+
# запускает установку связей у модели
|
273
|
+
@setRelationsType type for type in [ 'belongsTo', 'hasOne', 'hasMany', 'hasOneThrough', 'hasManyThrough' ]
|
274
|
+
@
|
275
|
+
|
276
|
+
setRelationsType: ( type ) ->
|
277
|
+
# запускает установку связей определенного типа
|
278
|
+
if params = @relations[ type ]
|
279
|
+
@[ 'set' + type.capitalize() ] param for param in params
|
280
|
+
@
|
281
|
+
|
282
|
+
setBelongsTo: ( { key, model, name, through } ) ->
|
283
|
+
# устанавливает геттер типа belongsTo возвращающий связанную модель
|
284
|
+
@getter name, => model.find @[ key ]
|
285
|
+
@
|
286
|
+
|
287
|
+
setHasOne: ( { key, model, name, through } ) ->
|
288
|
+
# устанавливает геттер типа hasOne возвращающий связанную модель
|
289
|
+
@getter name, =>
|
223
290
|
delete @[ name ]
|
224
|
-
( filters = {} )[
|
225
|
-
|
226
|
-
@getter name, =>
|
227
|
-
|
291
|
+
( filters = {} )[ key ] = @id
|
292
|
+
collection = model.where filters
|
293
|
+
@getter name, => collection.first()
|
294
|
+
@[ name ]
|
228
295
|
@
|
229
|
-
|
230
|
-
|
231
|
-
# устанавливает геттер типа
|
232
|
-
@getter name, =>
|
296
|
+
|
297
|
+
setHasMany: ( { key, model, name, through } ) ->
|
298
|
+
# устанавливает геттер типа hasMany возвращающий коллекцию связанных моделей
|
299
|
+
@getter name, =>
|
233
300
|
delete @[ name ]
|
234
|
-
( filters = {} )[
|
235
|
-
@[ name ] =
|
236
|
-
@
|
237
|
-
|
301
|
+
( filters = {} )[ key ] = @id
|
302
|
+
@[ name ] = model.where filters
|
303
|
+
@
|
304
|
+
|
305
|
+
setHasOneThrough: ( { key, model, name, through } ) ->
|
306
|
+
# устанавливает геттер типа hasOne возвращающий модель,
|
307
|
+
# связанную с текущей через модель through
|
308
|
+
@getter name, =>
|
309
|
+
delete @[ name ]
|
310
|
+
@getter name, => @[ through ][ key ]
|
311
|
+
@[ name ]
|
312
|
+
@
|
313
|
+
|
314
|
+
setHasManyThrough: ( { key, model, name, through } ) ->
|
315
|
+
# устанавливает геттер типа hasMany возвращающий коллекцию моделей,
|
316
|
+
# связанных с текущей через модель through
|
317
|
+
@getter name, =>
|
318
|
+
delete @[ name ]
|
319
|
+
@[ name ] = @Collection.new model, ->
|
320
|
+
return true for model in @[ through ] when model[ key ] is @
|
321
|
+
false
|
322
|
+
@[ name ].add @[ through ].pluck key
|
323
|
+
@[ name ].subscribeTo @[ through ], 'update.length.add', ( collection, model ) -> @add model[ key ]
|
324
|
+
@[ name ].subscribeTo @[ through ], 'update.length.remove', ( collection, model ) -> @remove model[ key ]
|
325
|
+
@[ name ]
|
326
|
+
@
|
327
|
+
|
238
328
|
# работа с видами
|
239
|
-
|
329
|
+
|
240
330
|
view: ( name ) ->
|
241
331
|
# возвращает объект вида, либо новый, либо ранее созданный
|
242
332
|
unless ( view = @views[ name ] )?
|
243
|
-
if ( view = @::views[ name ] )?
|
244
|
-
view = @views[ name ] = view.clone model: @
|
333
|
+
if ( view = @::views[ name ] )?
|
334
|
+
view = @views[ name ] = view.clone model: @
|
245
335
|
else console.error "View %s of model %O does not exist", name, @
|
246
336
|
view
|
247
|
-
|
337
|
+
|
248
338
|
show: ( name, insertTo ) ->
|
249
|
-
# вставляет html-код вида в указанное место ( это может быть селектор, html-элемент или ничего - тогда
|
250
|
-
# вставка произойдет в элемент указанный в самом виде либо в
|
339
|
+
# вставляет html-код вида в указанное место ( это может быть селектор, html-элемент или ничего - тогда
|
340
|
+
# вставка произойдет в элемент указанный в самом виде либо в элемент-контейнер приложения )
|
251
341
|
# функция возвращает объект вида при успехе либо null при неудаче
|
252
|
-
if ( view = @view( name ) )? then view.show insertTo else null
|
253
|
-
|
342
|
+
if ( view = @view( name ) )? then view.show insertTo else null
|
343
|
+
|
254
344
|
hide: ( name ) ->
|
255
345
|
# удаляет html-код вида со страницы
|
256
346
|
# функция возвращает объект вида при успехе либо null при неудаче
|
257
|
-
if ( view = @view( name ) )? then view.hide() else null
|
258
|
-
|
347
|
+
if ( view = @view( name ) )? then view.hide() else null
|
348
|
+
|
259
349
|
# валидации
|
260
|
-
|
261
|
-
validations:
|
350
|
+
|
351
|
+
validations:
|
262
352
|
# набор валидационных проверок
|
263
353
|
presence: ( value, filter ) -> if filter then value? else not value?
|
264
|
-
match: ( value, filter ) -> not value? or filter.test value
|
265
354
|
inclusion: ( value, filter ) -> not value? or value in filter
|
266
355
|
exclusion: ( value, filter ) -> not value? or value not in filter
|
267
356
|
length: ( value, filter ) ->
|
@@ -271,23 +360,24 @@ Nali.extend Model:
|
|
271
360
|
return false if filter.max? and value.length > filter.max
|
272
361
|
return false if filter.is? and value.length isnt filter.is
|
273
362
|
true
|
274
|
-
format: ( value, filter ) ->
|
363
|
+
format: ( value, filter ) ->
|
275
364
|
return true if not value?
|
276
|
-
return true if filter
|
277
|
-
return true if filter is '
|
278
|
-
return true if filter is '
|
279
|
-
return true if filter is '
|
365
|
+
return true if filter instanceof RegExp and filter.test value
|
366
|
+
return true if filter is 'boolean' and /^true|false$/.test value
|
367
|
+
return true if filter is 'number' and /^[0-9]+$/.test value
|
368
|
+
return true if filter is 'letters' and /^[A-zА-я]+$/.test value
|
369
|
+
return true if filter is 'email' and /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,4})+$/.test value
|
280
370
|
false
|
281
|
-
|
371
|
+
|
282
372
|
isValid: ->
|
283
|
-
# проверяет валидна ли модель, вызывается перед сохранением модели на сервер если модель валидна,
|
373
|
+
# проверяет валидна ли модель, вызывается перед сохранением модели на сервер если модель валидна,
|
284
374
|
# то вызов model.isValid() вернет true, иначе false
|
285
|
-
return false for name, value of @attributes when not @isValidAttributeValue( name, value )
|
375
|
+
return false for name, value of @attributes when not @isValidAttributeValue( name, value )
|
286
376
|
true
|
287
|
-
|
377
|
+
|
288
378
|
isValidAttributeValue: ( name, value ) ->
|
289
|
-
# проверяет валидно ли значение для определенного атрибута модели, вызывается при проверке
|
290
|
-
# валидности модели, а также в методе
|
379
|
+
# проверяет валидно ли значение для определенного атрибута модели, вызывается при проверке
|
380
|
+
# валидности модели, а также в методе updateAttribute() перед изменением значения атрибута, если значение
|
291
381
|
# валидно то вызов model.isValidAttributeValue( name, value )? вернет true, иначе false
|
292
382
|
for validation, tester of @validations when ( filter = @::attributes[ name ]?[ validation ] )?
|
293
383
|
unless tester.call @, value, filter
|
@@ -295,4 +385,4 @@ Nali.extend Model:
|
|
295
385
|
for type in [ 'info', 'warning', 'error' ] when ( message = @::attributes[ name ][ type ] )?
|
296
386
|
@Notice[ type ] message: message
|
297
387
|
return false
|
298
|
-
true
|
388
|
+
true
|