<commit_before># ECMA5Extend

Toolkit for writing GOOD JavaScript APIs for both Browser and NodeJS using ECMA5.

## Why?

JavaScript was originally invented to do basic form validation and arithmetic, and is evolving into a full-blow language for writing Apps.

**As JavaScript evolves, so should the developers that use it.**

A mature programming language provides:

- Inheritance
- Public, private and protected API
- Intelligent event system

Some of these are coming in ECMA6, and it will take years for browsers to implement it, plus the syntax changes.
This is why, after many painful projects, we've developed ExtendJS. 

Unlike other "extend-like" projects, this one relies on Object creation and manipulation tools provided by ECMA5, including Object.create and Object.defineProperty. This project does not use the "new" keyword and instead relies on inheritance using ECMA5 Object.create(). 

### Why inheritance?

Simple: Code Reuse.

### Why private?

A good API exposes only a subset of guts to the outside. The rest reside "under the hood", away from the developer. These are private APIs. 
Think of a thermostat, you don't have control over heat or cold directly. You set the temperature, and the thermostat decides which one to turn on, and for how long, based on the room temperature. Setting the temperature is your public API, while access to heat and cold directly are inside of the private API.

### Why protected?

What if your child type wants to inherit a non-public method and/or re-implement it? That's called protected.

## Structure

ECMA5Extend allows developers to clearly define their type definition, that compile into a **type** that have the following public API:

- _create(params)_ create instance of type and pass params into type's init() method

Once an **instance** is created, it has the following public API:

- _destroy()_ put destroy code specific to the type here
- _subscribe(eventName, listenerFunction)_ subscribe to an event
- _unsubscribe(eventName, listenerFunction)_ unsubscribe from an event
- _publish(eventName, value1, value2, internalOnly)_ publish an event on type

ECMA5Extend comes in two flavors:

