Cop.js gives better maintainability and evolution to web applications by providing contexts and traits. Cop.js is based on the context-oriented programming paradigm where objects are adapted at runtime with different behavior depending on active contexts.

The project is hosted on GitHub, with annotated source code made available, as well as an online test suite, and here is an example of how to use contexts. Cop.js is available for use under the Apache 2.0 software license.

Downloads & Dependencies (Right-click, and use "Save As")

Development Version (0.1.2) 25kb, Full source, lots of comments
Production Version (0.1.2) 7.4kb, Packed and gzipped

Cop.js dependencies are:


Context-oriented programming, for short COP, provides language level abstractions that simplify the development of context-aware applications. As of today, there is a lack of COP languages that can reach all major mobile platforms.

We propose Cop.js, a COP language extension for Javascript that can be used either in web apps or in hybrid apps. Hybrid apps, like those using Phonegap, have the advantage of running on all major mobile platforms. In addition, our approach overcomes some limitations of current COP solutions in solving conflicts between adaptations. Mainly, by treating adaptations as traits.

If you're new to context-oriented programming, and curious about what Cop.js can do for you, start by looking at the contexts demo. There you find a running example, where you can edit and run the code directly in the browser.


Contexts can be seen as "reifications of situations that can occur while an application executes". For example, an application running on mobile might be interested if the battery runs low, the internet connection is interrupted, or the GPS is momentarily disabled. A part from raw data being sensed, other contextual information might be of interest, like the user being logged as guest or as admin, if he speaks english or french, or if his current location is at home, at work, or at the university.

For example, if we are on mobile we might be interested in treating the battery low situation as a context. By using the Phonegap API we can listen to the "batterylow" event. Here is how we can create a batteryLow Context:

var batteryLow = new Cop.Context({
    name: 'batteryLow',
    initialize: function() {
        window.addEventListener("batterylow", onBatteryLow, false);
        function onBatteryLow(info) {
            if (info.level <= 30) this.activate();
            else this.deactivate();

However, a simple context can be created as follows:

context = new Cop.Context({ name: 'test' });

oncontext.on(event, callback, [object])
Bind a callback on a Context event. The event can be:

Here is an example of binding a callback that will be called after the context object is activated.

onActivate = function(context) {
  alert("context '" + + "' is now active");
context.on("activate", onActivate);

Here is an example of binding a callback that will be called after the context object is deactivated.

onDeactivate = function(context) {
  alert("context '" + + "' is no more active");
context.on("deactivate", onDeactivate);, callback, [object])
Remove a callback previously-bound on a Context event. For example, here we remove callbacks from the context object:"activate", onActivate);"deactivate", onDeactivate);

Activating a Context is done by calling the activate method:


Deactivating a Context is done by calling the deactivate method:


adaptcontext.adapt(object, trait)
A Context can store adaptations by calling adapt on the Context, and passing the object to be adapted and the adaptation as a trait.

Note: Traits are composable units of code reuse. We use trait as an adaptation, as it groups together all the methods and properties that exhibit the context-dependent behavior for the adapted object. In addition, conflicts for adapted objects between different contexts can be handled in a robust way by traits as name clashes (conflicting properties) must be explicitly resolved by a composing entity. More about traits can be learned at, which is the Javascript implementation Cop.js uses for manipulating traits.

Suppose we have the following object:

object = {
  greet: function() {
    alert("Normal behavior.");

To provide an adaptation for the context object we have to do the following:

context.adapt(object, Trait({
  greet: function() {
    // this._super.greet();
    alert("Context adapted behavior.");

However, in order to see the context-dependent behavior of greet() we must first create a ContextManager instance, pass it the context object, and then start the instance.


There should be just one ContextManager in the whole system. Upon creation, all Context objects should be provided along with known relations between contexts. Note: relations are not implemented for now.

Here is an example of creating the ContextManager:

contextManager = new Cop.ContextManager({
  contexts: [context],
  relations: {}

The ContextManager, once created needs to be started in order to allow objects acquire traits as needed depending on the active contexts. As a result, objects can exhibit context-dependent behavior.


For example, in order to see the modified behavior for object.greet() the following steps must be followed:


resolveConflictresolveConflict(object, contexts, [callback])
An adapted object can have different traits for different contexts - where a trait is just a map of properties (attributes and methods). At runtime adapted objects acquire traits depending on the current set of active contexts.

When traits are composed conflicts can happen. A conflict, also known as a name clash, occurs when two or more traits provide a property with the same name but different implementation - where a property is a method or an attribute.

The ContextManager provides the resolveConflict method used to solve a possible conflict that can happen at runtime between two or more traits for an adapted object.

resolveConflict method takes the following parameters:

Either the callback parameter is provided, or not, will result in two strategies for the ContextManager:

Strategy 1: with callback:

The callback, if present, is invoked by the ContextManager when the conflict occurs by passing it the traits that are in conflict for the adapted object, and expects to receive a conflict-free trait in return.

Strategy 2: without callback:

The ContextManager only uses the contexts array to resolve the conflict. In this case, the traits (adaptations) are applied in a mixin-like fashion. In particular, between the traits is defined a linearization scheme which is right from left respect to the contexts array. The right most trait is applied first on the adapted object. Here, invoking an adapted method will first call the behavior from the left most trait, and then if _super is used inside the method will proceed (delegate) to the next adapted method in the chain or, if no more adaptations are left, will proceed to the basic unadapted method of the object.

However, it should be treated with care as it is an experimental feature. The this reference in methods of an adapted object is bound at runtime, after each recomposition of adapted objects, to the original object reference. First tests were encouraging and proved expected results.

For example, we might have an object MYAPP, and two contexts batteryLow and offline, that declare two adaptations for the MYAPP object for the same initScreen method:

  initScreen: function() {
    alert("Normal initialization.");

batteryLow.adapt(MYAPP, Trait({
  initScreen: function() {
    alert("Low battery initialization.");

offline.adapt(MYAPP, Trait({
  initScreen: function() {
    alert("No network initialization.");

Resolving the conflict that is generated when the two contexts will be active requires using the resolveConflict functionality.

For example, here we solve the conflict with a callback function:

contextManager.resolveConflict(MYAPP, [batteryLow, offline],
function(batteryLowT, offlineT) {
  return Trait.compose(
    Trait.resolve({initScreen: 'initScreenBatteryLow'},
    Trait.resolve({initScreen: 'initScreenOffline'},
      initScreen: function() {
        alert("Running offline with low battery.");

While here we solve the conflict without a callback function:

contextManager.resolveConflict(MYAPP, [offline, batteryLow]);

When both offline and batteryLow contexts are active, calling the MYAPP.initScreen() method will first invoke the offline behavior, which proceeds to the batteryLow behavior, which proceeds to the basic initScreen behavior.


Contexts demo

Contexts demo is where you can begin your first steps towards learning more about Cop.js. Thanks to CodeMirror you can edit and run a few lines of code that use contexts directly in the browser. There are three examples:

Contexts demo


CiclaMi is both a web app and a mobile app with one codebase, and has different functionality for when running in the browser or on mobile (Android).

It has three tags:


Change Log

0.1.2June 25, 2012
Bug fix. When traits are applied like mixins, linearly, now work as expected.
CiclaMi has three releases: initial, traditional and contexts.

0.1.1June 8, 2012
ContextManager's resolveConflict method now takes optional callback for resolving a conflict for an adapted object between traits. When no callback is provided, traits will be applied like mixins - a linearization scheme will be defined between adaptations with right to left precedence. Improved documentation.

0.1.0May 21, 2012
Initial release of Cop.js library.

The RELEASeD Laboratory ADAPT Lab.