hoe.js is a lightweight javascript library designed to streamline the creation of user interface in HTML/javascript.
From one side you have toolkits like jQuery that simplifies DOM manipulation but lacks support for creating complex UI.
On the other side you have MVC frameworks that often impose a very heavy-weight mechanism to create applications.
hoe.js's goal is to let you write structured code for small components and let you scale up your application without "getting into your way". It relies on javascript protoypes and jQuery, just adding some missing pieces:
hoe.js does not enforce any kind of structure for your code, but it was specially designed to help you create custom UI components. Here is an idiomatic example of how a "component" would look like.
var Calculator = hoe.Type(function(){
// some data
this.sum = 0;
// reference to UI elements
this.$sum = null;
});
// create UI
Calculator.prototype.render = function(){
var $plus_one = button('+1');
this.listen($plus_one, 'click', this.add_one);
this.$sum = strong({style: "margin-left:5px"},
this.sum.toString());
return [$plus_one, this.$sum];
};
// logic - event handler
Calculator.prototype.add_one = function(){
// update data
this.sum += 1;
// update UI
this.$sum.html(this.sum);
};
$(document).ready(function(){
hoe.init(); // create DOM helper functions
$('#calculator').html((new Calculator()).render());
});
var row = hoe('div', {'class':'row'}, 'foo');
// <div class="row">foo</div>
The first argument is a string with tag name. It returns a jQuery object for the tag. It can take any number of extra arguments where:
var row = hoe.partial('div', {'class':'row'});
row('foo');
// <div class="row">foo</div>
row('bar');
// <div class="row">bar</div>
hoe.partial() is used to create helper functions to generate composed tags and/or include tag attributes.
hoe.init() defines function helpers to create most
commonly used tags.
The function's name is the tag it creates. In this example
tr() and td() are used.
hoe.init();
var row = tr(td('col1', {'class': "my_class"}));
//<tr>
// <td class="my_class">col1</td>
//</tr>
You can customize the namespace and tags that will be created (check the API)
Create new types by "inheriting" from other types:
function Base(){
this.x = 1;
}
Base.prototype.three = function(){
return 3;
};
var Sub = hoe.inherit(Base, function(){
this.x = 2;
});
var obj = new Sub();
obj.three();
hoe.Type is an abstract type that provides some convenience methods
that keep the scope to the object when passing methods as callbacks.
It also supports a basic event system to be used between objects.
When creating new type you should inherit from hoe.Type
var MyType = hoe.inherit(hoe.Type, function(){/*...*/});
// ... this shorthand has the same effect as above
var MyType = hoe.Type(function(){/*...*/});
jQuery.proxy() to be used in the current object scope.
var MyStuff = hoe.Type(function(){
this.x = 5;
});
var my = new MyStuff();
var get_on_scope = my.scope(function() {return this.x;});
get_on_scope(); // 5
var MyType = hoe.Type(function(){
this.class = 'my_class';
this.$ele = div();
};
MyType.prototype.add_span = function(content){
this.$ele.append(span({'class': this.class}, content));
}
var my = new MyType();
my.forEach(['ele1', 'ele2'], this.add_span);
my.$ele.html();
// <div>
// <span class="my_class">ele1</span>
// <span class="my_class">ele2</span>
// </div>
var MyType = hoe.Type(function(){
this.class = 'my_class';
};
MyType.prototype.create_span = function(content){
return span({'class': this.class}, content);
}
var my = new MyType();
var span_array = my.map(['ele1', 'ele2'], this.create_span);
div(span_array);
// <div>
// <span class="my_class">ele1</span>
// <span class="my_class">ele2</span>
// </div>
hoe.Type.listen() can be used to bind DOM events keeping the object context.
my_obj.listen($ele, 'click', function(){alert(this.my_attr)});
// is the same as plain jQuery
$ele.bind('click', $.proxy(function(){alert(this.my_attr)}, my_obj));
hoe.Type.fire().
my.fire('my-custom-event-name', "argument1", {arg: 2});
Other objects can register callbacks to handle events in a similar way it is done for DOM events, but the first argument is an object that generates events instead of a DOM element.
var my2 = new MyType();
my2.listen(my, 'my-custom-event-name', function(val){
this.ele.append(val);
});