Simple (1.98KB minified & gzipped & all features) class system for JavaScript. Designed to work with backbone.js and node.js.
- Core:
- Inheritance
__super__
- reference on super class
- Plugins:
- Mixins
- Interfaces
- Singleton
- Namespaces
- Properties
- getter / setter (Optional:Support for ECMA5 getter / setter)
- visibility
- type check (Class, Object, String, Number, Boolean, Function, Array, Element, Regex, more can be added)
- format value
- validation
- init value,
- nullable
- events (optional, event emitter needed: e.g. Backbone.Events, node.js events.EventEmitter)
- Extensible: Add your own definition keys and types
- Browser & commonJS support
- Well tested
Browser:
<script src="underscore.js"></script>
<script src="class.js"></script>
node.js:
npm install classjs
require("classjs");
var ICompany = {
addEmploye : function(employe) {
// Check passed arguments
if (Array.prototype.slice.call(arguments).length != 1) {
throw new Error("Wrong length of arguments");
}
if (typeof employe !== "object") {
throw new Error("Wrong type for argument employe");
}
}
};
// Define a new class. Extend from EventEmitter.
var Company = Class.define(EventEmitter, {
interfaces : [ICompany],
properties : {
activated : "Boolean",
name : {
type : "String",
init : "No Name",
validate : function(value, old, prop) {
return value != "foo"; // alternative you can return a custom error message as a string
},
apply : "_applyName",
event : "nameChanged"
},
street : {
type : "String",
format : function(value, old, prop) {
return value.toUpperCase()
},
get : false, // generate only private getter / setter
set : false
},
city : {
type : "String",
nullable : true
}
},
members : {
_applyName : function(value, old, prop) {
console.log(value, old, prop);
},
addEmploye : function(employe) {
console.log("employe");
}
}
});
// Extend from "Company"
var MyCompany = Company.extend({
namespace : "my.cool.Company",
constructor : function() {
Company.apply(this, arguments);
this.setName("My Company");
this._setStreet("Some Street", false);
this.setCity(null);
},
members : {
addEmploye : function(employe) {
// Call overridden method
this.__super__.addEmploye.apply(this, arguments);
}
}
});
var company = new MyCompany();
company.on("nameChanged", function(data) {
console.log("Name changed to %s", data.value);
});
company.addEmploye({name:"Lena"});
company.setName("My new Company");
class.js is using grunt (https://github.com/cowboy/grunt) to build the modules and to run the tests. If you would like to create a custom build of class.js or develop a feature, please follow these steps:
To install Grunt run the follwing command (npm (http://npmjs.org/) needed):
npm install -g grunt
Test & Build the project, run:
grunt
Automatically build project whenever a lib/*.js file is changed:
grunt watch
Run tests only:
grunt qunit
The tests are located in the test
folder. With the index*.html files you can run the tests manually in any browser you want.
Class.define(superClass, definition)
- superClass: Class (optional)
- definition: Object (optional)
Defines a new class.
Class.define(superClass, {
namespace : String,
singleton : true|false,
mixins : [Object|Class],
interfaces : [Object|Class],
constructor : Function, // Optional. Super constructor is called implicit when not available
properties : {
prop1 : "Number|Boolean|String|Object|Function|Array|Element|Regex" | Class, // Simple property definition
prop2 : {
type : "Number|Boolean|String|Object|Function|Array|Element|Regex" | Class, // Complex property definition
init : Mixed
format : "Function" | Function,
validate : "Function" | Function | ["Function"|Function],
apply : "Function" | Function,
set : true|false,
get : true|false,
nullable : true|false,
event : String
}
...
},
statics : {
static1 : Function,
static2 : Function,
...
},
members : {
member1 : Function
member2 : Function
...
}
});
SomeClass.extend(definition)
- definition: Object (optional) (see Class.extend for more details)
The extend
method is added automatically to every created Class. Extends from the given class.
var MyClass = Class.define();
var SomeClass = MyClass.extend();
var obj = new SomeClass();
Sometimes it can be usefull not to use the full feature set of class.js. You can use the methods that are used for the class definitions standalone as well:
Class.singleton(clazz, setSingleton)
Class.mixins(clazz, mixins)
Class.interfaces(clazz, interfaces)
Class.properties(clazz, properties)
Class.statics(clazz, statics)
Class.members(clazz, members)
Class.namespace(namespace, clazz)
Extending types
Class.types (provided by properties plugin)
For example:
Class.types["MyType"] = function(value) {
return value instanceof MyType;
}
Extending definition
Class.definition
For example:
Class.definition.push("mykey");
Class.mykey = function(clazz, definition) {
for (var key in definition) {
clazz.prototype[key] = function() {
alert("My New Extension");
}
}
}
Class define hooks
Class.onBeforeClassDefine
Class.onAfterClassDefine
For example:
Class.onBeforeClassDefine = function() {
console.log("Before Class Define called");
};
Class.onAfterClassDefine = function() {
console.log("After Class Define called");
};
Before instantiation hooks
Class.onBeforeInstantiation
Class.onAfterInstantiation
For example:
Class.onBeforeInstantiation = function() {
console.log("Before object is instantiated");
};
Class.onAfterInstantiation = function() {
console.log("After object is instantiated");
};
ECMA5 Getter / Setter
When ECMA5 Mode is activated instead of setProp / getProp methods, ECMA5 getter and setter are generated. This can be used like normal JavaScript properties, but will check for types / validate / format / etc.
Class.ECMA5;
For example:
Class.ECMA5 = true;
var MyClass = Class.define({
properties : {
foo : "Boolean"
bar : "Number"
}
});
var obj = new MyClass();
obj.bar = 1 // no setBar(1) needed
var bar = obj.bar; // no getBar() needed
obj.foo = "string" // will throw an exception
Error Types
Class.ValidationError
Class.TypeError // extends from validation error
For example you can override the default error handler for class.js:
Class.error = function(error) {
if (error instanceof Class.TypeError) {
console.log(error.message);
console.log(error.type);
console.log(error.value);
console.log(error.property);
}
if (error instanceof Class.ValidationError) {
console.log(error.message);
console.log(error.value);
console.log(error.property);
}
throw error;
}
or use it for validation:
var MyClass = Class.define({
properties : {
foo : "Boolean"
bar : "Number"
}
});
var data = {
foo : true,
bar : "Some String"
};
var obj = new MyClass();
var errors = [];
var validate = function(property, value) {
errors = [];
for (var property in data) {
try {
obj.set(property, data[value]);
} catch (exc) {
errors.push(exc);
}
}
return errors.length === 0;
}
for (var property in data) {
validate(property, data[property])
}
if (validate(data)) {
console.log("Validation OK. Submit form");
} else {
console.log("Errors", errors);
}
- 0.6 (2012/7/28, published to npm)
- Splitted up files
- Use grunt to build project
- Interfaces can now have parameter checks
- API & Feature freeze for 1.0
- 0.5.2 (2012/7/27, published to npm)
- Added node tests
- 0.5.1 (2012/7/27, published to npm)
- Node.js fixes
- 0.5 (2012/7/27, published to npm)
- Added ECMA5 getter/setter
- API stabilization / changes
- Removed "notfire" event parameter from property setter
- 0.4 (2012/7/27, not published to npm)
- Improved plugin system
- Added strict mode
- API stabilization / changes
- Removed instanceOf method
- Class.definition is now an array to ensure order of execution
- Before / After Class definition hooks
- Before / After instantiation hooks
- Bugfixes
- More tests
- 0.3 (2012/7/27, not published to npm)
- Plugin system
- QUnit tests
- Namespaces
- Bugfixes
- Validation can be an array of validators
- Simple properties (prop:type) now possible
- Valiator & Formater can now be a member function
- More documentation
- 0.2 (2012/7/26)
- Bugfixes
- API stabilization
- Documentation
- 0.1.1 (2012/7/26)
- Minor Bugfixes
- Docu
- 0.1 (2012/7/26)
- Inital release
- If you have a feature request or an issue please report it here: https://github.com/tjbutz/class.js/issues
- If you have developed a plugin for class.js please let me know. I will list the plugin on this page.
- Examples