Fork me on GitHub Your Feedback...

{StackJS: Framework}

Javascript Object Oriented Programming Framework By Elad Yarkoni

							
Class("Human", {
	
	firstname: null,
	lastname: null,

	toString: function() {
		return "Hi, my name is " + this.firstname + " " + this.lastname;
	}
});

Class("Doctor::Human", {
	
	// C'tor
	Doctor: function(fname, lname) {
		this.firstname = fname;
		this.lastname = lname;
	},

	checkPatient: function(human) {
		return human.getFirstname() + ", you're ok!";
	},

	toString: function() {
		return "Hi, my name is Dr " + this.firstname + " " + this.lastname;
	}

});

// Create new objects
var newDoctor = new Doctor("Gregory", "House");
var newPatient = new Human();

// automatic setters and getters generator
newPatient.setFirstname("John");
newPatient.setLastname("Smith");

newDoctor.checkPatient(newPatient);
							
						

Features

  • Object Oriented Programming
  • Automatic setter and getter generator
  • Inheritance
  • Exception Event Handling And Full Stack Trace
  • Object Delegations From ObjectiveC
  • Web Application MVC integrated framework

More Information


StackJS Versions

The View Object

The View is an integrated class since StackJS 0.1.0 which represents the dom element.
The View class has all you need to define your UI component.
Visit the Web Application MVC and the API Documentation sections for more information.
						
Class('TableView::View', {
	
	elementClass: 'table-view',
	elementType: 'ul',
	list: null,

	TableView: function(list) {
		this.list = list;
	},

	render: function() {
		for (var i = 0; i < this.list.length; i++) {
			this.addViews("<li><span>Name</span><span>$$</span></li>", this.list[i].name);
		}
		this.addEvent('li > span', 'onclick', 'nameClickEvent');
	},

	handleEvents: function(evt, name) {
		if (name === "nameClickEvent") {
			alert('table row is clicked');
		}
	}
	
});
						
					
With addViews method you can build any type of UI component that you desire.
						
render: function() {
	
	this.addViews('<div class="row" ><span>$$</span><span>$$</span><span>$$</span><<span>$$</span>/div>',
		myModel.getId(),
		myModel.getName(),
		myModel.getLabel(),
		new PictureView()
	);
}
						
					
The StackJS View object lets you link elements inside the view with the view data members by using Outlets:
						
Class('MyView::View', {
	
	nameTextBoxOutlet: null,

	render: function() {
		
		this.addViews('<form >$$</form>',
			'<input type="text" outlet="nameTextBoxOutlet" > </input >'
		);
	},

	getInputText: function() {
		return this.nameTextBoxOutlet.value;
	}
	
});
						
					

Automatic setter and getter generator

StackJS creates setters and getters for each class data member.
						
Class('Car', {
	engineSize: null,
	model: null,
	manufacturer: null,
	maxSpeed: null,
	Car: function(manufacturer) {
		this.manufacturer = manufacturer;
	}
});

var car = new Car('Toyota');
car.setModel(2007);
console.log(car.getManufacturer());
						
					

Object Delegation

StackJS adopt the object delegation mechanizm from objectiveC.
Object could be a delegate of another object and handle its events.
						
Class("Engine",{
	
	size: null,
	
	Engine: function(size) {
		this.size = size;
	},
	
	start: function() {
		// engine did broken after start
		this.callDelegate("didBrokenPart",[this]);	
	}
});

Class("Car",{

	engine: null,

	Car: function() {
		this.engine = new Engine(1600);
		// make this car the engine delegate
		this.engine.setDelegate(this);
	},

	drive: function() {
		console.log("start drive");
		this.engine.start();
	},

	stop: function() {
		console.log("car is stopped");
	},

	// broken engine stops the car
	didBrokenPart: function(object) {
		this.stop();
	}
});
						
					

Exception Handling

StackJS supports exceptions and manage your application call stack.
In case of an exception, a full stack trace will be printed to the browser console.
						
