UNPKG

syringejs

Version:

An ultra-lightweight dependency injection framework for JavaScript

1,170 lines (834 loc) 70 kB
<!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">&#182;</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">&#182;</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">&#182;</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">&#182;</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">&#182;</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">&#182;</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">&#182;</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 &amp; <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">&#182;</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) &amp;&amp; <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">&#182;</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 &amp;&amp; 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">&#182;</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">&#182;</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 &lt; <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">&#182;</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">&#182;</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">&#182;</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">&#182;</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 &amp;&amp; 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">&#182;</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">&#182;</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">&#182;</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">&#182;</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">&#182;</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>) &amp;&amp; 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">&#182;</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">&#182;</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">&#182;</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">&#182;</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">&#182;</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 &amp;&amp; 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">&#182;</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">&#182;</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">&#182;</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">&#182;</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">&#182;</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 &amp;&amp; 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">&#182;</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">&#182;</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>) &amp;&amp; (<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">&#182;</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>) &amp;&amp; <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">&#182;</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>) &amp;&amp; bindings) { value = <span class="hljs-keyword">this</span>.on(bindings, value); } <span class="hljs-keyword">var</span> arr = name.split(sep), str = (arr.length &gt; <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">&#182;</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">&#182;</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">&#182;</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">&#182;</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">&#182;</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">&#182;</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">&#182;</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">&#182;</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">&#182;</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">&#182;</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 &gt; <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">&#182;</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">&#182;</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">&#182;</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">&#182;</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