Skip to content
Browse files

more refactoring, recursive ajax and automated cloning

  • Loading branch information...
1 parent 506564d commit 04915f3957788eba365efa9ce42e27d4e0656b47 cloudhead committed Apr 30, 2009
View
25 htdocs/js/lib.js
@@ -0,0 +1,25 @@
+Array.prototype.map = function( fn )
+{
+ var a = [];
+ for( var i = 0; i < this.length; i++ ) {
+ if( i in this ) a.push( fn( this[ i ] ) );
+ }
+ return a;
+};
+Array.prototype.compact = function()
+{
+ var a = [];
+ for( var i = 0; i < this.length; i++ ) {
+ if( i in this )
+ if( this[ i ] != "" ) a.push( this[ i ] );
+ }
+ return a;
+};
+String.prototype.map = function( fn )
+{
+ return fn( this );
+};
+
+$.postJSON = function( url, data, callback ) {
+ $.post(url, data, callback, "json");
+};
View
162 htdocs/js/melon.js
@@ -1,63 +1,101 @@
+var Melon = {
+ get: function( url, callback )
+ {
+ var buffer = [], i = 0;
+
+ if( arguments.length == 4 ) {
+ i = arguments[ 2 ]; buffer = arguments[ 3 ];
+ }
+
+ if( i in url ) $.getJSON( url[ i ], function( json ) {
+ buffer[ i ] = json;
+ Melon.get( url, callback, ++i, buffer );
+ });
+ else callback( buffer );
+ }
+};
+
$( document ).ready( function() {
- $.path = {
+ var Path = {
s: window.location.pathname.toString(),
- id: window.location.pathname.replace(/\//g,'-').replace(/^-/, '')
+ id: window.location.pathname.replace(/\//g, '-').replace(/^-/, '')
};
-
+
/* Specify routes */
- Router.map({ from: "/#/#/#/$", to: "$1-$2-$3-$4.json" },
+ Router.map({ from: "/#/#/#/$", to: ["/posts/$1-$2-$3-$4",
+ "/comments/$1-$2-$3-$4"], page: "single" },
{ from: "/#/#/#", to: "/posts/archive/$1-$2-$3" },
- { from: "/", to: "/posts/frontpage", id: "home"},
+ { from: "/", to: "/posts/frontpage", page: "home"},
{ from: "/auth", to: "/login" },
{ from: "/*", to: "/posts/frontpage" });
-
- /* Landing page */
- if( $.path.s == "/") {
- $("#comments").hide();
- $.getJSON("/posts/frontpage.json", function( posts ) {
- for( var i = 0; i < posts.length; i++ ) {
- /* 2009-24-12-the-article => 2009/24/12/the-article */
- var date = posts[ i ].id.slice( 0, 11 ).replace( /-/g, '/');
- var title = posts[ i ].id.slice( 11 );
- $("#posts ul > li:first").clone().appendTo("#posts ul");
- post( posts[ i ] ).find("h1").wrapInner("<a href='/" +
- date + title + "'></a>");
- }
- $("#posts ul > li:first").remove();
- });
- }
- else {
- /* Posts */
- $.getJSON("/posts/" + $.path.id + ".json", function( json ) {
- post( json );
- });
- /* Comments */
- $.getJSON("/comments/" + $.path.id + ".json", function( comments ) {
- for( var i = 0; i < comments.length; i++ ) {
- $("#comments ul > li:first").clone().appentTo("#comments ul").addClass("comment");
- comment = $("#comments ul > li:last");
-
- for( var key in comments[ i ] ) {
- comment.find('.' + key ).html( comments[ i ][ key ] );
- }
- }
- });
- $("#comments").show();
- }
+ var route = Router.match( Path.s );
+
+ Melon.get( route.path, function( json ) {
+ if( route.page ) $("body").attr("id", route.page ); // Set the body id
+ if( json.length == 1 ) json = json[ 0 ];
+ Pages[ route.page ]( json );
+ });
+
+ // for( var i = 0; i < route.path.length; i++ ) {
+ // $.getJSON( route.path[i], function(json) {
+ // Pages[ route.]
+ // });
+ // }
});
+function clone( name, input )
+{
+ var element = $("#" + name + " ul > li:first").clone().appendTo("#" + name + " ul");
+ element.attr("id", input.id);
+
+ for( var key in input ) {
+ element.find('.' + key ).html( input[ key ] );
+ }
+ return element;
+}
+var Pages = {
+ home: function( input )
+ {
+ for( var i = 0; i < input.length; i++ ) {
+ /* 2009-24-12-the-article => 2009/24/12/the-article */
+ var date = input[ i ].id.slice( 0, 11 ).replace( /-/g, '/');
+ var title = input[ i ].id.slice( 11 );
+
+ clone("posts", input );
+ post( input[ i ] ).find("h1").wrapInner("<a href='/" + date + title + "'></a>");
+ }
+ $("#posts ul > li:first").remove();
+ },
+ single: function( input )
+ {
+ var posts = input[ 0 ];
+ var comments = input[ 1 ];
+
+ /* Posts */
+ clone( "posts", posts );
+ /* Comments */
+ for( var i = 0; i < comments.length; i++ ) {
+ var comment = clone("comments", comments);
+ }
+ $("#comments ul > li:first").remove(); // automate this
+ $("#posts ul > li:first").remove(); //
+ }
+};
var Router = {
- map: function() {
+ map: function()
+ {
for( var i = 0; i < arguments.length; i++ ) {
Router.routes.push( arguments[ i ] ); // Add route to array
}
},
- match: function( path ) {
+ match: function( path )
+ {
/* Loop through routes */
for( var i = 0; i < Router.routes.length; i++ ) {
/* Construct regex from route */
- var id = Router.routes[ i ].id;
+ var page = Router.routes[ i ].page;
+ var to = Router.routes[ i ].to;
var route = new RegExp( "^\\/?" +
Router.routes[ i ].from.toString().
replace(/#/g, "([0-9]+)").
@@ -67,12 +105,19 @@ var Router = {
"\\/?$");
if( path.match( route ) ) {
- if( id ) $("body").attr("id", id ); // Set the body id
- return path.replace( route, Router.routes[ i ].to );
+ if( $.isArray( to ) ) {
+ to = to.map( function( s ) {
+ return path.replace( route, s ) + ".json";
+ });
+ }
+ else {
+ to = [ path.replace( route, to ) + ".json"];
+ }
+ return { path: to, page: page };
}
}
return false; // If nothing matched, we return false
- },
+ }
routes: []
};
@@ -90,30 +135,3 @@ function post( data )
return post;
}
-$.postJSON = function(url, data, callback) {
- $.post(url, data, callback, "json");
-};
-
-Array.prototype.map = function ( fn )
-{
- var a = [];
- for( var i = 0; i < this.length; i++ ) {
- a[ i ] = fn( this[ i ] );
- }
- return a;
-};
-Array.prototype.compact = function()
-{
- var len = this.length >>> 0;
- var res = new Array();
-
- for( var i = 0; i < len; i++ ) {
- if( i in this ) {
- if( this[ i ] != "") res.push( this[ i ] );
- }
- }
- return res;
-};
-
-
-
View
105 lib/melon.rb
@@ -20,8 +20,10 @@
end
module Melon
- VERBOSE = true
-
+ Verbose = true
+ #
+ # Server
+ #
class Server
def initialize
puts "*"
@@ -33,76 +35,83 @@ def initialize
# Called on each request
def call env
- Router.new( env ).go.finish
- end
- end
-
- class Router
- def initialize env
@request = Rack::Request.new env
@response = Rack::Response.new
- @session, path, @input = Session.new( @request.env['rack.session'] ),
- @request.path_info,
- @request.params
-
- # Parse route from url
- route = path.
- split('.')[0]. # Drop .json
- split('/').
- reject { |i| i.empty? } # Clear empty strings
-
- route.shift if route.first == 'm' # Drop /m/ if necessary
-
- # Make sure request was an XHR, and the route is valid
- if route.size >= 2 && @request.xhr?
- if Melon.const_defined? route.first.capitalize
- r *route
- else
- puts route.first.capitalize + " doesnt exist!"
- r :error, :module, route.first.capitalize
- end
+
+ if @request.xhr? # Request has to be XHR, no fucking around
+ @session = Session.new( @request.env['rack.session'] )
+ @route = Route.new @request.path_info
+
+ say
+ say @route.to_s
+
+ @output = @route.go @request.params, @session # Process the request
+ @session.merge! @output[:session] # Merge and save!
+ @response.body = @output[:content].to_json
else
- r :error, :routing
+ @response.body = { error: "request must be xhr!" }.to_json
end
- say
- say "* Path: #@module/#@action/#@key" + " <= " + path
-
+ @response['Content-Length'] = @response.body.size.to_s
+ @response['Content-Type'] = 'application/json'
+ @response.finish
+ end
+ end
+
+ #
+ # Router
+ #
+ class Route
+ attr_reader :module, :action, :key
+
+ def initialize path
+ @path = path
+ @route = @path
+ .split('.').first.split('/') # Drop .json and split at /
+ .reject {|i| i.empty? }[1..-1] # Clear empty strings and drop [0]
self
end
-
- def r *args
- @module, @action, @key = *args
+
+ def to route
+ @module, @action, @key = *route
end
- #
- # Create controller object & call action
- #
- def go
- controller = Melon[ @module.capitalize ]::Controller.new( @key, @input, @session )
+ def go input, session
+ mod = @route.first.capitalize
- @output = controller.do( @action )
- (@session <= @output[:session]).save!
- @response.body = @output[:content].to_json
- @response['Content-Length'] = @response.body.size.to_s
- @response['Content-Type'] = 'application/json'
-
- @response
+ # Check for errors
+ to (if ! Melon.const_defined? mod
+ [:error, :module, mod]
+ elsif ! (2..3) === @route.size
+ [:error, :route]
+ else
+ @route
+ end)
+
+ # Create a new controller, based on the route, then call the action on it
+ controller = Melon[ @module.capitalize ]::Controller.new @key, input, session
+ controller.do @action
+ end
+
+ def to_s
+ '/' + @route * '/'
end
end
class Document < Hash
end
end
+# CORE CLASSES #
+
class Object
# Syntactic sugar for const_get()
def self.[](const) self.const_get( const ) end
def [](const) self.const_get( const ) end
def null() nil.to_json end
def say s = ''
- puts s if Melon::VERBOSE
+ puts s if Melon::Verbose
end
end
class String; alias each each_line end
View
14 lib/modules/session.rb
@@ -1,7 +1,7 @@
module Melon
module Session
- def self.new(*args)
- Session::Model.new(*args)
+ def self.new *args
+ Session::Model.new *args
end
class Model < Hash
@@ -11,17 +11,23 @@ def initialize session = {}
self[:auth] = false
self[:failed] = 0
- self <= session if session
+ self << session if session
self
end
# Copy a hash into the session
- def <= s
+ def merge s
s.each do |k, v|
self[ k ] = v
end
end
+ alias << merge
+
+ def merge! s
+ merge s
+ save!
+ end
def god?
self[:god]
View
0 test/2008-10-10
No changes.
View
0 test/2009-07-09
No changes.
View
0 test/2009-09-31
No changes.
View
0 test/2009-12-08
No changes.
View
0 test/2009-12-24
No changes.

0 comments on commit 04915f3

Please sign in to comment.
Something went wrong with that request. Please try again.