Browse files

fleshing it out a bit more

  • Loading branch information...
1 parent ca0c577 commit af236a32eecf1f3b577848bea68d98858a9e2ae3 @Kevnz committed Jun 21, 2011
View
26 _site/app/models/ToDo.js
@@ -0,0 +1,26 @@
+YUI.add('app-model-todo', function(Y){
+
+ var ToDo = function(config){
+ ToDo.superclass.constructor.apply(this, arguments);
+ }
+
+ ToDo.NAME = 'app-model-todo';
+ ToDo.ATTRS = {
+ description: {value:null},
+ due_date: {value:null, setter: function(value){
+
+ }}
+ }
+
+ ToDo = Y.extend(ToDo, Y.Model, {
+ initializer:function(){
+ Y.log('in the initializer', 'info', 'app-model-todo');
+ }
+ }
+ );
+
+ Y.namespace("App.Models").ToDo = ToDo;
+
+
+
+}, '0.0.1', {requires:['base', 'substitute', 'ymvc-model']});
View
0 _site/app/views/ToDo.js
No changes.
View
21 _site/scripts/config.js
@@ -12,6 +12,27 @@ var ymvc_Config = {
}
}
}
+ },
+ app : {
+ base : 'http://ymvc.dev/app/',
+ root : '/scripts/',
+ patterns: {
+ 'app-model-' : {
+ configFn : function( me ) {
+ me.path = 'models/'+ me.name.replace (/app-model-/g, "") + '.js'
+ }
+ },
+ 'app-controller-' : {
+ configFn : function( me ) {
+ me.path = 'controllers/'+ me.name.replace (/app-controller-/g, "") + '.js'
+ }
+ },
+ 'app-view-' : {
+ configFn : function( me ) {
+ me.path = 'views/'+ me.name.replace (/app-controller-/g, "") + '.js'
+ }
+ }
+ }
}
}
View
48 _site/scripts/model.js
@@ -2,26 +2,66 @@ YUI.add('ymvc-model', function(Y){
var Model = Y.Base.create('Model', Y.Base, [], {
initializer:function(){
- Y.log('in the initializer','info', 'ymvc-model');
+ Y.log('in the initializer of the base model','info', 'ymvc-model');
+
+ if(this.get('url')!==null && Y.Lang.isNumber(this.get('id'))){
+ Y.log('a url was passed in, request data and config it');
+ Y.log(Y.JSON.stringify(this.toJson()));
+ var cfg, request;
+ // Create a configuration object for the synchronous transaction.
+ cfg = {
+ sync: true,
+ data: this.toJson()
+ };
+ request = Y.io(this.get('url'), cfg);
+ var jsonResult = Y.JSON.parse(request.responseText);
+ this.setAttrs(jsonResult);
+
+ }
},
add: function(props){
for (var i = props.length - 1; i >= 0; i--){
this.addAttr( props[i], {value:null});
};
},
toJson: function(){
- return this.getAttrs();
+ var obj = {};
+ Y.each(this.getAttrs(), function(val, key, baseObj){
+ Y.log(key)
+ Y.log(key !== 'destroyed');
+ if(key === 'destroyed' || key === 'initialized' || key === 'url'){
+
+ }else{
+ Y.log('adding ' + key + ' to the json');
+ obj[key] = val;
+ }
+ });
+ return Y.JSON.stringify(obj);
},
+ save: function(){
+ if(this.get('url')!==null){
+ var cfg, request;
+ cfg = {
+ sync: true,
+ method: 'POST',
+ data: this.toJson()
+ }
+ request = Y.io(this.get('url'), cfg)
+ var jsonResult = Y.JSON.parse(request.responseText);
+ this.set('id', jsonResult.id);
+ }
+ }
},{
ATTRS :{
title:{value:null},
- id:{value:null}
+ id:{value:null},
+ url:{value:null}
}
}
);
Y.Model = Model;
-}, '0.0.1', {requires:['base', 'substitute']});
+}, '0.0.1', {requires:['base', 'substitute', 'io-base', 'json','querystring-stringify-simple']});
View
43 _site/tests/ToDoModel.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>ToDo Model Test</title>
+ <meta name="description" content="">
+ <meta name="author" content="">
+ <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;">
+ <link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/3.3.0/build/cssreset/reset-min.css">
+ <link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/3.3.0/build/cssbase/base-min.css">
+ <link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/3.3.0/build/cssfonts/fonts-min.css">
+ <script type="text/javascript" src="http://yui.yahooapis.com/3.3.0/build/yui/yui-min.js"></script>
+ <script type="text/javascript" src="/scripts/config.js"></script>
+ </head>
+ <!--[if lt IE 7 ]><body class="ie6 yui3-skin-sam"><![endif]-->
+ <!--[if IE 7 ]><body class="ie7 yui3-skin-sam yui-skin-sam"><![endif]-->
+ <!--[if IE 8 ]><body class="ie8 yui3-skin-sam yui-skin-sam"><![endif]-->
+ <!--[if IE 9 ]><body class="ie9 yui3-skin-sam yui-skin-sam"><![endif]-->
+ <!--[if (gt IE 9)|!(IE)]><!--> <body class="yui3-skin-sam yui-skin-sam"><!--<![endif]-->
+ <header> <h1>ToDo Model</h1></header>
+ <div id="content">
+
+ </div>
+ <footer> </footer>
+
+ <script>
+ YUI(ymvc_Config).use('node', 'ymvc-model', 'app-model-todo', function(Y){
+ var todo = new Y.App.Models.ToDo({title:'ToDo Test', id : 1, description: 'ToDo Model to test'});
+ Y.log(todo);
+ Y.log(todo.toJson());
+
+ var todoToo = new Y.App.Models.ToDo({url:'/data/todo/', id:2 });
+ Y.log(todoToo.get('title'));
+ var todo3 = new Y.App.Models.ToDo({url:'/data/todo/'});
+
+ todo3.set('title', 'from the page');
+ todo3.set('description', 'My Effort at posting back and saving');
+ todo3.save();
+ Y.log(todo3.toJson());
+ });
+ </script>
+ </body>
+</html>
View
6 _site/tests/api.html
@@ -27,8 +27,10 @@
var items = new Y.Collection({model:Y.Models.ToDo, url:'/data/todos'});
items.load();
- //ToDo Controller extends Controller
- var controller = new Y.ToDoController({data:todos, widget:Y.Widgets.ToDos});
+ //A Controller would fetch the data
+ //But would it? Why not have a generic controller that you pass the widget and data to
+ // The controller would then stick the two together.
+ var controller = new Y.Controller({data:items, widget: MyWidgetClass});
controller.index();
View
85 resources/extension.js
@@ -0,0 +1,85 @@
+YUI.add('myextension', function(Y) {
+
+ /* Any frequently used shortcuts, strings and constants */
+ var Lang = Y.Lang;
+
+ /*
+ * MyExtension initialization.
+ *
+ * Although this is a function constructor,
+ * since the extension gets mixed into another class, it's
+ * invoked during the host classes initialization phase.
+ */
+ function MyExtension(config) {
+
+ /*
+ * HOST METHOD OVERLAP - Use the AOP infrastructure
+ * to inject logic before/after methods on the main
+ * class.
+ *
+ * If the extension implements a method which
+ * exists on the main class, it will be replaced with
+ * the extensions version.
+ */
+
+ Y.Do.after(this._doSomethingAfterMainClassMethod, this, "doSomething");
+ Y.Do.before(this._doSomethingBeforeMainClassMethod, this, "doSomething");
+ }
+
+ /*
+ * The attributes this extension provides
+ */
+ MyExtension.ATTRS = {
+
+ attrA: {
+ value: "A" // The default value for attrA, used if the user does not set a value during construction.
+ /*
+ , valueFn: "_defAttrAVal" // Can be used as a substitute for "value", when you need access to "this" to set the default value.
+
+ , setter: "_setAttrA" // Used to normalize attrA's value while during set. Refers to a prototype method, to make customization easier
+ , getter: "_getAttrA" // Used to normalize attrA's value while during get. Refers to a prototype method, to make customization easier
+ , validator: "_validateAttrA" // Used to validate attrA's value before updating it. Refers to a prototype method, to make customization easier
+
+ , readOnly: true // Cannot be set by the end user. Can be set by the component developer at any time, using _set
+ , writeOnce: true // Can only be set once by the end user (usually during construction). Can be set by the component developer at any time, using _set
+
+ , lazyAdd: false // Add (configure) the attribute during initialization.
+
+ // You only need to set lazyAdd to false if your attribute is
+ // setting some other state in your setter which needs to be set during initialization
+ // (not generally recommended - the setter should be used for normalization.
+ // You should use listeners to update alternate state).
+
+ , broadcast: 1 // Whether the attribute change event should be broadcast or not.
+ */
+ }
+
+ // ... attrB, attrC, attrD ... attribute configurations.
+ };
+
+ MyExtension.prototype = {
+ myExtensionPublicMethod: function() {
+ // A new public method that the extension adds to the built class.
+ // When naming, you need to be aware of over-writing methods on the main class, since these
+ // methods get augmented onto the built class
+ },
+
+ _myExtensionProtectedMethod: function() {
+ // A new protected/private method the extension provides
+ // When naming, you need to be aware of over-writing methods on the main class, since these
+ // methods get augmented onto the built class
+ }
+
+ _doSomethingAfterMainClassMethod: function() {
+ // Custom behavior
+ },
+
+ _doSomethingBeforeMainClassMethod: function() {
+ // Custom behavior
+ }
+ };
+
+ Y.namespace("MyApp").MyExtension = MyExtension;
+
+},
+"3.1.0");
View
122 resources/plugin.js
@@ -0,0 +1,122 @@
+YUI.add("myplugin", function(Y) {
+
+ /* Any frequently used shortcuts, strings and constants */
+ var Lang = Y.Lang;
+
+ /* MyPlugin class constructor */
+ function MyPlugin(config) {
+ MyPlugin.superclass.constructor.apply(this, arguments);
+ }
+
+ /*
+ * Required NAME static field, to identify the class and
+ * used as an event prefix, to generate class names etc. (set to the
+ * class name in camel case).
+ */
+ MyPlugin.NAME = "myPlugin";
+
+ /*
+ * Required NS static field, to identify the property on the host which will,
+ * be used to refer to the plugin instance ( e.g. host.feature.doSomething() )
+ */
+ MyPlugin.NS = "feature";
+
+ /*
+ * The attribute configuration for the plugin. This defines the core user facing state of the plugin
+ */
+ MyPlugin.ATTRS = {
+
+ attrA: {
+ value: "A" // The default value for attrA, used if the user does not set a value during construction.
+ /*
+ , valueFn: "_defAttrAVal" // Can be used as a substitute for "value", when you need access to "this" to set the default value.
+
+ , setter: "_setAttrA" // Used to normalize attrA's value while during set. Refers to a prototype method, to make customization easier
+ , getter: "_getAttrA" // Used to normalize attrA's value while during get. Refers to a prototype method, to make customization easier
+ , validator: "_validateAttrA" // Used to validate attrA's value before updating it. Refers to a prototype method, to make customization easier
+
+ , readOnly: true // Cannot be set by the end user. Can be set by the component developer at any time, using _set
+ , writeOnce: true // Can only be set once by the end user (usually during construction). Can be set by the component developer at any time, using _set
+
+ , lazyAdd: false // Add (configure) the attribute during initialization.
+
+ // You only need to set lazyAdd to false if your attribute is
+ // setting some other state in your setter which needs to be set during initialization
+ // (not generally recommended - the setter should be used for normalization.
+ // You should use listeners to update alternate state).
+
+ , broadcast: 1 // Whether the attribute change event should be broadcast or not.
+ */
+ }
+
+ // ... attrB, attrC, attrD ... attribute configurations.
+ // Can also include attributes for the super class if you want to override or add configuration parameters
+ };
+
+ /* MyPlugin extends the base Plugin.Base class */
+ Y.extend(MyPlugin, Y.Plugin.Base, {
+
+ initializer: function() {
+ /*
+ * initializer is part of the lifecycle introduced by
+ * the Base class. It is invoked during construction, when
+ * the plugin is plugged into the host, and can be used to
+ * register listeners, or inject logic before or after methods
+ * on the host.
+ *
+ * It does not need to invoke the superclass initializer.
+ * init() will call initializer() for all classes in the hierarchy.
+ */
+
+ // See Y.Do.before, Y.Do.after
+ this.beforeHostMethod("show", this._beforeHostShowMethod);
+ this.afterHostMethod("show", this._afterHostShowMethod);
+
+ // See Y.EventTarget.on, Y.EventTarget.after
+ this.onHostEvent("render", this._onHostRenderEvent);
+ this.afterHostEvent("render", this._afterHostRenderEvent);
+
+ },
+
+ destructor: function() {
+ /*
+ * destructor is part of the lifecycle introduced by
+ * the Base class. It is invoked when the plugin is unplugged.
+ *
+ * Any listeners registered using Plugin.Base's onHostEvent/afterHostEvent methods,
+ * or any methods displaced using it's beforeHostMethod/afterHostMethod methods
+ * will be detached/restored by Plugin.Base's destructor.
+ *
+ * We only need to clean up anything we change on the host
+ *
+ * It does not need to invoke the superclass destructor.
+ * destroy() will call initializer() for all classes in the hierarchy.
+ */
+ },
+
+ /* Supporting Methods */
+
+ _onHostRenderEvent: function(e) {
+ /* React on the host render event */
+ },
+
+ _afterHostRenderEvent: function(e) {
+ /* React after the host render event */
+ },
+
+ _beforeHostShowMethod: function() {
+ /* Inject logic before the host's show method is called. */
+ },
+
+ _afterHostShowMethod: function() {
+ /* Inject logic after the host's show method is called. */
+ }
+
+ });
+
+ Y.namespace("Plugin.MyApp").MyPlugin = MyPlugin;
+
+},
+"3.1.0", {
+ requires: ["plugin"]
+});
View
185 resources/widget.js
@@ -0,0 +1,185 @@
+YUI.add("mywidget", function(Y) {
+
+ /* Any frequently used shortcuts, strings and constants */
+ var Lang = Y.Lang;
+
+ /* MyWidget class constructor */
+ function MyWidget(config) {
+ MyWidget.superclass.constructor.apply(this, arguments);
+ }
+
+ /*
+ * Required NAME static field, to identify the Widget class and
+ * used as an event prefix, to generate class names etc. (set to the
+ * class name in camel case).
+ */
+ MyWidget.NAME = "myWidget";
+
+ /*
+ * The attribute configuration for the widget. This defines the core user facing state of the widget
+ */
+ MyWidget.ATTRS = {
+
+ attrA: {
+ value: "A"
+ // The default value for attrA, used if the user does not set a value during construction.
+ /*
+ , valueFn: "_defAttrAVal" // Can be used as a substitute for "value", when you need access to "this" to set the default value.
+
+ , setter: "_setAttrA" // Used to normalize attrA's value while during set. Refers to a prototype method, to make customization easier
+ , getter: "_getAttrA" // Used to normalize attrA's value while during get. Refers to a prototype method, to make customization easier
+ , validator: "_validateAttrA" // Used to validate attrA's value before updating it. Refers to a prototype method, to make customization easier
+
+ , readOnly: true // Cannot be set by the end user. Can be set by the component developer at any time, using _set
+ , writeOnce: true // Can only be set once by the end user (usually during construction). Can be set by the component developer at any time, using _set
+
+ , lazyAdd: false // Add (configure) the attribute during initialization.
+
+ // You only need to set lazyAdd to false if your attribute is
+ // setting some other state in your setter which needs to be set during initialization
+ // (not generally recommended - the setter should be used for normalization.
+ // You should use listeners to update alternate state).
+
+ , broadcast: 1 // Whether the attribute change event should be broadcast or not.
+ */
+ }
+
+ // ... attrB, attrC, attrD ... attribute configurations.
+ // Can also include attributes for the super class if you want to override or add configuration parameters
+ };
+
+ /*
+ * The HTML_PARSER static constant is used if the Widget supports progressive enhancement, and is
+ * used to populate the configuration for the MyWidget instance from markup already on the page.
+ */
+ MyWidget.HTML_PARSER = {
+
+ attrA: function(srcNode) {
+ // If progressive enhancement is to be supported, return the value of "attrA" based on the contents of the srcNode
+ }
+
+ };
+
+ /* Templates for any markup the widget uses. Usually includes {} tokens, which are replaced through Y.substitute */
+ MyWidget.MYNODE_TEMPLATE = "<div id={mynodeid}></div>";
+
+ /* MyWidget extends the base Widget class */
+ Y.extend(MyWidget, Y.Widget, {
+
+ initializer: function() {
+ /*
+ * initializer is part of the lifecycle introduced by
+ * the Base class. It is invoked during construction,
+ * and can be used to setup instance specific state or publish events which
+ * require special configuration (if they don't need custom configuration,
+ * events are published lazily only if there are subscribers).
+ *
+ * It does not need to invoke the superclass initializer.
+ * init() will call initializer() for all classes in the hierarchy.
+ */
+
+ this.publish("myEvent", {
+ defaultFn: this._defMyEventFn,
+ bubbles: false
+ });
+ },
+
+ destructor: function() {
+ /*
+ * destructor is part of the lifecycle introduced by
+ * the Widget class. It is invoked during destruction,
+ * and can be used to cleanup instance specific state.
+ *
+ * Anything under the boundingBox will be cleaned up by the Widget base class
+ * We only need to clean up nodes/events attached outside of the bounding Box
+ *
+ * It does not need to invoke the superclass destructor.
+ * destroy() will call initializer() for all classes in the hierarchy.
+ */
+ },
+
+ renderUI: function() {
+ /*
+ * renderUI is part of the lifecycle introduced by the
+ * Widget class. Widget's renderer method invokes:
+ *
+ * renderUI()
+ * bindUI()
+ * syncUI()
+ *
+ * renderUI is intended to be used by the Widget subclass
+ * to create or insert new elements into the DOM.
+ */
+
+ // this._mynode = Node.create(Y.substitute(MyWidget.MYNODE_TEMPLATE, {mynodeid: this.get("id") + "_mynode"}));
+ },
+
+ bindUI: function() {
+ /*
+ * bindUI is intended to be used by the Widget subclass
+ * to bind any event listeners which will drive the Widget UI.
+ *
+ * It will generally bind event listeners for attribute change
+ * events, to update the state of the rendered UI in response
+ * to attribute value changes, and also attach any DOM events,
+ * to activate the UI.
+ */
+
+ // this.after("attrAChange", this._afterAttrAChange);
+ },
+
+ syncUI: function() {
+ /*
+ * syncUI is intended to be used by the Widget subclass to
+ * update the UI to reflect the initial state of the widget,
+ * after renderUI. From there, the event listeners we bound above
+ * will take over.
+ */
+
+ // this._uiSetAttrA(this.get("attrA"));
+ },
+
+ // Beyond this point is the MyWidget specific application and rendering logic
+ /* Attribute state supporting methods (see attribute config above) */
+
+ _defAttrAVal: function() {
+ // this.get("id") + "foo";
+ },
+
+ _setAttrA: function(attrVal, attrName) {
+ // return attrVal.toUpperCase();
+ },
+
+ _getAttrA: function(attrVal, attrName) {
+ // return attrVal.toUpperCase();
+ },
+
+ _validateAttrA: function(attrVal, attrName) {
+ // return Lang.isString(attrVal);
+ },
+
+ /* Listeners, UI update methods */
+
+ _afterAttrAChange: function(e) {
+ /* Listens for changes in state, and asks for a UI update (controller). */
+
+ // this._uiSetAttrA(e.newVal);
+ },
+
+ _uiSetAttrA: function(val) {
+ /* Update the state of attrA in the UI (view) */
+
+ // this._mynode.set("innerHTML", val);
+ },
+
+ _defMyEventFn: function(e) {
+ // The default behavior for the "myEvent" event.
+ }
+ });
+
+ Y.namespace("MyApp").MyWidget = MyWidget;
+
+},
+"0.1.0", {
+ requires: ["widget", "substitute"]
+});
View
42 static.rb
@@ -7,33 +7,55 @@
class ToDo < SuperModel::Base
include SuperModel::RandomID
- attributes :title, :description
- validates_presence_of :name
+ attributes :title, :description, :due_date
+ validates_presence_of :title
end
set :public, Proc.new { File.join(root, "_site") }
+@@todos = [{ :id => 1, :title => 'Make this work', :description=>'Get this to work the way I want it to' },
+ { :id => 2,:title => 'Get Models To work', :description => 'This would be a description' },
+ { :id => 3,:title => 'Get Controllers to work', :description => 'This would be a description' },
+ { :id => 4,:title => 'Get Views to work', :description => 'This would be a description' },
+ { :id => 5,:title => 'Get Models To work', :description => 'This would be a description' },
+ { :id => 6,:title => 'Get Controllers to work', :description => 'This would be a description' },
+ { :id => 7,:title => 'Get Views to work', :description => 'This would be a description' }
+ ]
+
+@@todos.each_index{|index|
+ td = ToDo.new do |todo|
+ todo.title = todos[index][:title]
+ todo.description = todos[index][:description]
+ end
+ td.save
+}
-
get '/' do
File.read('_site/index.html')
end
get '/data/todos' do
+
+
content_type :json
- [{ :title => 'My ToDo', :description=>'This would be a description' }, {:title => 'Another ToDo', :description => 'This would be a description' }].to_json
+ @@todos.to_json
+ #[{ :title => 'My ToDo', :description=>'This would be a description' }, {:title => 'Another ToDo', :description => 'This would be a description' }].to_json
end
-get '/data/models' do
+get '/data/todo/?' do
content_type :json
- [{ :title => 'Item 1', :id => '1' },
- {:title => 'Item 2', :id => '2' },
- {:title=>'Item 3', :id=>'3'},
- {:title=>'Item 4', :id=>'4'}].to_json
+ @@todos.find_all{|item| item[:id] == params[:id].to_i }[0].to_json
+end
+
+post '/data/todo/?' do
+ newid = @@todos[@@todos.length-1][:id]+1
+ td = {:title=> params[:title], :description => params[:description], :id=> @@todos[@@todos.length-1][:id]+1}
+ @@todos.push td
+ content_type :json
+ td.to_json
end
-
helpers do
def request_info
"#{ request.request_method.upcase } #{ request.path_info } #{ params.inspect }"
View
0 tmp/always_restart.txt
No changes.
View
0 tmp/restart.txt
No changes.

0 comments on commit af236a3

Please sign in to comment.