1. Standalone Library
2. RequireJS AMD Plugin (http://requirejs.org/)

### **Standalone Library**

``` javascript

var parent = {
	
		name : "parentType",
		
		public : { },

		private : { },
		
		protected : { },
		
		init : function(){ },
		
		destroy : function(){ }

	};

var child = {
	
		name : "childType",
		
		public : { },

		private : { },
		
		protected : { },
		
		init : function(){ },
		
		destroy : function(){ }

	};
	
```

ECMA5Extend has a single method:

_createType(definition, extends)_

```
//create both types
var parentType = ECMA5Extend.createType(parent);
var childType = ECMA5Extend.createType(child, parent);
```

A type has the following methods:



```
//create instances
var parentInstance = parentType.create();
var childInstance = childType.create();
```

Anything you pass into create, gets passed into the type's init() functions as arguments.

### **RequireJS AMD Plugin (http://requirejs.org/)**

To use ECMA5Extend as a RequireJS plugin. You need to:

1. Wrap the module in a define()
2. Import parent Types using the extend! plugin, ```define([extend!parent], function(parentType){ })```
3. Add an "extend" property that points at what was returned from the extend! plugin
4. Return the type definition, as with any RequireJS modules

```
//parent class
define("parent", function() {

	return {
	
		name : "parentType",
		
		extend : null, //parent Type

		public : { },

		private : { },
		
		protected : { },
		
		init : function(){ },
		
		destroy : function(){ }

	};

});


//child class
define(["extend!parent"], function(parent) {

	return {
	
		name : "childType"
		
		extend : parent, //this points at what extend!parent passes into this module

		public : { },

		private : { },
		
		protected : { },
		
		init : function(){ },
		
		destroy : function(){ }

	};

});
```

The result type will have a ```create()``` method, that creates instances.

```
require(["extend!child"], function(childType) {

	var newInstance = childType.create();

});
```


## Intelligent Event/Notification System

ECMA5Extend has an intelligent event system. Any property created in the "public" space, automatically gets setters and getters so that :

- Setting the public property to a specific value triggers an "<propertyName>Changed" event. All subscribers, and any "<propertyName>Changed" methods inside private get notified of the change.
- Setting the private property to a specific value allows you to go behind the property's back if you don't want to alarm the subscribers.

Example:


``` javascript

	var someType = {

		public : {
			<commit_msg>readme fixes<commit_after># ECMA5Extend

Toolkit for writing GOOD JavaScript APIs for both Browser and NodeJS using ECMA5.

## Why?

JavaScript was originally invented to do basic form validation and arithmetic, and is evolving into a full-blow language for writing Apps.

**As JavaScript evolves, so should the developers that use it.**

A mature programming language provides:

- Inheritance
- Public, private and protected API
- Intelligent event system

Some of these are coming in ECMA6, and it will take years for browsers to implement it, plus the syntax changes.
This is why, after many painful projects, we've developed ExtendJS. 

Unlike other "extend-like" projects, this one relies on Object creation and manipulation tools provided by ECMA5, including Object.create and Object.defineProperty. This project does not use the "new" keyword and instead relies on inheritance using ECMA5 Object.create(). 

### Why inheritance?

Simple: Code Reuse.

### Why private?

A good API exposes only a subset of guts to the outside. The rest reside "under the hood", away from the developer. These are private APIs. 
Think of a thermostat, you don't have control over heat or cold directly. You set the temperature, and the thermostat decides which one to turn on, and for how long, based on the room temperature. Setting the temperature is your public API, while access to heat and cold directly are inside of the private API.

### Why protected?

What if your child type wants to inherit a non-public method and/or re-implement it? That's called protected.

## Structure

ECMA5Extend allows developers to clearly define their type definition, that compile into a **type** that have the following public API:

- _create(params)_ create instance of type and pass params into type's init() method

Once an **instance** is created, it has the following public API:

- ```destroy()``` put destroy code specific to the type here
- ```subscribe(eventName, listenerFunction)``` subscribe to an event
- ```unsubscribe(eventName, listenerFunction)``` unsubscribe from an event
- ```publish(eventName, value1, value2, internalOnly)``` publish an event on current instance
	The publish method, looks for any methods in the public, private and subscribers list that match the eventName and calls them with two arguments.

Look at the Intelligent Event/Notification System section for examples.

ECMA5Extend comes in two flavors:

1. Standalone Library
2. RequireJS AMD Plugin (http://requirejs.org/)

### **Standalone Library**

``` javascript

var parent = {
	
		name : "parentType",
		
		public : { },

		private : { },
		
		protected : { },
		
		init : function(){ },
		
		destroy : function(){ }

	};

var child = {
	
		name : "childType",
		
		public : { },

		private : { },
		
		protected : { },
		
		init : function(){ },
		
		destroy : function(){ }

	};
	
```

ECMA5Extend has a single method:

_createType(definition, extends)_

```
//create both types
var parentType = ECMA5Extend.createType(parent);
var childType = ECMA5Extend.createType(child, parent);
```

A type has the following methods:



```
//create instances
var parentInstance = parentType.create();
var childInstance = childType.create();
```

Anything you pass into create, gets passed into the type's init() functions as arguments.

### **RequireJS AMD Plugin (http://requirejs.org/)**

To use ECMA5Extend as a RequireJS plugin. You need to:

1. Wrap the module in a define()
2. Import parent Types using the extend! plugin, ```define([extend!parent], function(parentType){ })```
3. Add an "extend" property that points at what was returned from the extend! plugin
4. Return the type definition, as with any RequireJS modules

```
//parent class
define("parent", function() {

	return {
	
		name : "parentType",
		
		extend : null, //parent Type

		public : { },

		private : { },
		
		protected : { },
		
		init : function(){ },
		
		destroy : function(){ }

	};

});


//child class
define(["extend!parent"], function(parent) {

	return {
	
		name : "childType"
		
		extend : parent, //this points at what extend!parent passes into this module

		public : { },

		private : { },
		
		protected : { },
		
		init : function(){ },
		
		destroy : function(){ }

	};

});
```

The result type will have a ```create()``` method, that creates instances.

```
require(["extend!child"], function(childType) {

	var newInstance = childType.create();

});
```


## Intelligent Event/Notification System

ECMA5Extend has an intelligent event system. Any property created in the "public" space, automatically gets setters and getters so that :

- Setting the public property to a specific value triggers an "<propertyName>Changed" event. All subscribers, and any "<propertyName>Changed" methods inside private and public get notified of the change.
- Setting the private property to a specific value allows you to go behind the property's back if you don't want to alarm the subscribers.
- Developers can manually publish events using the ```instance.publish()``` method

Example:


``` javascript

	var someType = {

		public : {
			
{'fraction_non_alphanumeric': 0.09706270962496188, 'fraction_numerical': 0.004065453806281126, 'mean_word_length': 3.972208185952501, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1233297', 'n_tokens_mistral': 2898, 'n_tokens_neox': 2560, 'n_words': 1214}