canjs-rails 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +7 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +3 -0
- data/LICENSE +21 -0
- data/README.md +36 -0
- data/Rakefile +2 -0
- data/canjs-rails.gemspec +23 -0
- data/lib/canjs-rails.rb +1 -0
- data/lib/canjs/rails.rb +7 -0
- data/lib/canjs/rails/engine.rb +6 -0
- data/lib/canjs/rails/version.rb +6 -0
- data/vendor/assets/javascripts/can.construct.proxy.js +60 -0
- data/vendor/assets/javascripts/can.construct.super.js +44 -0
- data/vendor/assets/javascripts/can.control.plugin.js +245 -0
- data/vendor/assets/javascripts/can.control.view.js +88 -0
- data/vendor/assets/javascripts/can.fixture.js +1020 -0
- data/vendor/assets/javascripts/can.jquery.js +2995 -0
- data/vendor/assets/javascripts/can.jquery.min.js +52 -0
- data/vendor/assets/javascripts/can.observe.attributes.js +293 -0
- data/vendor/assets/javascripts/can.observe.backup.js +368 -0
- data/vendor/assets/javascripts/can.observe.delegate.js +359 -0
- data/vendor/assets/javascripts/can.observe.setter.js +58 -0
- data/vendor/assets/javascripts/can.observe.validations.js +374 -0
- data/vendor/assets/javascripts/can.view.modifiers.js +292 -0
- data/vendor/assets/javascripts/download_canjs.sh +15 -0
- metadata +108 -0
data/.gitignore
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2012 Craig Wickesser
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# canjs-rails
|
2
|
+
|
3
|
+
CanJS for Rails!
|
4
|
+
|
5
|
+
This gem provides:
|
6
|
+
|
7
|
+
* can.jquery 1.0.7 (and can.jquery.min)
|
8
|
+
* all can.js plugins available as of CanJS 1.0.7
|
9
|
+
|
10
|
+
This gem requires the asset pipeline, so it should work with Rails 3.1 or later. The version of CanJS included with this gem (can.jquery) requires jQuery, conveniently Rails 3.1 and later includes jquery-rails by default, so you won't need to explicitly install jQuery. However, if you aren't using jquery-rails make sure you install jQuery and require it before can.jquery in your `app/assets/javascripts/application.js`.
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
Add the canjs-rails gem to your Gemfile.
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
gem "canjs-rails"
|
18
|
+
```
|
19
|
+
|
20
|
+
And run `bundle install`.
|
21
|
+
|
22
|
+
### Rails 3.1 or greater (with asset pipeline *enabled*)
|
23
|
+
|
24
|
+
To make the core CanJS library available add these lines to `app/assets/javascripts/application.js`:
|
25
|
+
|
26
|
+
```js
|
27
|
+
//= require can.jquery
|
28
|
+
```
|
29
|
+
|
30
|
+
You're done!
|
31
|
+
|
32
|
+
## Acknowledgements
|
33
|
+
|
34
|
+
Many thanks are due to [the jquery-rails project](https://github.com/rails/jquery-rails/) as it was used as the basis for this gem.
|
35
|
+
|
36
|
+
Copyright [Craig Wickesser](http://mindscratch.org), released under the MIT License.
|
data/Rakefile
ADDED
data/canjs-rails.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/canjs/rails/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "canjs-rails"
|
6
|
+
s.version = Canjs::Rails::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = ["Craig Wickesser"]
|
9
|
+
s.email = ["craig@mindscratch.org"]
|
10
|
+
s.homepage = "https://github.com/mindscratch/canjs-rails"
|
11
|
+
s.summary = "Use CanJS with Rails 3.1+"
|
12
|
+
s.description = "This gem provides CanJS for your Rails 3.1+ application."
|
13
|
+
|
14
|
+
s.required_rubygems_version = ">= 1.3.6"
|
15
|
+
s.rubyforge_project = "canjs-rails"
|
16
|
+
|
17
|
+
s.add_dependency "railties", ">= 3.2.0", "< 5.0"
|
18
|
+
s.add_dependency "thor", "~> 0.14"
|
19
|
+
|
20
|
+
s.files = `git ls-files`.split("\n")
|
21
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
22
|
+
s.require_path = 'lib'
|
23
|
+
end
|
data/lib/canjs-rails.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'canjs/rails'
|
data/lib/canjs/rails.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
(function(can, window, undefined){
|
2
|
+
var isFunction = can.isFunction,
|
3
|
+
isArray = can.isArray,
|
4
|
+
makeArray = can.makeArray,
|
5
|
+
|
6
|
+
proxy = function( funcs ) {
|
7
|
+
|
8
|
+
//args that should be curried
|
9
|
+
var args = makeArray(arguments),
|
10
|
+
self;
|
11
|
+
|
12
|
+
// get the functions to callback
|
13
|
+
funcs = args.shift();
|
14
|
+
|
15
|
+
// if there is only one function, make funcs into an array
|
16
|
+
if (!isArray(funcs) ) {
|
17
|
+
funcs = [funcs];
|
18
|
+
}
|
19
|
+
|
20
|
+
// keep a reference to us in self
|
21
|
+
self = this;
|
22
|
+
|
23
|
+
|
24
|
+
return function class_cb() {
|
25
|
+
// add the arguments after the curried args
|
26
|
+
var cur = args.concat(makeArray(arguments)),
|
27
|
+
isString,
|
28
|
+
length = funcs.length,
|
29
|
+
f = 0,
|
30
|
+
func;
|
31
|
+
|
32
|
+
// go through each function to call back
|
33
|
+
for (; f < length; f++ ) {
|
34
|
+
func = funcs[f];
|
35
|
+
if (!func ) {
|
36
|
+
continue;
|
37
|
+
}
|
38
|
+
|
39
|
+
// set called with the name of the function on self (this is how this.view works)
|
40
|
+
isString = typeof func == "string";
|
41
|
+
|
42
|
+
// call the function
|
43
|
+
cur = (isString ? self[func] : func).apply(self, cur || []);
|
44
|
+
|
45
|
+
// pass the result to the next function (if there is a next function)
|
46
|
+
if ( f < length - 1 ) {
|
47
|
+
cur = !isArray(cur) || cur._use_call ? [cur] : cur
|
48
|
+
}
|
49
|
+
}
|
50
|
+
return cur;
|
51
|
+
}
|
52
|
+
}
|
53
|
+
can.Construct.proxy = can.Construct.prototype.proxy = proxy;
|
54
|
+
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
})(this.can, this )
|
@@ -0,0 +1,44 @@
|
|
1
|
+
(function(can, window, undefined){
|
2
|
+
|
3
|
+
// tests if we can get super in .toString()
|
4
|
+
var isFunction = can.isFunction,
|
5
|
+
|
6
|
+
fnTest = /xyz/.test(function() {
|
7
|
+
xyz;
|
8
|
+
}) ? /\b_super\b/ : /.*/;
|
9
|
+
|
10
|
+
// overwrites a single property so it can still call super
|
11
|
+
can.Construct._overwrite = function(addTo, base, name, val){
|
12
|
+
// Check if we're overwriting an existing function
|
13
|
+
addTo[name] = isFunction(val) &&
|
14
|
+
isFunction(base[name]) &&
|
15
|
+
fnTest.test(val) ? (function( name, fn ) {
|
16
|
+
return function() {
|
17
|
+
var tmp = this._super,
|
18
|
+
ret;
|
19
|
+
|
20
|
+
// Add a new ._super() method that is the same method
|
21
|
+
// but on the super-class
|
22
|
+
this._super = base[name];
|
23
|
+
|
24
|
+
// The method only need to be bound temporarily, so we
|
25
|
+
// remove it when we're done executing
|
26
|
+
ret = fn.apply(this, arguments);
|
27
|
+
this._super = tmp;
|
28
|
+
return ret;
|
29
|
+
};
|
30
|
+
})(name, val) : val;
|
31
|
+
}
|
32
|
+
// overwrites an object with methods, sets up _super
|
33
|
+
// newProps - new properties
|
34
|
+
// oldProps - where the old properties might be
|
35
|
+
// addTo - what we are adding to
|
36
|
+
can.Construct._inherit = function( newProps, oldProps, addTo ) {
|
37
|
+
addTo = addTo || newProps
|
38
|
+
for ( var name in newProps ) {
|
39
|
+
can.Construct._overwrite(addTo, oldProps, name, newProps[name]);
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
|
44
|
+
})(this.can, this )
|
@@ -0,0 +1,245 @@
|
|
1
|
+
(function(can, window, undefined){
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
//used to determine if a control instance is one of controllers
|
6
|
+
//controllers can be strings or classes
|
7
|
+
var i,
|
8
|
+
isAControllerOf = function( instance, controllers ) {
|
9
|
+
for ( i = 0; i < controllers.length; i++ ) {
|
10
|
+
if ( typeof controllers[i] == 'string' ? instance.constructor._shortName == controllers[i] : instance instanceof controllers[i] ) {
|
11
|
+
return true;
|
12
|
+
}
|
13
|
+
}
|
14
|
+
return false;
|
15
|
+
},
|
16
|
+
data = function(el, data){
|
17
|
+
return $el.data('controls');
|
18
|
+
},
|
19
|
+
makeArray = can.makeArray,
|
20
|
+
old = can.Control.setup;
|
21
|
+
|
22
|
+
/*
|
23
|
+
* static
|
24
|
+
*/
|
25
|
+
can.Control.setup = function() {
|
26
|
+
// if you didn't provide a name, or are control, don't do anything
|
27
|
+
if ( this !== can.Control ) {
|
28
|
+
|
29
|
+
/**
|
30
|
+
* @attribute can.Control.plugin.static.pluginName
|
31
|
+
* @parent can.Control.plugin
|
32
|
+
*
|
33
|
+
* Setting the static `pluginName` property allows you to override the default name
|
34
|
+
* with your own.
|
35
|
+
*
|
36
|
+
* var Filler = can.Control({
|
37
|
+
* pluginName: 'fillWith'
|
38
|
+
* },{});
|
39
|
+
*
|
40
|
+
* $("#foo").fillWith();
|
41
|
+
*
|
42
|
+
* If you don't provide a `pluginName`, the control falls back to the
|
43
|
+
* [can.Construct.fullName fullName] attribute:
|
44
|
+
*
|
45
|
+
* can.Control('Ui.Layout.FillWith', {}, {});
|
46
|
+
* $("#foo").ui_layout_fill_with();
|
47
|
+
*
|
48
|
+
*/
|
49
|
+
var pluginName = this.pluginName || this._fullName;
|
50
|
+
|
51
|
+
// create jQuery plugin
|
52
|
+
if(pluginName !== 'can_control'){
|
53
|
+
this.plugin(pluginName);
|
54
|
+
}
|
55
|
+
|
56
|
+
old.apply(this, arguments);
|
57
|
+
}
|
58
|
+
};
|
59
|
+
|
60
|
+
/*
|
61
|
+
* prototype
|
62
|
+
*/
|
63
|
+
$.fn.extend({
|
64
|
+
|
65
|
+
/**
|
66
|
+
* @function jQuery.fn.controls
|
67
|
+
* @parent can.Control.plugin
|
68
|
+
*
|
69
|
+
* When the widget is initialized, the plugin control creates an array
|
70
|
+
* of control instance(s) with the DOM element it was initialized on using
|
71
|
+
* [can.data] method.
|
72
|
+
*
|
73
|
+
* The `controls` method allows you to get the control instance(s) for any element.
|
74
|
+
*
|
75
|
+
* //- Inits the widgets
|
76
|
+
* $('.widgets:eq(0)').my_box();
|
77
|
+
* $('.widgets:eq(1)').my_clock();
|
78
|
+
*
|
79
|
+
* <div class="widgets my_box" />
|
80
|
+
* <div class="widgets my_clock" />
|
81
|
+
*
|
82
|
+
* $('.widgets').controls() //-> [ MyBox, MyClock ]
|
83
|
+
*
|
84
|
+
* Additionally, you can invoke it passing the name of a control
|
85
|
+
* to fetch a specific instance(s).
|
86
|
+
*
|
87
|
+
* //- Inits the widgets
|
88
|
+
* $('.widgets:eq(0)').my_box();
|
89
|
+
* $('.widgets:eq(1)').my_clock();
|
90
|
+
*
|
91
|
+
* <div class="widgets my_box" />
|
92
|
+
* <div class="widgets my_clock" />
|
93
|
+
*
|
94
|
+
* $('.widgets').controls('MyBox') //-> [ MyBox ]
|
95
|
+
*
|
96
|
+
* @param {Object} control (optional) if exists the control instance(s) with that constructor function or type will be returned.
|
97
|
+
* @return {Array} an array of control instance(s).
|
98
|
+
*/
|
99
|
+
controls: function() {
|
100
|
+
var controllerNames = makeArray(arguments),
|
101
|
+
instances = [],
|
102
|
+
controls, c, cname;
|
103
|
+
//check if arguments
|
104
|
+
this.each(function() {
|
105
|
+
|
106
|
+
controls = can.$(this).data("controls");
|
107
|
+
if(!controls){
|
108
|
+
return;
|
109
|
+
}
|
110
|
+
for(var i=0; i<controls.length; i++){
|
111
|
+
c = controls[i];
|
112
|
+
if (!controllerNames.length || isAControllerOf(c, controllerNames) ) {
|
113
|
+
instances.push(c);
|
114
|
+
}
|
115
|
+
}
|
116
|
+
});
|
117
|
+
return instances;
|
118
|
+
},
|
119
|
+
|
120
|
+
/**
|
121
|
+
* @function jQuery.fn.control
|
122
|
+
* @parent can.Control.plugin
|
123
|
+
*
|
124
|
+
* The `control` does the same as [jQuery.fn.controls controls] execept it only
|
125
|
+
* returns the first instance found.
|
126
|
+
*
|
127
|
+
* //- Init MyBox widget
|
128
|
+
* $('.widgets').my_box();
|
129
|
+
*
|
130
|
+
* <div class="widgets my_box" />
|
131
|
+
*
|
132
|
+
* $('.widgets').controls() //-> MyBox
|
133
|
+
*
|
134
|
+
* @param {Object} control (optional) if exists the first control instance with that constructor function or type will be returned.
|
135
|
+
* @return {can.Control} the first control.
|
136
|
+
*/
|
137
|
+
control: function( control ) {
|
138
|
+
return this.controls.apply(this, arguments)[0];
|
139
|
+
}
|
140
|
+
});
|
141
|
+
|
142
|
+
can.Control.plugin = function(pluginname){
|
143
|
+
var control = this;
|
144
|
+
|
145
|
+
if (!$.fn[pluginname]) {
|
146
|
+
$.fn[pluginname] = function(options){
|
147
|
+
|
148
|
+
var args = makeArray(arguments), //if the arg is a method on this control
|
149
|
+
isMethod = typeof options == "string" && $.isFunction(control.prototype[options]), meth = args[0];
|
150
|
+
return this.each(function(){
|
151
|
+
//check if created
|
152
|
+
var plugin = can.$(this).control(control);
|
153
|
+
|
154
|
+
if (plugin) {
|
155
|
+
if (isMethod) {
|
156
|
+
// call a method on the control with the remaining args
|
157
|
+
plugin[meth].apply(plugin, args.slice(1));
|
158
|
+
}
|
159
|
+
else {
|
160
|
+
// call the plugin's update method
|
161
|
+
plugin.update.apply(plugin, args);
|
162
|
+
}
|
163
|
+
}
|
164
|
+
else {
|
165
|
+
//create a new control instance
|
166
|
+
control.newInstance.apply(control, [this].concat(args));
|
167
|
+
}
|
168
|
+
});
|
169
|
+
};
|
170
|
+
}
|
171
|
+
}
|
172
|
+
|
173
|
+
/**
|
174
|
+
* @function can.Control.prototype.update
|
175
|
+
* @parent can.Control.plugin
|
176
|
+
*
|
177
|
+
* Update extends [can.Control.prototype.options options]
|
178
|
+
* with the `options` argument and rebinds all events. It
|
179
|
+
* re-configures the control.
|
180
|
+
*
|
181
|
+
* For example, the following control wraps a recipe form. When the form
|
182
|
+
* is submitted, it creates the recipe on the server. When the recipe
|
183
|
+
* is `created`, it resets the form with a new instance.
|
184
|
+
*
|
185
|
+
* var Creator = can.Control({
|
186
|
+
* "{recipe} created" : function(){
|
187
|
+
* this.update({recipe : new Recipe()});
|
188
|
+
* this.element[0].reset();
|
189
|
+
* this.element.find("[type=submit]").val("Create Recipe")
|
190
|
+
* },
|
191
|
+
* "submit" : function(el, ev){
|
192
|
+
* ev.preventDefault();
|
193
|
+
* var recipe = this.options.recipe;
|
194
|
+
* recipe.attrs( this.element.formParams() );
|
195
|
+
* this.element.find("[type=submit]").val("Saving...")
|
196
|
+
* recipe.save();
|
197
|
+
* }
|
198
|
+
* });
|
199
|
+
*
|
200
|
+
* $('#createRecipes').creator({ recipe : new Recipe() })
|
201
|
+
*
|
202
|
+
* *Update* is called if a control's plugin helper is called with the plugin options on an element
|
203
|
+
* that already has a control instance of the same type. If you want to implement your
|
204
|
+
* own update method make sure to call the old one either using the [can.Construct.super super] plugin or
|
205
|
+
* by calling `can.Control.prototype.update.apply(this, arguments);`.
|
206
|
+
* For example, you can change the content of the control element every time the options change:
|
207
|
+
*
|
208
|
+
* var Plugin = can.Control({
|
209
|
+
* pluginName: 'myPlugin'
|
210
|
+
* }, {
|
211
|
+
* init : function(el, options) {
|
212
|
+
* this.updateCount = 0;
|
213
|
+
* this.update({
|
214
|
+
* text : 'Initialized'
|
215
|
+
* });
|
216
|
+
* },
|
217
|
+
* update : function(options) {
|
218
|
+
* // Call the can.Control update first.
|
219
|
+
* // Use this._super when using can/construct/super
|
220
|
+
* can.Control.prototype.update.call(this, options);
|
221
|
+
* this.element.html(this.options.text + ' ' +
|
222
|
+
* (++this.updateCount) + ' times');
|
223
|
+
* }
|
224
|
+
* });
|
225
|
+
*
|
226
|
+
* $('#control').myPlugin();
|
227
|
+
* $('#control').html();
|
228
|
+
* // Initialized. Updated 1 times
|
229
|
+
*
|
230
|
+
* $('#control').myPlugin({ text : 'Calling update. Updated' });
|
231
|
+
* $('#control').html();
|
232
|
+
* // Calling update. Updated 2 times
|
233
|
+
*
|
234
|
+
* @demo can/control/plugin/demo-update.html
|
235
|
+
*
|
236
|
+
* @param {Object} options A list of options to merge with
|
237
|
+
* [can.Control.prototype.options this.options]. Often this method
|
238
|
+
* is called by the [can.Control.plugin jQuery helper function].
|
239
|
+
*/
|
240
|
+
can.Control.prototype.update = function( options ) {
|
241
|
+
can.extend(this.options, options);
|
242
|
+
this.on();
|
243
|
+
};
|
244
|
+
|
245
|
+
})(this.can, this )
|