alpha-simprini-engine 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +3 -0
- data/Rakefile +38 -0
- data/app/assets/javascripts/alpha_simprini.coffee +15 -0
- data/app/assets/javascripts/alpha_simprini/application.coffee +22 -0
- data/app/assets/javascripts/alpha_simprini/coffee_kup/binding.coffee +119 -0
- data/app/assets/javascripts/alpha_simprini/coffee_kup/helpers.coffee +17 -0
- data/app/assets/javascripts/alpha_simprini/coffee_kup/tags.coffee +7 -0
- data/app/assets/javascripts/alpha_simprini/collection.coffee +62 -0
- data/app/assets/javascripts/alpha_simprini/delegate.coffee +21 -0
- data/app/assets/javascripts/alpha_simprini/event.coffee +75 -0
- data/app/assets/javascripts/alpha_simprini/html.coffee +56 -0
- data/app/assets/javascripts/alpha_simprini/mixin.coffee +10 -0
- data/app/assets/javascripts/alpha_simprini/model.coffee +137 -0
- data/app/assets/javascripts/alpha_simprini/models/radio_selection_model.coffee +9 -0
- data/app/assets/javascripts/alpha_simprini/packer.coffee +93 -0
- data/app/assets/javascripts/alpha_simprini/template_helpers.coffee +8 -0
- data/app/assets/javascripts/alpha_simprini/view.coffee +182 -0
- data/app/assets/javascripts/alpha_simprini/views/canvas.coffee +2 -0
- data/app/assets/javascripts/alpha_simprini/views/horizontal_split.coffee +9 -0
- data/app/assets/javascripts/alpha_simprini/views/panel.coffee +2 -0
- data/app/assets/javascripts/alpha_simprini/views/splitter.coffee +2 -0
- data/app/assets/javascripts/alpha_simprini/views/stage.coffee +7 -0
- data/app/assets/javascripts/alpha_simprini/views/vertical_split.coffee +8 -0
- data/app/assets/javascripts/alpha_simprini/views/viewport.coffee +0 -0
- data/app/assets/javascripts/bundle.js +16416 -0
- data/app/assets/javascripts/lib/backbone.coffee +11 -0
- data/app/assets/javascripts/lib/koffeecup_backbone_databind.coffee +25 -0
- data/app/assets/javascripts/lib/module.coffee +15 -0
- data/app/assets/javascripts/lib/state_machine.coffee +33 -0
- data/app/assets/javascripts/lib/string.coffee +13 -0
- data/app/assets/javascripts/qunit.js +1513 -0
- data/app/assets/javascripts/test.coffee +4 -0
- data/app/assets/javascripts/test/alpha_simprini/coffee_kup/binding.coffee +118 -0
- data/app/assets/javascripts/test/alpha_simprini/coffee_kup/helpers.coffee +10 -0
- data/app/assets/javascripts/test/alpha_simprini/coffee_kup/tags.coffee +18 -0
- data/app/assets/javascripts/test/alpha_simprini/collection.coffee +7 -0
- data/app/assets/javascripts/test/alpha_simprini/event.coffee +43 -0
- data/app/assets/javascripts/test/alpha_simprini/model.coffee +63 -0
- data/app/assets/javascripts/test/alpha_simprini/view.coffee +72 -0
- data/app/assets/javascripts/test/alpha_simprini/views/canvas.coffee +8 -0
- data/app/assets/javascripts/test/alpha_simprini/views/horizontal_split.coffee +13 -0
- data/app/assets/javascripts/test/alpha_simprini/views/vertical_split.coffee +13 -0
- data/app/assets/javascripts/test/backbone/collection.js +345 -0
- data/app/assets/javascripts/test/backbone/events.js +86 -0
- data/app/assets/javascripts/test/backbone/model.js +426 -0
- data/app/assets/javascripts/test/backbone/view.js +137 -0
- data/app/assets/stylesheets/bootstrap.sass +6 -0
- data/app/assets/stylesheets/paneling.sass +2 -0
- data/app/assets/stylesheets/qunit.scss +228 -0
- data/app/assets/stylesheets/table.sass +10 -0
- data/app/assets/stylesheets/typography.sass +19 -0
- data/app/controllers/alpha_simprini/test_controller.rb +3 -0
- data/app/controllers/resources_controller.rb +7 -0
- data/app/views/alpha_simprini/test/root.rb +13 -0
- data/app/views/resources/base.rb +2 -0
- data/app/views/resources/edit.rb +9 -0
- data/app/views/resources/form.rb +26 -0
- data/app/views/resources/index.rb +41 -0
- data/app/views/resources/new.rb +9 -0
- data/app/views/resources/show.rb +42 -0
- data/app/views/resources/show_has_many.rb +28 -0
- data/config/locales/en.yml +4 -0
- data/config/routes.rb +3 -0
- data/lib/alpha-simprini-engine.rb +33 -0
- data/lib/alpha-simprini-engine/version.rb +3 -0
- data/lib/alpha_simprini/directive_processor.rb +77 -0
- data/lib/alpha_simprini/packer.rb +161 -0
- data/lib/alpha_simprini/page.rb +37 -0
- data/lib/tasks/alpha-simprini-engine_tasks.rake +4 -0
- data/test/alpha-simprini-engine_test.rb +7 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +9 -0
- data/test/dummy/app/assets/stylesheets/application.css +7 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +42 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +27 -0
- data/test/dummy/config/environments/production.rb +51 -0
- data/test/dummy/config/environments/test.rb +39 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +10 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +4 -0
- data/test/dummy/config/routes.rb +58 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/log/development.log +800 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +26 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/dummy/tmp/cache/assets/C24/D70/sprockets%2F388a550030239f3784f207fa32954f64 +0 -0
- data/test/dummy/tmp/cache/assets/C34/620/sprockets%2F097ee8532856d48d70420c006f475889 +0 -0
- data/test/dummy/tmp/cache/assets/C6F/710/sprockets%2F908d18b0f21c18dad508851126164a41 +0 -0
- data/test/dummy/tmp/cache/assets/CA7/120/sprockets%2F35278a6c0150c40394fe02629c8b0eb9 +0 -0
- data/test/dummy/tmp/cache/assets/CDB/A80/sprockets%2F443b1c6e71b482fdd83b1833b7e27712 +0 -0
- data/test/dummy/tmp/cache/assets/CE3/FB0/sprockets%2F6d3f87a4232e0368bb86760780c5f1bd +0 -0
- data/test/dummy/tmp/cache/assets/D1C/160/sprockets%2F87876f7e55ebc78ae11c6c08a27f0605 +0 -0
- data/test/dummy/tmp/cache/assets/D26/6C0/sprockets%2F65bce2254bb3140a50326ea1654ea5df +0 -0
- data/test/dummy/tmp/cache/assets/D26/FA0/sprockets%2F1f50f59148df5f3e2ab889df381d9744 +0 -0
- data/test/dummy/tmp/cache/assets/D36/220/sprockets%2F841654b01d89eada195d7d1fe10b57b0 +0 -0
- data/test/dummy/tmp/cache/assets/D47/410/sprockets%2Ff1fe319eb4064bd5b861ac28f7d76555 +18122 -0
- data/test/dummy/tmp/cache/assets/D57/1E0/sprockets%2Fe267e3e1059799c429e4f5cfb95ec53c +0 -0
- data/test/dummy/tmp/cache/assets/D64/3E0/sprockets%2Fb49b7f8034b81ec601bc32fb127fbe08 +0 -0
- data/test/dummy/tmp/cache/assets/D65/850/sprockets%2F7a9b6a0e2d51adb43a1d3f859213e6b8 +15469 -0
- data/test/dummy/tmp/cache/assets/D6C/E30/sprockets%2Fcc7322b05ac2bef75e9f4f145d38117f +0 -0
- data/test/dummy/tmp/cache/assets/D7D/E00/sprockets%2Fce33b82451c73df1cfec69928b4f77b6 +0 -0
- data/test/dummy/tmp/cache/assets/D85/5D0/sprockets%2Fcf743946c378c148b19ce78eeaa9cc75 +0 -0
- data/test/dummy/tmp/cache/assets/DBB/560/sprockets%2F5a1d70cf7dd81a5ab5ce7a40a3a38d06 +0 -0
- data/test/dummy/tmp/cache/assets/DC1/670/sprockets%2Fefdfad0542298a1db90d24dc27ecc250 +0 -0
- data/test/dummy/tmp/cache/assets/DC5/1E0/sprockets%2F7517f22ad0f9dc13b8f0f6e0cc0e5de2 +0 -0
- data/test/dummy/tmp/cache/assets/DCC/220/sprockets%2F28d953c6ab9cc9a7db15600aabc6d77d +208 -0
- data/test/dummy/tmp/cache/assets/DCF/DF0/sprockets%2Ff0d3068f05825e1dfd9f5aaba946d3dc +0 -0
- data/test/dummy/tmp/cache/assets/DD3/0E0/sprockets%2F3e9e08a334bae7deadb5335f5e4f195f +0 -0
- data/test/dummy/tmp/cache/assets/DDB/980/sprockets%2Fbd2abc80a17c901e2f497f88f9be58cf +0 -0
- data/test/dummy/tmp/cache/assets/E00/ED0/sprockets%2Ffecf3bffeb200a47e96bd04cbc878076 +1535 -0
- data/test/dummy/tmp/cache/assets/EFB/560/sprockets%2Fbca0daf751c020cdeddabbefa51cb6ea +0 -0
- data/test/dummy/tmp/restart.txt +0 -0
- data/test/test_helper.rb +10 -0
- metadata +326 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2011 YOURNAME
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'AlphaSimpriniEngine'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
|
21
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
Bundler::GemHelper.install_tasks
|
27
|
+
|
28
|
+
require 'rake/testtask'
|
29
|
+
|
30
|
+
Rake::TestTask.new(:test) do |t|
|
31
|
+
t.libs << 'lib'
|
32
|
+
t.libs << 'test'
|
33
|
+
t.pattern = 'test/**/*_test.rb'
|
34
|
+
t.verbose = false
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
task :default => :test
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#= require bundle
|
2
|
+
#= require ./lib/string
|
3
|
+
#= require ./lib/module
|
4
|
+
#= require ./alpha_simprini/mixin
|
5
|
+
#= require ./alpha_simprini/delegate
|
6
|
+
#= require ./alpha_simprini/event
|
7
|
+
#= require ./alpha_simprini/event
|
8
|
+
#= require ./alpha_simprini/html
|
9
|
+
#= require ./alpha_simprini/view
|
10
|
+
#= require_tree ./alpha_simprini/coffee_kup
|
11
|
+
#= require ./alpha_simprini/views/panel
|
12
|
+
#= require_tree ./alpha_simprini/views
|
13
|
+
#= require_tree ./alpha_simprini
|
14
|
+
|
15
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module "AS", ->
|
2
|
+
class @Application
|
3
|
+
AS.Event.extends(this)
|
4
|
+
|
5
|
+
constructor: (args) ->
|
6
|
+
@template_source = @template_source()
|
7
|
+
for name, template of @template_source
|
8
|
+
@template_source[name] = CoffeeKup.compile(template, locals:yes, hardcode:AS.TemplateHelpers)
|
9
|
+
|
10
|
+
$ => @initialize?()
|
11
|
+
|
12
|
+
template_source: -> @Templates
|
13
|
+
|
14
|
+
view: (constructor, options={}) ->
|
15
|
+
options.application = this
|
16
|
+
new constructor options
|
17
|
+
|
18
|
+
render: (template_name, locals={}) ->
|
19
|
+
data = {context: this, locals:locals}
|
20
|
+
@template_source[template_name](data)
|
21
|
+
|
22
|
+
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module "AS.CK", ->
|
2
|
+
@Binding =
|
3
|
+
binding: (model, property, getter) ->
|
4
|
+
id = AS.CK.Helpers.autoId()
|
5
|
+
model.bind "destroy", -> id.query().remove()
|
6
|
+
if getter
|
7
|
+
model.bind "change:#{property}", -> id.query().text getter.call(this, model.get(property)) || ""
|
8
|
+
span id: id.string, -> getter.call(this, model.get(property))
|
9
|
+
else
|
10
|
+
model.bind "change:#{property}", -> id.query().text model.get(property) || ""
|
11
|
+
span id: id.string, -> model.get(property)
|
12
|
+
|
13
|
+
bound_input: (model, property, options={}) ->
|
14
|
+
id = AS.CK.Helpers.autoId()
|
15
|
+
model.bind "change:#{property}", -> id.query().val model.get(property)
|
16
|
+
id.query().live 'change', ->
|
17
|
+
data = {}
|
18
|
+
data[property] = id.query().val()
|
19
|
+
model.set data
|
20
|
+
id.query().live 'keyup', ->
|
21
|
+
data = {}
|
22
|
+
data[property] = id.query().val()
|
23
|
+
model.set data
|
24
|
+
input _.extend(options, id: id.string, value: model.get property)
|
25
|
+
|
26
|
+
bind_collection: (container_tag, collection, templateName) ->
|
27
|
+
# DONT FORGET TO COMBINE LOCALS AS NEEDED
|
28
|
+
|
29
|
+
id = AS.CK.Helpers.autoId()
|
30
|
+
|
31
|
+
# Unbind before you rebind, or you'll be very :(
|
32
|
+
# As you will have a lot of templates being added EVERYWHERE
|
33
|
+
|
34
|
+
collection.unbind "add.#{templateName}-bind_collection"
|
35
|
+
collection.bind "add.#{templateName}-bind_collection", (item) =>
|
36
|
+
not_wanted = id.query().find("[data-cid=#{item.cid}]")
|
37
|
+
if not_wanted[0]
|
38
|
+
debugger
|
39
|
+
console.error "Why u add", item, "to", collection, "again?"
|
40
|
+
return
|
41
|
+
if _.isFunction(templateName)
|
42
|
+
console.error "ADDING w/o named template unimplemented sucka"
|
43
|
+
else
|
44
|
+
content = @context.render(templateName, _.extend(data.locals, item:item))
|
45
|
+
index = collection.indexOf(item)
|
46
|
+
container = id.query()
|
47
|
+
siblings = container.children()
|
48
|
+
if siblings.get(0) is undefined or siblings.get(index) is undefined
|
49
|
+
container.append(content)
|
50
|
+
else
|
51
|
+
$(siblings.get(index)).before(content)
|
52
|
+
|
53
|
+
collection.unbind "remove.#{templateName}-bind_collection"
|
54
|
+
collection.bind "remove.#{templateName}-bind_collection", (item) ->
|
55
|
+
console.log "remove", item, "from", collection
|
56
|
+
not_wanted = id.query().find("[data-cid=#{item.cid}]")
|
57
|
+
if not_wanted[0] is undefined
|
58
|
+
console.error "Could not find element to remove."
|
59
|
+
not_wanted.remove()
|
60
|
+
|
61
|
+
if container_tag.constructor is String
|
62
|
+
container_tag = [container_tag, id:id.string]
|
63
|
+
else
|
64
|
+
container_tag[1] ?= {}
|
65
|
+
container_tag[1].id = id.string
|
66
|
+
|
67
|
+
if _.isFunction(templateName)
|
68
|
+
container_tag.push ->
|
69
|
+
for item in collection.models
|
70
|
+
templateName(item)
|
71
|
+
else
|
72
|
+
container_tag.push ->
|
73
|
+
for item in collection.models
|
74
|
+
# Combine locals
|
75
|
+
text @context.render(templateName, _.extend(data.locals, item:item))
|
76
|
+
|
77
|
+
tag.apply this, container_tag
|
78
|
+
|
79
|
+
bound_select: (model, property, options, option_value_key, config={}) ->
|
80
|
+
id = AS.CK.Helpers.autoId()
|
81
|
+
model.bind "change:#{property}", ->
|
82
|
+
id.query().val model.get(property).cid
|
83
|
+
|
84
|
+
id.query().live "change", ->
|
85
|
+
data = {}
|
86
|
+
data[property] = options.getByCid(id.query().val())
|
87
|
+
model.set data
|
88
|
+
|
89
|
+
options.bind "change:#{option_value_key}", (_option) ->
|
90
|
+
id.query().find("[value=#{_option.cid}]").text _option.get(option_value_key)
|
91
|
+
|
92
|
+
options.bind "add", (_option) =>
|
93
|
+
console.error "FIXME: add option at correct position"
|
94
|
+
|
95
|
+
# THIS HERE IS A LITTLE :(
|
96
|
+
template = ->
|
97
|
+
bound_select_option(_option, option_value_key)
|
98
|
+
|
99
|
+
compiled = CoffeeKup.compile template, locals: yes, hardcode: AS.TemplateHelpers
|
100
|
+
@locals ?={}
|
101
|
+
@locals.option_value_key = option_value_key
|
102
|
+
@locals._option = _option
|
103
|
+
# YES IT IS, BUT IT ALSO WORKS :)
|
104
|
+
|
105
|
+
id.query().append compiled this
|
106
|
+
|
107
|
+
options.bind "remove", (_option) ->
|
108
|
+
id.query().find("[value=#{_option.cid}]").remove()
|
109
|
+
id.query().change()
|
110
|
+
|
111
|
+
selection = model.get(property)
|
112
|
+
select id: id.string, ->
|
113
|
+
(option -> config.blank) if config.blank
|
114
|
+
bound_select_option(_option, option_value_key, _option == selection) for _option in options.models
|
115
|
+
|
116
|
+
bound_select_option: (model, property, selected) ->
|
117
|
+
id = AS.CK.Helpers.autoId()
|
118
|
+
model.bind "change:#{property}", -> id.query().text model.get(property)
|
119
|
+
option id: id.string, value: model.cid, selected: selected, -> model.get(property)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module "AS.CK", ->
|
2
|
+
@Helpers =
|
3
|
+
shy: (string="") ->
|
4
|
+
string.replace(/([a-z])([A-Z])/g, (a, b, c) -> b + "­" + c)
|
5
|
+
|
6
|
+
incr: 0
|
7
|
+
|
8
|
+
autoId: ->
|
9
|
+
id = "CoffeeKup-#{@incr++}"
|
10
|
+
query_function = -> @node = jQuery "##{id}"
|
11
|
+
return string: id, query: _.bind(query_function, {})
|
12
|
+
|
13
|
+
_cycles: {}
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
|
@@ -0,0 +1,62 @@
|
|
1
|
+
class module("AS").Collection
|
2
|
+
AS.Delegate.extends(this)
|
3
|
+
AS.Event.extends(this)
|
4
|
+
|
5
|
+
@delegate "first", "rest", "last", "compact", "flatten", "without", "union",
|
6
|
+
"intersection", "difference", "uniq", "zip", "indexOf", "find", "detect", "at",
|
7
|
+
"lastIndexOf", "range", "include", "each", "map", "reject","all", "toArray", to: "models"
|
8
|
+
|
9
|
+
@model: -> AS.Model
|
10
|
+
|
11
|
+
constructor: (@models=[]) ->
|
12
|
+
@initialize()
|
13
|
+
|
14
|
+
initialize: () ->
|
15
|
+
given_models = @models
|
16
|
+
@length = 0
|
17
|
+
@byId = {}
|
18
|
+
@byCid = {}
|
19
|
+
@models = _([]).chain()
|
20
|
+
@add(model) for model in given_models
|
21
|
+
|
22
|
+
add: (model={}, options={}) ->
|
23
|
+
throw new Error("Cannot add model to collection twice.") if @models.include(model).value()
|
24
|
+
|
25
|
+
unless model instanceof AS.Model
|
26
|
+
model = @build(model)
|
27
|
+
|
28
|
+
@_add(model, options)
|
29
|
+
|
30
|
+
model
|
31
|
+
|
32
|
+
_add: (model, options={}) ->
|
33
|
+
options.at ?= this.length
|
34
|
+
index = options.at
|
35
|
+
@byCid[model.cid] = @byId[model.id] = model
|
36
|
+
@models.splice index, 0, model
|
37
|
+
@length++
|
38
|
+
model.bind("all", @_on_model_event, this)
|
39
|
+
model.trigger "add", this, options
|
40
|
+
|
41
|
+
remove: (model, options) -> @_remove(model, options)
|
42
|
+
|
43
|
+
_remove: (model, options) ->
|
44
|
+
@length--
|
45
|
+
delete @byId[model.id]
|
46
|
+
delete @byCid[model.cid]
|
47
|
+
@models = @models.chain().without(model)
|
48
|
+
model.trigger("remove", this, options)
|
49
|
+
model.unbind("all", @_on_model_event)
|
50
|
+
|
51
|
+
build: (model) ->
|
52
|
+
if model._type
|
53
|
+
ctor = module(model._type)
|
54
|
+
else
|
55
|
+
ctor = @constructor.model()
|
56
|
+
new ctor(model)
|
57
|
+
|
58
|
+
# When an event is triggered from a model, it is bubbled up through the collection.
|
59
|
+
_on_model_event: (event, model, collection, options) ->
|
60
|
+
return if (event is "add" or event is "remove") and (this isnt collection)
|
61
|
+
@_remove(model, options) if event is "destroy"
|
62
|
+
@trigger.apply(this, arguments)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module("AS").Delegate = new AS.Mixin
|
2
|
+
class_methods:
|
3
|
+
delegate: (delegated_methods..., options) ->
|
4
|
+
delegatee = options.to
|
5
|
+
callOrReturn = (object, fn_or_object, args) ->
|
6
|
+
if _.isFunction(fn_or_object)
|
7
|
+
fn_or_object.apply(object, args)
|
8
|
+
else
|
9
|
+
object
|
10
|
+
|
11
|
+
_(delegated_methods).chain().flatten().each (method) =>
|
12
|
+
if _.isString(delegatee)
|
13
|
+
@::[method] = ->
|
14
|
+
_delegatee = @[delegatee]
|
15
|
+
callOrReturn _delegatee, _delegatee[method], arguments
|
16
|
+
else if _.isFunction(delegatee)
|
17
|
+
@::[method] = ->
|
18
|
+
_delegatee = delegatee()
|
19
|
+
callOrReturn _delegatee, _delegatee[method], arguments
|
20
|
+
else
|
21
|
+
@::[method] = -> callOrReturn delegatee, delegatee[method], arguments
|
@@ -0,0 +1,75 @@
|
|
1
|
+
@module "AS", ->
|
2
|
+
@Event = new AS.Mixin
|
3
|
+
instance_methods:
|
4
|
+
_eventNamespacer: /\.([\w-_]+)$/
|
5
|
+
bind: (ev, callback, context) ->
|
6
|
+
if match = ev.match @_eventNamespacer
|
7
|
+
[ev, namespace] = ev.split(".")
|
8
|
+
namespace ?= 'none'
|
9
|
+
|
10
|
+
calls = @_callbacks ?= {}
|
11
|
+
list = calls[ev] ?= { none: [] }
|
12
|
+
|
13
|
+
list[namespace] ?= []
|
14
|
+
list[namespace].push [callback, context]
|
15
|
+
this
|
16
|
+
|
17
|
+
unbind: (ev, callback) ->
|
18
|
+
if !ev
|
19
|
+
delete @_callbacks
|
20
|
+
else if calls = @_callbacks
|
21
|
+
if !callback
|
22
|
+
if ev[0] is "."
|
23
|
+
namespace = ev.slice(1)
|
24
|
+
for event, namespaces of calls
|
25
|
+
namespaces[namespace] = []
|
26
|
+
else
|
27
|
+
return this unless calls[ev.split(".")[0]]
|
28
|
+
if match = ev.match @_eventNamespacer
|
29
|
+
[ev, namespace] = ev.split(".")
|
30
|
+
calls[ev][namespace] = []
|
31
|
+
else
|
32
|
+
calls[ev] = { none: [] }
|
33
|
+
else
|
34
|
+
for key, handlers of calls[ev]
|
35
|
+
calls[ev][key] = _(handlers).reject (handler) -> handler[0] is callback
|
36
|
+
# for handler, index in handlers
|
37
|
+
# delete handlers[index] if handler[0] is callback
|
38
|
+
# break
|
39
|
+
# # Delete leaves around [undefined] nonsense
|
40
|
+
# cals[ev][key] = _.compact(handlers)
|
41
|
+
|
42
|
+
this
|
43
|
+
|
44
|
+
trigger: (eventName) ->
|
45
|
+
return this unless calls = @_callbacks
|
46
|
+
if eventName.match @_eventNamespacer
|
47
|
+
[eventName, namespace] = eventName.split(".")
|
48
|
+
both = 2
|
49
|
+
while both--
|
50
|
+
ev = if both
|
51
|
+
eventName
|
52
|
+
else
|
53
|
+
'all'
|
54
|
+
if list = calls[ev]
|
55
|
+
if namespace and ev isnt 'all'
|
56
|
+
if list[namespace]
|
57
|
+
for handler in list[namespace]
|
58
|
+
args = if both
|
59
|
+
Array::slice.call(arguments, 1)
|
60
|
+
else
|
61
|
+
arguments
|
62
|
+
handler[0].apply(handler[1] || this, args)
|
63
|
+
else
|
64
|
+
for key, handlers of list
|
65
|
+
for handler in handlers
|
66
|
+
args = if both
|
67
|
+
Array::slice.call(arguments, 1)
|
68
|
+
else
|
69
|
+
arguments
|
70
|
+
handler[0].apply(handler[1] || this, args)
|
71
|
+
this
|
72
|
+
|
73
|
+
# _.extend(Backbone.Model::, EventExtensions)
|
74
|
+
# _.extend(Backbone.Collection::, EventExtensions)
|
75
|
+
# _.extend(Backbone.View::, EventExtensions)
|
@@ -0,0 +1,56 @@
|
|
1
|
+
class module("AS").HTML
|
2
|
+
@elements: _('a abbr address article aside audio b bdi bdo blockquote body button
|
3
|
+
canvas caption cite code colgroup datalist dd del details dfn div dl dt em
|
4
|
+
fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 head header hgroup
|
5
|
+
html i iframe ins kbd label legend li map mark menu meter nav noscript object
|
6
|
+
ol optgroup option output p pre progress q rp rt ruby s samp script section
|
7
|
+
select small span strong style sub summary sup table tbody td textarea tfoot
|
8
|
+
th thead time title tr u ul video area base br col command embed hr img input keygen link meta param
|
9
|
+
source track wbr'.split(" ")).chain().compact()
|
10
|
+
|
11
|
+
constructor: (args) ->
|
12
|
+
# body...
|
13
|
+
|
14
|
+
text: (text_content) ->
|
15
|
+
@span text_content
|
16
|
+
|
17
|
+
raw: (html) ->
|
18
|
+
$(@span()).html(html)
|
19
|
+
|
20
|
+
tag: (name, attrs, content) ->
|
21
|
+
@current_node ?= document.createDocumentFragment()
|
22
|
+
|
23
|
+
if _.isFunction(attrs)
|
24
|
+
content = attrs
|
25
|
+
attrs = undefined
|
26
|
+
if _.isString(attrs)
|
27
|
+
text_content = attrs
|
28
|
+
attrs = undefined
|
29
|
+
|
30
|
+
# TODO: use jQuery for better compatibility / less performance
|
31
|
+
node = document.createElement(name)
|
32
|
+
node.setAttribute(key, value) for key, value of attrs unless attrs is undefined
|
33
|
+
@current_node.appendChild node
|
34
|
+
|
35
|
+
if text_content
|
36
|
+
$(node).text text_content
|
37
|
+
else if content
|
38
|
+
@within_node node, ->
|
39
|
+
last = content.call(this)
|
40
|
+
if _.isString(last)
|
41
|
+
@text(last)
|
42
|
+
|
43
|
+
node
|
44
|
+
|
45
|
+
within_node: (node, fn) ->
|
46
|
+
node = node[0] if node?.jquery
|
47
|
+
prior_node = @current_node
|
48
|
+
@current_node = node
|
49
|
+
content = fn.call(this)
|
50
|
+
@current_node = prior_node
|
51
|
+
content
|
52
|
+
|
53
|
+
dangling_content: (fn) -> @within_node(null, fn)
|
54
|
+
|
55
|
+
AS.HTML.elements.each (element) ->
|
56
|
+
AS.HTML::[element] = -> @tag.apply this, _(arguments).unshift(element)
|