GitHub Sale: sign up for any paid plan this week and pay nothing until January 1, 2009!  [ hide ]

public
Description: A full stack Javascript web development framework.
Clone URL: git://github.com/anthonycrumley/pseudo.git
pseudo /
name age message
file .gitignore Fri Oct 03 22:13:48 -0700 2008 Added Jetty servlet container. [anthonycrumley]
file LICENSE Sun Apr 06 19:27:56 -0700 2008 Added MIT License. [anthonycrumley]
file README.rdoc Fri Apr 18 22:50:22 -0700 2008 Event based view/controller interation proof of... [anthonycrumley]
directory script/ Fri Oct 03 22:13:48 -0700 2008 Added Jetty servlet container. [anthonycrumley]
directory server/ Fri Oct 03 22:13:48 -0700 2008 Added Jetty servlet container. [anthonycrumley]
README.rdoc
= Pseudo

Pseudo is currently in the design phase.  All the code in the project at this time is for proof of concept.  This 
document is in the process of being written and is currently very incomplete.

== Introduction

Pseudo is a full stack Javascript web framework based on the venerable model-view-controller design pattern.  Most all 
web frameworks are implemented with the model, controller, and most of the view running on the server side.  This 
division of work does not take advantage of client side processing.  With Pseudo, the view and controller run on the 
client while the model is executed on the client and server.  Client side model execution performs data validation, 
authorization, caching, and client side persistence.  Server side model execution performs data validation, 
authorization, caching, and server side persistence.  Yes, there is some duplication but it is necessary to prevent 
folks from meddling where they ought not.

Pseudo is appropriate for web applications but not for static content.  Since Pseudo creates the client side content 
with Javascript it is not appropriate for applications that need their content indexed by search engines, although this 
problem is not impossible to overcome.

== Model

The models run on the client and the server.  

The server side models act as a RESTful api.  

  GET:  /api/person // list people
  GET:  /api/person/1 // Retrieve one person
  GET:  /api/person/adults // Call adults method
  GET:  /api/person/1/projectMembership // All project memberships for person 1
  GET:  /api/person/1/project // All projects for person 1
  GET:  /api/person/1/project/3 // A particular project for person 1
  POST: /api/person // Create a person
  PUT:  /api/person/1 // Update a person
  PUT:  /api/person/1/terminate // Terminate a person
  PUT:  /api/person/1/reinstate // Reinstate a person
  DELETE: /api/person/1 // Delete a person

Model definition.

  pseudo.model('person',
    requireAuthentication('all'),
    requireAuthorization('admin', 'delete terminate reinstate'),
    restrict('status'),

    belongsTo('business'),
    
    hasMany('projectMembership'),
    hasMany('project').through('projectMembership'),
    
    hasMany('purchase'),
    hasMany('unpaidPurchases').from('purchase').where('isPaid = ?', false).and('dueDate < ?', new Date()),

    validateRequired('name', 'password'),
    validateUniquenessOf('name'),

    update({
      terminate: function() {
        person.update('status', 'terminated');
      },
      reinstate: function() {
        person.update('status', 'active');
      }
    }),
    
    read({
      adults: function() {
        return person.where('age > 18').read('all');
      }
    }),
    
    private({
      method1: function(p1, p2) {
        ...
      }
    })
  );

== View

The view is based on a markup derived from haml and shamelessly named jaml.  It is preprocessed on the server into 
Javascript that will be ran on the client.

Content Example:

  #content
    .left.column
      -h2 'Welcome to our site!'
      -p article.body
    -partial.right.column 'sidebar'

Form Example:

  -form!account {data: account}
    !name
    !address
    !phone
    -password!password {handle: 'blur'}
    -button.save
    -button.cancel

=== Syntax

expression | [-element][#id][!name][.class ...] [options] [expression]

Any combination of element, id, name and class is acceptable but at least one is required.  In jaml indentation 
determines nesting of content.

* expression - any valid Javascript expression
* element - an HTML element name or or special jaml markup like yield, partial, if and each
* id - HTML element id attribute\
* name - HTML element name attribute for input and form elements
* class - HTML element class attribute for CSS
* options - Javascript hash of options which include html attributes and jaml specific attributes like data, handle, 
validation, and validateOn

Prefixes
* - prefixes html element names and special markup like yield, partial, if and each.
* # prefixes element ids just as in css selectors
* . prefixes element classes just as in css selectors
* ! prefixes element names

If a line starts with a # or a . then the assumed element type is div.  If a line starts with a ! then the assumed 
element type is text.

Multiple classes can be added to the same element, e.g. "-p.article.summary".

=== Layouts

Page layouts will be defined by layout files.  A yield tag determines the placement of page content.

Example:

  -html
    -body
      #hd
      #bd
        .left
          -yield
        .right
      #ft

=== partials

== Controller

Controllers have an aspect oriented flavor.  When an event is handled in the view then controller methods that match the 
element will be called.  Controller method names are based on element, element type, element id, element class, element 
name and event.  Valid names are element, type, id, class, event, name, typeEvent, elementEvent, idEvent, nameEvent and 
classEvent.

Example

  -form!account {data: account}
    !name
    !address
    !phone
    -password!password {handle: 'blur'}
    -button.save
    -button.cancel

  pseudo.controller({
    cancel: function() {
      ...
    },
    save: function(account) {
      ...
    },
    passwordBlur: function(password) {
      ...
    }
  })

Anchors without an href and buttons are assumed to have a click handler.