syringejs
Version:
An ultra-lightweight dependency injection framework for JavaScript
1,170 lines (834 loc) • 70 kB
HTML
<!DOCTYPE html>
<html>
<head>
<title>syringe.js</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
<link rel="stylesheet" media="all" href="docco.css" />
</head>
<body>
<div id="container">
<div id="background"></div>
<ul class="sections">
<li id="title">
<div class="annotation">
<h1>syringe.js</h1>
</div>
</li>
<li id="section-1">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-1">¶</a>
</div>
<blockquote>
<p><a href="http://syringejs.org">http://syringejs.org</a>
syringe.js v0.6.5. Copyright (c) 2013-2015 M Holt
holt.org. Distributed under the MIT License</p>
</blockquote>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-comment">/* jshint forin:true, noarg:true, noempty:true, eqeqeq:true, bitwise:false, strict:true,
undef:true, unused:true, curly:true, indent:4, maxerr:50, laxcomma:true, evil: true,
laxbreak:true, multistr: true, camelcase:true, immed: true, latedef: true, nonew:true,
quotmark: true, node: true, newcap: true, browser:true */</span>
(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
<span class="hljs-pi">
'use strict'</span>;</pre></div></div>
</li>
<li id="section-2">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-2">¶</a>
</div>
<p>Globals</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span>
root = <span class="hljs-keyword">this</span>,
store = {},
hasProp = {}.hasOwnProperty,
slice = [].slice;</pre></div></div>
</li>
<li id="section-3">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-3">¶</a>
</div>
<p>Utility methods used by the API</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> utils = {</pre></div></div>
</li>
<li id="section-4">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-4">¶</a>
</div>
<p>Get an object from an (optional) context <code>ctx</code> using delimited
string notation. The <code>sep</code> parameter determines the delimiter
(a period <code>.</code> by default).</p>
</div>
<div class="content"><div class='highlight'><pre> getObj: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">str, ctx, sep</span>) </span>{
<span class="hljs-keyword">return</span> str.split((sep || <span class="hljs-string">'.'</span>)).filter(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">num</span>) </span>{
<span class="hljs-keyword">return</span> num.length;
}).reduce(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">prev, curr, index, list</span>) </span>{
<span class="hljs-keyword">if</span> (prev) {
<span class="hljs-keyword">return</span> prev[list[index]];
}
}, (ctx || <span class="hljs-keyword">this</span>));
},</pre></div></div>
</li>
<li id="section-5">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">¶</a>
</div>
<p>Create an object within an (optional) context <code>ctx</code> using
delimited string notation. The <code>sep</code> parameter determines
the delimiter (period by default). </p>
</div>
<div class="content"><div class='highlight'><pre> setObj: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">str, ctx, sep</span>) </span>{
<span class="hljs-keyword">return</span> str.split((sep || <span class="hljs-string">'.'</span>)).reduce(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">prev, curr</span>) </span>{
<span class="hljs-keyword">return</span> (prev[curr]) ? (prev[curr]) : (prev[curr]) = {};
}, (ctx || <span class="hljs-keyword">this</span>));
},</pre></div></div>
</li>
<li id="section-6">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-6">¶</a>
</div>
<p>In cases where no context is provided, we just want simple partial
application and no clobbering of the original <code>this</code> context. This
utility function allows .call() and .apply() to continue to work
properly on bound Syringe functions.</p>
</div>
<div class="content"><div class='highlight'><pre> bindArgs: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
<span class="hljs-keyword">var</span>
args = slice.call(<span class="hljs-built_in">arguments</span>),
fn = <span class="hljs-keyword">this</span>;
<span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
<span class="hljs-keyword">return</span> fn.apply(<span class="hljs-keyword">this</span>, args.concat(slice.call(<span class="hljs-built_in">arguments</span>)));
};
},</pre></div></div>
</li>
<li id="section-7">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-7">¶</a>
</div>
<p>RFC 4122 GUID generator</p>
</div>
<div class="content"><div class='highlight'><pre> makeId: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
<span class="hljs-keyword">return</span> <span class="hljs-string">'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'</span>.replace(<span class="hljs-regexp">/[xy]/g</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">b</span>) </span>{
<span class="hljs-keyword">var</span> a = <span class="hljs-number">16</span> * <span class="hljs-built_in">Math</span>.random() | <span class="hljs-number">0</span>;
<span class="hljs-keyword">return</span> (<span class="hljs-string">'x'</span> === b ? a : a & <span class="hljs-number">3</span> | <span class="hljs-number">8</span>).toString(<span class="hljs-number">16</span>);
});
},</pre></div></div>
</li>
<li id="section-8">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-8">¶</a>
</div>
<p>Get the object type as a string. If an <code>istype</code> value is passed the comparison
is against this value and returns <code>true</code> or <code>false</code>, otherwise the type itself
is returned.</p>
</div>
<div class="content"><div class='highlight'><pre> getType: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">obj, istype</span>) </span>{
<span class="hljs-keyword">var</span>
ret = <span class="hljs-string">'Undefined'</span>,
types = [<span class="hljs-string">'Window'</span>, <span class="hljs-string">'HTMLDocument'</span>, <span class="hljs-string">'Global'</span>, <span class="hljs-string">'Document'</span>];
<span class="hljs-keyword">if</span> (obj) {
ret = ({}).toString.call(obj).match(<span class="hljs-regexp">/\s([a-z|A-Z]+)/</span>)[<span class="hljs-number">1</span>];
types = types.some(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">item</span>) </span>{
<span class="hljs-keyword">return</span> item.toLowerCase() === ret.toLowerCase();
});
ret = types ? <span class="hljs-string">'Object'</span> : ret;
} <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">if</span> (obj === <span class="hljs-literal">null</span>) {
ret = <span class="hljs-string">'Null'</span>;
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (obj === <span class="hljs-literal">false</span>) {
ret = <span class="hljs-string">'Boolean'</span>;
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> obj === <span class="hljs-string">'string'</span>) {
ret = <span class="hljs-string">'String'</span>;
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (obj === <span class="hljs-number">0</span>) {
ret = <span class="hljs-string">'Number'</span>;
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">isNaN</span>(obj) && <span class="hljs-keyword">typeof</span> obj === <span class="hljs-string">'number'</span>) {
ret = <span class="hljs-string">'NaN'</span>;
}
}
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> istype === <span class="hljs-string">'string'</span>) {
<span class="hljs-keyword">return</span> (istype.toLowerCase() === ret.toLowerCase());
} <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">return</span> ret;
}
},</pre></div></div>
</li>
<li id="section-9">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">¶</a>
</div>
<p>Return an array that describes the type of items contained inside an arguments
object, or match an arguments object to an array of type names in order to
validate the payload</p>
</div>
<div class="content"><div class='highlight'><pre> matchArgs: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">args, istype</span>) </span>{
istype = istype || [];
args = [].slice.call(args);
<span class="hljs-keyword">if</span> (!istype.length) {
<span class="hljs-keyword">return</span> args.map(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">item</span>) </span>{
<span class="hljs-keyword">return</span> utils.getType(item);
});
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (istype.length === args.length) {
<span class="hljs-keyword">return</span> args.reduce(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">prev, curr, idx</span>) </span>{
<span class="hljs-keyword">if</span> (!prev && utils.getType(istype[idx], <span class="hljs-string">'string'</span>)) {
<span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
}
<span class="hljs-keyword">return</span> utils.getType(curr, istype[idx]);
}, <span class="hljs-literal">true</span>);
} <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
}
},</pre></div></div>
</li>
<li id="section-10">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-10">¶</a>
</div>
<p>Return a map of any items in the passed array that match items
in the registry object</p>
</div>
<div class="content"><div class='highlight'><pre> getReg: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">arr, id</span>) </span>{
<span class="hljs-keyword">var</span> reg = store[id].registry;
<span class="hljs-keyword">return</span> arr.map(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">item</span>) </span>{
<span class="hljs-keyword">switch</span> (item) {
<span class="hljs-keyword">case</span> <span class="hljs-string">''</span>:
<span class="hljs-keyword">return</span> <span class="hljs-literal">undefined</span>;
<span class="hljs-keyword">case</span> <span class="hljs-string">'*'</span>:
<span class="hljs-keyword">return</span> reg;
<span class="hljs-keyword">case</span> <span class="hljs-string">'this'</span>:
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
<span class="hljs-keyword">default</span>:
<span class="hljs-keyword">return</span> utils.getObj(item, reg, store[id].sep);
}
}, <span class="hljs-keyword">this</span>);
},</pre></div></div>
</li>
<li id="section-11">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-11">¶</a>
</div>
<p>Standard ajax retrieval operation</p>
</div>
<div class="content"><div class='highlight'><pre> getData: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">url, callback</span>) </span>{
<span class="hljs-keyword">var</span> xhr;
<span class="hljs-keyword">if</span> (!utils.getType(XMLHttpRequest, <span class="hljs-string">'undefined'</span>)) {
xhr = <span class="hljs-keyword">new</span> XMLHttpRequest();
} <span class="hljs-keyword">else</span> {
[
<span class="hljs-string">'MSXML2.XmlHttp.5.0'</span>,
<span class="hljs-string">'MSXML2.XmlHttp.4.0'</span>,
<span class="hljs-string">'MSXML2.XmlHttp.3.0'</span>,
<span class="hljs-string">'MSXML2.XmlHttp.2.0'</span>,
<span class="hljs-string">'Microsoft.XmlHttp'</span>
].forEach(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">item</span>) </span>{
<span class="hljs-keyword">try</span> {
xhr = <span class="hljs-keyword">new</span> <span class="hljs-built_in">window</span>.ActiveXObject(item);
<span class="hljs-keyword">return</span>;
} <span class="hljs-keyword">catch</span> (e) {
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(e);
}
});
}
xhr.onreadystatechange = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
<span class="hljs-keyword">if</span> (xhr.readyState < <span class="hljs-number">4</span>) {
<span class="hljs-keyword">return</span>;
}
<span class="hljs-keyword">if</span> (xhr.status !== <span class="hljs-number">200</span>) {
callback(<span class="hljs-literal">null</span>);
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (xhr.readyState === <span class="hljs-number">4</span>) {
callback(xhr);
}
};
xhr.open(<span class="hljs-string">'GET'</span>, url, <span class="hljs-literal">true</span>);
xhr.setRequestHeader(<span class="hljs-string">'Accept'</span>, <span class="hljs-string">'application/json, text/javascript, */*; q=0.01'</span>);
xhr.setRequestHeader(<span class="hljs-string">'Content-Type'</span>, <span class="hljs-string">'application/json; charset=utf-8'</span>);
xhr.send(<span class="hljs-string">''</span>);
},</pre></div></div>
</li>
<li id="section-12">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-12">¶</a>
</div>
<p>Returns <code>true</code> if an object contains no enumerable propeties</p>
</div>
<div class="content"><div class='highlight'><pre> isEmpty: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">obj</span>) </span>{
<span class="hljs-keyword">return</span> <span class="hljs-built_in">Object</span>.keys(obj).length ? <span class="hljs-literal">false</span> : <span class="hljs-literal">true</span>;
},</pre></div></div>
</li>
<li id="section-13">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-13">¶</a>
</div>
<p>Asynch fetch</p>
</div>
<div class="content"><div class='highlight'><pre> fetch: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">arr, props, ctx</span>) </span>{
props = props || {};
props.success = props.success || <span class="hljs-literal">false</span>;
props.xss = props.xss || <span class="hljs-literal">false</span>;
<span class="hljs-keyword">var</span>
self = <span class="hljs-keyword">this</span>,
count = <span class="hljs-number">0</span>,
url = <span class="hljs-string">''</span>;</pre></div></div>
</li>
<li id="section-14">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-14">¶</a>
</div>
<p>Test to see if a passed URL is local</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> isLocalURL = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">url</span>) </span>{
<span class="hljs-keyword">var</span> regexp = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'//'</span> + location.host + <span class="hljs-string">'($|/)'</span>);
<span class="hljs-keyword">return</span> <span class="hljs-string">'http'</span> === url.substring(<span class="hljs-number">0</span>, <span class="hljs-number">4</span>) ? regexp.test(url) : <span class="hljs-literal">true</span>;
};</pre></div></div>
</li>
<li id="section-15">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-15">¶</a>
</div>
<p>Keep a count of the script load events and reconcile it
against the length of the script list</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> stack = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">xhr</span>) </span>{
<span class="hljs-keyword">if</span> (xhr && xhr.responseText) {
<span class="hljs-keyword">var</span> data = <span class="hljs-built_in">JSON</span>.parse(xhr.responseText);
<span class="hljs-keyword">if</span> (data) {</pre></div></div>
</li>
<li id="section-16">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-16">¶</a>
</div>
<p>Handle “add” versus “set” scenarios. If the target binding path
exists then the object is extended, otherwise it is added. Note
that if the returned data is an array and the binding already
exists, the data is added to the object as a key named “json”.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (self.get(arr[count].bind)) {
<span class="hljs-keyword">if</span> (utils.getType(data, <span class="hljs-string">'array'</span>)) {
self.add(arr[count].bind + <span class="hljs-string">'.json'</span>, data);
}
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (utils.getType(data, <span class="hljs-string">'object'</span>)) {
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> key <span class="hljs-keyword">in</span> data) {
<span class="hljs-keyword">if</span> (data.hasOwnProperty(key)) {
self.add(arr[count].bind + <span class="hljs-string">'.'</span> + key, data[key]);
}
}
}
}
<span class="hljs-keyword">else</span> {
self.add(arr[count].bind, data);
}
}
}
<span class="hljs-keyword">if</span> (++count === arr.length) {
<span class="hljs-keyword">if</span> (utils.getType(props.success, <span class="hljs-string">'function'</span>)) {
props.success.apply(self, [(ctx || self), xhr]);
}
}
};
arr.forEach(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">item</span>) </span>{
<span class="hljs-keyword">if</span> (isLocalURL(url = item.path) || props.xss === <span class="hljs-literal">true</span>) {
utils.getData(item.path, stack);
}
});
},</pre></div></div>
</li>
<li id="section-17">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-17">¶</a>
</div>
<p>The <code>run</code> function resolves the dependencies of a bound method.
When it executes is retrieves the original <code>fn</code> method from the
<code>cabinet</code> object, and applies both the injected and free arguments
to it. </p>
</div>
<div class="content"><div class='highlight'><pre> run: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">arr, fn, syr</span>) </span>{
<span class="hljs-keyword">var</span>
args = slice.call(<span class="hljs-built_in">arguments</span>),
props, match, ins, res;</pre></div></div>
</li>
<li id="section-18">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-18">¶</a>
</div>
<p>Remove the id from the arguments</p>
</div>
<div class="content"><div class='highlight'><pre> args.splice(<span class="hljs-number">2</span>, <span class="hljs-number">1</span>);</pre></div></div>
</li>
<li id="section-19">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-19">¶</a>
</div>
<p>Locate the stored injection target function</p>
</div>
<div class="content"><div class='highlight'><pre> match = store[syr.id].cabinet.filter(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">item</span>) </span>{
<span class="hljs-keyword">return</span> item.fn === fn;
})[<span class="hljs-number">0</span>];
fn = match ? match.fn : fn;
props = utils.getReg
.apply(syr, [arr, syr.id])
.concat(args.slice(<span class="hljs-number">2</span>, args.length));</pre></div></div>
</li>
<li id="section-20">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-20">¶</a>
</div>
<p>Replace pointers to the global object with actual instances</p>
</div>
<div class="content"><div class='highlight'><pre> arr.forEach(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">item, idx</span>) </span>{
<span class="hljs-keyword">if</span> (utils.getType(item, <span class="hljs-string">'string'</span>) && item.indexOf(<span class="hljs-string">'global:'</span>) === <span class="hljs-number">0</span>) {
props[idx] = utils.getObj(item.slice(<span class="hljs-number">7</span>, item.length), root, <span class="hljs-string">'.'</span>);
}
});
<span class="hljs-keyword">if</span> (!utils.isEmpty(fn.prototype)) {
ins = <span class="hljs-built_in">Object</span>.create(fn.prototype);
res = fn.apply(ins, props);
<span class="hljs-keyword">return</span> (utils.getType(res, <span class="hljs-string">'object'</span>)) ? res : ins;
}</pre></div></div>
</li>
<li id="section-21">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-21">¶</a>
</div>
<p>Assume a regular function</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">return</span> fn.apply(<span class="hljs-keyword">this</span>, props);
}
},</pre></div></div>
</li>
<li id="section-22">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-22">¶</a>
</div>
<p>Execute any events associated with a type of passed action</p>
</div>
<div class="content"><div class='highlight'><pre> fire: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">type, id, arr</span>) </span>{</pre></div></div>
</li>
<li id="section-23">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-23">¶</a>
</div>
<p>Fire the events attached to this action</p>
</div>
<div class="content"><div class='highlight'><pre> store[id].events[type].forEach(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">event</span>) </span>{
<span class="hljs-keyword">if</span> (utils.getType(event.fn, <span class="hljs-string">'function'</span>)) {</pre></div></div>
</li>
<li id="section-24">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-24">¶</a>
</div>
<p>Add the event type</p>
</div>
<div class="content"><div class='highlight'><pre> arr.unshift(type);</pre></div></div>
</li>
<li id="section-25">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-25">¶</a>
</div>
<p>Match paths that terminate with a wildcard</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (event.path && event.path.split(store[id].separator).pop() === <span class="hljs-string">'*'</span>) {
<span class="hljs-keyword">var</span>
wldpath = event.path.split(store[id].separator),
arrpath = arr[<span class="hljs-number">1</span>].split(store[id].separator);
wldpath.pop();
arrpath.pop();
wldpath = wldpath.join(store[id].separator);
arrpath = arrpath.join(store[id].separator);
<span class="hljs-keyword">if</span> (arrpath === wldpath) {
event.fn.apply(<span class="hljs-keyword">this</span>, arr);
}
}
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (</pre></div></div>
</li>
<li id="section-26">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-26">¶</a>
</div>
<p>Match all types of event</p>
</div>
<div class="content"><div class='highlight'><pre> !event.path ||</pre></div></div>
</li>
<li id="section-27">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-27">¶</a>
</div>
<p>Events matching a deep path </p>
</div>
<div class="content"><div class='highlight'><pre> arr[<span class="hljs-number">1</span>] === event.path ||</pre></div></div>
</li>
<li id="section-28">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-28">¶</a>
</div>
<p>Events matching a shallow path</p>
</div>
<div class="content"><div class='highlight'><pre> arr[<span class="hljs-number">1</span>].split(store[id].separator).pop() === event.path
) {
event.fn.apply(<span class="hljs-keyword">this</span>, arr);
}</pre></div></div>
</li>
<li id="section-29">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-29">¶</a>
</div>
<p>Remove the event type</p>
</div>
<div class="content"><div class='highlight'><pre> arr.shift();
}
}, <span class="hljs-keyword">this</span>);
}
};</pre></div></div>
</li>
<li id="section-30">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-30">¶</a>
</div>
<p>Syringe base constructor</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> Syringe = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">props</span>) </span>{
store[<span class="hljs-keyword">this</span>.id = utils.makeId()] = {
cabinet : [],
registry : (props && utils.getType(props, <span class="hljs-string">'object'</span>)) ? props : {},
separator : <span class="hljs-string">'.'</span>,
events : {
add : [],
set : [],
get : [],
remove : [],
listops : [],
all : []
}
};
};</pre></div></div>
</li>
<li id="section-31">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-31">¶</a>
</div>
<p>Syringe object prototype methods</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> proto = Syringe.prototype = {</pre></div></div>
</li>
<li id="section-32">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-32">¶</a>
</div>
<p>Set the separator character used for creating, specifying, and
retrieving objects. Whitespace and alphanumeric characters are
not permitted. By default, the period ‘.’ character is used.</p>
</div>
<div class="content"><div class='highlight'><pre> separator: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">val</span>) </span>{
<span class="hljs-keyword">return</span> (utils.getType(val, <span class="hljs-string">'string'</span>) &&
(<span class="hljs-number">1</span> === val.replace(<span class="hljs-regexp">/[?a-zA-Z\d]|\s/g</span>, <span class="hljs-string">''</span>).length)) ?
(store[<span class="hljs-keyword">this</span>.id].separator = val, <span class="hljs-keyword">this</span>) : <span class="hljs-literal">false</span>;
},</pre></div></div>
</li>
<li id="section-33">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-33">¶</a>
</div>
<p>Convenience function that allows you to process array items directly
and which raises an event on completion.</p>
</div>
<div class="content"><div class='highlight'><pre> listops: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">name, fn</span>) </span>{
<span class="hljs-keyword">var</span>
reg = store[<span class="hljs-keyword">this</span>.id].registry,
sep = store[<span class="hljs-keyword">this</span>.id].separator,
arr = name.split(sep),
obj = utils.getObj(name, reg, sep),
res = <span class="hljs-literal">null</span>;
<span class="hljs-keyword">if</span> (utils.getType(obj, <span class="hljs-string">'array'</span>) && <span class="hljs-keyword">typeof</span> fn === <span class="hljs-string">'function'</span>) {
res = fn(obj);
arr = [name, obj];
<span class="hljs-keyword">if</span> (res) {
arr.push(res);
}
utils.fire(<span class="hljs-string">'listops'</span>, <span class="hljs-keyword">this</span>.id, arr);
}
<span class="hljs-keyword">else</span> {
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Key "'</span> + name + <span class="hljs-string">'" is not an array!'</span>);
}
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
},</pre></div></div>
</li>
<li id="section-34">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-34">¶</a>
</div>
<p>Add a new item to the Syringe registry. The name can be provided
in dot-notation, in which case a deep reference is built within
the registry. If <code>value</code> is a function, the optional <code>bindings</code>
parameter can contain an array of all the registry properties
with which to bind this function. In this way, registry methods
can be automatically bound to other registry methods.</p>
</div>
<div class="content"><div class='highlight'><pre> add: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">name, value, bindings</span>) </span>{
<span class="hljs-keyword">var</span>
reg = store[<span class="hljs-keyword">this</span>.id].registry,
sep = store[<span class="hljs-keyword">this</span>.id].separator;
<span class="hljs-keyword">switch</span> ((utils.getType(name))) {
<span class="hljs-keyword">case</span> <span class="hljs-string">'Array'</span>:
name.forEach(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">item</span>) </span>{
<span class="hljs-keyword">this</span>.add.apply(<span class="hljs-keyword">this</span>, [item]);
}, <span class="hljs-keyword">this</span>);
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
<span class="hljs-keyword">case</span> <span class="hljs-string">'Object'</span>:
<span class="hljs-built_in">Object</span>.keys(name).forEach(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">key</span>) </span>{
<span class="hljs-keyword">this</span>.add.apply(<span class="hljs-keyword">this</span>, [key, name[key]]);
}, <span class="hljs-keyword">this</span>);
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
<span class="hljs-keyword">if</span> (!utils.getType(name, <span class="hljs-string">'string'</span>)) {
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Name must be a string!'</span>);
}
name = name.trim();
<span class="hljs-keyword">if</span> (name.indexOf(<span class="hljs-string">'global:'</span>) === <span class="hljs-number">0</span>) {
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'You can\'t add a key with this prefix!'</span>);
}
<span class="hljs-keyword">if</span> (utils.getObj(name, reg, sep)) {
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Key "'</span> + name +
<span class="hljs-string">'" already exists in the map; use .remove() to unregister it first!'</span>);
} <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">if</span> (utils.getType(value, <span class="hljs-string">'function'</span>) && bindings) {
value = <span class="hljs-keyword">this</span>.on(bindings, value);
}
<span class="hljs-keyword">var</span>
arr = name.split(sep),
str = (arr.length > <span class="hljs-number">1</span>) ? arr.pop() : <span class="hljs-literal">false</span>;
<span class="hljs-keyword">if</span> (str) {
utils.setObj(arr.join(sep), reg, sep)[str] = value;
} <span class="hljs-keyword">else</span> {
reg[arr.toString()] = value;
}
}</pre></div></div>
</li>
<li id="section-35">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-35">¶</a>
</div>
<p>Raise an “add” event, passing the name and value</p>
</div>
<div class="content"><div class='highlight'><pre> utils.fire(<span class="hljs-string">'add'</span>, <span class="hljs-keyword">this</span>.id, [name, value]);
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
},</pre></div></div>
</li>
<li id="section-36">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-36">¶</a>
</div>
<p>Remove a named item from the registry</p>
</div>
<div class="content"><div class='highlight'><pre> remove: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">name</span>) </span>{</pre></div></div>
</li>
<li id="section-37">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-37">¶</a>
</div>
<p>Remove an array of items</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (utils.getType(name, <span class="hljs-string">'array'</span>)) {
name.forEach(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">item</span>) </span>{
<span class="hljs-keyword">if</span> (utils.getType(item, <span class="hljs-string">'string'</span>)) {
<span class="hljs-keyword">this</span>.remove(item);
}
}, <span class="hljs-keyword">this</span>);
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}</pre></div></div>
</li>
<li id="section-38">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-38">¶</a>
</div>
<p>Remove a single item</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (utils.getType(name, <span class="hljs-string">'string'</span>)) {
name = name.trim();
<span class="hljs-keyword">var</span>
reg = store[<span class="hljs-keyword">this</span>.id].registry,
sep = store[<span class="hljs-keyword">this</span>.id].separator,
snm = name.trim().split(sep),
lst = snm.pop(),
nrg = {},
obj = {};
snm = snm.join(sep);
obj = snm ? utils.getObj(snm, reg, sep) : reg;
<span class="hljs-keyword">if</span> (utils.getType(obj, <span class="hljs-string">'object'</span>)) {
name = lst || snm;
<span class="hljs-built_in">Object</span>.keys(obj).forEach(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">key</span>) </span>{
<span class="hljs-keyword">if</span> (key !== name) {
nrg[key] = obj[key];
}
});</pre></div></div>
</li>
<li id="section-39">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-39">¶</a>
</div>
<p>Deep removal (delimited name)</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (snm) {
<span class="hljs-keyword">this</span>.set(snm, nrg);
}</pre></div></div>
</li>
<li id="section-40">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-40">¶</a>
</div>
<p>Shallow removal (non-delimited name)</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">else</span> {
store[<span class="hljs-keyword">this</span>.id].registry = nrg;
}
}</pre></div></div>
</li>
<li id="section-41">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-41">¶</a>
</div>
<p>Raise a remove event, passing the name</p>
</div>
<div class="content"><div class='highlight'><pre> utils.fire(<span class="hljs-string">'remove'</span>, <span class="hljs-keyword">this</span>.id, [snm + sep + name]);
}
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
},</pre></div></div>
</li>
<li id="section-42">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-42">¶</a>
</div>
<p>Bind a method to the dependency registry. This function accepts
a variety of different arguments, the formulation of which
determine what type of binding takes place. The variations are
described below. </p>
</div>
<div class="content"><div class='highlight'><pre> on: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"> <span class="hljs-comment">/* 2, 3, or 4 params */</span> </span>) </span>{
<span class="hljs-keyword">var</span>
cab = store[<span class="hljs-keyword">this</span>.id].cabinet,
args = slice.call(<span class="hljs-built_in">arguments</span>),
ctx = root,
obj = { args: args },
gtp = utils.getType,
mtc = utils.matchArgs,
anon, anonctx, named, namedctx;</pre></div></div>
</li>
<li id="section-43">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-43">¶</a>
</div>
<p>Bind arguments only, no context - used when a context is
provided</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> bindArgsOnly = utils.bindArgs.bind(utils.run);</pre></div></div>
</li>
<li id="section-44">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-44">¶</a>
</div>
<p>Utility that adds named methods to a provided context</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> namedFuncFactory = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">name, fn, target</span>) </span>{
<span class="hljs-keyword">var</span>
sep = store[<span class="hljs-keyword">this</span>.id].separator,
arr = name.split(sep),
str = (arr.length > <span class="hljs-number">1</span>) ? arr.pop() : <span class="hljs-literal">false</span>;
target = gtp(target, <span class="hljs-string">'object'</span>) ? target : root;
<span class="hljs-keyword">if</span> (str) {
utils.setObj(arr.join(sep), target, sep)[str] = fn;
} <span class="hljs-keyword">else</span> {
target[arr.join(sep)] = fn;
}
}.bind(<span class="hljs-keyword">this</span>);</pre></div></div>
</li>
<li id="section-45">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-45">¶</a>
</div>
<p><strong>Two</strong> parameters: the registry array <code>args[0]</code> and method
<code>args[1]</code>. No name or context object is provided. The
bound function will be returned as an anonymous function.</p>
</div>
</li>
<li id="section-46">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-46">¶</a>
</div>
<p><strong>Three</strong> parameters (1): the registry array <code>args[0]</code>, the
method <code>args[1]</code>, and a context object <code>args[2]</code>.
When the bound method executes the provided context
will be used.</p>
</div>
</li>
<li id="section-47">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-47">¶</a>
</div>
<p><strong>Three</strong> parameters (2): a name <code>args[0]</code>, the registry array
<code>args[1]</code>, and method <code>args[2]</code>. No context object
is provided. The bound function will be assigned to
whatever the root object is.</p>
</div>
</li>
<li id="section-48">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-48">¶</a>
</div>
<p><strong>Four</strong> parameters: a name <code>args[0]</code>, the registry array
<code>args[1]</code>, the method <code>args[2]</code>, and a context object
<code>args[3]</code>. When the bound method executes the provided
context will be used.</p>
</div>
<div class="content"><div class='highlight'><pre>
anon = mtc(args, [<span class="hljs-string">'array'</span>, <span class="hljs-string">'function'</span>]);
anonctx = mtc(args, [<span class="hljs-string">'array'</span>, <span class="hljs-string">'function'</span>, <span class="hljs-string">'object'</span>]);
named = mtc(args, [<span class="hljs-string">'string'</span>, <span class="hljs-string">'array'</span>, <span class="hljs-string">'function'</span>]);
namedctx = mtc(args, [<span class="hlj