// Define new exception
Class("StillAliveException::Exception", {
	human: null,
	StillAliveException: function(human) {
		this.human = human;
		this.message = "Human is still alive";
	}
});

Class("Human", {
	firstname: null,
	lastname: null,
	godmode: false,
	Human: function(fname,lname) {
		this.firstname = fname;
		this.lastname = lname;
	},
	kill: function(human) {
		if (human.getGodmode()) {
			Throw(new StillAliveException(human));
		}
	}
});

// Main
var killer = new Human("Tony", "Soprano");
var victim = new Human("John", "Smith");
victim.setGodmode(true);

// register exception events by exception type
Catch('StillAliveException', function(ex) {
	/* Handle still alive exception */
});

killer.kill(victim);
						
					

The Visitor Design Pattern

						
Class("Shape",{
	x: null,
	y: null,
	Shape: function(x,y) {
		this.x = x;
		this.y = y;
	}
});

Class("Rectangle::Shape",{
	edgeSize: null,
	Rectangle: function(x,y,edgeSize){
		this.x = x;
		this.y = y;
		this.edgeSize = edgeSize;
	},
	accept: function(visitor) {
		visitor.visitRectange(this);
	}
});

Class("Circle::Shape",{
	radius: null,
	Circle: function(x,y,radius) {
		this.x = x;
		this.y = y;
		this.radius = radius;
	},
	accept: function(visitor) {
		visitor.visitCircle(this);
	}
});


Class("CanvasVisitor",{
	visitCircle: function(circle) {
		var mycanvas = document.createElement('canvas');
		mycanvas.style.position = 'absolute';
		mycanvas.style.left = circle.getX() - circle.getRadius() + 'px';
		mycanvas.style.top = circle.getY() - circle.getRadius() + 'px';
		mycanvas.style.width = (circle.getRadius() * 2) + 'px';
		mycanvas.style.height = (circle.getRadius() * 2) + 'px';
		var ctx = mycanvas.getContext('2d');
		ctx.beginPath();
		ctx.arc(circle.getRadius(), circle.getRadius(), circle.getRadius(), 0, 2 * Math.PI, false);
		ctx.fillStyle = "#8ED6FF";
		ctx.fill();
		document.body.appendChild(mycanvas);
	},
	visitRectange: function(rectange) {
		var mycanvas = document.createElement('canvas');
		mycanvas.style.position = 'absolute';
		mycanvas.style.left = rectange.getX() + 'px';
		mycanvas.style.top = rectange.getY() + 'px';
		mycanvas.style.width = rectange.getEdgeSize() + 'px';
		mycanvas.style.height = rectange.getEdgeSize() + 'px';
		var ctx = mycanvas.getContext('2d');
		ctx.beginPath();
		ctx.rect(0, 0, rectange.getX() + rectange.getEdgeSize(), rectange.getY() + rectange.getEdgeSize());
		ctx.fillStyle = '#8ED6FF';
		ctx.fill();
		ctx.strokeStyle = 'black';
		document.body.appendChild(mycanvas);
	}
});

/*
*
*	Main
*/

var shapes = [
	new Circle(100,50,50),
	new Rectangle(300,50,100)
];

for (var i = 0; i < shapes.length; i++) {
	shapes[i].accept(new CanvasVisitor());
}
						
					

The Prototype Design Pattern

StackJS base object has the clone method.
						
Class('Car', {
	
	type: null,

	Car: function(type) {
		this.type = type;
	}
});

Class('ToyotaFactory', {

	prototypeObject: null,

	ToyotaFactory: function() {
		this.prototypeObject = new Car('Toyota');
	},

	createCars: function(size) {
		var carsArray = [];
		for (var i = 0; i < size; i++) {
			carsArray.push(this.prototypeObject.clone());
		}
		return carsArray;
	}

});

var toyotaFactory = new ToyotaFactory();
var toyotaCars = toyotaFactory.createCars(50);

						
					

The Singleton Design Pattern

StackJS has its own implementation of singleton classes, just omit the 'new' declaration and your OK.
						
Class('Application', {
			
	applicationName: null,

	start: function() {
		console.log('application has started');
	}
});

