Permalink
Browse files

Add new JavaScripts - prepare for first public version

  • Loading branch information...
1 parent a7ce25f commit db6664b8f7071a2f35c922e44aca04e3809f19d4 @maccman committed May 11, 2010
View
11 README.txt
@@ -103,7 +103,7 @@ Which will generate code a bit like this:
Now, in the view you can bind HTML to this collection, by
using the following javascript:
- $('#users').bowlineBind('UsersBinder');
+ $('#users').bowlineChain('UsersBinder');
You should probably become familiar with Chain.js (which bowline uses for binding): http://wiki.github.com/raid-ox/chain.js/
@@ -220,7 +220,7 @@ Usage for a collection (of users):
jQuery(function($){
$.bowline.ready(function(){
// Bind the element users to UserBinder
- var users = $('#users').bowlineBind('UsersBinder', function(){
+ var users = $('#users').bowlineChain('UsersBinder', function(){
var self = $(this);
self.find('.destroy').click(function(){
self.invoke('destroy');
@@ -274,8 +274,11 @@ Usage for a collection (of users):
Install the Twitter gem:
>> sudo gem install twitter
- Add the Twitter gem to config/environment.rb:
- config.gem "twitter"
+ Add the Twitter gem to Gemfile:
+ gem "twitter"
+
+ Bundle gems:
+ >> gem bundle
run:
>> script/run
View
4 Rakefile
@@ -11,7 +11,7 @@ begin
gemspec.add_dependency('activesupport', '>= 3.0.0.beta')
gemspec.add_dependency('rubyzip2', '>= 2.0.1')
gemspec.add_dependency('bundler08', '>= 0.8.5')
- gemspec.add_dependency('supermodel')
+ gemspec.add_dependency('supermodel', '>= 0.1.3')
gemspec.post_install_message = <<-POST_INSTALL_MESSAGE
#{'*'*50}
@@ -25,7 +25,7 @@ begin
POST_INSTALL_MESSAGE
end
rescue LoadError
- puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
+ puts "Jeweler not available. Install it with: sudo gem install jeweler"
end
task :write_version do
View
2 VERSION
@@ -1 +1 @@
-0.6.3
+0.9.0
View
0 assets/application.js
No changes.
View
87 assets/bowline.chain.js
@@ -0,0 +1,87 @@
+if (typeof Bowline == "undefined") throw 'Bowline required';
+
+// Usage:
+// var chain = new Bowline.Chain(element);
+// chain.bind("AssetBinder");
+
+(function($){
+
+Bowline.Chain = new SuperClass();
+Bowline.Chain.include({
+ init: function(element, options){
+ this.options = options || {};
+ this.singleton = this.options.singleton || false;
+
+ this.element = $(element);
+ this.select = function(){ return true };
+
+ this.element.chain(options);
+ },
+
+ bind: function(binderName, options){
+ return Bowline.bind(binderName, this, options);
+ },
+
+ replace: function(value){
+ if (this.singleton) {
+ this.element.item("replace", value);
+ } else {
+ this.element.items("replace", value);
+ }
+ },
+
+ create: function(item){
+ if ( !item.id ) return;
+ if (this.singleton) {
+ var data = this.element.item();
+ // Different item has been created
+ if ( !data || data.id != item.id ) return;
+ this.element.item(item);
+ } else {
+ if ( !this.select(item) ) return;
+ this.element.items("add", item);
+ }
+ },
+
+ update: function(id, item){
+ if (this.singleton) {
+ var data = this.element.item();
+ if ( !data || data.id != item.id ) return;
+ this.element.item(item);
+ } else {
+ if ( !this.select(item) ) return;
+ var element = this.element.findItem({id:id});
+ if ( element ) element.item(item);
+ this.element.update();
+ }
+ },
+
+ destroy: function(id){
+ if (this.singleton) {
+ this.element.item("replace", {});
+ } else {
+ if ( !this.select(item) ) return;
+ var element = this.element.findItem({id:id});
+ if ( element ) element.item("remove");
+ this.element.update();
+ }
+ }
+});
+
+$.fn.findItem = function(item){
+ var result = $.grep(
+ this.items(true),
+ function(el){
+ return($(el).item().id == item.id);
+ }
+ );
+ return $(result);
+};
+
+$.fn.bowlineChain = function(){
+ var chain = new Bowline.Chain(this);
+ chain.bind.apply(chain, arguments);
+ return this;
+};
+
+})(jQuery);
View
443 assets/bowline.js
@@ -1,350 +1,185 @@
-/*
- Bowline JavaScript API
-
- This library lets you call Ruby methods, and bind up elements.
- It requires jQuery and Chain.js:
- http://jquery.com
- http://github.com/raid-ox/chain.js
-
- = Functions
-
- invoke(klass, method, *args)
- Invoke a class method on a particular class. Usually
- used to invoke methods on a binder. The class needs to
- be exposed to JS (using the Bowline::Desktop::Bridge#js_expose).
- Usage:
- Bowline.invoke('MyClass', 'my_method');
-
- instanceInvoke(klass, id, method, *args)
- Invoke an instance method an a binder.
- Usually called via the jQuery helper functions.
- Usage:
- Bowline.instanceInvoke('UsersBinder', 1, 'charge!');
-
- windowInvoke(method, *args)
- Invoke class method on this window's class.
- Usage:
- Bowline.windowInvoke('close');
-
- helper(method, *args)
- Invoke a method defined in any helper.
-
- bind(element, klass, options = {})
- Bind a element to a Bowline binder.
- Usually called via the jQuery helper functions.
- Usage:
- Bowline.bind('#users', 'UsersBinder');
-
- The options can either be a template hash:
- {
- '.name .first': {
- style: 'color: blue;',
- content: 'First Name: {first}'
- },
- '.name .last': 'Family Name: {last}',
- '.address': function(data, el){
- if(!data.address)
- el.hide();
- return data.address;
- },
- builder: function(){
- var data = this.item();
- this.find('.name').click(function(){alert(data.name)});
- }
- }
-
- Or the options can be a builder function:
- (function(){
- this.bind('click', function(){
- var data = this.item();
- alert(data);
- })
-
- For more documentation, look at the Chain.js library:
- http://wiki.github.com/raid-ox/chain.js/elementchain
-
- = Filtering items
-
- $('#users').items('filter', 'value');
-
- = Sorting items
-
- $('#users').items('sort', 'first_name');
-
- = Update events
-
- $('#users').update(function(){
- //...
- });
-
- = JQuery functions
-
- These are how you usually bind elements, or invoke a binders class/instance methods.
-
- $.fn.bowlineBind(klass, options)
- Associate an an element with a Bowline binder.
- Example:
- $("#users").bowlineBind('UsersBinder');
-
- $.fn.bowlineUnbind(klass)
- Opposite of bowlineBind.
- Example:
- $("#users").bowlineUnbind('UsersBinder');
-
- $.fn.invoke(method, *args)
- Invoke a class/instance method on a Bowline binder.
-
- If called on the bound element, in this example the #users div, then a class method
- will be called on the binder.
- Example:
- $("#users").invoke("my_class_method", "arg1");
-
- If called on a item inside a bound element, an instance method will be called.
- Example:
- $("#users").items(10).invoke("my_instance_method");
-
- = Debugging
-
- Turn on Bowline.trace to show debugging information:
- Bowline.trace = true
-
- = Using other libraries (e.g. Prototype)
-
- Although this library requires jQuery, its API is not jQuery
- specific. It's perfectly feasible to rewrite to use Prototype instead.
- Additionally, jQuery plays nicely with other libraries using it's noConflict() method.
- So you're still free to use other JavaScript libraries without fear of conflicts.
+var Bowline = new SuperClass();
-*/
-
-var BowlineBound = function(klass){
- this.klass = klass;
- this.options = {};
- this.elements = jQuery();
-};
-
-BowlineBound.fn = BowlineBound.prototype;
-
-BowlineBound.fn.updateOptions = function(opts){
- this.options = jQuery.extend({}, this.options, opts);
- this.singleton = this.options.singleton;
-}
-
-BowlineBound.fn.push = function(element){
- this.elements = this.elements.add(element);
- this.setup();
-}
-
-BowlineBound.fn.replace = function(items){
- if(this.singleton) {
- this.elements.item("replace", items);
- } else {
- this.elements.items("replace", items);
- }
-}
-
-BowlineBound.fn.create = function(id, item){
- if(this.singleton) {
- this.elements.item(item);
- } else {
- this.elements.items("add", item);
- }
-}
-
-BowlineBound.fn.update = function(id, item){
- if(!item.id) item.id = id;
- if(this.singleton){
- this.elements.item(item);
- } else {
- this.findElement(id).item(item);
- }
-}
-
-BowlineBound.fn.remove = function(id){
- if(this.singleton) {
- this.elements.item("replace", {});
- } else {
- this.findElement(id).item("remove");
- }
-}
-
-BowlineBound.fn.invoke = function(){
- var args = $.makeArray(arguments);
- args.unshift(this.klass);
- Bowline.invoke.apply(Bowline, args);
-}
-
-BowlineBound.fn.findElement = function(id){
- // TODO - increase efficiency
- var element = jQuery();
- jQuery.each(this.elements.items(true), function(){
- var sameItem = $(this).item().id == id;
- if(sameItem) element = element.add(this);
- });
- return element;
-}
-
-BowlineBound.fn.setup = function(){
- if (this.hasSetup) return;
- this.hasSetup = true;
- var self = this;
- jQuery(function(){
- Bowline.invoke(self.klass, "setup", function(opts){
- self.updateOptions(opts);
- });
- });
-}
-
-var Bowline = {
+Bowline.extend({
callbacks: {},
uuid: 0,
bounds: {},
trace: false,
- // _app is a function defined in Objective C
+ updating: false,
+ // _app is a function defined in bowline-desktop
enabled: typeof(_app) != "undefined",
id: function(){
- return ++Bowline.uuid;
+ return ++this.uuid;
},
// Usage: invoke(klass, method, *args)
invoke: function(){
+ if( this.updating ) return;
var args = jQuery.makeArray(arguments);
var klass = args.shift();
var method = args.shift();
var id = -1;
-
+
var callback = args.pop();
if(typeof(callback) == "function"){
- id = Bowline.id();
- Bowline.callbacks[id] = callback;
+ id = this.id();
+ this.callbacks[id] = callback;
} else if(callback) {
args.push(callback);
- }
+ }
var msg = {
klass: klass,
method: method,
args: args,
id: id,
- };
+ };
- Bowline.log("New message:", msg);
+ this.log("New message:", msg);
- if(Bowline.enabled)
- _app.call(JSON.stringify(msg));
+ // Support for SuperModel instances
+ var serializer = function(key, value){
+ if (value == null) return value;
+ if (typeof value == "object" &&
+ typeof value.attributes == "function"){
+ return value.attributes();
+ } else {
+ return value;
+ }
+ };
+
+ if(this.enabled)
+ _app.call(JSON.stringify(msg, serializer));
},
// Usage: instanceInvoke(klass, id, method, *args)
instanceInvoke: function(){
var args = jQuery.makeArray(arguments);
args.splice(1, 0, "instance_invoke");
- Bowline.invoke.apply(this, args);
+ this.invoke.apply(this, args);
},
// Usage: windowInvoke(method, *args)
windowInvoke: function(){
var args = jQuery.makeArray(arguments);
args.unshift("_window");
- Bowline.invoke.apply(this, args);
+ this.invoke.apply(this, args);
},
helper: function(){
var args = jQuery.makeArray(arguments);
args.unshift("Bowline::Helpers");
- Bowline.invoke.apply(this, args);
- },
-
- bind: function(el, klass, options){
- el = jQuery(el);
-
- el.data("bowline", klass);
- el.chain(options);
-
- if(!Bowline.bounds[klass])
- Bowline.bounds[klass] = new BowlineBound(klass);
-
- Bowline.bounds[klass].push(el);
-
- // Shortcut
- Bowline[klass] = Bowline.bounds[klass];
- },
-
- unbind: function(el, klass){
- // TODO
- // var array = Bowline.bounds[klass];
- // if(!array) return;
- // array = jQuery.grep(array,
- // function(n){ return n.el != el }
- // );
- // Bowline.bounds[klass] = array;
+ this.invoke.apply(this, args);
},
openInspector: function(){
- if(Bowline.enabled)
+ if(this.enabled)
_app.openInspector();
},
+ bind: function(klass, object, options){
+ if ( !this.bounds[klass] ) {
+ this.bounds[klass] = [];
+ this.bounds[klass].push(object);
+ this.invoke(klass, "setup");
+ } else {
+ this.bounds[klass].push(object);
+ }
+ if (object.isModel)
+ this.extendModel(klass, object, options);
+ },
+
// Bowline functions
invokeJS: function(str){
- Bowline.log("Invoking:", str);
+ this.log("Invoking:", str);
+ this.updating = true;
+ var value;
try {
- return JSON.stringify(eval(str));
+ value = JSON.stringify(eval(str));
} catch(e) {
- Bowline.warn(e);
+ this.warn("Error at: " + e.sourceURL + ":" + e.line);
+ this.warn(str);
+ this.error(e);
}
+ this.updating = false;
+ return value;
},
invokeCallback: function(id, res){
- Bowline.log("Callback:", id, res);
- if(!Bowline.callbacks[id]) return;
+ this.log("Callback:", id, res);
+ if(!this.callbacks[id]) return;
try {
- Bowline.callbacks[id](JSON.parse(res));
- delete Bowline.callbacks[id];
+ this.callbacks[id](JSON.parse(res));
+ delete this.callbacks[id];
} catch(e) {
- Bowline.warn(e)
+ this.warn("Error at: " + e.sourceURL + ":" + e.line);
+ this.error(e);
}
},
replace: function(klass, items){
- if(!Bowline.bounds[klass]) return;
- Bowline.bounds[klass].replace(items);
+ if(!this.bounds[klass]) return;
+ this.eachBound(klass, function(object){
+ object.replace(items);
+ });
},
created: function(klass, id, item){
- if(!Bowline.bounds[klass]) return;
- Bowline.bounds[klass].create(id, item);
+ if(!this.bounds[klass]) return;
+ this.eachBound(klass, function(object){
+ object.create(item);
+ });
},
updated: function(klass, id, item){
- if(!Bowline.bounds[klass]) return;
- Bowline.bounds[klass].update(id, item);
+ if(!this.bounds[klass]) return;
+ this.eachBound(klass, function(object){
+ object.update(id, item);
+ });
},
- removed: function(klass, id){
- if(!Bowline.bounds[klass]) return;
- Bowline.bounds[klass].remove(id);
+ destroyed: function(klass, id){
+ if(!this.bounds[klass]) return;
+ this.eachBound(klass, function(object){
+ object.destroy(id);
+ });
},
- trigger: function(klass, event, data){
- if(!Bowline.bounds[klass]) return;
- Bowline.bounds[klass].elements.trigger(event, data);
- },
+ // System functions
- element: function(klass, id){
- if(!Bowline.bounds[klass]) return;
- return Bowline.bounds[klass].findElement(id);
+ eachBound: function(klass, callback){
+ for(var i in this.bounds[klass]){
+ callback(this.bounds[klass][i]);
+ }
},
- // System functions
-
loaded: function(){
- Bowline.windowInvoke("loaded!");
+ this.windowInvoke("loaded!");
+ },
+
+ extendModel: function(klass, object, options){
+ var self = this;
+ if ( !options ) options = {};
+
+ if (options.duplex) {
+ object.afterCreate(function(item){
+ object.invoke("create", item);
+ });
+
+ object.afterUpdate(function(item){
+ item.invoke("update", item);
+ });
+
+ object.afterDestroy(function(item){
+ item.invoke("destroy");
+ });
+ }
},
log: function(){
- if( !Bowline.trace ) return;
+ if( !this.trace ) return;
var args = jQuery.makeArray(arguments);
args.unshift("(Bowline)");
console.log.apply(console, args);
@@ -354,42 +189,52 @@ var Bowline = {
var args = jQuery.makeArray(arguments);
args.unshift("(Bowline)");
console.warn.apply(console, args);
+ },
+
+ error: function(){
+ var args = jQuery.makeArray(arguments);
+ args.unshift("(Bowline)");
+ console.error.apply(console, args);
}
-};
+});
(function($){
- $.fn.invoke = function(){
- if($(this).chain("active")){
- var args = $.makeArray(arguments);
- var element = $(this).item("root");
- var klass = element.data("bowline");
- if(!klass) throw "Unknown class: " + klass;
+ if (typeof SuperModel != "undefined") {
+ SuperModel.extend({
+ bind: function(klass, options){
+ this.boundKlass = klass;
+ Bowline.bind(this.boundKlass, this, options);
+ },
- if(Bowline[klass].singleton){
- var id = element.item().id;
- args.unshift(id);
- args.unshift(klass);
- Bowline.instanceInvoke.apply(Bowline, args);
- } else {
- args.unshift(klass);
- Bowline.invoke.apply(Bowline, args);
+ delegateInvoke: function(){
+ var calls = jQuery.makeArray(arguments);
+ var self = this;
+ jQuery.each(calls, function(i, item){
+ self[item] = function(){
+ var args = jQuery.makeArray(arguments);
+ args.unshift(item);
+ this.invoke.apply(this, args);
+ }
+ });
+ },
+
+ invoke: function(){
+ var args = jQuery.makeArray(arguments);
+ args.unshift(this.boundKlass);
+ Bowline.invoke.apply(Bowline, args);
}
- } else {
- throw 'Chain not active';
- }
- };
+ });
- $.fn.bowlineBind = function(){
- var args = $.makeArray(arguments);
- args.unshift(this);
- Bowline.bind.apply(Bowline, args);
- };
-
- $.fn.bowlineUnbind = function(){
- var args = $.makeArray(arguments);
- args.unshift(this);
- Bowline.unbind.apply(Bowline, args);
- };
+ SuperModel.fn.delegateInvoke = SuperModel.delegateInvoke;
+ SuperModel.include({
+ invoke: function(){
+ var args = jQuery.makeArray(arguments);
+ args.unshift(this.id);
+ args.unshift(this._class.boundKlass);
+ Bowline.instanceInvoke.apply(Bowline, args);
+ }
+ });
+ }
$.fn.bowlineSerialize = function(){
var array = $(this).serializeArray();
@@ -399,8 +244,8 @@ var Bowline = {
});
return object;
};
-})(jQuery);
-
-jQuery(function($){
- Bowline.loaded();
-})
+
+ $(function(){
+ Bowline.loaded();
+ });
+})(jQuery);
View
81 assets/bowline.menu.js
@@ -1,81 +0,0 @@
-var BowlineMenu = function(element, options){
- var defaults = {childSelector: "li", trace: false};
- this.options = jQuery.extend({}, defaults, options);
-
- this.element = jQuery(element);
-
- if(this.options.current) this.change(this.options.current);
-
- var self = this;
- this.elements().click(function(){
- var view = self.viewName(this);
- self.change(view);
- });
-};
-
-BowlineMenu.fn = BowlineMenu.prototype;
-
-BowlineMenu.fn.log = function(){
- if( !this.options.trace ) return;
- var args = jQuery.makeArray(arguments);
- args.unshift("(BowlineMenu)");
- console.log.apply(console, args);
-};
-
-BowlineMenu.fn.onChange = function(func){
- this.element.bind("change.bowline", func);
-};
-
-BowlineMenu.fn.triggerChange = function(data){
- this.element.trigger("change.bowline", data);
-};
-
-BowlineMenu.fn.viewName = function(element){
- return jQuery(element).dataset("view");
-};
-
-BowlineMenu.fn.currentName = function(){
- return this.viewName(this.current);
-};
-
-BowlineMenu.fn.elements = function(){
- return this.element.find(this.options.childSelector);
-};
-
-BowlineMenu.fn.elementFor = function(name){
- return this.element.find(
- "[data-view='" + name + "']:first"
- );
-};
-
-BowlineMenu.fn.items = function(){
- var self = this;
- return jQuery.map(this.elements(), function(n){
- return self.viewName(n);
- });
-};
-
-BowlineMenu.fn.change = function(name){
- if(name != false && jQuery.inArray(name, this.items()) == -1) return false;
-
- var fromView = this.current;
- var fromViewName = this.viewName(fromView);
-
- var toView = this.elementFor(name);
- var toViewName = name;
-
- this.log("changing:", fromViewName, toViewName);
-
- this.elements().removeClass("current");
- if(toView) {
- this.current = toView;
- toView.addClass("current");
- }
-
- this.triggerChange({
- toView: toView,
- toViewName: toViewName,
- fromView: fromView,
- fromViewName: fromViewName
- });
-};
View
66 assets/bowline.state.js
@@ -1,66 +0,0 @@
-function BowlineState(opts){
- this.options = opts || {};
- this.states = {}
- this.events = {}
- this.current = this.options.initial;
-}
-
-BowlineState.fn = BowlineState.prototype;
-
-BowlineState.fn.log = function(){
- if( !this.options.trace ) return;
- var args = jQuery.makeArray(arguments);
- args.unshift("(BowlineState)");
- console.log.apply(console, args);
-};
-
-BowlineState.fn.newEvent = function(name, opts){
- if(!name) throw "Must supply name";
- // Defaults to the same named state
- if(!opts) opts = {};
- if(!opts.to) opts.to = name;
- this.events[name] = opts;
-}
-
-BowlineState.fn.newState = function(name, callbacks){
- if(!name) throw "Must supply name";
- this.states[name] = callbacks || {};
-}
-
-BowlineState.fn.change = function(){
- var args = $.makeArray(arguments);
- var name = args.shift();
-
- var event = this.events[name]
- if(!event) throw "Unknown event: " + name;
- // TODO support arrays in event.from
- if(event.from &&
- event.from != "all" &&
- this.current &&
- event.from != this.current) {
- this.log("Not changing state to:", event.to);
- return;
- }
-
- if(!this.states.hasOwnProperty(event.to)) {
- throw "Unknown state: " + event.to;
- }
-
- // Already at state
- if(event.to == this.current) return;
-
- var oldState = this.current;
- var oldStateCB = this.states[oldState];
- var newState = event.to;
- var newStateCB = this.states[newState];
-
- this.log("changing:", oldState, newState);
-
- if(oldStateCB && oldStateCB.beforeExit) oldStateCB.beforeExit();
- if(newStateCB.beforeEnter) newStateCB.beforeEnter.apply(this, args);
-
- this.current = newState;
-
- if(oldStateCB && oldStateCB.afterExit) oldStateCB.afterExit();
- if(newStateCB.afterEnter) newStateCB.afterEnter();
-}
View
86 assets/bowline.test.js
@@ -1,86 +0,0 @@
-// Emulates a Bowline backend
-
-BowlineTest = {};
-BowlineTest.trace = true;
-BowlineTest.setup = function(){
- window._app = {}
- window._app.call = function(json){
- var msg = JSON.parse(json);
-
- if(msg.klass == "_window") return;
-
- var klass = BowlineTest.klasses[msg.klass];
- if(klass)
- var method = klass[msg.method];
-
- if(!method && msg.method == "setup"){
- return;
- }
-
- if(!klass || !method) {
- BowlineTest.log("Missing method:", msg.klass + "#" + msg.method);
- return;
- }
-
- BowlineTest.log("Handling method:", msg.klass + "#" + msg.method);
-
- var replace = function(val){
- Bowline.replace(msg.klass, val);
- }
-
- var created = function(id, val){
- Bowline.created(msg.klass, id, val);
- }
-
- var updated = function(id, val){
- Bowline.updated(msg.klass, id, val);
- }
-
- var removed = function(id){
- Bowline.removed(msg.klass, id);
- }
-
- var context = {
- replace: replace,
- created: created,
- updated: updated,
- removed: removed
- };
-
- var result;
- try {
- result = method.apply(context, msg.args);
- } catch(e) {
- console.error("Error in method:", klass + "#" + method);
- throw(e);
- }
-
- if(msg.id != -1) {
- Bowline.invokeCallback(
- msg.id, JSON.stringify(result)
- )
- }
- }
- Bowline.enabled = true;
-};
-
-BowlineTest.log = function(){
- if( !BowlineTest.trace ) return;
- var args = jQuery.makeArray(arguments);
- args.unshift("(BowlineTest)");
- console.log.apply(console, args);
-};
-
-BowlineTest.klasses = {};
-BowlineTest.register = function(className, object) {
- BowlineTest.klasses[className] = object;
- var bound = Bowline.bounds[className];
- if(bound) bound.singleton = object.singleton;
-}
-
-BowlineTest.enabled = !Bowline.enabled;
-
-if(BowlineTest.enabled){
- BowlineTest.log("Enabled");
- BowlineTest.setup();
-}
View
108 assets/bowline.view.js
@@ -1,108 +0,0 @@
-// #view > *:not(.current) {
-// display: none;
-// }
-
-jQuery.support.WebKitAnimationEvent = (typeof WebKitTransitionEvent == "object");
-
-var BowlineView = function(element, options){
- var defaults = {trace:false};
- this.options = jQuery.extend({}, defaults, options);
-
- if (this.options.preloadImages) {
- jQuery.each(this.options.preloadImages, function(e){
- (new Image()).src = e;
- });
- }
-
- this.element = jQuery(element);
-
- if(this.options.current){
- this.current = jQuery(this.options.current);
- this.current.addClass("current");
- }
-};
-
-BowlineView.fn = BowlineView.prototype;
-
-BowlineView.fn.log = function(){
- if( !this.options.trace ) return;
- var args = jQuery.makeArray(arguments);
- args.unshift("(BowlineView)");
- console.log.apply(console, args);
-};
-
-BowlineView.fn.onChange = function(func){
- this.element.bind("change.bowline", func);
-};
-
-BowlineView.fn.triggerChange = function(data){
- this.element.trigger("change.bowline", data);
-};
-
-BowlineView.fn.elements = function(){
- return this.element.find(">*");
-}
-
-BowlineView.fn.findView = function(name){
- return this.element.find("[data-view='" + name + "']:first");
-};
-
-BowlineView.fn.viewName = function(element){
- return jQuery(element).dataset("view");
-};
-
-BowlineView.fn.change = function(name){
- var fromView = this.current;
- var fromViewName = this.viewName(fromView);
- var toView = this.findView(name);
- var toViewName = name;
-
- this.log("changing:", fromViewName, toViewName);
-
- if(toView.length == 0) throw 'Unknown view: ' + toViewName;
-
- if(fromViewName == toViewName) return;
-
- var animation = null;
- if(this.options.animationCallback){
- animation = this.options.animationCallback(
- fromViewName, toViewName
- );
- } else {
- // Could be blank - doesn't matter.
- animation = this.current.dataset("animation");
- }
-
- if(!fromView) {
- animation = null;
- }
-
- var self = this;
- var callback = function(){
- if (animation){
- toView.removeClass("in " + animation);
- if(fromView) {
- fromView.removeClass("current out " + animation);
- }
- } else {
- if(fromView) fromView.removeClass("current");
- }
- self.current = toView;
- self.triggerChange({
- fromView: fromView,
- fromViewName: fromViewName,
- toView: toView,
- toViewName: toViewName
- });
- }
-
- if(jQuery.support.WebKitAnimationEvent && animation){
- toView.one("webkitAnimationEnd", callback);
- this.log("using animation:", animation, toViewName);
- toView.addClass(animation + " in current");
- if(fromView) fromView.addClass(animation + " out");
- } else {
- toView.addClass("current");
- callback();
- }
-};
View
167 assets/jquery.dataset.js
@@ -1,167 +0,0 @@
-/// jquery.dataset v0.1.0 -- HTML5 dataset jQuery plugin
-/// http://orangesoda.net/jquery.dataset.html
-
-/// Copyright (c) 2009, Ben Weaver. All rights reserved.
-/// This software is issued "as is" under a BSD license
-/// <http://orangesoda.net/license.html>. All warrenties disclaimed.
-
-/// The HTML5 specification allows elements to have custom data
-/// attributes that are prefixed with `data-'. They may be
-/// conveniently accessed through an element's `dataset' property.
-/// This plugin provides similar functionality.
-///
-/// The methods in the plugin are designed to be similar to the
-/// built-in `attr' and `data' methods. All names are without the
-/// `data-' prefix.
-//
-/// These methods are defined:
-///
-/// dataset()
-/// Return an object with all custom attribute (name, value) items.
-///
-/// dataset(name)
-/// Return the value of the attribute `data-NAME'.
-///
-/// dataset(name, value)
-/// Set the value of attribtue `data-NAME' to VALUE.
-///
-/// dataset({...})
-/// Set many custom attributes at once.
-///
-/// removeDataset(name)
-/// Remove the attribute `data-NAME'.
-///
-/// removeDataset([n1, n2, ...])
-/// Remove the attributes `data-N1', `data-N2', ...
-
-(function($) {
- var PREFIX = 'data-',
- PATTERN = /^data\-(.*)$/;
-
- function dataset(name, value) {
- if (value !== undefined) {
- // dataset(name, value): set the NAME attribute to VALUE.
- return this.attr(PREFIX + name, value);
- }
-
- switch (typeof name) {
- case 'string':
- // dataset(name): get the value of the NAME attribute.
- return this.attr(PREFIX + name);
-
- case 'object':
- // dataset(items): set the values of all (name, value) items.
- return set_items.call(this, name);
-
- case 'undefined':
- // dataset(): return a mapping of (name, value) items for the
- // first element.
- return get_items.call(this);
-
- default:
- throw 'dataset: invalid argument ' + name;
- }
- }
-
- function get_items() {
- return this.foldAttr(function(index, attr, result) {
- var match = PATTERN.exec(this.name);
- if (match) result[match[1]] = this.value;
- });
- }
-
- function set_items(items) {
- for (var key in items) {
- this.attr(PREFIX + key, items[key]);
- }
- return this;
- }
-
- function remove(name) {
- if (typeof name == 'string') {
- // Remove a single attribute;
- return this.removeAttr(PREFIX + name);
- }
- return remove_names(name);
- }
-
- function remove_names(obj) {
- var idx, length = obj && obj.length;
-
- // For any object, remove attributes named by the keys.
- if (length === undefined) {
- for (idx in obj) {
- this.removeAttr(PREFIX + idx);
- }
- }
- // For an array, remove attributes named by the values.
- else {
- for (idx = 0; idx < length; idx++) {
- this.removeAttr(PREFIX + obj[idx]);
- }
- }
-
- return this;
- }
-
- $.fn.dataset = dataset;
- $.fn.removeDataset = remove_names;
-
-})(jQuery);
-
-(function($) {
-
- function each_attr(proc) {
- if (this.length > 0) {
- $.each(this[0].attributes, proc);
- }
- return this;
- }
-
- function fold_attr(proc, acc) {
- return fold((this.length > 0) && this[0].attributes, proc, acc);
- }
-
- /*
- * A left-fold operator. The behavior is the same as $.each(),
- * but the callback is called with the accumulator as the third
- * argument. The default accumulator is an empty object.
- */
- function fold(object, proc, acc) {
- var length = object && object.length;
-
- // The default accumulator is an empty object.
- if (acc === undefined) acc = {};
-
- // Returning an empty accumulator when OBJECT is "false"
- // makes FOLD more composable.
- if (!object) return acc;
-
- // Check to see if OBJECT is an array.
- if (length !== undefined) {
- for (var i = 0, value = object[i];
- (i < length) && (proc.call(value, i, value, acc) !== false);
- value = object[++i])
- { }
- }
- // Object is a map of (name, value) items.
- else {
- for (var name in object) {
- if (proc.call(object[name], name, object[name], acc) === false) break;
- }
- }
-
- return acc;
- }
-
- function fold_jquery(proc, acc) {
- if (acc === undefined) acc = [];
- return fold(this, proc, acc);
- }
-
- $.fn.eachAttr = each_attr;
- $.fn.foldAttr = fold_attr;
- $.fn.fold = fold_jquery;
- $.fold = fold;
-
-})(jQuery);
View
93 assets/superclass.js
@@ -0,0 +1,93 @@
+var SuperClass = function(parent){
+ var result = function(){
+ this.init.apply(this, arguments);
+ };
+
+ result.prototype.init = function(){};
+
+ if (parent){
+ for(var i in parent){
+ result[i] = SuperClass.clone(parent[i]);
+ }
+
+ for(var i in parent.prototype){
+ result.prototype[i] = SuperClass.clone(parent.prototype[i]);
+ }
+
+ result.parent = parent;
+ result.prototype.parent = parent.prototype;
+
+ result._super = function(){
+ var parent = this.parent;
+
+ var key = this.findProperty(arguments.callee.caller);
+ var method = parent[key];
+
+ if (!method) return;
+
+ var oldParent = parent;
+ var oldFindProperty = this.findProperty;
+
+ // In case parent method calls super
+ this.findProperty = $.proxy(this.findProperty, parent);
+ this.parent = parent.parent;
+ var value = method.apply(this, arguments);
+
+ // Reset functions refs
+ this.findProperty = oldFindProperty;
+ this.parent = oldParent;
+
+ return value;
+ };
+ result.prototype._super = result._super;
+ }
+
+ result.fn = result.prototype;
+ result.fn._class = result;
+
+ result.findProperty = function(val){
+ for(var key in this)
+ if(this[key] == val) return key;
+ };
+ result.fn.findProperty = result.findProperty;
+
+ result.extend = function(obj){
+ var extended = obj.extended;
+ delete obj.extended;
+ for(var i in obj){
+ result[i] = obj[i];
+ }
+
+ if (extended) extended(result)
+ };
+
+ result.include = function(obj){
+ var included = obj.included;
+ delete obj.included;
+ for(var i in obj){
+ result.fn[i] = obj[i];
+ }
+
+ if (included) included(result)
+ };
+
+ result.aliasMethod = function(newName, oldName){
+ this[newName] = this[oldName];
+ };
+ result.fn.aliasMethod = result.aliasMethod;
+
+ result.aliasMethodChain = function(method, name){
+ this.aliasMethod(method + "Without" + name, method);
+ this.aliasMethod(method, method + "With" + name);
+ };
+ result.fn.aliasMethodChain = result.aliasMethodChain;
+
+ return result;
+};
+
+SuperClass.clone = function(obj){
+ if (typeof obj == "function") return obj;
+ if (typeof obj != "object") return obj;
+ if (jQuery.isArray(obj)) return jQuery.extend([], obj);
+ return jQuery.extend({}, obj);
+};
View
10 bowline.gemspec
@@ -5,11 +5,11 @@
Gem::Specification.new do |s|
s.name = %q{bowline}
- s.version = "0.6.3"
+ s.version = "0.9.0"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Alex MacCaw"]
- s.date = %q{2010-04-26}
+ s.date = %q{2010-05-11}
s.default_executable = %q{bowline-gen}
s.description = %q{Ruby/JS GUI framework}
s.email = %q{alex@leadthinking.com}
@@ -150,20 +150,20 @@ Gem::Specification.new do |s|
s.add_runtime_dependency(%q<activesupport>, [">= 3.0.0.beta"])
s.add_runtime_dependency(%q<rubyzip2>, [">= 2.0.1"])
s.add_runtime_dependency(%q<bundler08>, [">= 0.8.5"])
- s.add_runtime_dependency(%q<supermodel>, [">= 0"])
+ s.add_runtime_dependency(%q<supermodel>, [">= 0.1.3"])
else
s.add_dependency(%q<templater>, [">= 0.3.2"])
s.add_dependency(%q<activesupport>, [">= 3.0.0.beta"])
s.add_dependency(%q<rubyzip2>, [">= 2.0.1"])
s.add_dependency(%q<bundler08>, [">= 0.8.5"])
- s.add_dependency(%q<supermodel>, [">= 0"])
+ s.add_dependency(%q<supermodel>, [">= 0.1.3"])
end
else
s.add_dependency(%q<templater>, [">= 0.3.2"])
s.add_dependency(%q<activesupport>, [">= 3.0.0.beta"])
s.add_dependency(%q<rubyzip2>, [">= 2.0.1"])
s.add_dependency(%q<bundler08>, [">= 0.8.5"])
- s.add_dependency(%q<supermodel>, [">= 0"])
+ s.add_dependency(%q<supermodel>, [">= 0.1.3"])
end
end
View
2 examples/example.js
@@ -1,4 +1,4 @@
-$('#users').bowlineBind('UsersBinder');
+$('#users').bowlineChain('UsersBinder');
// invoke collection method
// This will invoke UserBinder.admins and fill #users with admins
View
2 examples/twitter.html
@@ -10,7 +10,7 @@
<script src="javascripts/application.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
jQuery(function($){
- var tweets = $('#tweets').bowlineBind('TweetsBinder');
+ var tweets = $('#tweets').bowlineChain('TweetsBinder');
$('#updateSubmit').click(function(){
tweets.invoke('update', $('#updateText').val());
View
7 lib/bowline/generators/model.rb
@@ -5,19 +5,14 @@ class ModelGenerator < NamedGenerator
DESC
def class_name
- if local
- super + " < SuperModel::Base"
- else
- super + " < ActiveRecord::Base"
- end
+ super + " < SuperModel::Base"
end
def modules
[]
end
first_argument :name, :required => true, :desc => "model name"
- second_argument :local, :required => false
template :model do |template|
template.source = "model.rb"
View
4 lib/bowline/version.rb
@@ -1,8 +1,8 @@
module Bowline
module Version #:nodoc:
MAJOR = 0
- MINOR = 6
- TINY = 3
+ MINOR = 9
+ TINY = 0
STRING = [MAJOR, MINOR, TINY].join('.')
View
3 templates/config/boot.rb
@@ -1,13 +1,14 @@
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), "..")) unless defined?(APP_ROOT)
+require "rubygems"
+
# Use Bundler (preferred)
environment = File.expand_path("../../vendor/gems/environment", __FILE__)
if File.exist?("#{environment}.rb")
require environment
# Use RubyGems
else
- require "rubygems"
require "bundler"
Bundler.setup
end
View
4 templates/model.rb
@@ -1,4 +1,2 @@
-<%- with_modules(modules) do -%>
class <%= class_name %>
-end
-<%- end -%>
+end
View
4 templates/public/index.html
@@ -6,12 +6,14 @@
<link rel="stylesheet" href="stylesheets/application.css" type="text/css" charset="utf-8">
<script src="javascripts/jquery.js" type="text/javascript" charset="utf-8"></script>
<script src="javascripts/jquery.chain.js" type="text/javascript" charset="utf-8"></script>
+ <script src="javascripts/superclass.js" type="text/javascript" charset="utf-8"></script>
<script src="javascripts/bowline.js" type="text/javascript" charset="utf-8"></script>
+ <script src="javascripts/bowline.chain.js" type="text/javascript" charset="utf-8"></script>
<script src="javascripts/application.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
// Binder Example:
// jQuery(function($){
- // $('#tweets').bowlineBind('TweetsBinder');
+ // $('#tweets').bowlineChain('TweetsBinder');
// });
</script>
</head>

0 comments on commit db6664b

Please sign in to comment.