nali 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|