//
// Main Program
//

var myApplication = Application();
var anotherMyApplication = Application();
myApplication.setApplicationName('StackJS Application');
console.log(anotherMyApplication.getApplicationName()); // prints 'StackJS Application'
						
					

The Factory Design Pattern

						
Class('PrivateCar', {
	manufacturer: null,
	PrivateCar: function(manufacturer) {
		this.manufacturer = manufacturer;
	}
});

Class('Truck', {
	manufacturer: null,
	Truck: function(manufacturer) {
		this.manufacturer = manufacturer;
	}
});

Class('Bus', {
	manufacturer: null,
	Bus: function(manufacturer) {
		this.manufacturer = manufacturer;
	}
});

Class('VehicleFactory', {
	createPrivateCar: function(manufacturer) {
		return new PrivateCar(manufacturer); 
	},
	createTruck: function(manufacturer) {
		return new Truck(manufacturer); 
	},
	createBus: function(manufacturer) {
		return new Bus(manufacturer); 
	}
});
						
					

The Observer Design Pattern

This example implements the NSNotificationCenter mechanizm from the iOS SDK
						
// Notification Object
Class('NSNotification', {
	
	object: null,
	name: null,
	NSNotification: function(name, object) {
		this.name = name;
		this.object = object;
	}

});

// Notification Center
Class('NSNotificationCenter', {
	
	_observers: [],
	
	addObserver: function(observer, method, notificationName) {
		this._observers.push({
			name: notificationName,
			observer: observer,
			method: method
		});
	},

	postNotificationName: function(name, object) {
		for (var i = 0; i < this._observers.length; i++) {
			if (this._observers[i].name === name) {
				this._observers[i].observer[this._observers[i].method](new NSNotification(name, object));
			}
		}
	}

});

Class('Human', {
	name: null,
	sick: function() {
		NSNotificationCenter().postNotificationName('humanSick', this);
	}
});

Class('Doctor', {
	Doctor: function() {
		NSNotificationCenter().addObserver(this, 'humanIsSick', 'humanSick');
	},
	humanIsSick: function(nsnotification) {
		console.log("Hi " + nsnotification.getObject().getName() + ", I will take care of you");
	}
});
						
					
More Design Patterns will be available soon.

StackJS Application Framework

StackJS framework helps you to build web and mobile applications easily, based on model-view-controller design pattern. StackJS keeps your application code readable and makes your developement process swift and simple.

API Documentation

Demos

TODO's Application   War (Card Game)

StackJS Application Architecture

The Model

The model represents the data structure.

Example

Shopping list model with items and quantity for each item.
						
Class('ShoppingList', {
	
	shoppingList: [],

	addItem: function(name, quantity) {
		this.shoppingList.push({
			name: name,
			quantity: quantity
		});	
	},

	removeItemByName: function(name) {
		for (var i = 0; i < this.shoppingList.length; i++) {
			if (this.shoppingList[i].name === name) {
				this.shoppingList.splice(i, 1);
			}
		}
	},

	getItem: function(index) {
		return this.shoppingList[i];
	},

	size: function() {
		return this.shoppingList.length;
	}
});
						
					

The View

The view object manages the DOM element.
View objects should inherit from StackJS View class.

Example

The shopping list will be rendered inside a table view.
This example defines two views, one represents the cell view and the second is for the table view.
						
Class('TableView::View', {
	
	// View class rendering method
	render: function() {
		this.clearViews();
		this.addClasses("table-view");
		for (var i = 0; i < this.getModel().size(); i++) {
			this.addViews('$$', new TableCellView(i));
		}
	}

});
						
					
						
Class('TableCellView::View', {
	
	index: null,

	TableCellView: function(index) {
		this.index = index;
	},
	
	render: function: function() {
		this.addClasses("table-cell", "no-border");
		this.addViews('<span>$$</span><span>$$</span>', 
			this.getModel().getItem(this.index).name,
			this.getModel().getItem(this.index).quantity
		);
		this.addEvent("span", "onclick", "tableCellClicked");
	},

	handleEvents: function(evt, eventName) {
		if (eventName === "tableCellClicked") {
			this.callDelegate("shoppingCartItemClicked", [this.index]);
		}
	}
});							
						
					

