Overview

Yellow code is jQuery plugin for 2-way data binding.

  • You don't have to manipulate the DOM.
  • You only manipulate a model - a plain JavaScript object.
  • Changes in the model are propagated to the view - defined as an HTML template.
  • Changes in the view input elements are propagated back to the model.
  • Dynamic view attributes: text, input value, CSS and much more.
  • View can also contain loops and conditional elements.

Basic Example

Controller

All the model manipulation is done from within the controller. The controller is a plain JavaScript object which consists of methods.

The init method is called automatically when the plugin initializes. Its task is to initialize the model. It takes the model as its first parameter.

The other methods are event handlers. They are called when an event is triggered. Their task is to update the model accordingly. The event handlers also take the model as their first parameter.

Events

To specify the event handler, add an attribute called data-ylcEvents to the element which triggers the event.

  • To the left of the colon specify the event name. The event name is the same as used by jQuery. That means that you can even specify your own event, such as data-ylcEvents="myEvent: myHandler" and trigger it via jQuery: $("myElement").trigger("myEvent").
  • To the right of the colon specify the event handler. That is just the name of the controller object property which contains the handler function.
You can specify more event mappings, simply separate them by semicolon: data-ylcEvents="event1: handler1; event2: handler2"

Attributes

To specify a mapping of an element attribute onto a model variable, add an attribute called data-ylcBind to the element.

  • To the left of the colon specify the attribute name. The attribute name is the same as the name of the jQuery getter / setter for that attribute. So to map the inner text of the element, use text, to manipulate the value of an input field, use val, etc. For some attributes jQuery uses getters / setters with a fairly generic name and the the first argument of the getter / setter further specifies the exact attribute to change. (For example take css or attr.) In Yellow code such attributes are defined using a dot notation: to the left of the dot is the getter / setter name and to the right there is the first argument passed to the getter / setter. So for example if your model contains a variable called color and you wish to map it to a paragraph color, your mapping will look like this: data-ylcBind="css.color: color" .
    If you create a jQuery plugin which follows the standard jQuery getter / setter convention, you can refer to the associated property from the Yellow code bindings: data-ylcBind="myProperty: myModelVariable". This means that you can easily extend Yellow code simply by extending jQuery.
  • To the right of the colon is the model variable name.

Loops

Yellow code allows you to generate some of the DOM elements dynamically. In the example above the model contains an array and we want to have one <li> element (with children) for each array element.

To specify that an element should be generated for each model array element, add an attribute data-ylcLoop="element,status: list" to the corresponding view element. The status variable is optional, you don't have to specify it: data-ylcLoop="element: list".

list
Replace this with the name of the model variable which represents the array to iterate through.
element
Replace this with the name of the variable which will refer to the current element. This is not the model variable, but it can be used anywhere where a model variable would be used (such as in the data-ylcBind binding). The variable is writable - changing it will change the corresponding array element.
status
Replace this with the name of the variable which will refer to the current iteration status. This is not the model variable, but it can be used anywhere where a model variable would be used (such as in the data-ylcBind binding). The variable is read-only. It encapsulates the iteration index, which can be accessed like this: status.index.
Also note that the status variable is accessible from within the controller method. The second parameter passed to the controller method is the context, which contains a field called loopStatuses. Because our status variable defined in the view is called status, we can access the status object like this: context.loopStatuses.status. The value of the status object will be the iteration status valid for the element which triggered the event. Note that context.loopStatuses may contain multiple status objects - this will happen if you have a nested loop in your view and both the parent and the child loop define a status variable.

Putting it all together

Once you have your view and controller ready, initialize the plugin by calling:
$("your_view_selector").yellowCode(controller);.

Advanced features

Expression evaluation

An element attribute can be bound not only to a model variable, but to an expression consisting of model variables. The example above illustrates what kinds of operators may be used.

Note that if you need to define a custom utility function, that must go to the controller, not to the model.

Writable expression

This example shows that the value of the view element attribute may be not only computed from an expression, but that the value may also be assigned to that expression. If the values of the above input fields are changed, their values will be assigned to the corresponding expressions. Not all expressions are assignable. One may write a value to the expression persons[0].name, but not to "Mrs. " + persons[0].name + " " + persons[0].surname.

Conditional elements

To show an element only if a certain condition is fulfilled, add the following attribute: data-ylcIf="condition".

External events

Sometimes it's useful to read or update the model upon an event which is not triggered by any Yellow code view element. For example, if only a fraction of your page uses Yellow code and the rest uses conventional jQuery or plain JavaScript, it's useful if the parts outside the Yellow code view can somehow read and/or manipulate the model and refresh the view accordingly.

That's exactly what the concept of external events is for.

To invoke an external event, first get so called model adapter. Model adapter is a JavaScript object which for every controller method contains exactly one method with the same name as the controller. The adapter method, however, doesn't take the two parameters that every controller method gets - neither model nor context.

Example: If the controller contains methods
myMethod1(model, context, additionalArg1, additionalArg2) and
myMethod2(model, context, additionalArg1), the controller adapter object will contain methods
myMethod1(additionalArg1, additionalArg2) and
myMethod2(additionalArg1).

If you call the adapter method, Yellow code will call the corresponding controller method on your behalf, passing it the up-to-date model and the context object. After the controller method finishes, Yellow code will automatically redraw the view and apply all the changes the controller method did to the model.

If the controller method returns a value, this value will be also returned by the corresponding adapter method.

To get the adapter object, call
$(your_view_selector).yellowCode("getAdapter") passing the root element of the view after the Yellow code plugin was initialized on that element by passing it the controller.

Asynchronous model update

Normally the view is redrawn as soon as the controller method exits. Sometimes, however, the controller method can't update the model before it exists, and in that case the changes to the model would not be reflected in the view. The most notable example is an AJAX call. If the controller method calls AJAX and updates the model according to the result of the call, the model will be updated long after the controller method exists.

That's exactly the problem the asynchronous model solves. In the above example we simulate an AJAX call. In the controller method we synchronously set a model variable value to "(please wait)" and trigger an asynchronous event. Upon that event we can't simply change the model, because it's too late. The changes would not be reflected in the view. Instead, we call context.updateModel (remember context is the second parameter passed to every controller method). We pass an updater function to it. The updater function takes the same parameters as the controller methods do. When it exists, changes in the model it makes will be propagated to the view.

Using a jQuery plugin from within the view

The above example shows how to install the datepicker jQuery plugin as soon as a (potentially dynamic) view element becomes visible. First, mark the element with the following attribute:
data-ylcEvents="ylcElementInitialized: controller_method".
The ylcElementInitialized is a special Yellow code event which will be triggered just when the view element is initialized. For static element this happens after installing the Yellow code plugin, for dynamic elements (elements within loops and conditional elements) this happens when they are added to the view and become visible. Replace controller_method with the name of the controller method which will install your desired jQuery plugin. To install the plugin the controller method needs the DOM element. It will get it through the context object (passed to it as its second parameter): context.domElement.

Also note that the controller method in the above example makes use of asynchronous events to react to an event which is triggered by the datepicker plugin.

More examples

Nested loop

Dynamic sum

Password strength

Download (version 0.99.12)

Source code repository

The full source code can be checked out from https://github.com/pr83/ylc.

License

Yellow code is licensed under the the BSD 2-Clause License.

Contact

If you have any questions, comments, or suggestions, please send us an email to ylc@any3w.com.