Skip to content

Commit

Permalink
Merge pull request arturadib#85 from pindia/feature-bubble
Browse files Browse the repository at this point in the history
Agility event bubbling
  • Loading branch information
arturadib committed Jul 3, 2012
2 parents 29bfab1 + 3190ce9 commit 16a5df3
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 0 deletions.
7 changes: 7 additions & 0 deletions agility.js
Expand Up @@ -194,6 +194,7 @@
}
this._container.children[obj._id] = obj; // children is *not* an array; this is for simpler lookups by global object id
this.trigger(method, [obj, selector]);
obj._parent = this;
// ensures object is removed from container when destroyed:
obj.bind('destroy', function(event, id){
self._container.remove(id);
Expand Down Expand Up @@ -312,6 +313,8 @@
// put the order of events back
util.reverseEvents(this._events.data, 'pre:' + eventObj.type);
$(this._events.data).trigger(eventObj.type, params);
if(this.parent())
this.parent().trigger((eventObj.type.match(/^child:/) ? '' : 'child:') + eventObj.type, params);
$(this._events.data).trigger('post:' + eventObj.type, params);
}
return this; // for chainable calls
Expand Down Expand Up @@ -725,6 +728,9 @@
this.trigger('destroy', this._id); // parent must listen to 'remove' event and handle container removal!
// can't return this as it might not exist anymore!
},
parent: function(){
return this._parent;
},

//
// _container shortcuts
Expand Down Expand Up @@ -811,6 +817,7 @@

// Fresh 'own' properties (i.e. properties that are not inherited at all)
object._id = idCounter++;
object._parent = null;
object._events.data = {}; // event bindings will happen below
object._container.children = {};
object.view.$root = $(); // empty jQuery object
Expand Down
28 changes: 28 additions & 0 deletions docs/_docs.md
Expand Up @@ -296,6 +296,21 @@ The example below defines both a DOM and a Model event handler:
$$.document.append(catcher);
<div class="demo"></div>

**Agility event bubbling**

Like DOM events, Agility events automatically bubble to the containers of objects. However, bubbling events do not trigger event handlers on the parent objects by default. An event handler must declare that it is interested in receiving bubbled events by including the `child:` prefix in its event specification:

:::javascript
var parent = $$({
controller: {
'child:testevent': function(){
alert('testevent fired in descendant');
}
}
});

Events can bubble up multiple levels. Only a single `child:` prefix is required to catch an event in any descendant of an obect.

## [Auto-proxying](#auto-proxy)

All user-defined controllers initialized by the factory function `$$()` have their `this` auto-proxied to the owner MVC object, for quick access and consistent behavior no matter what context:
Expand Down Expand Up @@ -532,6 +547,19 @@ _Erases self view, removes self from parent container._

Nothing.

### [.parent()](#core-parent)

_Returns the parent container to which the object has been added, or null if it has not yet been added to a container._

**Syntax:**

:::javascript
.parent()

**Returns:**

Parent Agility object.




Expand Down
23 changes: 23 additions & 0 deletions docs/docs.html
Expand Up @@ -372,6 +372,19 @@ <h3><a href="#events-agility">Agility events</a></h3>


<p><div class="demo"></div></p>
<p><strong>Agility event bubbling</strong></p>
<p>Like DOM events, Agility events automatically bubble to the containers of objects. However, bubbling events do not trigger event handlers on the parent objects by default. An event handler must declare that it is interested in receiving bubbled events by including the <code>child:</code> prefix in its event specification:</p>
<div class="codehilite"><pre><span class="kd">var</span> <span class="nx">parent</span> <span class="o">=</span> <span class="nx">$$</span><span class="p">({</span>
<span class="nx">controller</span><span class="o">:</span> <span class="p">{</span>
<span class="s1">&#39;child:testevent&#39;</span><span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">alert</span><span class="p">(</span><span class="s1">&#39;testevent fired in descendant&#39;</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">});</span>
</pre></div>


<p>Events can bubble up multiple levels. Only a single <code>child:</code> prefix is required to catch an event in any descendant of an obect.</p>
<h2><a href="#auto-proxy">Auto-proxying</a></h2>
<p>All user-defined controllers initialized by the factory function <code>$$()</code> have their <code>this</code> auto-proxied to the owner MVC object, for quick access and consistent behavior no matter what context:</p>
<div class="codehilite"><pre><span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="nx">$$</span><span class="p">({</span><span class="nx">msg</span><span class="o">:</span><span class="s1">&#39;I only exist because of auto-proxying&#39;</span><span class="p">},</span> <span class="s1">&#39;&lt;div/&gt;&#39;</span><span class="p">,</span> <span class="p">{</span>
Expand Down Expand Up @@ -578,6 +591,15 @@ <h3><a href="#core-destroy">.destroy()</a></h3>

<p><strong>Returns:</strong></p>
<p>Nothing.</p>
<h3><a href="#core-parent">.parent()</a></h3>
<p><em>Returns the parent container to which the object has been added, or null if it has not yet been added to a container.</em></p>
<p><strong>Syntax:</strong></p>
<div class="codehilite"><pre><span class="p">.</span><span class="nx">parent</span><span class="p">()</span>
</pre></div>


<p><strong>Returns:</strong></p>
<p>Parent Agility object.</p>
<h3><a href="#container">&mdash;</a></h3>
<p>The methods below are specific to the object container.</p>
<h3><a href="#core-append">.append()</a></h3>
Expand Down Expand Up @@ -947,6 +969,7 @@ <h3><a href="#persist-restful">$$.adapter.restful</a></h3>
api/resource/123
</pre></div>


</div>
</div>

Expand Down
25 changes: 25 additions & 0 deletions test/public/core.js
Expand Up @@ -1047,6 +1047,31 @@
ok(o===obj1 && s==='sel', "append() called");
});

test("Agility event bubbling", function(){
var parent1Called = false;
var parent2Called = false;
var parent1 = $$({
controller: {
'child:testevent': function(){
parent1Called = true;
}
}
});
var parent2 = $$({
controller: {
'child:testevent': function(){
parent2Called = true;
}
}
});
var obj = $$();
parent1.append(parent2);
parent2.append(obj);
obj.trigger('testevent')
ok(parent1Called, "event bubbled to parent 1");
ok(parent2Called, "event bubbled to parent 2");
});

test("Model events", function(){
var t = false;
var obj = $$({}, {}, {
Expand Down

0 comments on commit 16a5df3

Please sign in to comment.