The Controller

The controller manages the model and the view objects.
The controller act as a delegate of its views and handle both the view and the application events.

Example

The TableViewController class represents the table controller.
This table controller owns the view and the model, define itself as the view delegate and implements the view delegate method - shoppingCartItemClicked.
						
Class('TableViewController', {
	model: null,
	view: null,
	// C'tor
	TableViewController: function() {
		this.view = new TableView();
		this.model = new ShoppingList();
		this.view.setDelegate(this);
		this.view.setModel(this.model);
		Viewport().addViews('$$',this.view);
	},

	// delegation method
	shoppingCartItemClicked: function(index) {
		// do something...
	}
});
						
					

StackJS Boilerplate Generator


StackJS Playground
Play
API Documentation
The Default Object Class
The Default object class called 'STObject' and each object in stackJS derived from it.
this.delegate
Holds the delegate class.
function isExtends(classStr)
returns true if the object extends the classname: classStr
function callDelegate(methodName, params)
call delegate method with params array.
Example: this.callDelegate('didClassChanged', [param1, param2...]);
function clone()
returns a copy of the object.
function setTimeout(callback, milliseconds)
The javascript setTimeout method with the object context.
function setInterval(callback, milliseconds)
The javascript setInterval method with the object context.
The View Class
The View class handle the dom element and has a set of methods to customize the view.
this.element
The element property holds the dom object.
this.elementType
The elementType property defines the dom element type (div, ul, li, etc.).
this.elementClass
The elementClass property defines the css class name.
function addClasses(class1, class2...)
The addClasses method set css classes to the view element.
function getView(selector)
The getView method returns a single element from the view root element by giving a query selector string.
function getViews(selector)
The getViews method returns elements array from the view root element by giving a query selector string.
function addViews(templateString, view1, view2...)
The addViews method add subviews to the view object.
The first parameter will be html string and the next parameters will be views to add in four different types: 1-string 2-boolean 3-number 4-View object.
The html string will contain the '$$' signs when each '$$' sign will be replaced with view parameter in the same order.
For example:
this.addViews('<div><span>$$</span><span>$$</span></div>', "first view", new View());
add the dom element: <div><span>first view</span><span><div></div></span></div> to the view element.
The addViews method passes the delegate and the model of the view to the added subviews.
function clearViews()
The clearViews method make the view root element empty.
function removeView()
The removeView method remove the root element from its parent view.
function addEvent(selector, eventType, eventName, preventDefault (boolean))
The addEvent method will add a new dom event.
The selector parameter selects the element which gets the event, the eventType parameter represents the dom event name like: onclick, onmousedown, etc... and the eventName parameter represents a unique name which will be sent to the view event handler.
function removeEvent(selector, eventType)
Remove event listener by selector and eventType.
function handleEvents(eventObject, eventName)
The handleEvents method is handle the dom events that we added earlier with the addEvent method.
When event occurs, the handleEvents method is called. the eventObject parameter gets the dom event object and the eventName gets the eventName unique string.
Each view class should override this method to handle the dom events.
function render()
The render method is called when the view is added as a subview to another view object or to the viewport.
Each view class should override this method to customize the view.
The Viewport Class
The Viewport is a singleton class represents the viewport of the document.
The Viewport inherit from the View class and has the same functionality as a single view.
The main application controller should be the viewport delegate when application is initialized.
function getWidth()
gets the viewport width.
function getHeight()
gets the viewport height.
function didBecomeActive() [Delegate method]
The didBecomeActive delegate method is called when the dom is ready.
function willResignActive() [Delegate method]
The willResignActive delegate method is called when dom event onbeforeunload is raised.
function willTerminate() [Delegate method]
The willTerminate delegate method is called when dom event onunload is raised.
function didHashChanged() [Delegate method]
The didHashChanged delegate method is called when url hash is changed.