<commit_before>Synapse (The Backbone KVO Library)
==================================

Synapse provides a mechanism for defining a communication hub between two
objects. In order for two objects to communicate, there are three components
needing to be defined:

    - the event that will trigger the pipeline ``A`` -> ``B``
    - the function to call on ``A`` that returns a message for ``B``
    - the function to call on ``B`` that accepts the message from ``A``

The hub can be defined with respect to either the subject ``A`` or the observer
``B`` depending on the system. In either case, whenever a change in state occurs
in ``A``, it will notify ``B`` (and all other observers for that event).

To facilitate the most common cases, Synapse infers the three components above
from the objects' types. Currently, Synapse has built-in support for "plain"
objects (or instances), jQuery objects (and thus DOM elements), and Backbone
Model instances. The various subject/observer combinations infer different
interactions between the objects. For example:

    var A = $('input[name=title]');
    var B = new Backbone.Model;

    Synapse(A).addObserver(B);

The subject ``A`` is an input element with a name attribute of 'title'.
Assuming the input element is a text input, Synapse determines the appropriate
event to be 'keyup'. That is, whenever the 'keyup' event is triggered (via user
interaction) ``A`` will notify ``B`` of this occurence.

To infer the next two components, the types of ``A`` and ``B`` in combination
must be considered. Since ``A`` is a form element, the *message* that is
sent by the notification is the value of input element at that current state.

Given that ``B`` is model instance, we can assume to store the *message* from
``A`` as a property on ``B``, but under what name? We use the name attribute
'title'. Thus the non-Synapse code would look like this:

    A.bind('keyup', function() {
        var key = A.attr('name'),
            value = A.val(),
            data = {};

        data[key] = value;

        B.set(data);
    });

The above is not difficult to write, but there may be a lot of these depending
on the types of objects that are interacting. For example:

    var C = $(':checkbox');
    Synapse(A).addObserver(C);

The observer in this case is a checkbox. The default behavior (in virtually all
cases) is to become 'checked' or 'unchecked' depending the *falsy* nature of
the message sent by the subject. The non-Synapse code:

     A.bind('keyup', function() {
        var value = A.val();
        C.prop('checked', Boolean(value));
    });

That is, ``C`` will only be checked if the value of ``A`` is not the empty
string.

The goal of Synapse is to handle majority of the common behaviors between
various objects, but with the ability to explicitly define these behaviors.


TODO
----
* Add more examples
* Provide way to unobserve an object
* Determine if format of options is totally obscure
* Determine if options can be simplified
* Implement conditional detection for combinations of objects<commit_msg>updated README to provide more context about the library and a better introduction.<commit_after>Synapse (The Backbone KVO Library)
==================================

Introduction
------------
Synapse provides a mechanism for defining a communication hub between two
objects. In order for two objects to communicate, there are three components
needing to be defined:

    - the event that will trigger the pipeline ``A`` -> ``B``
    - the function to call on ``A`` that returns a message for ``B``
    - the function to call on ``B`` that accepts the message from ``A``

The hub can be defined with respect to either the subject ``A`` or the observer
``B`` depending on the system. In either case, whenever a change in state occurs
in ``A``, it will notify ``B`` (and all other observers for that event).

To facilitate the most common cases, Synapse infers the three components above
from the objects' types. Currently, Synapse has built-in support for "plain"
objects (or instances), jQuery objects (and thus DOM elements), and Backbone
Model instances. The various subject/observer combinations infer different
interactions between the objects. For example:

```javascript
    var A = $('input[name=title]');
    var B = new Backbone.Model;

    Synapse(A).addObserver(B);
```

The subject ``A`` is an input element with a name attribute of 'title'.
Assuming the input element is a text input, Synapse determines the appropriate
event to be 'keyup'. That is, whenever the 'keyup' event is triggered (via user
interaction) ``A`` will notify ``B`` of this occurence.

To infer the next two components, the types of ``A`` and ``B`` in combination
must be considered. Since ``A`` is a form element, the *message* that is
sent by the notification is the value of input element at that current state.

Given that ``B`` is a model instance, we assume to store the *message* from
``A`` as a property on ``B``, but under what name? We use the name attribute
'title'. Thus the non-Synapse code would look like this:

```javascript
    A.bind('keyup', function() {
        var key = A.attr('name'),
            value = A.val(),
            data = {};

        data[key] = value;

        B.set(data);
    });
```

The above is not difficult to write, but there may be a lot of these depending
on the types of objects that are interacting. For example:

```javascript
    var C = $(':checkbox');
    Synapse(A).addObserver(C);
```

The observer in this case is a checkbox. The default behavior (in virtually all
cases) is to become 'checked' or 'unchecked' depending the *falsy* nature of
the message sent by the subject. Here is the non-Synapse code:

```javascript
     A.bind('keyup', function() {
        var value = A.val();
        C.prop('checked', Boolean(value));
    });
```

That is, ``C`` will only be checked if the value of ``A`` is not the empty
string.

The goal of Synapse is to handle the majority of common behaviors between
various objects, but with the ability to explicitly define custom
behaviors.


Interfaces
----------
The above examples explain the most simple interactions between two
objects. But how does each object return or accept a message from the
other object?

As stated above, Synapse is aware of each object's type and whether they
are the subject or observer for a given pipeline. For the cases when an
object is the subject, the message is typically derived from a subject's
property to be notified to it's observers. The observer on the other hand,
must know how to accept the message and usually persists it by storing it
locally.

Continuing the example from above using ``A`` and ``B``, since ``A`` is the
subject, the input value will be sent to it's observers every time it changes.
The observer, ``B``, is a model instance and thus *sets* the property on
itself.

```javascript
    A.trigger('keyup');     // sends the 'value' to observers
                            // B.get('title') returns the value
```javascript

Just like how events are inferred by the objects' types, the *interfaces*
for getting/setting properties are also inferred. ``Synapse.interfaces``
is a registry of interfaces by name that each have a ``get`` and ``set``
method associated with them. Synapse has quite a few built-in ones for
interfacing with DOM elements (represented as a jQuery instance) for the
most common behaviors. For example:

```javascript

    A.get('value');             // $('input[name=title]').val()
    A.set('value', 'hello')     // $('input[name=title]').val('hello')
```

The concept was derived from the simple API the Backbone Model class provides
for getting/setting attributes. That being said, the ``get`` and ``set``
methods when used on a wrapped model instance will use the native ones.
Likewise when ``get`` and ``set`` are called on a wrapped plain object, it
will simply get or set the property on the object.

The interfaces registry can be extended by registering new interfaces or
unregistering built-in interfaces and overriding them with custom ones.


Examples
--------
View examples here to gradually learn the API:
http://bruth.github.com/backbone-kvo/examples/


TODO
----
* Add more examples
* Provide way to unobserve an object
* Determine if format of options is totally obscure
* Determine if options can be simplified
* Implement conditional detection for combinations of objects
{'fraction_non_alphanumeric': 0.0985731272294887, 'fraction_numerical': 0.0, 'mean_word_length': 3.7925925925925927, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3031702', 'n_tokens_mistral': 2213, 'n_tokens_neox': 2121, 'n_words': 1208}