forked from yui/yui3-gallery
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
gallery-2011.04.27-17-14 nzakas gallery-mediator
- Loading branch information
YUI Builder
committed
Apr 27, 2011
1 parent
b61ff36
commit b1c759b
Showing
4 changed files
with
264 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
builddir=../../../builder/componentbuild | ||
component=gallery-mediator | ||
component.jsfiles=mediator.js | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project name="YUI" default="local"> | ||
<property file="build.properties" /> | ||
<import file="${builddir}/3.x/bootstrap.xml" | ||
description="Default Build Properties and Targets" /> | ||
</project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
/*global YUI*/ | ||
/* | ||
* Copyright (c) 2011 Yahoo! Inc. All rights reserved. | ||
* Author: Nicholas C. Zakas, nczonline.net | ||
*/ | ||
|
||
/** | ||
* Mediator pattern in JavaScript. For more info on Mediator pattern: | ||
* http://en.wikipedia.org/wiki/Mediator_pattern | ||
* @module gallery-mediator | ||
*/ | ||
|
||
/** | ||
* Implementation of the mediator pattern. Purposely does not | ||
* require Y.Event.Target to avoid confusion with regular | ||
* event target pattern and also to keep the code as light | ||
* and simple as possible. | ||
* @class Mediator | ||
* @static | ||
*/ | ||
Y.Mediator = function(){ | ||
/** | ||
* Array of listeners. | ||
* @type Array | ||
* @property _listeners | ||
* @private | ||
*/ | ||
this._listeners = {}; | ||
}; | ||
|
||
Y.Mediator.prototype = { | ||
|
||
//restore constructor | ||
constructor: Y.Mediator, | ||
|
||
/** | ||
* Broadcasts a message throughout the system, calling any | ||
* registered callbacks. | ||
* @param {String} name The name of the message to fire. | ||
* @param {variant} data (Optional) Any additional data. | ||
* @return {void} | ||
* @method broadcast | ||
*/ | ||
broadcast: function(name, data){ | ||
var i, len, | ||
nameListeners = this._listeners[name]; | ||
|
||
if (nameListeners){ | ||
/* | ||
* Create a clone of the array list. This handles the case where | ||
* a callback calls listen() or unlisten() and thus alters the number of | ||
* listeners. Using the clone ensures that the original listeners all | ||
* get called. | ||
*/ | ||
nameListeners = nameListeners.concat(); | ||
for (i=0, len=nameListeners.length; i < len; i++){ | ||
nameListeners[i].callback.call(nameListeners[i].scope, { | ||
type: name, | ||
data: data | ||
}); | ||
} | ||
} | ||
}, | ||
|
||
/** | ||
* Registers a listener for a particular message. | ||
* @param {String} name The name of the message to listen for. | ||
* @param {Function} callback The function to call when the message occurs. | ||
* @param {Object} scope The value for "this" inside of the callback. | ||
* @return {void} | ||
* @method listen | ||
*/ | ||
listen: function(name, callback, scope){ | ||
var listeners = this._listeners; | ||
|
||
if (!listeners[name]){ | ||
listeners[name] = []; | ||
} | ||
|
||
/* | ||
* In my experience, the #1 cause of issues with callback functions | ||
* is that someone passes in a value that they think contains a | ||
* function but actually doesn't. Then when something tries to call | ||
* that function, there's an error that's hard to track down. Throwing | ||
* an error here allows you to trap the issue at the listen() method, | ||
* which is where the wrong value is being passed in. This improves | ||
* debugging such issues dramatically. | ||
*/ | ||
if (typeof callback == "function"){ | ||
listeners[name].push({ | ||
callback: callback, | ||
scope:scope | ||
}); | ||
} else { | ||
throw new Error("Callback must be a function."); | ||
} | ||
}, | ||
|
||
/** | ||
* Unregisters a listener for a particular message. The callback function | ||
* and the scope must match the ones passed into listen() to be removed. | ||
* @param {String} name The name of the message the listener was registered for. | ||
* @param {Function} callback The function to remove. | ||
* @param {Object} scope The value for "this" inside of the callback. | ||
* @return {Boolean} True if the callback was removed, false if not. | ||
* @method listen | ||
*/ | ||
unlisten: function(name, callback, scope){ | ||
var i, len, | ||
nameListeners = this._listeners[name], | ||
removed = false; | ||
|
||
if (nameListeners){ | ||
for (i=0, len=nameListeners.length; i < len; i++){ | ||
if (nameListeners[i].callback === callback && nameListeners[i].scope === scope){ | ||
nameListeners[i].splice(i, 1); | ||
removed = true; | ||
break; | ||
} | ||
} | ||
} | ||
|
||
return removed; | ||
} | ||
|
||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
<html> | ||
<head> | ||
<title>Mediator Tests</title> | ||
<script type="text/javascript" src="http://yui.yahooapis.com/combo?3.3.0/build/yui/yui-min.js"></script> | ||
</head> | ||
<body class="yui3-skin-sam"> | ||
<h1>Mediator Tests</h1> | ||
<div id="c"></div> | ||
<script type="text/javascript"> | ||
|
||
YUI({ | ||
gallery: 'gallery-2009.12.08-22', | ||
modules: { | ||
'gallery-mediator': { | ||
fullpath: '../../../build/gallery-mediator/gallery-mediator.js', | ||
requires: [], | ||
optional: [], | ||
supersedes: [] | ||
} | ||
|
||
}, | ||
logInclude: { TestRunner: true } | ||
}).use('test', 'console', 'gallery-mediator', function (Y) { | ||
|
||
Y.namespace("Tests"); | ||
|
||
Y.Tests.Mediator = (function(){ | ||
|
||
var Assert = Y.Assert, | ||
ObjectAssert = Y.ObjectAssert; | ||
|
||
//------------------------------------------------------------------------- | ||
// Base Test Suite | ||
//------------------------------------------------------------------------- | ||
|
||
var suite = new Y.Test.Suite("Mediator Tests"); | ||
|
||
//------------------------------------------------------------------------- | ||
// Test Case for listening | ||
//------------------------------------------------------------------------- | ||
|
||
suite.add(new Y.Test.Case({ | ||
|
||
name : "Broadcast/Listen Tests", | ||
|
||
//--------------------------------------------------------------------- | ||
// Tests | ||
//--------------------------------------------------------------------- | ||
|
||
testBroadcastListen: function(){ | ||
var mediator = new Y.Mediator(), | ||
msg = "foo", | ||
handler = new Y.Mock(), | ||
data = {}; | ||
|
||
Y.Mock.expect(handler, { | ||
method: "handleMessage", | ||
args: [Y.Mock.Value(function(value){ | ||
Y.Assert.areSame(data, value.data); | ||
Y.Assert.areEqual(msg, value.type); | ||
})] | ||
}); | ||
|
||
mediator.listen(msg, handler.handleMessage, handler); | ||
|
||
mediator.broadcast(msg, data); | ||
|
||
Y.Mock.verify(handler); | ||
}, | ||
|
||
testBroadcastListenWithScope: function(){ | ||
var mediator = new Y.Mediator(), | ||
msg = "foo", | ||
handler = new Y.Mock(), | ||
data = {}; | ||
|
||
handler.handleMessage = function(value){ | ||
this.message = msg; | ||
}; | ||
|
||
Y.Mock.expect(handler, { | ||
property: "message", | ||
value: "foo" | ||
}); | ||
|
||
mediator.listen(msg, handler.handleMessage, handler); | ||
|
||
mediator.broadcast(msg, data); | ||
|
||
Y.Mock.verify(handler); | ||
} | ||
|
||
|
||
})); | ||
|
||
|
||
|
||
//return it | ||
return suite; | ||
|
||
})(); | ||
|
||
|
||
var r = new Y.Console({ | ||
verbose : true, | ||
//consoleLimit : 10, | ||
newestOnTop : false | ||
}); | ||
|
||
r.render('#c'); | ||
|
||
|
||
//add to the testrunner and run | ||
Y.Test.Runner.add(Y.Tests.Mediator); | ||
Y.Test.Runner.run(); | ||
|
||
/*if (parent && parent != window) { | ||
YAHOO.tool.TestManager.load(); | ||
} else { | ||
YAHOO.tool.TestRunner.run(); | ||
}*/ | ||
|
||
}); | ||
|
||
|
||
</script> | ||
</body> | ||
</html> |