diff --git a/frontend-masters-exercises/exercises/ex1/README.md b/frontend-masters-exercises/exercises/ex1/README.md new file mode 100755 index 0000000..1208cfc --- /dev/null +++ b/frontend-masters-exercises/exercises/ex1/README.md @@ -0,0 +1,9 @@ +# Instructions + +1. This exercise calls for you to write some async flow-control code. To start off with, you'll use callbacks only. + +2. Expected behavior: + - Request all 3 files at the same time (in "parallel"). + - Render them ASAP (don't just blindly wait for all to finish loading) + - BUT, render them in proper (obvious) order: "file1", "file2", "file3". + - After all 3 are done, output "Complete!". diff --git a/frontend-masters-exercises/exercises/ex1/ex1-fixed.html b/frontend-masters-exercises/exercises/ex1/ex1-fixed.html new file mode 100755 index 0000000..c71f974 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex1/ex1-fixed.html @@ -0,0 +1,13 @@ + + + + +Exercise 1 - Fixed + + +

Exercise 1 - Fixed

+ + + + + diff --git a/frontend-masters-exercises/exercises/ex1/ex1-fixed.js b/frontend-masters-exercises/exercises/ex1/ex1-fixed.js new file mode 100755 index 0000000..99a9065 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex1/ex1-fixed.js @@ -0,0 +1,63 @@ +function fakeAjax(url,cb) { + var fake_responses = { + "file1": "The first text", + "file2": "The middle text", + "file3": "The last text" + }; + var randomDelay = (Math.round(Math.random() * 1E4) % 8000) + 1000; + + console.log("Requesting: " + url); + + setTimeout(function(){ + cb(fake_responses[url]); + },randomDelay); +} + +function output(text) { + console.log(text); +} + +// ************************************** +// The old-n-busted callback way + +function getFile(file) { + fakeAjax(file,function(text){ + fileReceived(file,text); + }); +} + +function fileReceived(file,text) { + // haven't received this text yet? + if (!responses[file]) { + responses[file] = text; + } + + var files = ["file1","file2","file3"]; + + // loop through responses in order for rendering + for (var i=0; i + + + +Exercise 1 + + +

Exercise 1

+ + + + + diff --git a/frontend-masters-exercises/exercises/ex1/ex1.js b/frontend-masters-exercises/exercises/ex1/ex1.js new file mode 100755 index 0000000..d46e30a --- /dev/null +++ b/frontend-masters-exercises/exercises/ex1/ex1.js @@ -0,0 +1,77 @@ +function fakeAjax(url,cb) { + var fake_responses = { + "file1": "The first text", + "file2": "The middle text", + "file3": "The last text" + }; + + var randomDelay = (Math.round(Math.random() * 1E4) % 8000) + 1000; + + console.log("Requesting: " + url); + + setTimeout(function(){ + cb(fake_responses[url]); + },randomDelay); +} + +function output(text) { + console.log(text); +} + +// ************************************** +// The old-n-busted callback way +let first = null +let secondStatus = 0 +let second = null +letthirdStatus = 0 +let third = null + +function getFile(file) { + fakeAjax(file,function(text){ + // what do we do here? + if(file === "file1") { + first = "done" + output(text) + if(secondStatus === 1) { + output(second) + second = "done" + } + if(second === "done" && thirdStatus === 1) { + output(third) + } + } + + if(first !== "done" && file === "file2") { + secondStatus = 1 + second = text + } + + if(first === "done" && file === "file2") { + second = "done" + output(text) + if(thirdStatus === 1) { + output(third) + } + } + + if(second !== "done" && file === "file3") { + thirdStatus = 1 + third = text + } + + if(second === "done" && file === "file3" ) { + third = "done" + output(text) + } + + + }); +} + +// request all files at once in "parallel" +console.log("FILE 1") +getFile("file1"); +console.log("FILE 2") +getFile("file2"); +console.log("FILE 3") +getFile("file3"); diff --git a/frontend-masters-exercises/exercises/ex10/README.md b/frontend-masters-exercises/exercises/ex10/README.md new file mode 100755 index 0000000..c208d37 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex10/README.md @@ -0,0 +1,13 @@ +# Instructions + +1. In this exercise, we're going to practice what we've learned about various async patterns so far, using the challenging "A Tale Of Three Lists" demos. + +2. Study the similarities/differences of the `ui.js` and `feeds.js` files on the repo (https://github.com/getify/a-tale-of-three-lists#compared-patterns), between these versions: "Plain Callbacks", "Thunks", "Promises", and "Promises+Generators". + + Then look at the version of the `ui.js` and `feeds.js` files as included in this exercise, which correspond to the "asynquence Flavored" demo version on the repo. + +3. Pick either reactive sequences or CSP -- whichever you feel most comfortable with or want most practice with -- and modify the `ui.js` and `feeds.js` files to use the appropriate concepts. For reactive sequences, you'll be creating sequences for each type of event and subscribing to them. For CSP, you'll be creating channels for the same. + + If you have time and want a real challenge, try both versions! + +4. Compare your approach to the "Reactive Sequences" and/or "CSP" demo versions on the repo (https://github.com/getify/a-tale-of-three-lists#compared-patterns). diff --git a/frontend-masters-exercises/exercises/ex10/asq.bundle.js b/frontend-masters-exercises/exercises/ex10/asq.bundle.js new file mode 100755 index 0000000..93c9ada --- /dev/null +++ b/frontend-masters-exercises/exercises/ex10/asq.bundle.js @@ -0,0 +1,2333 @@ +/*! asynquence + v0.8.2 (c) Kyle Simpson + MIT License: http://getify.mit-license.org +*/ +!function UMD(e,n,t){"function"==typeof define&&define.amd?define(t):"undefined"!=typeof module&&module.exports?module.exports=t():n[e]=t(e,n)}("ASQ",this,function DEF(e,n){"use strict";function Queue(){function Item(e){this.fn=e,this.next=void 0}var e,n,r;return{add:function $$add(t){r=new Item(t),n?n.next=r:e=r,n=r,r=void 0},drain:function $$drain(){var r=e;for(e=n=t=null;r;)r.fn(),r=r.next}}}function schedule(e){r.add(e),t||(t=u(r.drain))}function tapSequence(e){function trigger(){e.seq=createSequence.apply(h,arguments).defer()}trigger.fail=function $$trigger$fail(){var n=f.call(arguments);e.seq=createSequence(function $$create$sequence(e){e.fail.apply(h,n)}).defer()},e.seq.val(function $$val(){return trigger.apply(h,arguments),c.apply(h,arguments)}).or(function $$or(){trigger.fail.apply(h,arguments)}),e.seq=createSequence(function $$create$sequence(e){trigger=e}).defer()}function createSequence(){function scheduleSequenceTick(){r?sequenceTick():e||(e=schedule(sequenceTick))}function throwSequenceErrors(){throw 1===$.length?$[0]:$}function sequenceTick(){var a,c;if(e=null,delete d.unpause,r)clearTimeout(e),e=null,s.length=p.length=g.length=$.length=0;else if(n)for(0!==p.length||t||(t=!0,throwSequenceErrors());p.length;){t=!0,a=p.shift();try{a.apply(h,$)}catch(i){l(i)?$=$.concat(i):($.push(i),i.stack&&$.push(i.stack)),0===p.length&&throwSequenceErrors()}}else if(u&&s.length>0){u=!1,a=s.shift(),c=g.slice(),g.length=0,c.unshift(createStepCompletion());try{a.apply(h,c)}catch(i){l(i)?$=$.concat(i):$.push(i),n=!0,scheduleSequenceTick()}}}function createStepCompletion(){function done(){n||r||u||(u=!0,g.push.apply(g,arguments),$.length=0,scheduleSequenceTick())}return done.fail=function $$step$fail(){n||r||u||(n=!0,g.length=0,$.push.apply($,arguments),scheduleSequenceTick())},done.abort=function $$step$abort(){n||r||(u=!1,r=!0,g.length=$.length=0,scheduleSequenceTick())},done.errfcb=function $$step$errfcb(e){e?done.fail(e):done.apply(h,f.call(arguments,1))},done}function createGate(e,t,u){function resetGate(){clearTimeout(s),s=d=m=o=null}function scheduleGateTick(){return g?gateTick():void(s||(s=schedule(gateTick)))}function gateTick(){if(!(n||r||$)){var t=[];s=null,p?(e.fail.apply(h,o),resetGate()):g?(e.abort(),resetGate()):checkGate()&&($=!0,d.forEach(function $$each(e,n){t.push(m["s"+n])}),e.apply(h,t),resetGate())}}function checkGate(){if(0!==d.length){var e=!0;return d.some(function $$some(n){return null===n?(e=!1,!0):void 0}),e}}function createSegmentCompletion(){function done(){if(!(n||r||p||g||$||d[e])){var t=c.apply(h,arguments);m["s"+e]=t.length>1?t:t[0],d[e]=!0,scheduleGateTick()}}var e=d.length;return done.fail=function $$segment$fail(){n||r||p||g||$||d[e]||(p=!0,o=f.call(arguments),scheduleGateTick())},done.abort=function $$segment$abort(){n||r||p||g||$||(g=!0,gateTick())},done.errfcb=function $$segment$errfcb(e){e?done.fail(e):done.apply(h,f.call(arguments,1))},d[e]=null,done}var a,i,o,s,p=!1,g=!1,$=!1,d=[],m={};t.some(function $$some(e){if(p||g)return!0;a=u.slice(),a.unshift(createSegmentCompletion());try{e.apply(h,a)}catch(n){return i=n,p=!0,!0}}),i&&(l(i)?e.fail.apply(h,i):e.fail(i))}function then(){return n||r||0===arguments.length?d:(wrapArgs(arguments,thenWrapper).forEach(function $$each(e){i(e)?seq(e):s.push(e)}),scheduleSequenceTick(),d)}function or(){return r||0===arguments.length?d:(p.push.apply(p,arguments),scheduleSequenceTick(),d)}function gate(){if(n||r||0===arguments.length)return d;var e=f.call(arguments).map(function $$map(e){var n;return i(e)?(n={seq:e},tapSequence(n),function $$segment(e){n.seq.pipe(e)}):e});return then(function $$then(n){var t=f.call(arguments,1);createGate(n,e,t)}),d}function pipe(){return r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){then(function $$then(n){e.apply(h,f.call(arguments,1)),n()}).or(e.fail)}),d)}function seq(){return n||r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){var n={seq:e};i(e)&&tapSequence(n),then(function $$then(e){var t=n.seq;i(t)||(t=n.seq.apply(h,f.call(arguments,1))),t.pipe(e)})}),d)}function val(){return n||r||0===arguments.length?d:(f.call(wrapArgs(arguments,valWrapper)).forEach(function $$each(e){then(function $$then(n){var t=e.apply(h,f.call(arguments,1));l(t)||(t=c(t)),n.apply(h,t)})}),d)}function promise(){function wrap(e){return function $$fn(){e.apply(h,l(arguments[0])?arguments[0]:arguments)}}return n||r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){then(function $$then(n){var t=e;"function"==typeof e&&"function"!=typeof e.then&&(t=e.apply(h,f.call(arguments,1))),t.then(wrap(n),wrap(n.fail))})}),d)}function fork(){var e;return val(function $$val(){return e?e.apply(h,arguments):e=createSequence.apply(h,arguments).defer(),c.apply(h,arguments)}),or(function $$or(){if(e)e.fail.apply(h,arguments);else{var n=f.call(arguments);e=createSequence().then(function $$then(e){e.fail.apply(h,n)}).defer()}}),createSequence().then(function $$then(n){e?e.pipe(n):e=n}).defer()}function abort(){return n?d:(r=!0,sequenceTick(),d)}function duplicate(){var e;return a={then_queue:s.slice(),or_queue:p.slice()},e=createSequence(),a=null,e}function unpause(){g.push.apply(g,arguments),e===!0&&(e=null),scheduleSequenceTick()}function defer(){return p.push(function ignored(){}),d}function internals(e,t){var a=arguments.length>1;switch(e){case"seq_error":if(!a)return n;n=t;break;case"seq_aborted":if(!a)return r;r=t;break;case"then_ready":if(!a)return u;u=t;break;case"then_queue":return s;case"or_queue":return p;case"sequence_messages":return g;case"sequence_errors":return $}}function includeExtensions(){Object.keys(o).forEach(function $$each(e){d[e]=o[e](d,internals)})}var e,n=!1,t=!1,r=!1,u=!0,s=[],p=[],g=[],$=[],d=brandIt({then:then,or:or,onerror:or,gate:gate,all:gate,pipe:pipe,seq:seq,val:val,promise:promise,fork:fork,abort:abort,duplicate:duplicate,defer:defer});return includeExtensions(),a&&(s=a.then_queue.slice(),p=a.or_queue.slice(),d.unpause=unpause,e=!0),d.then.apply(h,arguments),d}function brandIt(e){return Object.defineProperty(e,p,{enumerable:!1,value:!0})}function checkBranding(e){return!(null==e||"object"!=typeof e||!e[p])}function valWrapper(e){return c.apply(h,f.call(arguments).slice(1,e+1))}function thenWrapper(e){arguments[e+1].apply(h,f.call(arguments).slice(1,e+1))}function wrapArgs(e,n){var t,r;for(e=f.call(e),t=0;t 1 ? + ARRAY_SLICE.call(arguments,1) : + void 0 + ; + num = +num || 0; + + api.then(function $$then(done){ + var args = orig_args || ARRAY_SLICE.call(arguments,1); + + setTimeout(function $$set$timeout(){ + done.apply(ø,args); + },num); + }); + + return api; + }; +}); + +ASQ.after = function $$after() { + return ASQ().after.apply(ø,arguments); +}; +// "any" +ASQ.extend("any",function $$extend(api,internals){ + return function $$any() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + function reset() { + finished = true; + error_messages.length = 0; + success_messages.length = 0; + } + + function complete(trigger) { + if (success_messages.length > 0) { + // any successful segment's message(s) sent + // to main sequence to proceed as success + success_messages.length = fns.length; + trigger.apply(ø,success_messages); + } + else { + // send errors into main sequence + error_messages.length = fns.length; + trigger.fail.apply(ø,error_messages); + } + + reset(); + } + + function success(trigger,idx,args) { + if (!finished) { + completed++; + success_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + + // all segments complete? + if (completed === fns.length) { + finished = true; + + complete(trigger); + } + } + } + + function failure(trigger,idx,args) { + if (!finished && + !(idx in error_messages) + ) { + completed++; + error_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + } + + // all segments complete? + if (!finished && + completed === fns.length + ) { + finished = true; + + complete(trigger); + } + } + + var completed = 0, error_messages = [], finished = false, + success_messages = [], + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)) + ; + + wrapGate(sq,fns,success,failure,reset); + + sq.pipe(done); + }); + + return api; + }; +}); +// "errfcb" +ASQ.extend("errfcb",function $$extend(api,internals){ + return function $$errfcb() { + // create a fake sequence to extract the callbacks + var sq = { + val: function $$then(cb){ sq.val_cb = cb; return sq; }, + or: function $$or(cb){ sq.or_cb = cb; return sq; } + }; + + // trick `seq(..)`s checks for a sequence + sq[brand] = true; + + // immediately register our fake sequence on the + // main sequence + api.seq(sq); + + // provide the "error-first" callback + return function $$errorfirst$callback(err) { + if (err) { + sq.or_cb(err); + } + else { + sq.val_cb.apply(ø,ARRAY_SLICE.call(arguments,1)); + } + }; + }; +}); +// "failAfter" +ASQ.extend("failAfter",function $$extend(api,internals){ + return function $$failAfter(num) { + var args = arguments.length > 1 ? + ARRAY_SLICE.call(arguments,1) : + void 0 + ; + num = +num || 0; + + api.then(function $$then(done){ + setTimeout(function $$set$timeout(){ + done.fail.apply(ø,args); + },num); + }); + + return api; + }; +}); + +ASQ.failAfter = function $$fail$after() { + return ASQ().failAfter.apply(ø,arguments); +}; +// "first" +ASQ.extend("first",function $$extend(api,internals){ + return function $$first() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + function reset() { + error_messages.length = 0; + } + + function success(trigger,idx,args) { + if (!finished) { + finished = true; + + // first successful segment triggers + // main sequence to proceed as success + trigger( + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ); + + reset(); + } + } + + function failure(trigger,idx,args) { + if (!finished && + !(idx in error_messages) + ) { + completed++; + error_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + + // all segments complete without success? + if (completed === fns.length) { + finished = true; + + // send errors into main sequence + error_messages.length = fns.length; + trigger.fail.apply(ø,error_messages); + + reset(); + } + } + } + + var completed = 0, error_messages = [], finished = false, + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)) + ; + + wrapGate(sq,fns,success,failure,reset); + + sq.pipe(done); + }); + + return api; + }; +}); +// "go-style CSP" +(function IIFE(){ + + // filter out already-resolved queue entries + function filterResolved(queue) { + return queue.filter(function $$filter(entry){ + return !entry.resolved; + }); + } + + function closeQueue(queue,finalValue) { + queue.forEach(function $$each(iter){ + if (!iter.resolved) { + iter.next(); + iter.next(finalValue); + } + }); + queue.length = 0; + } + + function channel(bufSize) { + var ch = { + close: function $$close(){ + ch.closed = true; + closeQueue(ch.put_queue,false); + closeQueue(ch.take_queue,ASQ.csp.CLOSED); + }, + closed: false, + messages: [], + put_queue: [], + take_queue: [], + buffer_size: +bufSize || 0 + }; + return ch; + } + + function unblock(iter) { + if (iter && !iter.resolved) { + iter.next(iter.next().value); + } + } + + function put(channel,value) { + var ret; + + if (channel.closed) { + return false; + } + + // remove already-resolved entries + channel.put_queue = filterResolved(channel.put_queue); + channel.take_queue = filterResolved(channel.take_queue); + + // immediate put? + if (channel.messages.length < channel.buffer_size) { + channel.messages.push(value); + unblock(channel.take_queue.shift()); + return true; + } + // queued put + else { + channel.put_queue.push( + // make a notifiable iterable for 'put' blocking + ASQ.iterable() + .then(function $$then(){ + if (!channel.closed) { + channel.messages.push(value); + return true; + } + else { + return false; + } + }) + ); + + // wrap a sequence/promise around the iterable + ret = ASQ( + channel.put_queue[channel.put_queue.length - 1] + ); + + // take waiting on this queued put? + if (channel.take_queue.length > 0) { + unblock(channel.put_queue.shift()); + unblock(channel.take_queue.shift()); + } + + return ret; + } + } + + function putAsync(channel,value,cb) { + var ret = ASQ(put(channel,value)); + + if (cb && typeof cb == "function") { + ret.val(cb); + } + else { + return ret; + } + } + + function take(channel) { + var ret; + + try { + ret = takem(channel); + } + catch (err) { + ret = err; + } + + if (ASQ.isSequence(ret)) { + ret.pCatch(function $$pcatch(err){ + return err; + }); + } + + return ret; + } + + function takeAsync(channel,cb) { + var ret = ASQ(take(channel)); + + if (cb && typeof cb == "function") { + ret.val(cb); + } + else { + return ret; + } + } + + function takem(channel) { + var msg; + + if (channel.closed) { + return ASQ.csp.CLOSED; + } + + // remove already-resolved entries + channel.put_queue = filterResolved(channel.put_queue); + channel.take_queue = filterResolved(channel.take_queue); + + // immediate take? + if (channel.messages.length > 0) { + msg = channel.messages.shift(); + unblock(channel.put_queue.shift()); + if (msg instanceof Error) { + throw msg; + } + return msg; + } + // queued take + else { + channel.take_queue.push( + // make a notifiable iterable for 'take' blocking + ASQ.iterable() + .then(function $$then(){ + if (!channel.closed) { + var v = channel.messages.shift(); + if (v instanceof Error) { + throw v; + } + return v; + } + else { + return ASQ.csp.CLOSED; + } + }) + ); + + // wrap a sequence/promise around the iterable + msg = ASQ( + channel.take_queue[channel.take_queue.length - 1] + ); + + // put waiting on this take? + if (channel.put_queue.length > 0) { + unblock(channel.put_queue.shift()); + unblock(channel.take_queue.shift()); + } + + return msg; + } + } + + function takemAsync(channel,cb) { + var ret = ASQ(takem(channel)); + + if (cb && typeof cb == "function") { + ret.pThen(cb,cb); + } + else { + return ret.val(function $$val(v){ + if (v instanceof Error) { + throw v; + } + return v; + }); + } + } + + function alts(actions) { + var closed, open, handlers, i, isq, ret, resolved = false; + + // used `alts(..)` incorrectly? + if (!Array.isArray(actions) || actions.length == 0) { + throw Error("Invalid usage"); + } + + closed = []; + open = []; + handlers = []; + + // separate actions by open/closed channel status + actions.forEach(function $$each(action){ + var channel = Array.isArray(action) ? action[0] : action; + + // remove already-resolved entries + channel.put_queue = filterResolved(channel.put_queue); + channel.take_queue = filterResolved(channel.take_queue); + + if (channel.closed) { + closed.push(channel); + } + else { + open.push(action); + } + }); + + // if no channels are still open, we're done + if (open.length == 0) { + return { value: ASQ.csp.CLOSED, channel: closed }; + } + + // can any channel action be executed immediately? + for (i=0; i 0) { + return { value: take(open[i]), channel: open[i] }; + } + } + + isq = ASQ.iterable(); + var ret = ASQ(isq); + + // setup channel action handlers + for (i=0; i 0) { + schedule(function handleUnblocking(){ + if (!resolved) { + unblock(channel.put_queue.shift()); + unblock(channel.take_queue.shift()); + } + },0); + } + } + // take action? + else { + channel = action; + + // define take handler + handlers.push( + ASQ.iterable() + .then(function $$then(){ + resolved = true; + + // mark all handlers across this `alts(..)` as resolved now + handlers = handlers.filter(function $$filter(handler){ + return !(handler.resolved = true); + }); + + // channel still open? + if (!channel.closed) { + isq.next({ value: channel.messages.shift(), channel: channel }); + } + // channel already closed? + else { + isq.next({ value: ASQ.csp.CLOSED, channel: channel }); + } + }) + ); + + // queue up take handler + channel.take_queue.push(handlers[handlers.length-1]); + + // put waiting on this queued take? + if (channel.put_queue.length > 0) { + schedule(function handleUnblocking(){ + if (!resolved) { + unblock(channel.put_queue.shift()); + unblock(channel.take_queue.shift()); + } + }); + } + } + })(open[i]); + } + + return ret; + } + + function altsAsync(chans,cb) { + var ret = ASQ(alts(chans)); + + if (cb && typeof cb == "function") { + ret.pThen(cb,cb); + } + else { + return ret; + } + } + + function timeout(delay) { + var ch = channel(); + setTimeout(ch.close,delay); + return ch; + } + + function go(gen,args) { + // goroutine arguments passed? + if (arguments.length > 1) { + if (!args || !Array.isArray(args)) { + args = [args]; + } + } + else { + args = []; + } + + return function *$$go(token) { + + // unblock the overall goroutine handling + function unblock() { + token.unblock_count++; + + if (token.block && !token.block.marked) { + token.block.marked = true; + token.block.next(); + } + } + + var ret, msg, err, type, done = false, it; + + // keep track of how many requests for unblocking + // have occurred + token.unblock_count = (token.unblock_count || 0); + + // keep track of how many goroutines are running + // so we can infer when we're done go'ing + token.go_count = (token.go_count || 0) + 1; + + // need to initialize a set of goroutines? + if (token.go_count === 1) { + // create a default channel for these goroutines + token.channel = channel(); + token.channel.messages = token.messages; + token.channel.go = function $$go(){ + // unblock the goroutine handling for this + // new goroutine + unblock(); + // add the goroutine (called with any args) to + // the handling queue + token.add( go.apply(ø,arguments) ); + }; + // starting out with initial channel messages? + if (token.channel.messages.length > 0) { + // fake back-pressure blocking for each + token.channel.put_queue = token.channel.messages.map(function $$map(){ + // make a notifiable iterable for 'put' blocking + return ASQ.iterable() + .then(function $$then(){ + unblock(token.channel.take_queue.shift()); + return !token.channel.closed; + }); + }); + } + } + + // initialize the generator + it = gen.apply(ø,[token.channel].concat(args)); + + (function iterate(){ + + function next() { + // keep going with next step in goroutine? + if (!done) { + iterate(); + } + // unblock overall goroutine handling to + // continue with other goroutines + else { + unblock(); + } + } + + // has a resumption value been achieved yet? + if (!ret) { + // try to resume the goroutine + try { + // resume with injected exception? + if (err) { + ret = it.throw(err); + err = null; + } + // resume normally + else { + ret = it.next(msg); + } + } + // resumption failed, so bail + catch (e) { + done = true; + err = e; + msg = null; + unblock(); + return; + } + + // keep track of the result of the resumption + done = ret.done; + ret = ret.value; + type = typeof ret; + + // if this goroutine is complete, unblock the + // overall goroutine handling + if (done) { + unblock(); + } + + // received a thenable/promise back? + if (isPromise(ret)) { + ret = ASQ().promise(ret); + } + + // wait for the value? + if (ASQ.isSequence(ret)) { + ret.val(function $$val(){ + ret = null; + msg = arguments.length > 1 ? + ASQ.messages.apply(ø,arguments) : + arguments[0] + ; + next(); + }) + .or(function $$or(){ + ret = null; + msg = arguments.length > 1 ? + ASQ.messages.apply(ø,arguments) : + arguments[0] + ; + if (msg instanceof Error) { + err = msg; + msg = null; + } + next(); + }); + } + // immediate value, prepare it to go right back in + else { + msg = ret; + ret = null; + next(); + } + } + })(); + + // keep this goroutine alive until completion + while (!done) { + // transfer control to another goroutine + yield token; + + // need to block overall goroutine handling + // while idle? + if (!done && !token.block && token.unblock_count === 0) { + // wait here while idle + yield (token.block = ASQ.iterable()); + + token.block = false; + } + + if (token.unblock_count > 0) token.unblock_count--; + } + + // this goroutine is done now + token.go_count--; + + // all goroutines done? + if (token.go_count === 0) { + // any lingering blocking need to be cleaned up? + unblock(); + + // capture any untaken messages + msg = ASQ.messages.apply(ø,token.messages); + + // need to implicitly force-close channel? + if (token.channel && !token.channel.closed) { + token.channel.closed = true; + token.channel.put_queue.length = token.channel.take_queue.length = 0; + token.channel.close = token.channel.go = token.channel.messages = null; + } + token.channel = null; + } + + // make sure leftover error or message are + // passed along + if (err) { + throw err; + } + else if (token.go_count === 0) { + return msg; + } + else { + return token; + } + }; + } + + ASQ.csp = { + chan: channel, + put: put, + putAsync: putAsync, + take: take, + takeAsync: takeAsync, + takem: takem, + takemAsync: takemAsync, + alts: alts, + altsAsync: altsAsync, + timeout: timeout, + go: go, + CLOSED: {} + }; + +})(); +// "ASQ.iterable()" +(function IIFE(){ + var template; + + ASQ.iterable = function $$iterable() { + function throwSequenceErrors() { + throw (sequence_errors.length === 1 ? sequence_errors[0] : sequence_errors); + } + + function notifyErrors() { + var fn; + + seq_tick = null; + + if (seq_error) { + if (or_queue.length === 0 && !error_reported) { + error_reported = true; + throwSequenceErrors(); + } + + while (or_queue.length > 0) { + error_reported = true; + fn = or_queue.shift(); + try { + fn.apply(ø,sequence_errors); + } + catch (err) { + if (checkBranding(err)) { + sequence_errors = sequence_errors.concat(err); + } + else { + sequence_errors.push(err); + } + if (or_queue.length === 0) { + throwSequenceErrors(); + } + } + } + } + } + + function val() { + if (seq_error || seq_aborted || arguments.length === 0) { + return sequence_api; + } + + var args = ARRAY_SLICE.call(arguments).map(function mapper(arg){ + if (typeof arg != "function") return function $$val() { return arg; }; + else return arg; + }); + + val_queue.push.apply(val_queue,args); + + return sequence_api; + } + + function or() { + if (seq_aborted || arguments.length === 0) { + return sequence_api; + } + + or_queue.push.apply(or_queue,arguments); + + if (!seq_tick) { + seq_tick = schedule(notifyErrors); + } + + return sequence_api; + } + + function pipe() { + if (seq_aborted || arguments.length === 0) { + return sequence_api; + } + + ARRAY_SLICE.call(arguments) + .forEach(function $$each(fn){ + val(fn).or(fn.fail); + }); + + return sequence_api; + } + + function next() { + if (seq_error || seq_aborted || val_queue.length === 0) { + if (val_queue.length > 0) { + $throw$("Sequence cannot be iterated"); + } + return { done: true }; + } + + try { + return { value: val_queue.shift().apply(ø,arguments) }; + } + catch (err) { + if (ASQ.isMessageWrapper(err)) { + $throw$.apply(ø,err); + } + else { + $throw$(err); + } + + return {}; + } + } + + function $throw$() { + if (seq_error || seq_aborted) { + return sequence_api; + } + + sequence_errors.push.apply(sequence_errors,arguments); + seq_error = true; + if (!seq_tick) { + seq_tick = schedule(notifyErrors); + } + + return sequence_api; + } + + function $return$(val) { + if (seq_error || seq_aborted) { + val = void 0; + } + + abort(); + + return { done: true, value: val }; + } + + function abort() { + if (seq_error || seq_aborted) { + return; + } + + seq_aborted = true; + + clearTimeout(seq_tick); + seq_tick = null; + val_queue.length = or_queue.length = sequence_errors.length = 0; + } + + function duplicate() { + var isq; + + template = { + val_queue: val_queue.slice(), + or_queue: or_queue.slice() + }; + isq = ASQ.iterable(); + template = null; + + return isq; + } + + // opt-out of global error reporting for this sequence + function defer() { + or_queue.push(function $$ignored(){}); + return sequence_api; + } + + // *********************************************** + // Object branding utilities + // *********************************************** + function brandIt(obj) { + Object.defineProperty(obj,brand,{ + enumerable: false, + value: true + }); + + return obj; + } + + var sequence_api, + + seq_error = false, + error_reported = false, + seq_aborted = false, + + seq_tick, + + val_queue = [], + or_queue = [], + + sequence_errors = [] + ; + + // *********************************************** + // Setup the ASQ.iterable() public API + // *********************************************** + sequence_api = brandIt({ + val: val, + then: val, + or: or, + pipe: pipe, + next: next, + "throw": $throw$, + "return": $return$, + abort: abort, + duplicate: duplicate, + defer: defer + }); + + // useful for ES6 `for..of` loops, + // add `@@iterator` to simply hand back + // our iterable sequence itself! + sequence_api[(typeof Symbol == "function" && Symbol.iterator) || "@@iterator"] = function $$iter() { + return sequence_api; + }; + + // templating the iterable-sequence setup? + if (template) { + val_queue = template.val_queue.slice(0); + or_queue = template.or_queue.slice(0); + } + + // treat ASQ.iterable() constructor parameters as having been + // passed to `val()` + sequence_api.val.apply(ø,arguments); + + return sequence_api; + }; + +})(); +// "last" +ASQ.extend("last",function $$extend(api,internals){ + return function $$last() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + function reset() { + finished = true; + error_messages.length = 0; + success_messages = null; + } + + function complete(trigger) { + if (success_messages != null) { + // last successful segment's message(s) sent + // to main sequence to proceed as success + trigger( + success_messages.length > 1 ? + ASQ.messages.apply(ø,success_messages) : + success_messages[0] + ); + } + else { + // send errors into main sequence + error_messages.length = fns.length; + trigger.fail.apply(ø,error_messages); + } + + reset(); + } + + function success(trigger,idx,args) { + if (!finished) { + completed++; + success_messages = args; + + // all segments complete? + if (completed === fns.length) { + finished = true; + + complete(trigger); + } + } + } + + function failure(trigger,idx,args) { + if (!finished && + !(idx in error_messages) + ) { + completed++; + error_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + } + + // all segments complete? + if (!finished && + completed === fns.length + ) { + finished = true; + + complete(trigger); + } + } + + var completed = 0, error_messages = [], finished = false, + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)), + success_messages + ; + + wrapGate(sq,fns,success,failure,reset); + + sq.pipe(done); + }); + + return api; + }; +}); +// "map" +ASQ.extend("map",function $$extend(api,internals){ + return function $$map(pArr,pEach) { + if (internals("seq_error") || internals("seq_aborted")) { + return api; + } + + api.seq(function $$seq(){ + var tmp, args = ARRAY_SLICE.call(arguments), + arr = pArr, each = pEach; + + // if missing `map(..)` args, use value-messages (if any) + if (!each) each = args.shift(); + if (!arr) arr = args.shift(); + + // if arg types in reverse order (each,arr), swap + if (typeof arr === "function" && Array.isArray(each)) { + tmp = arr; + arr = each; + each = tmp; + } + + return ASQ.apply(ø,args) + .gate.apply(ø,arr.map(function $$map(item){ + return function $$segment(){ + each.apply(ø,[item].concat(ARRAY_SLICE.call(arguments))); + }; + })); + }) + .val(function $$val(){ + // collect all gate segment output into one value-message + // Note: return a normal array here, not a message wrapper! + return ARRAY_SLICE.call(arguments); + }); + + return api; + }; +}); +// "none" +ASQ.extend("none",function $$extend(api,internals){ + return function $$none() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + function reset() { + finished = true; + error_messages.length = 0; + success_messages.length = 0; + } + + function complete(trigger) { + if (success_messages.length > 0) { + // any successful segment's message(s) sent + // to main sequence to proceed as **error** + success_messages.length = fns.length; + trigger.fail.apply(ø,success_messages); + } + else { + // send errors as **success** to main sequence + error_messages.length = fns.length; + trigger.apply(ø,error_messages); + } + + reset(); + } + + function success(trigger,idx,args) { + if (!finished) { + completed++; + success_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + + // all segments complete? + if (completed === fns.length) { + finished = true; + + complete(trigger); + } + } + } + + function failure(trigger,idx,args) { + if (!finished && + !(idx in error_messages) + ) { + completed++; + error_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + } + + // all segments complete? + if (!finished && + completed === fns.length + ) { + finished = true; + + complete(trigger); + } + } + + var completed = 0, error_messages = [], finished = false, + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)), + success_messages = [] + ; + + wrapGate(sq,fns,success,failure,reset); + + sq.pipe(done); + }); + + return api; + }; +}); +// "pThen" +ASQ.extend("pThen",function $$extend(api,internals){ + return function $$pthen(success,failure) { + if (internals("seq_aborted")) { + return api; + } + + var ignore_success_handler = false, ignore_failure_handler = false; + + if (typeof success === "function") { + api.then(function $$then(done){ + if (!ignore_success_handler) { + var ret, msgs = ASQ.messages.apply(ø,arguments); + msgs.shift(); + + if (msgs.length === 1) { + msgs = msgs[0]; + } + + ignore_failure_handler = true; + + try { + ret = success(msgs); + } + catch (err) { + if (!ASQ.isMessageWrapper(err)) { + err = [err]; + } + done.fail.apply(ø,err); + return; + } + + // returned a sequence? + if (ASQ.isSequence(ret)) { + ret.pipe(done); + } + // returned a message wrapper? + else if (ASQ.isMessageWrapper(ret)) { + done.apply(ø,ret); + } + // returned a promise/thenable? + else if (isPromise(ret)) { + ret.then(done,done.fail); + } + // just a normal value to pass along + else { + done(ret); + } + } + else { + done.apply(ø,ARRAY_SLICE.call(arguments,1)); + } + }); + } + if (typeof failure === "function") { + api.or(function $$or(){ + if (!ignore_failure_handler) { + var ret, msgs = ASQ.messages.apply(ø,arguments), smgs, + or_queue = ARRAY_SLICE.call(internals("or_queue")) + ; + + if (msgs.length === 1) { + msgs = msgs[0]; + } + + ignore_success_handler = true; + + // NOTE: if this call throws, that'll automatically + // be handled by core as we'd want it to be + ret = failure(msgs); + + // if we get this far: + // first, inject return value (if any) as + // next step's sequence messages + smgs = internals("sequence_messages"); + smgs.length = 0; + if (typeof ret !== "undefined") { + if (!ASQ.isMessageWrapper(ret)) { + ret = [ret]; + } + smgs.push.apply(smgs,ret); + } + + // reset internal error state, because we've exclusively + // handled any errors up to this point of the sequence + internals("sequence_errors").length = 0; + internals("seq_error",false); + internals("then_ready",true); + + // temporarily empty the or-queue + internals("or_queue").length = 0; + + // make sure to schedule success-procession on the chain + api.val(function $$val(){ + // pass thru messages + return ASQ.messages.apply(ø,arguments); + }); + + // at next cycle, reinstate the or-queue (if any) + if (or_queue.length > 0) { + schedule(function $$schedule(){ + api.or.apply(ø,or_queue); + }); + } + } + }); + } + return api; + }; +}); + +// "pCatch" +ASQ.extend("pCatch",function $$extend(api,internals){ + return function $$pcatch(failure) { + if (internals("seq_aborted")) { + return api; + } + + api.pThen(void 0,failure); + + return api; + }; +}); +// "race" +ASQ.extend("race",function $$extend(api,internals){ + return function $$race() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments) + .map(function $$map(v){ + var def; + // tap any directly-provided sequences immediately + if (ASQ.isSequence(v)) { + def = { seq: v }; + tapSequence(def); + return function $$fn(done) { + def.seq.pipe(done); + }; + } + else return v; + }); + + api.then(function $$then(done){ + var args = ARRAY_SLICE.call(arguments); + + fns.forEach(function $$each(fn){ + fn.apply(ø,args); + }); + }); + + return api; + }; +}); +// "react" (reactive sequences) +ASQ.react = function $$react(reactor) { + function next() { + if (!paused) { + if (template) { + var sq = template.duplicate(); + sq.unpause.apply(ø,arguments); + return sq; + } + return ASQ(function $$asq(){ throw "Disabled Sequence"; }); + } + } + + function registerTeardown(fn) { + if (template && typeof fn === "function") { + teardowns.push(fn); + } + } + + var template = ASQ().duplicate(), + teardowns = [], paused = false + ; + + // add reactive sequence kill switch + template.stop = function $$stop() { + if (template) { + template = null; + teardowns.forEach(Function.call,Function.call); + teardowns.length = 0; + } + }; + + template.pause = function $$pause() { + if (!paused && template) { + paused = true; + teardowns.forEach(Function.call,Function.call); + teardowns.length = 0; + } + }; + + template.resume = function $$resume() { + if (paused && template) { + paused = false; + reactor.call(template,next,registerTeardown); + } + }; + + template.push = next; + + next.onStream = function $$onStream() { + ARRAY_SLICE.call(arguments) + .forEach(function $$each(stream){ + stream.on("data",next); + stream.on("error",next); + }); + }; + + next.unStream = function $$unStream() { + ARRAY_SLICE.call(arguments) + .forEach(function $$each(stream){ + stream.removeListener("data",next); + stream.removeListener("error",next); + }); + }; + + // make sure `reactor(..)` is called async + ASQ.__schedule(function $$schedule(){ + reactor.call(template,next,registerTeardown); + }); + + return template; +}; +// "react" helpers +(function IIFE(){ + + var Ar = ASQ.react; + + Ar.of = function $$react$of() { + function reactor(next) { + if (!started) { + started = true; + if (args.length > 0) { + args.shift().val(function val(){ + next.apply(ø,arguments); + if (args.length > 0) { + args.shift().val(val); + } + }); + } + } + } + + var started, args = ARRAY_SLICE.call(arguments) + .map(function wrapper(arg){ + if (!ASQ.isSequence(arg)) arg = ASQ(arg); + return arg; + }); + + return Ar(reactor); + }; + + Ar.all = Ar.zip = makeReactOperator(/*buffer=*/true); + Ar.allLatest = makeReactOperator(/*buffer=false*/); + Ar.latest = Ar.combineLatest = makeReactOperator(/*buffer=*/false,/*keep=*/true); + + Ar.any = Ar.merge = function $$react$any(){ + function reactor(next,registerTeardown){ + function processSequence(def){ + function trigger(){ + var args = ASQ.messages.apply(ø,arguments); + // still observing sequence-streams? + if (seqs && seqs.length > 0) { + // fire off reactive sequence instance + next.apply(ø,args); + } + // keep sequence going + return args; + } + + // sequence-stream event listener + def.seq.val(trigger); + } + + // observe all sequence-streams + seqs.forEach(processSequence); + + // listen for stop() of reactive sequence + registerTeardown(function $$teardown(){ + seqs = null; + }); + } + + // observe all sequence-streams + var seqs = tapSequences.apply(null,arguments); + + if (seqs.length == 0) return; + + return Ar(reactor); + }; + + Ar.distinct = function $$react$distinct(seq){ + return Ar.filter(seq,makeDistinctFilterer(/*keepAll=*/true)); + }; + + Ar.distinctConsecutive = Ar.distinctUntilChanged = function $$react$distinct$consecutive(seq) { + return Ar.filter(seq,makeDistinctFilterer(/*keepAll=*/false)); + }; + + Ar.filter = function $$react$filter(seq,filterer){ + function reactor(next,registerTeardown) { + function trigger(){ + var messages = ASQ.messages.apply(ø,arguments); + + if (filterer && filterer.apply(ø,messages)) { + // fire off reactive sequence instance + next.apply(ø,messages); + } + + // keep sequence going + return messages; + } + + // sequence-stream event listener + def.seq.val(trigger); + + // listen for stop() of reactive sequence + registerTeardown(function $$teardown(){ + def = filterer = null; + }); + } + + // observe sequence-stream + var def = tapSequences(seq)[0]; + + if (!def) return; + + return Ar(reactor); + }; + + Ar.fromObservable = function $$react$from$observable(obsv){ + function reactor(next,registerTeardown){ + // process buffer (if any) + buffer.forEach(next); + buffer.length = 0; + + // start non-buffered notifications? + if (!buffer.complete) { + notify = next; + } + + registerTeardown(function $$teardown(){ + obsv.dispose(); + }); + } + + function notify(v) { + buffer.push(v); + } + + var buffer = []; + + obsv.subscribe( + function $$on$next(v){ + notify(v); + }, + function $$on$error(){}, + function $$on$complete(){ + buffer.complete = true; + obsv.dispose(); + } + ); + + return Ar(reactor); + }; + + ASQ.extend("toObservable",function $$extend(api,internals){ + return function $$to$observable(){ + function init(observer) { + function define(pair){ + function listen(){ + var args = ASQ.messages.apply(ø,arguments); + observer[pair[1]].apply(observer, + args.length == 1 ? [args[0]] : args + ); + return args; + } + + api[pair[0]](listen); + } + + [["val","onNext"],["or","onError"]] + .forEach(define); + } + + return Rx.Observable.create(init); + }; + }); + + function tapSequences() { + function tapSequence(seq) { + // temporary `trigger` which, if called before being replaced + // below, creates replacement proxy sequence with the + // event message(s) re-fired + function trigger() { + var args = ARRAY_SLICE.call(arguments); + def.seq = Ar(function $$react(next){ + next.apply(ø,args); + }); + } + + if (ASQ.isSequence(seq)) { + var def = { seq: seq }; + + // listen for events from the sequence-stream + seq.val(function $$val(){ + trigger.apply(ø,arguments); + return ASQ.messages.apply(ø,arguments); + }); + + // make a reactive sequence to act as a proxy to the original + // sequence + def.seq = Ar(function $$react(next){ + // replace the temporary trigger (created above) + // with this proxy's trigger + trigger = next; + }); + + return def; + } + } + + return ARRAY_SLICE.call(arguments) + .map(tapSequence) + .filter(Boolean); + } + + function makeReactOperator(buffer,keep) { + return function $$react$operator(){ + function reactor(next,registerTeardown){ + function processSequence(def) { + // sequence-stream event listener + function trigger() { + var args = ASQ.messages.apply(ø,arguments); + // still observing sequence-streams? + if (seqs && seqs.length > 0) { + // store event message(s), if any + seq_events[seq_id] = + (buffer ? seq_events[seq_id] : []).concat( + args.length > 0 ? (args.length > 1 ? [args] : args[0]) : undefined + ); + + // collect event message(s) across the + // sequence-stream sources + var messages = seq_events.reduce(function reducer(msgs,eventList,idx){ + if (eventList.length > 0) msgs.push(eventList[0]); + return msgs; + },[]); + + // did all sequence-streams get an event? + if (messages.length == seq_events.length) { + if (messages.length == 1) messages = messages[0]; + + // fire off reactive sequence instance + next.apply(ø,messages); + + // discard stored event message(s)? + if (!keep) { + seq_events.forEach(function $$each(eventList){ + eventList.shift(); + }); + } + } + } + // keep sequence going + return args; + } + + var seq_id = seq_events.length; + seq_events.push([]); + def.seq.val(trigger); + } + + // process all sequence-streams + seqs.forEach(processSequence); + + // listen for stop() of reactive sequence + registerTeardown(function $$teardown(){ + seqs = seq_events = null; + }); + } + + var seq_events = [], + // observe all sequence-streams + seqs = tapSequences.apply(null,arguments) + ; + + if (seqs.length == 0) return; + + return Ar(reactor); + }; + } + + function makeDistinctFilterer(keepAll) { + function filterer() { + function isDuplicate(msgSet) { + return ( + msgSet.length == message_set.length && + msgSet.every(function $$every(val,idx){ + return val === message_set[idx]; + }) + ); + } + + var message_set = ASQ.messages.apply(ø,arguments); + + // any messages in message-set to check against? + if (message_set.length > 0) { + // duplicate message-set? + if (msg_sets.some(isDuplicate)) { + return false; + } + + // remember all message-sets for future distinct checking? + if (keepAll) { + msg_sets.push(message_set); + } + // only keep the last message-set for distinct-consecutive + // checking + else { + msg_sets[0] = message_set; + } + } + + // allow distinct non-duplicate value through + return true; + } + + var msg_sets = []; + + return filterer; + } + +})(); +// "runner" +ASQ.extend("runner",function $$extend(api,internals){ + + return function $$runner() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var args = ARRAY_SLICE.call(arguments); + + api + .then(function $$then(mainDone){ + + function wrap(v) { + // function? expected to produce an iterator + // (like a generator) or a promise + if (typeof v === "function") { + // call function passing in the control token + // note: neutralize `this` in call to prevent + // unexpected behavior + v = v.call(ø,token); + + // promise returned (ie, from async function)? + if (isPromise(v)) { + // wrap it in iterable sequence + v = ASQ.iterable(v); + } + } + // an iterable sequence? duplicate it (in case of multiple runs) + else if (ASQ.isSequence(v) && "next" in v) { + v = v.duplicate(); + } + // wrap anything else in iterable sequence + else { + v = ASQ.iterable(v); + } + + // a sequence to tap for errors? + if (ASQ.isSequence(v)) { + // listen for any sequence failures + v.or(function $$or(){ + // signal iteration-error + mainDone.fail.apply(ø,arguments); + }); + } + + return v; + } + + function addWrapped() { + iterators.push.apply( + iterators, + ARRAY_SLICE.call(arguments).map(wrap) + ); + } + + function iterateOrQuit(iterFn,now) { + // still have some co-routine runs to process? + if (iterators.length > 0) { + if (now) iterFn(); + else schedule(iterFn); + } + // all done! + else { + // previous value message? + if (typeof next_val !== "undefined") { + // not a message wrapper array? + if (!ASQ.isMessageWrapper(next_val)) { + // wrap value for the subsequent `apply(..)` + next_val = [next_val]; + } + } + else { + // nothing to affirmatively pass along + next_val = []; + } + + // signal done with all co-routine runs + mainDone.apply(ø,next_val); + } + } + + var iterators = args, + token = { + messages: ARRAY_SLICE.call(arguments,1), + add: addWrapped + }, + iter, ret, next_val = token + ; + + // map co-routines to round-robin list of iterators + iterators = iterators.map(wrap); + + // async iteration of round-robin list + (function iterate(){ + // get next co-routine in list + iter = iterators.shift(); + + // process the iteration + try { + // multiple messages to send to an iterable + // sequence? + if (ASQ.isMessageWrapper(next_val) && + ASQ.isSequence(iter) + ) { + ret = iter.next.apply(iter,next_val); + } + else { + ret = iter.next(next_val); + } + } + catch (err) { + return mainDone.fail(err); + } + + // bail on run in aborted sequence + if (internals("seq_aborted")) return; + + // was the control token yielded? + if (ret.value === token) { + // round-robin: put co-routine back into the list + // at the end where it was so it can be processed + // again on next loop-iteration + if (!ret.done) { + iterators.push(iter); + } + next_val = token; + iterateOrQuit(iterate,/*now=*/false); + } + else { + // not a recognized ASQ instance returned? + if (!ASQ.isSequence(ret.value)) { + // received a thenable/promise back? + if (isPromise(ret.value)) { + // wrap in a sequence + ret.value = ASQ().promise(ret.value); + } + // thunk yielded? + else if (typeof ret.value === "function") { + // wrap thunk call in a sequence + var fn = ret.value; + ret.value = ASQ(function $$ASQ(done){ + fn(done.errfcb); + }); + } + // message wrapper returned? + else if (ASQ.isMessageWrapper(ret.value)) { + // wrap message(s) in a sequence + ret.value = ASQ.apply(ø, + // don't let `apply(..)` discard an empty message + // wrapper! instead, pass it along as its own value + // itself. + ret.value.length > 0 ? ret.value : ASQ.messages(undefined) + ); + } + // non-undefined value returned? + else if (typeof ret.value !== "undefined") { + // wrap the value in a sequence + ret.value = ASQ(ret.value); + } + else { + // make an empty sequence + ret.value = ASQ(); + } + } + + ret.value + .val(function $$val(){ + // bail on run in aborted sequence + if (internals("seq_aborted")) return; + + if (arguments.length > 0) { + // save any return messages for input + // to next iteration + next_val = arguments.length > 1 ? + ASQ.messages.apply(ø,arguments) : + arguments[0] + ; + } + + // still more to iterate? + if (!ret.done) { + // was the control token passed along? + if (next_val === token) { + // round-robin: put co-routine back into the list + // at the end, so that the the next iterator can be + // processed on next loop-iteration + iterators.push(iter); + } + else { + // put co-routine back in where it just + // was so it can be processed again on + // next loop-iteration + iterators.unshift(iter); + } + } + + iterateOrQuit(iterate,/*now=*/true); + }) + .or(function $$or(){ + // bail on run in aborted sequence + if (internals("seq_aborted")) return; + + try { + // if an error occurs in the step-continuation + // promise or sequence, throw it back into the + // generator or iterable-sequence + iter["throw"].apply(iter,arguments); + } + catch (err) { + // if an error comes back out of after the throw, + // pass it out to the main sequence, as iteration + // must now be complete + mainDone.fail(err); + } + }); + } + })(); + }); + + return api; + }; +}); +// "toPromise" +ASQ.extend("toPromise",function $$extend(api,internals){ + return function $$to$promise() { + return new Promise(function $$executor(resolve,reject){ + api + .val(function $$val(){ + var args = ARRAY_SLICE.call(arguments); + resolve.call(ø,args.length > 1 ? args : args[0]); + return ASQ.messages.apply(ø,args); + }) + .or(function $$or(){ + var args = ARRAY_SLICE.call(arguments); + reject.call(ø,args.length > 1 ? args : args[0]); + }); + }); + }; +}); +// "try" +ASQ.extend("try",function $$extend(api,internals){ + return function $$try() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments) + .map(function $$map(fn){ + return function $$then(mainDone) { + var main_args = ARRAY_SLICE.call(arguments), + sq = ASQ.apply(ø,main_args.slice(1)) + ; + + sq + .then(function $$inner$then(){ + fn.apply(ø,arguments); + }) + .val(function $$val(){ + mainDone.apply(ø,arguments); + }) + .or(function $$inner$or(){ + var msgs = ASQ.messages.apply(ø,arguments); + // failed, so map error(s) as `catch` + mainDone({ + "catch": msgs.length > 1 ? msgs : msgs[0] + }); + }); + }; + }); + + api.then.apply(ø,fns); + + return api; + }; +}); +// "until" +ASQ.extend("until",function $$extend(api,internals){ + return function $$until() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments) + .map(function $$map(fn){ + return function $$then(mainDone) { + var main_args = ARRAY_SLICE.call(arguments), + sq = ASQ.apply(ø,main_args.slice(1)) + ; + + sq + .then(function $$inner$then(){ + var args = ARRAY_SLICE.call(arguments); + args[0]["break"] = function $$break(){ + mainDone.fail.apply(ø,arguments); + sq.abort(); + }; + + fn.apply(ø,args); + }) + .val(function $$val(){ + mainDone.apply(ø,arguments); + }) + .or(function $$inner$or(){ + // failed, retry + $$then.apply(ø,main_args); + }); + }; + }); + + api.then.apply(ø,fns); + + return api; + }; +}); +// "waterfall" +ASQ.extend("waterfall",function $$extend(api,internals){ + return function $$waterfall() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + var msgs = ASQ.messages(), + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)) + ; + + fns.forEach(function $$each(fn){ + sq.then(fn) + .val(function $$val(){ + var args = ASQ.messages.apply(ø,arguments); + msgs.push(args.length > 1 ? args : args[0]); + return msgs; + }); + }); + + sq.pipe(done); + }); + + return api; + }; +}); +// "wrap" +ASQ.wrap = function $$wrap(fn,opts) { + function checkThis(t,o) { + return (!t || + (typeof window != "undefined" && t === window) || + (typeof global != "undefined" && t === global) + ) ? o : t; + } + + function paramSpread(gen) { + return function *paramSpread(token) { + yield *gen.apply(this,token.messages); + }; + } + + var errfcb, params_first, act, this_obj; + + opts = (opts && typeof opts == "object") ? opts : {}; + + if ( + (opts.errfcb && opts.splitcb) || + (opts.errfcb && opts.simplecb) || + (opts.splitcb && opts.simplecb) || + ("errfcb" in opts && !opts.errfcb && !opts.splitcb && !opts.simplecb) || + (opts.params_first && opts.params_last) || + (opts.spread && !opts.gen) + ) { + throw Error("Invalid options"); + } + + // initialize default flags + this_obj = (opts["this"] && typeof opts["this"] == "object") ? opts["this"] : ø; + errfcb = opts.errfcb || !(opts.splitcb || opts.simplecb); + params_first = !!opts.params_first || + (!opts.params_last && !("params_first" in opts || opts.params_first)) || + ("params_last" in opts && !opts.params_first && !opts.params_last) + ; + + if (params_first) { + act = "push"; + } + else { + act = "unshift"; + } + + if (opts.gen) { + if (opts.spread) { + fn = paramSpread(fn); + } + return function $$wrapped$gen() { + return ASQ.apply(ø,arguments).runner(fn); + }; + } + if (errfcb) { + return function $$wrapped$errfcb() { + var args = ARRAY_SLICE.call(arguments), + _this = checkThis(this,this_obj) + ; + + return ASQ(function $$asq(done){ + args[act](done.errfcb); + fn.apply(_this,args); + }); + }; + } + if (opts.splitcb) { + return function $$wrapped$splitcb() { + var args = ARRAY_SLICE.call(arguments), + _this = checkThis(this,this_obj) + ; + + return ASQ(function $$asq(done){ + args[act](done,done.fail); + fn.apply(_this,args); + }); + }; + } + if (opts.simplecb) { + return function $$wrapped$simplecb() { + var args = ARRAY_SLICE.call(arguments), + _this = checkThis(this,this_obj) + ; + + return ASQ(function $$asq(done){ + args[act](done); + fn.apply(_this,args); + }); + }; + } +}; + + + // just return `ASQ` itself for convenience sake + return ASQ; +}); diff --git a/frontend-masters-exercises/exercises/ex10/dummy-data.js b/frontend-masters-exercises/exercises/ex10/dummy-data.js new file mode 100755 index 0000000..31c2a85 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex10/dummy-data.js @@ -0,0 +1,16 @@ +var ItemsText = (function(){ + + var words = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent vulputate consectetur sem sed efficitur. Nulla ac egestas velit. Cras elementum orci vel sodales dapibus. Etiam tempus ac mi eu elementum. Proin nibh lorem, luctus eget dolor eget, sollicitudin pharetra velit. Quisque scelerisque libero ut elit consectetur, vel placerat diam finibus. Vestibulum vitae velit eget orci mattis bibendum id sed nibh. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam bibendum nibh at nisi ullamcorper euismod. Phasellus sed varius metus. Nullam pretium ex id augue ultricies condimentum. Nunc nisl arcu, placerat quis condimentum in, consequat vel lectus. Pellentesque ullamcorper sed enim quis congue. Pellentesque et elit in dui fermentum tempor. Praesent enim quam, viverra sed ipsum non, iaculis aliquet libero. Maecenas quis egestas sem. Sed sit amet malesuada turpis. Nam tempor velit at nisi lacinia, at vestibulum dolor bibendum. Sed venenatis in eros quis blandit. Maecenas nec aliquet ex, at accumsan quam. Vestibulum semper, libero ac rhoncus facilisis, augue diam interdum ex, in eleifend turpis lorem euismod sem. Vivamus sit amet ipsum et nunc dignissim tincidunt vel eget risus. Sed et nunc tempus, cursus ante eget, egestas quam. Integer turpis nulla, rutrum a nunc non, maximus malesuada massa. Suspendisse vel egestas felis. Donec vehicula neque augue, sit amet mattis nulla pellentesque eu. Vestibulum gravida malesuada rhoncus. Curabitur rhoncus diam nunc, non dignissim risus ultrices at. Cras id ligula mattis, scelerisque diam nec, sagittis nibh. Quisque malesuada ipsum at magna molestie, ac ultricies ante consectetur. Vivamus turpis neque, faucibus et molestie vulputate, dictum at diam. Ut et massa vitae neque ultricies rutrum. Donec aliquet elementum tincidunt. In viverra sem ante, vel imperdiet nisi facilisis non. Nunc interdum, urna at tempor semper, sapien justo feugiat nisl, condimentum finibus metus nibh in diam. Aliquam erat volutpat. Maecenas ut felis euismod, vehicula augue ut, aliquet lorem. Suspendisse iaculis, magna nec ullamcorper rhoncus, sapien ex pellentesque odio, ut interdum ante sapien eu erat. Donec quam orci, aliquet eu varius in, tincidunt eu est. Proin vitae est a lectus congue laoreet. Vestibulum id sodales mauris. Vestibulum eu lacus a felis tempus fringilla eu et nunc. Curabitur et imperdiet enim. Vivamus sollicitudin efficitur risus hendrerit euismod. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nam sed auctor velit, sit amet facilisis nunc. Donec vestibulum convallis neque sed eleifend. Cras dapibus quis sem id sodales. Maecenas metus massa, facilisis quis scelerisque vel, commodo molestie enim. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Maecenas pulvinar ultrices nulla, vel convallis ex laoreet vel. Sed ornare dui eget ante luctus, mollis vehicula neque pulvinar. Nulla posuere, quam quis dapibus rutrum, arcu massa laoreet metus, at condimentum felis justo a est. Nullam pharetra est nunc, a accumsan metus pellentesque ut. Duis auctor justo sit amet tincidunt iaculis. Pellentesque sollicitudin mauris ut ligula suscipit sagittis. Nullam scelerisque tortor sed sem egestas, non auctor nulla fermentum. Aliquam ut nunc condimentum, pellentesque quam feugiat, lacinia elit. Fusce maximus nulla id justo efficitur, congue imperdiet purus feugiat. Pellentesque egestas ultrices tempus. Vestibulum interdum accumsan nulla quis ornare. Duis cursus vel ipsum nec mattis. Donec quam eros, convallis condimentum iaculis a, egestas id tellus. Nullam imperdiet velit sed purus porta, vitae vulputate elit vulputate. Vivamus in maximus libero. Etiam condimentum hendrerit bibendum. Morbi id urna eu erat placerat iaculis. Donec a vehicula purus, a tempus lacus. Mauris quis auctor metus. Maecenas id venenatis libero, nec faucibus est. Sed auctor scelerisque augue, vel efficitur sem sollicitudin quis. Aliquam non justo eu diam convallis posuere. Quisque consequat porta nulla. Nunc lacinia, eros pulvinar dictum mattis, justo lorem finibus nibh, non pellentesque justo metus vitae ligula. Interdum et malesuada fames ac ante ipsum primis in faucibus. Phasellus ac interdum lorem, in elementum mi. Suspendisse auctor ex eget efficitur porta. Nam mollis lectus a ipsum gravida, eget hendrerit metus blandit. Suspendisse potenti. Quisque aliquet augue ut facilisis porttitor. Ut dui felis, interdum vitae lectus sit amet, consequat accumsan felis. Etiam malesuada ipsum vitae lacinia condimentum. Aliquam ac turpis eu risus tincidunt molestie. Sed ac leo libero. Quisque rutrum lacus sit amet augue eleifend sollicitudin. Nulla facilisi. Praesent egestas tortor et nibh rutrum accumsan. Suspendisse potenti. Proin vehicula massa id pretium aliquet. Nunc sed euismod justo, a ullamcorper odio. In ullamcorper diam ut leo pellentesque, at sollicitudin dolor suscipit. Interdum et malesuada fames ac ante ipsum primis in faucibus. Proin felis leo, mollis ut eros ut, dapibus imperdiet diam. Donec iaculis placerat ante, ac commodo nibh luctus id. Suspendisse iaculis feugiat massa quis vehicula. Mauris consequat finibus posuere. Aenean non turpis et quam luctus mattis a id enim. Ut ullamcorper, felis et ultricies lobortis, velit tellus mattis justo, a malesuada odio turpis at nisl. In sed augue maximus, bibendum tellus nec, maximus sapien. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut sem lorem, rhoncus a congue a, tempor nec metus. Suspendisse potenti. Curabitur ultrices pretium odio, et sollicitudin mauris vehicula in. Aenean sed semper neque, vitae lobortis lectus. In id interdum velit. Duis tempus purus diam, vitae tincidunt lacus commodo egestas. Morbi vestibulum, magna eget sollicitudin efficitur, ex libero consectetur odio, sollicitudin tincidunt mauris ante ac velit. Mauris a augue lacus. In bibendum, dui a pellentesque sagittis, tortor risus dignissim enim, eu tristique velit odio sit amet ex. Cras eros leo, convallis sit amet posuere vel, lacinia at enim. Maecenas nec feugiat ipsum. Nunc pellentesque tortor vitae mauris dictum imperdiet. Phasellus porttitor lectus vel neque sollicitudin, nec commodo leo faucibus. Aliquam dignissim ut est in vulputate. Donec ultrices, ex ac molestie porta, ligula sem efficitur velit, at pretium nisl tellus vel nisi. Sed volutpat nisi sed risus vulputate efficitur. Praesent venenatis nisl quis diam condimentum aliquet. Vestibulum et turpis tincidunt, pharetra urna id, egestas diam. Aliquam vitae gravida enim, eu scelerisque dolor. Nunc placerat vitae nisi eget commodo. In tincidunt viverra pellentesque. Duis a lacinia felis. Sed pharetra nibh eget diam finibus, a euismod ipsum placerat."; + + return { + more: function() { + var start = Math.trunc( Math.random() * 1E9 ) % + (words.length - 200); + var text = words.substr(start).match( + /(?:^|(?:\.\s+))((?:[A-Z][^\.]+\.(?:\s+|$)){3})/ + ); + return text ? text[0].replace(/^\.\s+/,"") : next(); + } + }; + +})(); diff --git a/frontend-masters-exercises/exercises/ex10/eventemitter2.js b/frontend-masters-exercises/exercises/ex10/eventemitter2.js new file mode 100755 index 0000000..bde69e8 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex10/eventemitter2.js @@ -0,0 +1,573 @@ +/*! + * EventEmitter2 + * https://github.com/hij1nx/EventEmitter2 + * + * Copyright (c) 2013 hij1nx + * Licensed under the MIT license. + */ +;!function(undefined) { + + var isArray = Array.isArray ? Array.isArray : function _isArray(obj) { + return Object.prototype.toString.call(obj) === "[object Array]"; + }; + var defaultMaxListeners = 10; + + function init() { + this._events = {}; + if (this._conf) { + configure.call(this, this._conf); + } + } + + function configure(conf) { + if (conf) { + + this._conf = conf; + + conf.delimiter && (this.delimiter = conf.delimiter); + conf.maxListeners && (this._events.maxListeners = conf.maxListeners); + conf.wildcard && (this.wildcard = conf.wildcard); + conf.newListener && (this.newListener = conf.newListener); + + if (this.wildcard) { + this.listenerTree = {}; + } + } + } + + function EventEmitter(conf) { + this._events = {}; + this.newListener = false; + configure.call(this, conf); + } + + // + // Attention, function return type now is array, always ! + // It has zero elements if no any matches found and one or more + // elements (leafs) if there are matches + // + function searchListenerTree(handlers, type, tree, i) { + if (!tree) { + return []; + } + var listeners=[], leaf, len, branch, xTree, xxTree, isolatedBranch, endReached, + typeLength = type.length, currentType = type[i], nextType = type[i+1]; + if (i === typeLength && tree._listeners) { + // + // If at the end of the event(s) list and the tree has listeners + // invoke those listeners. + // + if (typeof tree._listeners === 'function') { + handlers && handlers.push(tree._listeners); + return [tree]; + } else { + for (leaf = 0, len = tree._listeners.length; leaf < len; leaf++) { + handlers && handlers.push(tree._listeners[leaf]); + } + return [tree]; + } + } + + if ((currentType === '*' || currentType === '**') || tree[currentType]) { + // + // If the event emitted is '*' at this part + // or there is a concrete match at this patch + // + if (currentType === '*') { + for (branch in tree) { + if (branch !== '_listeners' && tree.hasOwnProperty(branch)) { + listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i+1)); + } + } + return listeners; + } else if(currentType === '**') { + endReached = (i+1 === typeLength || (i+2 === typeLength && nextType === '*')); + if(endReached && tree._listeners) { + // The next element has a _listeners, add it to the handlers. + listeners = listeners.concat(searchListenerTree(handlers, type, tree, typeLength)); + } + + for (branch in tree) { + if (branch !== '_listeners' && tree.hasOwnProperty(branch)) { + if(branch === '*' || branch === '**') { + if(tree[branch]._listeners && !endReached) { + listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], typeLength)); + } + listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i)); + } else if(branch === nextType) { + listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i+2)); + } else { + // No match on this one, shift into the tree but not in the type array. + listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i)); + } + } + } + return listeners; + } + + listeners = listeners.concat(searchListenerTree(handlers, type, tree[currentType], i+1)); + } + + xTree = tree['*']; + if (xTree) { + // + // If the listener tree will allow any match for this part, + // then recursively explore all branches of the tree + // + searchListenerTree(handlers, type, xTree, i+1); + } + + xxTree = tree['**']; + if(xxTree) { + if(i < typeLength) { + if(xxTree._listeners) { + // If we have a listener on a '**', it will catch all, so add its handler. + searchListenerTree(handlers, type, xxTree, typeLength); + } + + // Build arrays of matching next branches and others. + for(branch in xxTree) { + if(branch !== '_listeners' && xxTree.hasOwnProperty(branch)) { + if(branch === nextType) { + // We know the next element will match, so jump twice. + searchListenerTree(handlers, type, xxTree[branch], i+2); + } else if(branch === currentType) { + // Current node matches, move into the tree. + searchListenerTree(handlers, type, xxTree[branch], i+1); + } else { + isolatedBranch = {}; + isolatedBranch[branch] = xxTree[branch]; + searchListenerTree(handlers, type, { '**': isolatedBranch }, i+1); + } + } + } + } else if(xxTree._listeners) { + // We have reached the end and still on a '**' + searchListenerTree(handlers, type, xxTree, typeLength); + } else if(xxTree['*'] && xxTree['*']._listeners) { + searchListenerTree(handlers, type, xxTree['*'], typeLength); + } + } + + return listeners; + } + + function growListenerTree(type, listener) { + + type = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); + + // + // Looks for two consecutive '**', if so, don't add the event at all. + // + for(var i = 0, len = type.length; i+1 < len; i++) { + if(type[i] === '**' && type[i+1] === '**') { + return; + } + } + + var tree = this.listenerTree; + var name = type.shift(); + + while (name) { + + if (!tree[name]) { + tree[name] = {}; + } + + tree = tree[name]; + + if (type.length === 0) { + + if (!tree._listeners) { + tree._listeners = listener; + } + else if(typeof tree._listeners === 'function') { + tree._listeners = [tree._listeners, listener]; + } + else if (isArray(tree._listeners)) { + + tree._listeners.push(listener); + + if (!tree._listeners.warned) { + + var m = defaultMaxListeners; + + if (typeof this._events.maxListeners !== 'undefined') { + m = this._events.maxListeners; + } + + if (m > 0 && tree._listeners.length > m) { + + tree._listeners.warned = true; + console.error('(node) warning: possible EventEmitter memory ' + + 'leak detected. %d listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.', + tree._listeners.length); + console.trace(); + } + } + } + return true; + } + name = type.shift(); + } + return true; + } + + // By default EventEmitters will print a warning if more than + // 10 listeners are added to it. This is a useful default which + // helps finding memory leaks. + // + // Obviously not all Emitters should be limited to 10. This function allows + // that to be increased. Set to zero for unlimited. + + EventEmitter.prototype.delimiter = '.'; + + EventEmitter.prototype.setMaxListeners = function(n) { + this._events || init.call(this); + this._events.maxListeners = n; + if (!this._conf) this._conf = {}; + this._conf.maxListeners = n; + }; + + EventEmitter.prototype.event = ''; + + EventEmitter.prototype.once = function(event, fn) { + this.many(event, 1, fn); + return this; + }; + + EventEmitter.prototype.many = function(event, ttl, fn) { + var self = this; + + if (typeof fn !== 'function') { + throw new Error('many only accepts instances of Function'); + } + + function listener() { + if (--ttl === 0) { + self.off(event, listener); + } + fn.apply(this, arguments); + } + + listener._origin = fn; + + this.on(event, listener); + + return self; + }; + + EventEmitter.prototype.emit = function() { + + this._events || init.call(this); + + var type = arguments[0]; + + if (type === 'newListener' && !this.newListener) { + if (!this._events.newListener) { return false; } + } + + // Loop through the *_all* functions and invoke them. + if (this._all) { + var l = arguments.length; + var args = new Array(l - 1); + for (var i = 1; i < l; i++) args[i - 1] = arguments[i]; + for (i = 0, l = this._all.length; i < l; i++) { + this.event = type; + this._all[i].apply(this, args); + } + } + + // If there is no 'error' event listener then throw. + if (type === 'error') { + + if (!this._all && + !this._events.error && + !(this.wildcard && this.listenerTree.error)) { + + if (arguments[1] instanceof Error) { + throw arguments[1]; // Unhandled 'error' event + } else { + throw new Error("Uncaught, unspecified 'error' event."); + } + return false; + } + } + + var handler; + + if(this.wildcard) { + handler = []; + var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); + searchListenerTree.call(this, handler, ns, this.listenerTree, 0); + } + else { + handler = this._events[type]; + } + + if (typeof handler === 'function') { + this.event = type; + if (arguments.length === 1) { + handler.call(this); + } + else if (arguments.length > 1) + switch (arguments.length) { + case 2: + handler.call(this, arguments[1]); + break; + case 3: + handler.call(this, arguments[1], arguments[2]); + break; + // slower + default: + var l = arguments.length; + var args = new Array(l - 1); + for (var i = 1; i < l; i++) args[i - 1] = arguments[i]; + handler.apply(this, args); + } + return true; + } + else if (handler) { + var l = arguments.length; + var args = new Array(l - 1); + for (var i = 1; i < l; i++) args[i - 1] = arguments[i]; + + var listeners = handler.slice(); + for (var i = 0, l = listeners.length; i < l; i++) { + this.event = type; + listeners[i].apply(this, args); + } + return (listeners.length > 0) || !!this._all; + } + else { + return !!this._all; + } + + }; + + EventEmitter.prototype.on = function(type, listener) { + + if (typeof type === 'function') { + this.onAny(type); + return this; + } + + if (typeof listener !== 'function') { + throw new Error('on only accepts instances of Function'); + } + this._events || init.call(this); + + // To avoid recursion in the case that type == "newListeners"! Before + // adding it to the listeners, first emit "newListeners". + this.emit('newListener', type, listener); + + if(this.wildcard) { + growListenerTree.call(this, type, listener); + return this; + } + + if (!this._events[type]) { + // Optimize the case of one listener. Don't need the extra array object. + this._events[type] = listener; + } + else if(typeof this._events[type] === 'function') { + // Adding the second element, need to change to array. + this._events[type] = [this._events[type], listener]; + } + else if (isArray(this._events[type])) { + // If we've already got an array, just append. + this._events[type].push(listener); + + // Check for listener leak + if (!this._events[type].warned) { + + var m = defaultMaxListeners; + + if (typeof this._events.maxListeners !== 'undefined') { + m = this._events.maxListeners; + } + + if (m > 0 && this._events[type].length > m) { + + this._events[type].warned = true; + console.error('(node) warning: possible EventEmitter memory ' + + 'leak detected. %d listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.', + this._events[type].length); + console.trace(); + } + } + } + return this; + }; + + EventEmitter.prototype.onAny = function(fn) { + + if (typeof fn !== 'function') { + throw new Error('onAny only accepts instances of Function'); + } + + if(!this._all) { + this._all = []; + } + + // Add the function to the event listener collection. + this._all.push(fn); + return this; + }; + + EventEmitter.prototype.addListener = EventEmitter.prototype.on; + + EventEmitter.prototype.off = function(type, listener) { + if (typeof listener !== 'function') { + throw new Error('removeListener only takes instances of Function'); + } + + var handlers,leafs=[]; + + if(this.wildcard) { + var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); + leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0); + } + else { + // does not use listeners(), so no side effect of creating _events[type] + if (!this._events[type]) return this; + handlers = this._events[type]; + leafs.push({_listeners:handlers}); + } + + for (var iLeaf=0; iLeaf 0) { + fns = this._all; + for(i = 0, l = fns.length; i < l; i++) { + if(fn === fns[i]) { + fns.splice(i, 1); + return this; + } + } + } else { + this._all = []; + } + return this; + }; + + EventEmitter.prototype.removeListener = EventEmitter.prototype.off; + + EventEmitter.prototype.removeAllListeners = function(type) { + if (arguments.length === 0) { + !this._events || init.call(this); + return this; + } + + if(this.wildcard) { + var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); + var leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0); + + for (var iLeaf=0; iLeaf + + + +Exercise 10 + + + +

Exercise 10

+ +
+
+ +
+
+
+
+
+
+ +
+ + + + + + + + + + diff --git a/frontend-masters-exercises/exercises/ex10/feeds.js b/frontend-masters-exercises/exercises/ex10/feeds.js new file mode 100755 index 0000000..c26e829 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex10/feeds.js @@ -0,0 +1,238 @@ +(function Feeds(){ + "use strict"; + + var // signal event handler(s) + item_feed; + + EVT.on("setup-feeds",setupFeeds); + + + // *********************************** + + function setupFeeds() { + // setup fake item feed + fakeItemFeed(function setupItemFeed(sq){ + item_feed = sq; + }); + + // setup slow feed (feed 1) + var slow_feed_toggle; + setupFeed( + /*feedID=*/1, + /*delay=*/2000, + function setupSlowFeedToggle(sq){ + slow_feed_toggle = sq; + } + ); + + // setup fast feed (feed 2) + var fast_feed_toggle; + setupFeed( + /*feedID=*/2, + /*delay=*/1300, + function setupFastFeedToggle(sq){ + fast_feed_toggle = sq; + } + ); + + // track feed statuses + var st1 = true, st2 = true; + + // monitor feed statuses + var listenToFeedStatus = ASQ.wrap(function *wrapped(){ + // monitor each status + slow_feed_toggle.val(function val(st){ + st1 = st; + }); + fast_feed_toggle.then(function val(st){ + st2 = st; + }); + + // listen for either status to toggle + yield ASQ().race(slow_feed_toggle,fast_feed_toggle); + + monitorFeedStatus(st1,st2); + + // wait for next tick + yield ASQ(); + + listenToFeedStatus(); + },{ gen: true }); + listenToFeedStatus(); + + // setup my feed (duplicate checking) + setupMyFeed(); + } + + // fake a network stream of data + function fakeItemFeed(defineSequence) { + var next = sequenceBasedEventHandler(defineSequence); + + // fake a delay + var intv = setInterval(function timer(){ + // signal a new item + next( ItemsText.more() ); + },50); + } + + function setupFeed(feedID,delay,defineToggleSequence) { + // setup feed reactive sequences + var feed_is_running = true, + feed_status, feed_toggle, + + PAUSED_FEED = ASQ(function noop(){}); + + // start with feed running + feed_status = ASQ(true); + + setupNextFeedToggle(); + + fromEvent( + "status-" + feedID, + setupFeedToggle + ); + + sampledStream( + delay, + ASQ.wrap(setupStreamEventHandler,{ gen: true, spread: true }) + ); + + + // *********************************** + + function *setupFeedToggle(sq) { + // distinct consecutive + handleFeedToggle( yield sq ); + } + + function setupNextFeedToggle() { + feed_toggle = ASQ.iterable(); + defineToggleSequence(feed_toggle); + } + + function handleFeedToggle(st) { + // resuming feed? + if (st !== feed_is_running && st === true) { + feed_is_running = true; + feed_status = ASQ(true); + } + // switching to paused feed + else { + feed_is_running = false; + feed_status = PAUSED_FEED; + } + + feed_toggle.next(feed_is_running); + + setupNextFeedToggle(); + } + + function *setupStreamEventHandler(sq) { + var args = yield ASQ().all(sq,feed_status); + handleItemText(args[0]); + } + + function handleItemText(itemText) { + // feed still running? + if (feed_is_running) { + EVT.emit("feed-insertion",feedID,itemText); + } + } + } + + function sampledStream(delay,defineSequence) { + // throttle feed sampling + var intv = setInterval( + ASQ.wrap(timer,{ gen: true }), + delay + ); + + + // *********************************** + + function *timer() { + var sq = ASQ.iterable(); + + defineSequence(ASQ.messages(sq)); + + // signal a new feed item + sq.next( yield item_feed ); + } + } + + function monitorFeedStatus(running1,running2) { + // both feeds paused? + if (!running1 && !running2) { + // TODO: pause the item feed + } + // keep calm and carry on + else { + // TODO: resume the item feed + } + } + + function setupMyFeed() { + var my_feed_text = {}; + + fromEvent( + "item-selection", + function *setupItemSelection(sq){ + handleItemSelection.apply( null, yield sq ); + } + ); + + + // *********************************** + + function handleItemSelection(feedID,itemText,$item) { + // not a duplicate message? + if (!(itemText in my_feed_text)) { + my_feed_text[itemText] = true; + + // signal my-feed insertion + EVT.emit("my-feed-insertion",feedID,$item); + } + else { + // signal kill (duplicate) item + EVT.emit("feed-kill",$item); + } + } + } + + function fromEvent(evtName,defineSequence) { + EVT.on( + evtName, + sequenceBasedEventHandler( + ASQ.wrap(defineSequence,{ gen: true, spread: true }) + ) + ); + } + + function sequenceBasedEventHandler(defineSequence) { + var sq; + + // start out with a sequence + getNextSequence(); + + return eventHandler; + + + // *********************************** + + function eventHandler() { + // resolve previous sequence + sq.next.apply(null,arguments); + + // get the next sequence ready in case + // this event fires again + getNextSequence(); + } + + function getNextSequence() { + sq = ASQ.iterable(); + + defineSequence(ASQ.messages(sq)); + } + } + +})(); diff --git a/frontend-masters-exercises/exercises/ex10/jquery.js b/frontend-masters-exercises/exercises/ex10/jquery.js new file mode 100755 index 0000000..45477c0 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex10/jquery.js @@ -0,0 +1,2 @@ +/*! jQuery v1.8.3 jquery.com | jquery.org/license */ +(function(e,t){function _(e){var t=M[e]={};return v.each(e.split(y),function(e,n){t[n]=!0}),t}function H(e,n,r){if(r===t&&e.nodeType===1){var i="data-"+n.replace(P,"-$1").toLowerCase();r=e.getAttribute(i);if(typeof r=="string"){try{r=r==="true"?!0:r==="false"?!1:r==="null"?null:+r+""===r?+r:D.test(r)?v.parseJSON(r):r}catch(s){}v.data(e,n,r)}else r=t}return r}function B(e){var t;for(t in e){if(t==="data"&&v.isEmptyObject(e[t]))continue;if(t!=="toJSON")return!1}return!0}function et(){return!1}function tt(){return!0}function ut(e){return!e||!e.parentNode||e.parentNode.nodeType===11}function at(e,t){do e=e[t];while(e&&e.nodeType!==1);return e}function ft(e,t,n){t=t||0;if(v.isFunction(t))return v.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return v.grep(e,function(e,r){return e===t===n});if(typeof t=="string"){var r=v.grep(e,function(e){return e.nodeType===1});if(it.test(t))return v.filter(t,r,!n);t=v.filter(t,r)}return v.grep(e,function(e,r){return v.inArray(e,t)>=0===n})}function lt(e){var t=ct.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function At(e,t){if(t.nodeType!==1||!v.hasData(e))return;var n,r,i,s=v._data(e),o=v._data(t,s),u=s.events;if(u){delete o.handle,o.events={};for(n in u)for(r=0,i=u[n].length;r").appendTo(i.body),n=t.css("display");t.remove();if(n==="none"||n===""){Pt=i.body.appendChild(Pt||v.extend(i.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!Ht||!Pt.createElement)Ht=(Pt.contentWindow||Pt.contentDocument).document,Ht.write(""),Ht.close();t=Ht.body.appendChild(Ht.createElement(e)),n=Dt(t,"display"),i.body.removeChild(Pt)}return Wt[e]=n,n}function fn(e,t,n,r){var i;if(v.isArray(t))v.each(t,function(t,i){n||sn.test(e)?r(e,i):fn(e+"["+(typeof i=="object"?t:"")+"]",i,n,r)});else if(!n&&v.type(t)==="object")for(i in t)fn(e+"["+i+"]",t[i],n,r);else r(e,t)}function Cn(e){return function(t,n){typeof t!="string"&&(n=t,t="*");var r,i,s,o=t.toLowerCase().split(y),u=0,a=o.length;if(v.isFunction(n))for(;u)[^>]*$|#([\w\-]*)$)/,E=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,S=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,T=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,N=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,C=/^-ms-/,k=/-([\da-z])/gi,L=function(e,t){return(t+"").toUpperCase()},A=function(){i.addEventListener?(i.removeEventListener("DOMContentLoaded",A,!1),v.ready()):i.readyState==="complete"&&(i.detachEvent("onreadystatechange",A),v.ready())},O={};v.fn=v.prototype={constructor:v,init:function(e,n,r){var s,o,u,a;if(!e)return this;if(e.nodeType)return this.context=this[0]=e,this.length=1,this;if(typeof e=="string"){e.charAt(0)==="<"&&e.charAt(e.length-1)===">"&&e.length>=3?s=[null,e,null]:s=w.exec(e);if(s&&(s[1]||!n)){if(s[1])return n=n instanceof v?n[0]:n,a=n&&n.nodeType?n.ownerDocument||n:i,e=v.parseHTML(s[1],a,!0),E.test(s[1])&&v.isPlainObject(n)&&this.attr.call(e,n,!0),v.merge(this,e);o=i.getElementById(s[2]);if(o&&o.parentNode){if(o.id!==s[2])return r.find(e);this.length=1,this[0]=o}return this.context=i,this.selector=e,this}return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e)}return v.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),v.makeArray(e,this))},selector:"",jquery:"1.8.3",length:0,size:function(){return this.length},toArray:function(){return l.call(this)},get:function(e){return e==null?this.toArray():e<0?this[this.length+e]:this[e]},pushStack:function(e,t,n){var r=v.merge(this.constructor(),e);return r.prevObject=this,r.context=this.context,t==="find"?r.selector=this.selector+(this.selector?" ":"")+n:t&&(r.selector=this.selector+"."+t+"("+n+")"),r},each:function(e,t){return v.each(this,e,t)},ready:function(e){return v.ready.promise().done(e),this},eq:function(e){return e=+e,e===-1?this.slice(e):this.slice(e,e+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(l.apply(this,arguments),"slice",l.call(arguments).join(","))},map:function(e){return this.pushStack(v.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:[].sort,splice:[].splice},v.fn.init.prototype=v.fn,v.extend=v.fn.extend=function(){var e,n,r,i,s,o,u=arguments[0]||{},a=1,f=arguments.length,l=!1;typeof u=="boolean"&&(l=u,u=arguments[1]||{},a=2),typeof u!="object"&&!v.isFunction(u)&&(u={}),f===a&&(u=this,--a);for(;a0)return;r.resolveWith(i,[v]),v.fn.trigger&&v(i).trigger("ready").off("ready")},isFunction:function(e){return v.type(e)==="function"},isArray:Array.isArray||function(e){return v.type(e)==="array"},isWindow:function(e){return e!=null&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return e==null?String(e):O[h.call(e)]||"object"},isPlainObject:function(e){if(!e||v.type(e)!=="object"||e.nodeType||v.isWindow(e))return!1;try{if(e.constructor&&!p.call(e,"constructor")&&!p.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||p.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw new Error(e)},parseHTML:function(e,t,n){var r;return!e||typeof e!="string"?null:(typeof t=="boolean"&&(n=t,t=0),t=t||i,(r=E.exec(e))?[t.createElement(r[1])]:(r=v.buildFragment([e],t,n?null:[]),v.merge([],(r.cacheable?v.clone(r.fragment):r.fragment).childNodes)))},parseJSON:function(t){if(!t||typeof t!="string")return null;t=v.trim(t);if(e.JSON&&e.JSON.parse)return e.JSON.parse(t);if(S.test(t.replace(T,"@").replace(N,"]").replace(x,"")))return(new Function("return "+t))();v.error("Invalid JSON: "+t)},parseXML:function(n){var r,i;if(!n||typeof n!="string")return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(s){r=t}return(!r||!r.documentElement||r.getElementsByTagName("parsererror").length)&&v.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&g.test(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(C,"ms-").replace(k,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,n,r){var i,s=0,o=e.length,u=o===t||v.isFunction(e);if(r){if(u){for(i in e)if(n.apply(e[i],r)===!1)break}else for(;s0&&e[0]&&e[a-1]||a===0||v.isArray(e));if(f)for(;u-1)a.splice(n,1),i&&(n<=o&&o--,n<=u&&u--)}),this},has:function(e){return v.inArray(e,a)>-1},empty:function(){return a=[],this},disable:function(){return a=f=n=t,this},disabled:function(){return!a},lock:function(){return f=t,n||c.disable(),this},locked:function(){return!f},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],a&&(!r||f)&&(i?f.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},v.extend({Deferred:function(e){var t=[["resolve","done",v.Callbacks("once memory"),"resolved"],["reject","fail",v.Callbacks("once memory"),"rejected"],["notify","progress",v.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return v.Deferred(function(n){v.each(t,function(t,r){var s=r[0],o=e[t];i[r[1]](v.isFunction(o)?function(){var e=o.apply(this,arguments);e&&v.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===i?n:this,[e])}:n[s])}),e=null}).promise()},promise:function(e){return e!=null?v.extend(e,r):r}},i={};return r.pipe=r.then,v.each(t,function(e,s){var o=s[2],u=s[3];r[s[1]]=o.add,u&&o.add(function(){n=u},t[e^1][2].disable,t[2][2].lock),i[s[0]]=o.fire,i[s[0]+"With"]=o.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=l.call(arguments),r=n.length,i=r!==1||e&&v.isFunction(e.promise)?r:0,s=i===1?e:v.Deferred(),o=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?l.call(arguments):r,n===u?s.notifyWith(t,n):--i||s.resolveWith(t,n)}},u,a,f;if(r>1){u=new Array(r),a=new Array(r),f=new Array(r);for(;t
a",n=p.getElementsByTagName("*"),r=p.getElementsByTagName("a")[0];if(!n||!r||!n.length)return{};s=i.createElement("select"),o=s.appendChild(i.createElement("option")),u=p.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:r.getAttribute("href")==="/a",opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:u.value==="on",optSelected:o.selected,getSetAttribute:p.className!=="t",enctype:!!i.createElement("form").enctype,html5Clone:i.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",boxModel:i.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},u.checked=!0,t.noCloneChecked=u.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!o.disabled;try{delete p.test}catch(d){t.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",h=function(){t.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick"),p.detachEvent("onclick",h)),u=i.createElement("input"),u.value="t",u.setAttribute("type","radio"),t.radioValue=u.value==="t",u.setAttribute("checked","checked"),u.setAttribute("name","t"),p.appendChild(u),a=i.createDocumentFragment(),a.appendChild(p.lastChild),t.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,t.appendChecked=u.checked,a.removeChild(u),a.appendChild(p);if(p.attachEvent)for(l in{submit:!0,change:!0,focusin:!0})f="on"+l,c=f in p,c||(p.setAttribute(f,"return;"),c=typeof p[f]=="function"),t[l+"Bubbles"]=c;return v(function(){var n,r,s,o,u="padding:0;margin:0;border:0;display:block;overflow:hidden;",a=i.getElementsByTagName("body")[0];if(!a)return;n=i.createElement("div"),n.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",a.insertBefore(n,a.firstChild),r=i.createElement("div"),n.appendChild(r),r.innerHTML="
t
",s=r.getElementsByTagName("td"),s[0].style.cssText="padding:0;margin:0;border:0;display:none",c=s[0].offsetHeight===0,s[0].style.display="",s[1].style.display="none",t.reliableHiddenOffsets=c&&s[0].offsetHeight===0,r.innerHTML="",r.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=r.offsetWidth===4,t.doesNotIncludeMarginInBodyOffset=a.offsetTop!==1,e.getComputedStyle&&(t.pixelPosition=(e.getComputedStyle(r,null)||{}).top!=="1%",t.boxSizingReliable=(e.getComputedStyle(r,null)||{width:"4px"}).width==="4px",o=i.createElement("div"),o.style.cssText=r.style.cssText=u,o.style.marginRight=o.style.width="0",r.style.width="1px",r.appendChild(o),t.reliableMarginRight=!parseFloat((e.getComputedStyle(o,null)||{}).marginRight)),typeof r.style.zoom!="undefined"&&(r.innerHTML="",r.style.cssText=u+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=r.offsetWidth===3,r.style.display="block",r.style.overflow="visible",r.innerHTML="
",r.firstChild.style.width="5px",t.shrinkWrapBlocks=r.offsetWidth!==3,n.style.zoom=1),a.removeChild(n),n=r=s=o=null}),a.removeChild(p),n=r=s=o=u=a=p=null,t}();var D=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;v.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(v.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?v.cache[e[v.expando]]:e[v.expando],!!e&&!B(e)},data:function(e,n,r,i){if(!v.acceptData(e))return;var s,o,u=v.expando,a=typeof n=="string",f=e.nodeType,l=f?v.cache:e,c=f?e[u]:e[u]&&u;if((!c||!l[c]||!i&&!l[c].data)&&a&&r===t)return;c||(f?e[u]=c=v.deletedIds.pop()||v.guid++:c=u),l[c]||(l[c]={},f||(l[c].toJSON=v.noop));if(typeof n=="object"||typeof n=="function")i?l[c]=v.extend(l[c],n):l[c].data=v.extend(l[c].data,n);return s=l[c],i||(s.data||(s.data={}),s=s.data),r!==t&&(s[v.camelCase(n)]=r),a?(o=s[n],o==null&&(o=s[v.camelCase(n)])):o=s,o},removeData:function(e,t,n){if(!v.acceptData(e))return;var r,i,s,o=e.nodeType,u=o?v.cache:e,a=o?e[v.expando]:v.expando;if(!u[a])return;if(t){r=n?u[a]:u[a].data;if(r){v.isArray(t)||(t in r?t=[t]:(t=v.camelCase(t),t in r?t=[t]:t=t.split(" ")));for(i=0,s=t.length;i1,null,!1))},removeData:function(e){return this.each(function(){v.removeData(this,e)})}}),v.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=v._data(e,t),n&&(!r||v.isArray(n)?r=v._data(e,t,v.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=v.queue(e,t),r=n.length,i=n.shift(),s=v._queueHooks(e,t),o=function(){v.dequeue(e,t)};i==="inprogress"&&(i=n.shift(),r--),i&&(t==="fx"&&n.unshift("inprogress"),delete s.stop,i.call(e,o,s)),!r&&s&&s.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return v._data(e,n)||v._data(e,n,{empty:v.Callbacks("once memory").add(function(){v.removeData(e,t+"queue",!0),v.removeData(e,n,!0)})})}}),v.fn.extend({queue:function(e,n){var r=2;return typeof e!="string"&&(n=e,e="fx",r--),arguments.length1)},removeAttr:function(e){return this.each(function(){v.removeAttr(this,e)})},prop:function(e,t){return v.access(this,v.prop,e,t,arguments.length>1)},removeProp:function(e){return e=v.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,s,o,u;if(v.isFunction(e))return this.each(function(t){v(this).addClass(e.call(this,t,this.className))});if(e&&typeof e=="string"){t=e.split(y);for(n=0,r=this.length;n=0)r=r.replace(" "+n[s]+" "," ");i.className=e?v.trim(r):""}}}return this},toggleClass:function(e,t){var n=typeof e,r=typeof t=="boolean";return v.isFunction(e)?this.each(function(n){v(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if(n==="string"){var i,s=0,o=v(this),u=t,a=e.split(y);while(i=a[s++])u=r?u:!o.hasClass(i),o[u?"addClass":"removeClass"](i)}else if(n==="undefined"||n==="boolean")this.className&&v._data(this,"__className__",this.className),this.className=this.className||e===!1?"":v._data(this,"__className__")||""})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;n=0)return!0;return!1},val:function(e){var n,r,i,s=this[0];if(!arguments.length){if(s)return n=v.valHooks[s.type]||v.valHooks[s.nodeName.toLowerCase()],n&&"get"in n&&(r=n.get(s,"value"))!==t?r:(r=s.value,typeof r=="string"?r.replace(R,""):r==null?"":r);return}return i=v.isFunction(e),this.each(function(r){var s,o=v(this);if(this.nodeType!==1)return;i?s=e.call(this,r,o.val()):s=e,s==null?s="":typeof s=="number"?s+="":v.isArray(s)&&(s=v.map(s,function(e){return e==null?"":e+""})),n=v.valHooks[this.type]||v.valHooks[this.nodeName.toLowerCase()];if(!n||!("set"in n)||n.set(this,s,"value")===t)this.value=s})}}),v.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,s=e.type==="select-one"||i<0,o=s?null:[],u=s?i+1:r.length,a=i<0?u:s?i:0;for(;a=0}),n.length||(e.selectedIndex=-1),n}}},attrFn:{},attr:function(e,n,r,i){var s,o,u,a=e.nodeType;if(!e||a===3||a===8||a===2)return;if(i&&v.isFunction(v.fn[n]))return v(e)[n](r);if(typeof e.getAttribute=="undefined")return v.prop(e,n,r);u=a!==1||!v.isXMLDoc(e),u&&(n=n.toLowerCase(),o=v.attrHooks[n]||(X.test(n)?F:j));if(r!==t){if(r===null){v.removeAttr(e,n);return}return o&&"set"in o&&u&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r)}return o&&"get"in o&&u&&(s=o.get(e,n))!==null?s:(s=e.getAttribute(n),s===null?t:s)},removeAttr:function(e,t){var n,r,i,s,o=0;if(t&&e.nodeType===1){r=t.split(y);for(;o=0}})});var $=/^(?:textarea|input|select)$/i,J=/^([^\.]*|)(?:\.(.+)|)$/,K=/(?:^|\s)hover(\.\S+|)\b/,Q=/^key/,G=/^(?:mouse|contextmenu)|click/,Y=/^(?:focusinfocus|focusoutblur)$/,Z=function(e){return v.event.special.hover?e:e.replace(K,"mouseenter$1 mouseleave$1")};v.event={add:function(e,n,r,i,s){var o,u,a,f,l,c,h,p,d,m,g;if(e.nodeType===3||e.nodeType===8||!n||!r||!(o=v._data(e)))return;r.handler&&(d=r,r=d.handler,s=d.selector),r.guid||(r.guid=v.guid++),a=o.events,a||(o.events=a={}),u=o.handle,u||(o.handle=u=function(e){return typeof v=="undefined"||!!e&&v.event.triggered===e.type?t:v.event.dispatch.apply(u.elem,arguments)},u.elem=e),n=v.trim(Z(n)).split(" ");for(f=0;f=0&&(y=y.slice(0,-1),a=!0),y.indexOf(".")>=0&&(b=y.split("."),y=b.shift(),b.sort());if((!s||v.event.customEvent[y])&&!v.event.global[y])return;n=typeof n=="object"?n[v.expando]?n:new v.Event(y,n):new v.Event(y),n.type=y,n.isTrigger=!0,n.exclusive=a,n.namespace=b.join("."),n.namespace_re=n.namespace?new RegExp("(^|\\.)"+b.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,h=y.indexOf(":")<0?"on"+y:"";if(!s){u=v.cache;for(f in u)u[f].events&&u[f].events[y]&&v.event.trigger(n,r,u[f].handle.elem,!0);return}n.result=t,n.target||(n.target=s),r=r!=null?v.makeArray(r):[],r.unshift(n),p=v.event.special[y]||{};if(p.trigger&&p.trigger.apply(s,r)===!1)return;m=[[s,p.bindType||y]];if(!o&&!p.noBubble&&!v.isWindow(s)){g=p.delegateType||y,l=Y.test(g+y)?s:s.parentNode;for(c=s;l;l=l.parentNode)m.push([l,g]),c=l;c===(s.ownerDocument||i)&&m.push([c.defaultView||c.parentWindow||e,g])}for(f=0;f=0:v.find(h,this,null,[s]).length),u[h]&&f.push(c);f.length&&w.push({elem:s,matches:f})}d.length>m&&w.push({elem:this,matches:d.slice(m)});for(r=0;r0?this.on(t,null,e,n):this.trigger(t)},Q.test(t)&&(v.event.fixHooks[t]=v.event.keyHooks),G.test(t)&&(v.event.fixHooks[t]=v.event.mouseHooks)}),function(e,t){function nt(e,t,n,r){n=n||[],t=t||g;var i,s,a,f,l=t.nodeType;if(!e||typeof e!="string")return n;if(l!==1&&l!==9)return[];a=o(t);if(!a&&!r)if(i=R.exec(e))if(f=i[1]){if(l===9){s=t.getElementById(f);if(!s||!s.parentNode)return n;if(s.id===f)return n.push(s),n}else if(t.ownerDocument&&(s=t.ownerDocument.getElementById(f))&&u(t,s)&&s.id===f)return n.push(s),n}else{if(i[2])return S.apply(n,x.call(t.getElementsByTagName(e),0)),n;if((f=i[3])&&Z&&t.getElementsByClassName)return S.apply(n,x.call(t.getElementsByClassName(f),0)),n}return vt(e.replace(j,"$1"),t,n,r,a)}function rt(e){return function(t){var n=t.nodeName.toLowerCase();return n==="input"&&t.type===e}}function it(e){return function(t){var n=t.nodeName.toLowerCase();return(n==="input"||n==="button")&&t.type===e}}function st(e){return N(function(t){return t=+t,N(function(n,r){var i,s=e([],n.length,t),o=s.length;while(o--)n[i=s[o]]&&(n[i]=!(r[i]=n[i]))})})}function ot(e,t,n){if(e===t)return n;var r=e.nextSibling;while(r){if(r===t)return-1;r=r.nextSibling}return 1}function ut(e,t){var n,r,s,o,u,a,f,l=L[d][e+" "];if(l)return t?0:l.slice(0);u=e,a=[],f=i.preFilter;while(u){if(!n||(r=F.exec(u)))r&&(u=u.slice(r[0].length)||u),a.push(s=[]);n=!1;if(r=I.exec(u))s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=r[0].replace(j," ");for(o in i.filter)(r=J[o].exec(u))&&(!f[o]||(r=f[o](r)))&&(s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=o,n.matches=r);if(!n)break}return t?u.length:u?nt.error(e):L(e,a).slice(0)}function at(e,t,r){var i=t.dir,s=r&&t.dir==="parentNode",o=w++;return t.first?function(t,n,r){while(t=t[i])if(s||t.nodeType===1)return e(t,n,r)}:function(t,r,u){if(!u){var a,f=b+" "+o+" ",l=f+n;while(t=t[i])if(s||t.nodeType===1){if((a=t[d])===l)return t.sizset;if(typeof a=="string"&&a.indexOf(f)===0){if(t.sizset)return t}else{t[d]=l;if(e(t,r,u))return t.sizset=!0,t;t.sizset=!1}}}else while(t=t[i])if(s||t.nodeType===1)if(e(t,r,u))return t}}function ft(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function lt(e,t,n,r,i){var s,o=[],u=0,a=e.length,f=t!=null;for(;u-1&&(s[f]=!(o[f]=c))}}else g=lt(g===o?g.splice(d,g.length):g),i?i(null,o,g,a):S.apply(o,g)})}function ht(e){var t,n,r,s=e.length,o=i.relative[e[0].type],u=o||i.relative[" "],a=o?1:0,f=at(function(e){return e===t},u,!0),l=at(function(e){return T.call(t,e)>-1},u,!0),h=[function(e,n,r){return!o&&(r||n!==c)||((t=n).nodeType?f(e,n,r):l(e,n,r))}];for(;a1&&ft(h),a>1&&e.slice(0,a-1).join("").replace(j,"$1"),n,a0,s=e.length>0,o=function(u,a,f,l,h){var p,d,v,m=[],y=0,w="0",x=u&&[],T=h!=null,N=c,C=u||s&&i.find.TAG("*",h&&a.parentNode||a),k=b+=N==null?1:Math.E;T&&(c=a!==g&&a,n=o.el);for(;(p=C[w])!=null;w++){if(s&&p){for(d=0;v=e[d];d++)if(v(p,a,f)){l.push(p);break}T&&(b=k,n=++o.el)}r&&((p=!v&&p)&&y--,u&&x.push(p))}y+=w;if(r&&w!==y){for(d=0;v=t[d];d++)v(x,m,a,f);if(u){if(y>0)while(w--)!x[w]&&!m[w]&&(m[w]=E.call(l));m=lt(m)}S.apply(l,m),T&&!u&&m.length>0&&y+t.length>1&&nt.uniqueSort(l)}return T&&(b=k,c=N),x};return o.el=0,r?N(o):o}function dt(e,t,n){var r=0,i=t.length;for(;r2&&(f=u[0]).type==="ID"&&t.nodeType===9&&!s&&i.relative[u[1].type]){t=i.find.ID(f.matches[0].replace($,""),t,s)[0];if(!t)return n;e=e.slice(u.shift().length)}for(o=J.POS.test(e)?-1:u.length-1;o>=0;o--){f=u[o];if(i.relative[l=f.type])break;if(c=i.find[l])if(r=c(f.matches[0].replace($,""),z.test(u[0].type)&&t.parentNode||t,s)){u.splice(o,1),e=r.length&&u.join("");if(!e)return S.apply(n,x.call(r,0)),n;break}}}return a(e,h)(r,t,s,n,z.test(e)),n}function mt(){}var n,r,i,s,o,u,a,f,l,c,h=!0,p="undefined",d=("sizcache"+Math.random()).replace(".",""),m=String,g=e.document,y=g.documentElement,b=0,w=0,E=[].pop,S=[].push,x=[].slice,T=[].indexOf||function(e){var t=0,n=this.length;for(;ti.cacheLength&&delete e[t.shift()],e[n+" "]=r},e)},k=C(),L=C(),A=C(),O="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",_=M.replace("w","w#"),D="([*^$|!~]?=)",P="\\["+O+"*("+M+")"+O+"*(?:"+D+O+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+_+")|)|)"+O+"*\\]",H=":("+M+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+P+")|[^:]|\\\\.)*|.*))\\)|)",B=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+O+"*((?:-\\d)?\\d*)"+O+"*\\)|)(?=[^-]|$)",j=new RegExp("^"+O+"+|((?:^|[^\\\\])(?:\\\\.)*)"+O+"+$","g"),F=new RegExp("^"+O+"*,"+O+"*"),I=new RegExp("^"+O+"*([\\x20\\t\\r\\n\\f>+~])"+O+"*"),q=new RegExp(H),R=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,U=/^:not/,z=/[\x20\t\r\n\f]*[+~]/,W=/:not\($/,X=/h\d/i,V=/input|select|textarea|button/i,$=/\\(?!\\)/g,J={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),NAME:new RegExp("^\\[name=['\"]?("+M+")['\"]?\\]"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+H),POS:new RegExp(B,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+O+"*(even|odd|(([+-]|)(\\d*)n|)"+O+"*(?:([+-]|)"+O+"*(\\d+)|))"+O+"*\\)|)","i"),needsContext:new RegExp("^"+O+"*[>+~]|"+B,"i")},K=function(e){var t=g.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}},Q=K(function(e){return e.appendChild(g.createComment("")),!e.getElementsByTagName("*").length}),G=K(function(e){return e.innerHTML="",e.firstChild&&typeof e.firstChild.getAttribute!==p&&e.firstChild.getAttribute("href")==="#"}),Y=K(function(e){e.innerHTML="";var t=typeof e.lastChild.getAttribute("multiple");return t!=="boolean"&&t!=="string"}),Z=K(function(e){return e.innerHTML="",!e.getElementsByClassName||!e.getElementsByClassName("e").length?!1:(e.lastChild.className="e",e.getElementsByClassName("e").length===2)}),et=K(function(e){e.id=d+0,e.innerHTML="
",y.insertBefore(e,y.firstChild);var t=g.getElementsByName&&g.getElementsByName(d).length===2+g.getElementsByName(d+0).length;return r=!g.getElementById(d),y.removeChild(e),t});try{x.call(y.childNodes,0)[0].nodeType}catch(tt){x=function(e){var t,n=[];for(;t=this[e];e++)n.push(t);return n}}nt.matches=function(e,t){return nt(e,null,null,t)},nt.matchesSelector=function(e,t){return nt(t,null,null,[e]).length>0},s=nt.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(i===1||i===9||i===11){if(typeof e.textContent=="string")return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=s(e)}else if(i===3||i===4)return e.nodeValue}else for(;t=e[r];r++)n+=s(t);return n},o=nt.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?t.nodeName!=="HTML":!1},u=nt.contains=y.contains?function(e,t){var n=e.nodeType===9?e.documentElement:e,r=t&&t.parentNode;return e===r||!!(r&&r.nodeType===1&&n.contains&&n.contains(r))}:y.compareDocumentPosition?function(e,t){return t&&!!(e.compareDocumentPosition(t)&16)}:function(e,t){while(t=t.parentNode)if(t===e)return!0;return!1},nt.attr=function(e,t){var n,r=o(e);return r||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):r||Y?e.getAttribute(t):(n=e.getAttributeNode(t),n?typeof e[t]=="boolean"?e[t]?t:null:n.specified?n.value:null:null)},i=nt.selectors={cacheLength:50,createPseudo:N,match:J,attrHandle:G?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},find:{ID:r?function(e,t,n){if(typeof t.getElementById!==p&&!n){var r=t.getElementById(e);return r&&r.parentNode?[r]:[]}}:function(e,n,r){if(typeof n.getElementById!==p&&!r){var i=n.getElementById(e);return i?i.id===e||typeof i.getAttributeNode!==p&&i.getAttributeNode("id").value===e?[i]:t:[]}},TAG:Q?function(e,t){if(typeof t.getElementsByTagName!==p)return t.getElementsByTagName(e)}:function(e,t){var n=t.getElementsByTagName(e);if(e==="*"){var r,i=[],s=0;for(;r=n[s];s++)r.nodeType===1&&i.push(r);return i}return n},NAME:et&&function(e,t){if(typeof t.getElementsByName!==p)return t.getElementsByName(name)},CLASS:Z&&function(e,t,n){if(typeof t.getElementsByClassName!==p&&!n)return t.getElementsByClassName(e)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace($,""),e[3]=(e[4]||e[5]||"").replace($,""),e[2]==="~="&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),e[1]==="nth"?(e[2]||nt.error(e[0]),e[3]=+(e[3]?e[4]+(e[5]||1):2*(e[2]==="even"||e[2]==="odd")),e[4]=+(e[6]+e[7]||e[2]==="odd")):e[2]&&nt.error(e[0]),e},PSEUDO:function(e){var t,n;if(J.CHILD.test(e[0]))return null;if(e[3])e[2]=e[3];else if(t=e[4])q.test(t)&&(n=ut(t,!0))&&(n=t.indexOf(")",t.length-n)-t.length)&&(t=t.slice(0,n),e[0]=e[0].slice(0,n)),e[2]=t;return e.slice(0,3)}},filter:{ID:r?function(e){return e=e.replace($,""),function(t){return t.getAttribute("id")===e}}:function(e){return e=e.replace($,""),function(t){var n=typeof t.getAttributeNode!==p&&t.getAttributeNode("id");return n&&n.value===e}},TAG:function(e){return e==="*"?function(){return!0}:(e=e.replace($,"").toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[d][e+" "];return t||(t=new RegExp("(^|"+O+")"+e+"("+O+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==p&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r,i){var s=nt.attr(r,e);return s==null?t==="!=":t?(s+="",t==="="?s===n:t==="!="?s!==n:t==="^="?n&&s.indexOf(n)===0:t==="*="?n&&s.indexOf(n)>-1:t==="$="?n&&s.substr(s.length-n.length)===n:t==="~="?(" "+s+" ").indexOf(n)>-1:t==="|="?s===n||s.substr(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r){return e==="nth"?function(e){var t,i,s=e.parentNode;if(n===1&&r===0)return!0;if(s){i=0;for(t=s.firstChild;t;t=t.nextSibling)if(t.nodeType===1){i++;if(e===t)break}}return i-=r,i===n||i%n===0&&i/n>=0}:function(t){var n=t;switch(e){case"only":case"first":while(n=n.previousSibling)if(n.nodeType===1)return!1;if(e==="first")return!0;n=t;case"last":while(n=n.nextSibling)if(n.nodeType===1)return!1;return!0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||nt.error("unsupported pseudo: "+e);return r[d]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?N(function(e,n){var i,s=r(e,t),o=s.length;while(o--)i=T.call(e,s[o]),e[i]=!(n[i]=s[o])}):function(e){return r(e,0,n)}):r}},pseudos:{not:N(function(e){var t=[],n=[],r=a(e.replace(j,"$1"));return r[d]?N(function(e,t,n,i){var s,o=r(e,null,i,[]),u=e.length;while(u--)if(s=o[u])e[u]=!(t[u]=s)}):function(e,i,s){return t[0]=e,r(t,null,s,n),!n.pop()}}),has:N(function(e){return function(t){return nt(e,t).length>0}}),contains:N(function(e){return function(t){return(t.textContent||t.innerText||s(t)).indexOf(e)>-1}}),enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&!!e.checked||t==="option"&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},parent:function(e){return!i.pseudos.empty(e)},empty:function(e){var t;e=e.firstChild;while(e){if(e.nodeName>"@"||(t=e.nodeType)===3||t===4)return!1;e=e.nextSibling}return!0},header:function(e){return X.test(e.nodeName)},text:function(e){var t,n;return e.nodeName.toLowerCase()==="input"&&(t=e.type)==="text"&&((n=e.getAttribute("type"))==null||n.toLowerCase()===t)},radio:rt("radio"),checkbox:rt("checkbox"),file:rt("file"),password:rt("password"),image:rt("image"),submit:it("submit"),reset:it("reset"),button:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&e.type==="button"||t==="button"},input:function(e){return V.test(e.nodeName)},focus:function(e){var t=e.ownerDocument;return e===t.activeElement&&(!t.hasFocus||t.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},active:function(e){return e===e.ownerDocument.activeElement},first:st(function(){return[0]}),last:st(function(e,t){return[t-1]}),eq:st(function(e,t,n){return[n<0?n+t:n]}),even:st(function(e,t){for(var n=0;n=0;)e.push(r);return e}),gt:st(function(e,t,n){for(var r=n<0?n+t:n;++r",e.querySelectorAll("[selected]").length||i.push("\\["+O+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||i.push(":checked")}),K(function(e){e.innerHTML="

",e.querySelectorAll("[test^='']").length&&i.push("[*^$]="+O+"*(?:\"\"|'')"),e.innerHTML="",e.querySelectorAll(":enabled").length||i.push(":enabled",":disabled")}),i=new RegExp(i.join("|")),vt=function(e,r,s,o,u){if(!o&&!u&&!i.test(e)){var a,f,l=!0,c=d,h=r,p=r.nodeType===9&&e;if(r.nodeType===1&&r.nodeName.toLowerCase()!=="object"){a=ut(e),(l=r.getAttribute("id"))?c=l.replace(n,"\\$&"):r.setAttribute("id",c),c="[id='"+c+"'] ",f=a.length;while(f--)a[f]=c+a[f].join("");h=z.test(e)&&r.parentNode||r,p=a.join(",")}if(p)try{return S.apply(s,x.call(h.querySelectorAll(p),0)),s}catch(v){}finally{l||r.removeAttribute("id")}}return t(e,r,s,o,u)},u&&(K(function(t){e=u.call(t,"div");try{u.call(t,"[test!='']:sizzle"),s.push("!=",H)}catch(n){}}),s=new RegExp(s.join("|")),nt.matchesSelector=function(t,n){n=n.replace(r,"='$1']");if(!o(t)&&!s.test(n)&&!i.test(n))try{var a=u.call(t,n);if(a||e||t.document&&t.document.nodeType!==11)return a}catch(f){}return nt(n,null,null,[t]).length>0})}(),i.pseudos.nth=i.pseudos.eq,i.filters=mt.prototype=i.pseudos,i.setFilters=new mt,nt.attr=v.attr,v.find=nt,v.expr=nt.selectors,v.expr[":"]=v.expr.pseudos,v.unique=nt.uniqueSort,v.text=nt.getText,v.isXMLDoc=nt.isXML,v.contains=nt.contains}(e);var nt=/Until$/,rt=/^(?:parents|prev(?:Until|All))/,it=/^.[^:#\[\.,]*$/,st=v.expr.match.needsContext,ot={children:!0,contents:!0,next:!0,prev:!0};v.fn.extend({find:function(e){var t,n,r,i,s,o,u=this;if(typeof e!="string")return v(e).filter(function(){for(t=0,n=u.length;t0)for(i=r;i=0:v.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,s=[],o=st.test(e)||typeof e!="string"?v(e,t||this.context):0;for(;r-1:v.find.matchesSelector(n,e)){s.push(n);break}n=n.parentNode}}return s=s.length>1?v.unique(s):s,this.pushStack(s,"closest",e)},index:function(e){return e?typeof e=="string"?v.inArray(this[0],v(e)):v.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(e,t){var n=typeof e=="string"?v(e,t):v.makeArray(e&&e.nodeType?[e]:e),r=v.merge(this.get(),n);return this.pushStack(ut(n[0])||ut(r[0])?r:v.unique(r))},addBack:function(e){return this.add(e==null?this.prevObject:this.prevObject.filter(e))}}),v.fn.andSelf=v.fn.addBack,v.each({parent:function(e){var t=e.parentNode;return t&&t.nodeType!==11?t:null},parents:function(e){return v.dir(e,"parentNode")},parentsUntil:function(e,t,n){return v.dir(e,"parentNode",n)},next:function(e){return at(e,"nextSibling")},prev:function(e){return at(e,"previousSibling")},nextAll:function(e){return v.dir(e,"nextSibling")},prevAll:function(e){return v.dir(e,"previousSibling")},nextUntil:function(e,t,n){return v.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return v.dir(e,"previousSibling",n)},siblings:function(e){return v.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return v.sibling(e.firstChild)},contents:function(e){return v.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:v.merge([],e.childNodes)}},function(e,t){v.fn[e]=function(n,r){var i=v.map(this,t,n);return nt.test(e)||(r=n),r&&typeof r=="string"&&(i=v.filter(r,i)),i=this.length>1&&!ot[e]?v.unique(i):i,this.length>1&&rt.test(e)&&(i=i.reverse()),this.pushStack(i,e,l.call(arguments).join(","))}}),v.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),t.length===1?v.find.matchesSelector(t[0],e)?[t[0]]:[]:v.find.matches(e,t)},dir:function(e,n,r){var i=[],s=e[n];while(s&&s.nodeType!==9&&(r===t||s.nodeType!==1||!v(s).is(r)))s.nodeType===1&&i.push(s),s=s[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)e.nodeType===1&&e!==t&&n.push(e);return n}});var ct="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ht=/ jQuery\d+="(?:null|\d+)"/g,pt=/^\s+/,dt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,vt=/<([\w:]+)/,mt=/]","i"),Et=/^(?:checkbox|radio)$/,St=/checked\s*(?:[^=]|=\s*.checked.)/i,xt=/\/(java|ecma)script/i,Tt=/^\s*\s*$/g,Nt={option:[1,""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},Ct=lt(i),kt=Ct.appendChild(i.createElement("div"));Nt.optgroup=Nt.option,Nt.tbody=Nt.tfoot=Nt.colgroup=Nt.caption=Nt.thead,Nt.th=Nt.td,v.support.htmlSerialize||(Nt._default=[1,"X
","
"]),v.fn.extend({text:function(e){return v.access(this,function(e){return e===t?v.text(this):this.empty().append((this[0]&&this[0].ownerDocument||i).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(v.isFunction(e))return this.each(function(t){v(this).wrapAll(e.call(this,t))});if(this[0]){var t=v(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&e.firstChild.nodeType===1)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return v.isFunction(e)?this.each(function(t){v(this).wrapInner(e.call(this,t))}):this.each(function(){var t=v(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=v.isFunction(e);return this.each(function(n){v(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){v.nodeName(this,"body")||v(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(e,this.firstChild)})},before:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(e,this),"before",this.selector)}},after:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this.nextSibling)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(this,e),"after",this.selector)}},remove:function(e,t){var n,r=0;for(;(n=this[r])!=null;r++)if(!e||v.filter(e,[n]).length)!t&&n.nodeType===1&&(v.cleanData(n.getElementsByTagName("*")),v.cleanData([n])),n.parentNode&&n.parentNode.removeChild(n);return this},empty:function(){var e,t=0;for(;(e=this[t])!=null;t++){e.nodeType===1&&v.cleanData(e.getElementsByTagName("*"));while(e.firstChild)e.removeChild(e.firstChild)}return this},clone:function(e,t){return e=e==null?!1:e,t=t==null?e:t,this.map(function(){return v.clone(this,e,t)})},html:function(e){return v.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return n.nodeType===1?n.innerHTML.replace(ht,""):t;if(typeof e=="string"&&!yt.test(e)&&(v.support.htmlSerialize||!wt.test(e))&&(v.support.leadingWhitespace||!pt.test(e))&&!Nt[(vt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(dt,"<$1>");try{for(;r1&&typeof f=="string"&&St.test(f))return this.each(function(){v(this).domManip(e,n,r)});if(v.isFunction(f))return this.each(function(i){var s=v(this);e[0]=f.call(this,i,n?s.html():t),s.domManip(e,n,r)});if(this[0]){i=v.buildFragment(e,this,l),o=i.fragment,s=o.firstChild,o.childNodes.length===1&&(o=s);if(s){n=n&&v.nodeName(s,"tr");for(u=i.cacheable||c-1;a0?this.clone(!0):this).get(),v(o[i])[t](r),s=s.concat(r);return this.pushStack(s,e,o.selector)}}),v.extend({clone:function(e,t,n){var r,i,s,o;v.support.html5Clone||v.isXMLDoc(e)||!wt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(kt.innerHTML=e.outerHTML,kt.removeChild(o=kt.firstChild));if((!v.support.noCloneEvent||!v.support.noCloneChecked)&&(e.nodeType===1||e.nodeType===11)&&!v.isXMLDoc(e)){Ot(e,o),r=Mt(e),i=Mt(o);for(s=0;r[s];++s)i[s]&&Ot(r[s],i[s])}if(t){At(e,o);if(n){r=Mt(e),i=Mt(o);for(s=0;r[s];++s)At(r[s],i[s])}}return r=i=null,o},clean:function(e,t,n,r){var s,o,u,a,f,l,c,h,p,d,m,g,y=t===i&&Ct,b=[];if(!t||typeof t.createDocumentFragment=="undefined")t=i;for(s=0;(u=e[s])!=null;s++){typeof u=="number"&&(u+="");if(!u)continue;if(typeof u=="string")if(!gt.test(u))u=t.createTextNode(u);else{y=y||lt(t),c=t.createElement("div"),y.appendChild(c),u=u.replace(dt,"<$1>"),a=(vt.exec(u)||["",""])[1].toLowerCase(),f=Nt[a]||Nt._default,l=f[0],c.innerHTML=f[1]+u+f[2];while(l--)c=c.lastChild;if(!v.support.tbody){h=mt.test(u),p=a==="table"&&!h?c.firstChild&&c.firstChild.childNodes:f[1]===""&&!h?c.childNodes:[];for(o=p.length-1;o>=0;--o)v.nodeName(p[o],"tbody")&&!p[o].childNodes.length&&p[o].parentNode.removeChild(p[o])}!v.support.leadingWhitespace&&pt.test(u)&&c.insertBefore(t.createTextNode(pt.exec(u)[0]),c.firstChild),u=c.childNodes,c.parentNode.removeChild(c)}u.nodeType?b.push(u):v.merge(b,u)}c&&(u=c=y=null);if(!v.support.appendChecked)for(s=0;(u=b[s])!=null;s++)v.nodeName(u,"input")?_t(u):typeof u.getElementsByTagName!="undefined"&&v.grep(u.getElementsByTagName("input"),_t);if(n){m=function(e){if(!e.type||xt.test(e.type))return r?r.push(e.parentNode?e.parentNode.removeChild(e):e):n.appendChild(e)};for(s=0;(u=b[s])!=null;s++)if(!v.nodeName(u,"script")||!m(u))n.appendChild(u),typeof u.getElementsByTagName!="undefined"&&(g=v.grep(v.merge([],u.getElementsByTagName("script")),m),b.splice.apply(b,[s+1,0].concat(g)),s+=g.length)}return b},cleanData:function(e,t){var n,r,i,s,o=0,u=v.expando,a=v.cache,f=v.support.deleteExpando,l=v.event.special;for(;(i=e[o])!=null;o++)if(t||v.acceptData(i)){r=i[u],n=r&&a[r];if(n){if(n.events)for(s in n.events)l[s]?v.event.remove(i,s):v.removeEvent(i,s,n.handle);a[r]&&(delete a[r],f?delete i[u]:i.removeAttribute?i.removeAttribute(u):i[u]=null,v.deletedIds.push(r))}}}}),function(){var e,t;v.uaMatch=function(e){e=e.toLowerCase();var t=/(chrome)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+)/.exec(e)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(e)||/(msie) ([\w.]+)/.exec(e)||e.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(e)||[];return{browser:t[1]||"",version:t[2]||"0"}},e=v.uaMatch(o.userAgent),t={},e.browser&&(t[e.browser]=!0,t.version=e.version),t.chrome?t.webkit=!0:t.webkit&&(t.safari=!0),v.browser=t,v.sub=function(){function e(t,n){return new e.fn.init(t,n)}v.extend(!0,e,this),e.superclass=this,e.fn=e.prototype=this(),e.fn.constructor=e,e.sub=this.sub,e.fn.init=function(r,i){return i&&i instanceof v&&!(i instanceof e)&&(i=e(i)),v.fn.init.call(this,r,i,t)},e.fn.init.prototype=e.fn;var t=e(i);return e}}();var Dt,Pt,Ht,Bt=/alpha\([^)]*\)/i,jt=/opacity=([^)]*)/,Ft=/^(top|right|bottom|left)$/,It=/^(none|table(?!-c[ea]).+)/,qt=/^margin/,Rt=new RegExp("^("+m+")(.*)$","i"),Ut=new RegExp("^("+m+")(?!px)[a-z%]+$","i"),zt=new RegExp("^([-+])=("+m+")","i"),Wt={BODY:"block"},Xt={position:"absolute",visibility:"hidden",display:"block"},Vt={letterSpacing:0,fontWeight:400},$t=["Top","Right","Bottom","Left"],Jt=["Webkit","O","Moz","ms"],Kt=v.fn.toggle;v.fn.extend({css:function(e,n){return v.access(this,function(e,n,r){return r!==t?v.style(e,n,r):v.css(e,n)},e,n,arguments.length>1)},show:function(){return Yt(this,!0)},hide:function(){return Yt(this)},toggle:function(e,t){var n=typeof e=="boolean";return v.isFunction(e)&&v.isFunction(t)?Kt.apply(this,arguments):this.each(function(){(n?e:Gt(this))?v(this).show():v(this).hide()})}}),v.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Dt(e,"opacity");return n===""?"1":n}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":v.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(!e||e.nodeType===3||e.nodeType===8||!e.style)return;var s,o,u,a=v.camelCase(n),f=e.style;n=v.cssProps[a]||(v.cssProps[a]=Qt(f,a)),u=v.cssHooks[n]||v.cssHooks[a];if(r===t)return u&&"get"in u&&(s=u.get(e,!1,i))!==t?s:f[n];o=typeof r,o==="string"&&(s=zt.exec(r))&&(r=(s[1]+1)*s[2]+parseFloat(v.css(e,n)),o="number");if(r==null||o==="number"&&isNaN(r))return;o==="number"&&!v.cssNumber[a]&&(r+="px");if(!u||!("set"in u)||(r=u.set(e,r,i))!==t)try{f[n]=r}catch(l){}},css:function(e,n,r,i){var s,o,u,a=v.camelCase(n);return n=v.cssProps[a]||(v.cssProps[a]=Qt(e.style,a)),u=v.cssHooks[n]||v.cssHooks[a],u&&"get"in u&&(s=u.get(e,!0,i)),s===t&&(s=Dt(e,n)),s==="normal"&&n in Vt&&(s=Vt[n]),r||i!==t?(o=parseFloat(s),r||v.isNumeric(o)?o||0:s):s},swap:function(e,t,n){var r,i,s={};for(i in t)s[i]=e.style[i],e.style[i]=t[i];r=n.call(e);for(i in t)e.style[i]=s[i];return r}}),e.getComputedStyle?Dt=function(t,n){var r,i,s,o,u=e.getComputedStyle(t,null),a=t.style;return u&&(r=u.getPropertyValue(n)||u[n],r===""&&!v.contains(t.ownerDocument,t)&&(r=v.style(t,n)),Ut.test(r)&&qt.test(n)&&(i=a.width,s=a.minWidth,o=a.maxWidth,a.minWidth=a.maxWidth=a.width=r,r=u.width,a.width=i,a.minWidth=s,a.maxWidth=o)),r}:i.documentElement.currentStyle&&(Dt=function(e,t){var n,r,i=e.currentStyle&&e.currentStyle[t],s=e.style;return i==null&&s&&s[t]&&(i=s[t]),Ut.test(i)&&!Ft.test(t)&&(n=s.left,r=e.runtimeStyle&&e.runtimeStyle.left,r&&(e.runtimeStyle.left=e.currentStyle.left),s.left=t==="fontSize"?"1em":i,i=s.pixelLeft+"px",s.left=n,r&&(e.runtimeStyle.left=r)),i===""?"auto":i}),v.each(["height","width"],function(e,t){v.cssHooks[t]={get:function(e,n,r){if(n)return e.offsetWidth===0&&It.test(Dt(e,"display"))?v.swap(e,Xt,function(){return tn(e,t,r)}):tn(e,t,r)},set:function(e,n,r){return Zt(e,n,r?en(e,t,r,v.support.boxSizing&&v.css(e,"boxSizing")==="border-box"):0)}}}),v.support.opacity||(v.cssHooks.opacity={get:function(e,t){return jt.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=v.isNumeric(t)?"alpha(opacity="+t*100+")":"",s=r&&r.filter||n.filter||"";n.zoom=1;if(t>=1&&v.trim(s.replace(Bt,""))===""&&n.removeAttribute){n.removeAttribute("filter");if(r&&!r.filter)return}n.filter=Bt.test(s)?s.replace(Bt,i):s+" "+i}}),v(function(){v.support.reliableMarginRight||(v.cssHooks.marginRight={get:function(e,t){return v.swap(e,{display:"inline-block"},function(){if(t)return Dt(e,"marginRight")})}}),!v.support.pixelPosition&&v.fn.position&&v.each(["top","left"],function(e,t){v.cssHooks[t]={get:function(e,n){if(n){var r=Dt(e,t);return Ut.test(r)?v(e).position()[t]+"px":r}}}})}),v.expr&&v.expr.filters&&(v.expr.filters.hidden=function(e){return e.offsetWidth===0&&e.offsetHeight===0||!v.support.reliableHiddenOffsets&&(e.style&&e.style.display||Dt(e,"display"))==="none"},v.expr.filters.visible=function(e){return!v.expr.filters.hidden(e)}),v.each({margin:"",padding:"",border:"Width"},function(e,t){v.cssHooks[e+t]={expand:function(n){var r,i=typeof n=="string"?n.split(" "):[n],s={};for(r=0;r<4;r++)s[e+$t[r]+t]=i[r]||i[r-2]||i[0];return s}},qt.test(e)||(v.cssHooks[e+t].set=Zt)});var rn=/%20/g,sn=/\[\]$/,on=/\r?\n/g,un=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,an=/^(?:select|textarea)/i;v.fn.extend({serialize:function(){return v.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?v.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||an.test(this.nodeName)||un.test(this.type))}).map(function(e,t){var n=v(this).val();return n==null?null:v.isArray(n)?v.map(n,function(e,n){return{name:t.name,value:e.replace(on,"\r\n")}}):{name:t.name,value:n.replace(on,"\r\n")}}).get()}}),v.param=function(e,n){var r,i=[],s=function(e,t){t=v.isFunction(t)?t():t==null?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};n===t&&(n=v.ajaxSettings&&v.ajaxSettings.traditional);if(v.isArray(e)||e.jquery&&!v.isPlainObject(e))v.each(e,function(){s(this.name,this.value)});else for(r in e)fn(r,e[r],n,s);return i.join("&").replace(rn,"+")};var ln,cn,hn=/#.*$/,pn=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,dn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,vn=/^(?:GET|HEAD)$/,mn=/^\/\//,gn=/\?/,yn=/)<[^<]*)*<\/script>/gi,bn=/([?&])_=[^&]*/,wn=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,En=v.fn.load,Sn={},xn={},Tn=["*/"]+["*"];try{cn=s.href}catch(Nn){cn=i.createElement("a"),cn.href="",cn=cn.href}ln=wn.exec(cn.toLowerCase())||[],v.fn.load=function(e,n,r){if(typeof e!="string"&&En)return En.apply(this,arguments);if(!this.length)return this;var i,s,o,u=this,a=e.indexOf(" ");return a>=0&&(i=e.slice(a,e.length),e=e.slice(0,a)),v.isFunction(n)?(r=n,n=t):n&&typeof n=="object"&&(s="POST"),v.ajax({url:e,type:s,dataType:"html",data:n,complete:function(e,t){r&&u.each(r,o||[e.responseText,t,e])}}).done(function(e){o=arguments,u.html(i?v("
").append(e.replace(yn,"")).find(i):e)}),this},v.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,t){v.fn[t]=function(e){return this.on(t,e)}}),v.each(["get","post"],function(e,n){v[n]=function(e,r,i,s){return v.isFunction(r)&&(s=s||i,i=r,r=t),v.ajax({type:n,url:e,data:r,success:i,dataType:s})}}),v.extend({getScript:function(e,n){return v.get(e,t,n,"script")},getJSON:function(e,t,n){return v.get(e,t,n,"json")},ajaxSetup:function(e,t){return t?Ln(e,v.ajaxSettings):(t=e,e=v.ajaxSettings),Ln(e,t),e},ajaxSettings:{url:cn,isLocal:dn.test(ln[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":Tn},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":v.parseJSON,"text xml":v.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:Cn(Sn),ajaxTransport:Cn(xn),ajax:function(e,n){function T(e,n,s,a){var l,y,b,w,S,T=n;if(E===2)return;E=2,u&&clearTimeout(u),o=t,i=a||"",x.readyState=e>0?4:0,s&&(w=An(c,x,s));if(e>=200&&e<300||e===304)c.ifModified&&(S=x.getResponseHeader("Last-Modified"),S&&(v.lastModified[r]=S),S=x.getResponseHeader("Etag"),S&&(v.etag[r]=S)),e===304?(T="notmodified",l=!0):(l=On(c,w),T=l.state,y=l.data,b=l.error,l=!b);else{b=T;if(!T||e)T="error",e<0&&(e=0)}x.status=e,x.statusText=(n||T)+"",l?d.resolveWith(h,[y,T,x]):d.rejectWith(h,[x,T,b]),x.statusCode(g),g=t,f&&p.trigger("ajax"+(l?"Success":"Error"),[x,c,l?y:b]),m.fireWith(h,[x,T]),f&&(p.trigger("ajaxComplete",[x,c]),--v.active||v.event.trigger("ajaxStop"))}typeof e=="object"&&(n=e,e=t),n=n||{};var r,i,s,o,u,a,f,l,c=v.ajaxSetup({},n),h=c.context||c,p=h!==c&&(h.nodeType||h instanceof v)?v(h):v.event,d=v.Deferred(),m=v.Callbacks("once memory"),g=c.statusCode||{},b={},w={},E=0,S="canceled",x={readyState:0,setRequestHeader:function(e,t){if(!E){var n=e.toLowerCase();e=w[n]=w[n]||e,b[e]=t}return this},getAllResponseHeaders:function(){return E===2?i:null},getResponseHeader:function(e){var n;if(E===2){if(!s){s={};while(n=pn.exec(i))s[n[1].toLowerCase()]=n[2]}n=s[e.toLowerCase()]}return n===t?null:n},overrideMimeType:function(e){return E||(c.mimeType=e),this},abort:function(e){return e=e||S,o&&o.abort(e),T(0,e),this}};d.promise(x),x.success=x.done,x.error=x.fail,x.complete=m.add,x.statusCode=function(e){if(e){var t;if(E<2)for(t in e)g[t]=[g[t],e[t]];else t=e[x.status],x.always(t)}return this},c.url=((e||c.url)+"").replace(hn,"").replace(mn,ln[1]+"//"),c.dataTypes=v.trim(c.dataType||"*").toLowerCase().split(y),c.crossDomain==null&&(a=wn.exec(c.url.toLowerCase()),c.crossDomain=!(!a||a[1]===ln[1]&&a[2]===ln[2]&&(a[3]||(a[1]==="http:"?80:443))==(ln[3]||(ln[1]==="http:"?80:443)))),c.data&&c.processData&&typeof c.data!="string"&&(c.data=v.param(c.data,c.traditional)),kn(Sn,c,n,x);if(E===2)return x;f=c.global,c.type=c.type.toUpperCase(),c.hasContent=!vn.test(c.type),f&&v.active++===0&&v.event.trigger("ajaxStart");if(!c.hasContent){c.data&&(c.url+=(gn.test(c.url)?"&":"?")+c.data,delete c.data),r=c.url;if(c.cache===!1){var N=v.now(),C=c.url.replace(bn,"$1_="+N);c.url=C+(C===c.url?(gn.test(c.url)?"&":"?")+"_="+N:"")}}(c.data&&c.hasContent&&c.contentType!==!1||n.contentType)&&x.setRequestHeader("Content-Type",c.contentType),c.ifModified&&(r=r||c.url,v.lastModified[r]&&x.setRequestHeader("If-Modified-Since",v.lastModified[r]),v.etag[r]&&x.setRequestHeader("If-None-Match",v.etag[r])),x.setRequestHeader("Accept",c.dataTypes[0]&&c.accepts[c.dataTypes[0]]?c.accepts[c.dataTypes[0]]+(c.dataTypes[0]!=="*"?", "+Tn+"; q=0.01":""):c.accepts["*"]);for(l in c.headers)x.setRequestHeader(l,c.headers[l]);if(!c.beforeSend||c.beforeSend.call(h,x,c)!==!1&&E!==2){S="abort";for(l in{success:1,error:1,complete:1})x[l](c[l]);o=kn(xn,c,n,x);if(!o)T(-1,"No Transport");else{x.readyState=1,f&&p.trigger("ajaxSend",[x,c]),c.async&&c.timeout>0&&(u=setTimeout(function(){x.abort("timeout")},c.timeout));try{E=1,o.send(b,T)}catch(k){if(!(E<2))throw k;T(-1,k)}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var Mn=[],_n=/\?/,Dn=/(=)\?(?=&|$)|\?\?/,Pn=v.now();v.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Mn.pop()||v.expando+"_"+Pn++;return this[e]=!0,e}}),v.ajaxPrefilter("json jsonp",function(n,r,i){var s,o,u,a=n.data,f=n.url,l=n.jsonp!==!1,c=l&&Dn.test(f),h=l&&!c&&typeof a=="string"&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Dn.test(a);if(n.dataTypes[0]==="jsonp"||c||h)return s=n.jsonpCallback=v.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,o=e[s],c?n.url=f.replace(Dn,"$1"+s):h?n.data=a.replace(Dn,"$1"+s):l&&(n.url+=(_n.test(f)?"&":"?")+n.jsonp+"="+s),n.converters["script json"]=function(){return u||v.error(s+" was not called"),u[0]},n.dataTypes[0]="json",e[s]=function(){u=arguments},i.always(function(){e[s]=o,n[s]&&(n.jsonpCallback=r.jsonpCallback,Mn.push(s)),u&&v.isFunction(o)&&o(u[0]),u=o=t}),"script"}),v.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(e){return v.globalEval(e),e}}}),v.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),v.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=i.head||i.getElementsByTagName("head")[0]||i.documentElement;return{send:function(s,o){n=i.createElement("script"),n.async="async",e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,i){if(i||!n.readyState||/loaded|complete/.test(n.readyState))n.onload=n.onreadystatechange=null,r&&n.parentNode&&r.removeChild(n),n=t,i||o(200,"success")},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(0,1)}}}});var Hn,Bn=e.ActiveXObject?function(){for(var e in Hn)Hn[e](0,1)}:!1,jn=0;v.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&Fn()||In()}:Fn,function(e){v.extend(v.support,{ajax:!!e,cors:!!e&&"withCredentials"in e})}(v.ajaxSettings.xhr()),v.support.ajax&&v.ajaxTransport(function(n){if(!n.crossDomain||v.support.cors){var r;return{send:function(i,s){var o,u,a=n.xhr();n.username?a.open(n.type,n.url,n.async,n.username,n.password):a.open(n.type,n.url,n.async);if(n.xhrFields)for(u in n.xhrFields)a[u]=n.xhrFields[u];n.mimeType&&a.overrideMimeType&&a.overrideMimeType(n.mimeType),!n.crossDomain&&!i["X-Requested-With"]&&(i["X-Requested-With"]="XMLHttpRequest");try{for(u in i)a.setRequestHeader(u,i[u])}catch(f){}a.send(n.hasContent&&n.data||null),r=function(e,i){var u,f,l,c,h;try{if(r&&(i||a.readyState===4)){r=t,o&&(a.onreadystatechange=v.noop,Bn&&delete Hn[o]);if(i)a.readyState!==4&&a.abort();else{u=a.status,l=a.getAllResponseHeaders(),c={},h=a.responseXML,h&&h.documentElement&&(c.xml=h);try{c.text=a.responseText}catch(p){}try{f=a.statusText}catch(p){f=""}!u&&n.isLocal&&!n.crossDomain?u=c.text?200:404:u===1223&&(u=204)}}}catch(d){i||s(-1,d)}c&&s(u,f,c,l)},n.async?a.readyState===4?setTimeout(r,0):(o=++jn,Bn&&(Hn||(Hn={},v(e).unload(Bn)),Hn[o]=r),a.onreadystatechange=r):r()},abort:function(){r&&r(0,1)}}}});var qn,Rn,Un=/^(?:toggle|show|hide)$/,zn=new RegExp("^(?:([-+])=|)("+m+")([a-z%]*)$","i"),Wn=/queueHooks$/,Xn=[Gn],Vn={"*":[function(e,t){var n,r,i=this.createTween(e,t),s=zn.exec(t),o=i.cur(),u=+o||0,a=1,f=20;if(s){n=+s[2],r=s[3]||(v.cssNumber[e]?"":"px");if(r!=="px"&&u){u=v.css(i.elem,e,!0)||n||1;do a=a||".5",u/=a,v.style(i.elem,e,u+r);while(a!==(a=i.cur()/o)&&a!==1&&--f)}i.unit=r,i.start=u,i.end=s[1]?u+(s[1]+1)*n:n}return i}]};v.Animation=v.extend(Kn,{tweener:function(e,t){v.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;r-1,f={},l={},c,h;a?(l=i.position(),c=l.top,h=l.left):(c=parseFloat(o)||0,h=parseFloat(u)||0),v.isFunction(t)&&(t=t.call(e,n,s)),t.top!=null&&(f.top=t.top-s.top+c),t.left!=null&&(f.left=t.left-s.left+h),"using"in t?t.using.call(e,f):i.css(f)}},v.fn.extend({position:function(){if(!this[0])return;var e=this[0],t=this.offsetParent(),n=this.offset(),r=er.test(t[0].nodeName)?{top:0,left:0}:t.offset();return n.top-=parseFloat(v.css(e,"marginTop"))||0,n.left-=parseFloat(v.css(e,"marginLeft"))||0,r.top+=parseFloat(v.css(t[0],"borderTopWidth"))||0,r.left+=parseFloat(v.css(t[0],"borderLeftWidth"))||0,{top:n.top-r.top,left:n.left-r.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||i.body;while(e&&!er.test(e.nodeName)&&v.css(e,"position")==="static")e=e.offsetParent;return e||i.body})}}),v.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);v.fn[e]=function(i){return v.access(this,function(e,i,s){var o=tr(e);if(s===t)return o?n in o?o[n]:o.document.documentElement[i]:e[i];o?o.scrollTo(r?v(o).scrollLeft():s,r?s:v(o).scrollTop()):e[i]=s},e,i,arguments.length,null)}}),v.each({Height:"height",Width:"width"},function(e,n){v.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){v.fn[i]=function(i,s){var o=arguments.length&&(r||typeof i!="boolean"),u=r||(i===!0||s===!0?"margin":"border");return v.access(this,function(n,r,i){var s;return v.isWindow(n)?n.document.documentElement["client"+e]:n.nodeType===9?(s=n.documentElement,Math.max(n.body["scroll"+e],s["scroll"+e],n.body["offset"+e],s["offset"+e],s["client"+e])):i===t?v.css(n,r,i,u):v.style(n,r,i,u)},n,o?i:t,o,null)}})}),e.jQuery=e.$=v,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return v})})(window); diff --git a/frontend-masters-exercises/exercises/ex10/npo.js b/frontend-masters-exercises/exercises/ex10/npo.js new file mode 100755 index 0000000..c363ed4 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex10/npo.js @@ -0,0 +1,5 @@ +/*! Native Promise Only + v0.8.1 (c) Kyle Simpson + MIT License: http://getify.mit-license.org +*/ +!function(t,n,e){n[t]=n[t]||e(),"undefined"!=typeof module&&module.exports?module.exports=n[t]:"function"==typeof define&&define.amd&&define(function(){return n[t]})}("Promise","undefined"!=typeof global?global:this,function(){"use strict";function t(t,n){l.add(t,n),h||(h=y(l.drain))}function n(t){var n,e=typeof t;return null==t||"object"!=e&&"function"!=e||(n=t.then),"function"==typeof n?n:!1}function e(){for(var t=0;t0&&t(e,u))}catch(a){i.call(new f(u),a)}}}function i(n){var o=this;o.triggered||(o.triggered=!0,o.def&&(o=o.def),o.msg=n,o.state=2,o.chain.length>0&&t(e,o))}function c(t,n,e,o){for(var r=0;r .toggle, +#feed-2 > .toggle { + position: absolute; + left: 50%; + transform: translate(-50%); + bottom: -25px; +} + +#my-feed { + padding: 5px 15px; + margin: 0px 30px; + display: inline-block; + position: relative; + width: 400px; + height: 500px; + border: 3px solid #000; + background-color: #f0f0f0; + vertical-align: top; +} + +#feed-1 > .content, +#feed-2 > .content, +#my-feed > .content { + position: relative; + width: 100%; + height: 100%; + overflow-y: scroll; +} + +.item { + display: block; + position: relative; + margin: 10px 0px; + padding: 5px; + width: 100%; + color: #000; + overflow: hidden; + white-space: nowrap; + text-decoration: none; + text-overflow: ellipsis; +} + +.item.floating { + cursor: default; + position: absolute; + transition: left 0.3s ease-out, top 0.3s ease-out; + max-width: 214px; + max-height: 100px; +} + +.item.killed { + text-decoration: line-through; +} + +#feed-1 > .content > .item, +#feed-2 > .content > .item { + max-height: 100px; +} + +#feed-1 > .content > .item:hover, +#feed-2 > .content > .item:hover { + background-color: rgba(0,0,0,0.1); +} + +#my-feed > .content > .item { + cursor: default; + max-height: inherit; + white-space: normal; + overflow: auto; + text-overflow: inherit; +} + +.first-list { + background-color: #ffb8b3; +} + +.second-list { + background-color: #b3caff; +} diff --git a/frontend-masters-exercises/exercises/ex10/ui.js b/frontend-masters-exercises/exercises/ex10/ui.js new file mode 100755 index 0000000..2655c99 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex10/ui.js @@ -0,0 +1,238 @@ +(function UI(global){ + "use strict"; + + var $body, $feed_1, $feed_2, $my_feed, + $feed_1_content, $feed_2_content, + $my_feed_content, + + // signal event handler(s) + toggle_clicks, + item_clicks, + + // sequence wrapper(s) + rAF, + docready; + + // pubsub hub + global.EVT = new EventEmitter2(); + + // run everything! + ASQ().runner(setup); + + + // *********************************** + + function *setup() { + // sequence-wrapper for requestAnimationFrame event + // note: this is a one-time event, so sequence OK + rAF = function rAF() { + return ASQ(function asq(done){ + requestAnimationFrame(done); + }); + }, + + // sequence-wrapper for DOM-ready event + // note: this is a one-time event, so sequence OK + docready = function docready() { + return ASQ(function asq(done){ + $(document).ready(done); + }); + }; + + // DOM event handlers from sequences + toggle_clicks = sequenceBasedEventHandler(function *setupToggleClicks(sq){ + toggleFeed( yield sq ); + }); + item_clicks = sequenceBasedEventHandler(function *setupItemClicks(sq){ + selectItem( yield sq ); + }); + + // wait for DOM-ready + yield docready(); + + $body = $(document.body); + + $feed_1 = $("[rel*=js-feed-1]"); + $feed_1_content = $feed_1.children("[rel*=js-content]"); + $feed_1.children("[rel*=js-toggle]") + .on("click",toggle_clicks); + + $feed_2 = $("[rel*=js-feed-2]"); + $feed_2_content = $feed_2.children("[rel*=js-content]"); + $feed_2.children("[rel*=js-toggle]") + .on("click",toggle_clicks); + + $my_feed = $("[rel*=js-my-feed]"); + $my_feed_content = $my_feed.children("[rel*=js-content]"); + $my_feed_content.on("click","[rel*=js-item]",noop); + + $feed_1.on("click","[rel*=js-item]",item_clicks); + $feed_2.on("click","[rel*=js-item]",item_clicks); + + EVT.on("feed-insertion",insertFeedItem); + EVT.on("my-feed-insertion",ASQ.wrap(insertMyFeedItem,{ gen: true, spread: true })); + EVT.on("feed-kill",ASQ.wrap(killFeedItem,{ gen: true, spread: true })); + + // signal the feeds setup to proceed + EVT.emit("setup-feeds"); + } + + function toggleFeed($btn) { + var $feed = $btn.closest("[rel*=js-feed-]"); + var feed_id = Number( $feed.attr("rel").substr(8) ); + var running = ($feed.attr("data-paused") !== "true"); + + // currently running feed? + if (running) { + // pause it + $feed.attr({ "data-paused": "true" }); + $btn.text("resume"); + } + // paused feed + else { + // resume it + $feed.removeAttr("data-paused"); + $btn.text("pause list"); + } + + // signal status message + EVT.emit("status-" + feed_id,!running); + } + + function insertFeedItem(feedID,itemText) { + var $content; + + // which feed to insert into? + if (feedID == 1) $content = $feed_1_content; + else if (feedID == 2) $content = $feed_2_content; + + var $item = $("") + .addClass("item") + .attr({ href: "#", rel: "js-item" }) + .text(itemText); + + $content.prepend($item); + + var $items = $content.children("[rel*=js-item]"); + if ($items.length > 20) { + $items.last().remove(); + } + } + + function selectItem($item) { + // item not yet killed? + if (!$item.is(".killed")) { + var $feed = $item.closest("[rel*=js-feed-]"); + var feed_id = Number( $feed.attr("rel").substr(8) ); + + // signal item selection + EVT.emit("item-selection",feed_id,$item.text(),$item); + } + } + + function *insertMyFeedItem(feed_id,$item) { + var $floating_item = $item.clone().addClass("floating"); + + if (feed_id == 1) $floating_item.addClass("first-list"); + else if (feed_id == 2) $floating_item.addClass("second-list"); + + var item_dims = $item.offset(); + var item_margin_left = parseInt($item.css("margin-left"),10); + var item_margin_top = parseInt($item.css("margin-top"),10); + + $floating_item.css({ + left: (Math.round(item_dims.left) - item_margin_left) + "px", + top: (Math.round(item_dims.top) - item_margin_top) + "px" + }) + .appendTo($body); + + $item.remove(); + + // wait for the next animation frame (CSS junk) + yield rAF(); + + var my_feed_dims = $my_feed_content.offset(); + + $floating_item.css({ + left: Math.round(my_feed_dims.left) + "px", + top: Math.round(my_feed_dims.top) + "px" + }); + + // wait for the transition to end + yield fromEventOnce($floating_item,"transitionend"); + + $floating_item + .unbind("transitionend") + .css({ left: "", top: "" }) + .removeClass("floating") + .prependTo($my_feed_content); + } + + function *killFeedItem($item) { + $item.addClass("killed"); + + // wait for a second + yield ASQ.after(1000); + + $item.remove(); + } + + // bridge DOM events to sequences + function fromEventOnce($el,evtName,defineSequenceChain) { + var sq = ASQ.iterable(); + + $el.on(evtName,onevt); + + return sq; + + + // *********************************** + + function onevt(evt) { + noop(evt); + + // unbind event handler since sequences are + // resolvable only once + $el.off(evtName,onevt); + + sq.next($(evt.target)); + } + } + + function sequenceBasedEventHandler(defineSequenceChain) { + var sq; + + defineSequenceChain = ASQ.wrap(defineSequenceChain,{ gen: true, spread: true }); + + // start out with a sequence + getNextSequence(); + + return eventHandler; + + // *********************************** + + function eventHandler(evt) { + noop(evt); + + // resolve previous sequence + sq.next($(evt.target)); + + // get the next sequence ready in case + // this event fires again + getNextSequence(); + } + + function getNextSequence() { + sq = ASQ.iterable(); + + defineSequenceChain(ASQ.messages(sq)); + } + } + + function noop(evt) { + evt.preventDefault(); + evt.stopPropagation(); + evt.stopImmediatePropagation(); + } + +})(window); diff --git a/frontend-masters-exercises/exercises/ex2/README.md b/frontend-masters-exercises/exercises/ex2/README.md new file mode 100755 index 0000000..626c49b --- /dev/null +++ b/frontend-masters-exercises/exercises/ex2/README.md @@ -0,0 +1,9 @@ +# Instructions + +1. You'll do the same thing as the previous exercise(s), but now you should use thunks. + +2. Expected behavior: + - Request all 3 files at the same time (in "parallel"). + - Render them ASAP (don't just blindly wait for all to finish loading) + - BUT, render them in proper (obvious) order: "file1", "file2", "file3". + - After all 3 are done, output "Complete!". diff --git a/frontend-masters-exercises/exercises/ex2/ex2-fixed.html b/frontend-masters-exercises/exercises/ex2/ex2-fixed.html new file mode 100755 index 0000000..22db9bb --- /dev/null +++ b/frontend-masters-exercises/exercises/ex2/ex2-fixed.html @@ -0,0 +1,13 @@ + + + + +Exercise 2 - Fixed + + +

Exercise 2 - Fixed

+ + + + + diff --git a/frontend-masters-exercises/exercises/ex2/ex2-fixed.js b/frontend-masters-exercises/exercises/ex2/ex2-fixed.js new file mode 100755 index 0000000..3c82b52 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex2/ex2-fixed.js @@ -0,0 +1,50 @@ +function fakeAjax(url,cb) { + var fake_responses = { + "file1": "The first text", + "file2": "The middle text", + "file3": "The last text" + }; + var randomDelay = (Math.round(Math.random() * 1E4) % 8000) + 1000; + + console.log("Requesting: " + url); + + setTimeout(function(){ + cb(fake_responses[url]); + },randomDelay); +} + +function output(text) { + console.log(text); +} + +// ************************************** + +function getFile(file) { + var resp; + + fakeAjax(file,function(text){ + if (!resp) resp = text; + else resp(text); + }); + + return function th(cb) { + if (resp) cb(resp); + else resp = cb; + }; +} + +// request all files at once in "parallel" +var th1 = getFile("file1"); +var th2 = getFile("file2"); +var th3 = getFile("file3"); + +th1(function ready(text){ + output(text); + th2(function ready(text){ + output(text); + th3(function ready(text){ + output(text); + output("Complete!"); + }); + }); +}); diff --git a/frontend-masters-exercises/exercises/ex2/ex2.html b/frontend-masters-exercises/exercises/ex2/ex2.html new file mode 100755 index 0000000..f858f4c --- /dev/null +++ b/frontend-masters-exercises/exercises/ex2/ex2.html @@ -0,0 +1,13 @@ + + + + +Exercise 2 + + +

Exercise 2

+ + + + + diff --git a/frontend-masters-exercises/exercises/ex2/ex2.js b/frontend-masters-exercises/exercises/ex2/ex2.js new file mode 100755 index 0000000..0d738b0 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex2/ex2.js @@ -0,0 +1,27 @@ +function fakeAjax(url,cb) { + var fake_responses = { + "file1": "The first text", + "file2": "The middle text", + "file3": "The last text" + }; + var randomDelay = (Math.round(Math.random() * 1E4) % 8000) + 1000; + + console.log("Requesting: " + url); + + setTimeout(function(){ + cb(fake_responses[url]); + },randomDelay); +} + +function output(text) { + console.log(text); +} + +// ************************************** + +function getFile(file) { + // what do we do here? +} + +// request all files at once in "parallel" +// ??? diff --git a/frontend-masters-exercises/exercises/ex3/README.md b/frontend-masters-exercises/exercises/ex3/README.md new file mode 100755 index 0000000..3565e50 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex3/README.md @@ -0,0 +1,9 @@ +# Instructions + +1. You'll do the same thing as the previous exercise(s), but now you should use promises. + +2. Expected behavior: + - Request all 3 files at the same time (in "parallel"). + - Render them ASAP (don't just blindly wait for all to finish loading) + - BUT, render them in proper (obvious) order: "file1", "file2", "file3". + - After all 3 are done, output "Complete!". diff --git a/frontend-masters-exercises/exercises/ex3/ex3-fixed.html b/frontend-masters-exercises/exercises/ex3/ex3-fixed.html new file mode 100755 index 0000000..abc2494 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex3/ex3-fixed.html @@ -0,0 +1,14 @@ + + + + +Exercise 3 - Fixed + + +

Exercise 3 - Fixed

+ + + + + + diff --git a/frontend-masters-exercises/exercises/ex3/ex3-fixed.js b/frontend-masters-exercises/exercises/ex3/ex3-fixed.js new file mode 100755 index 0000000..9a97735 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex3/ex3-fixed.js @@ -0,0 +1,49 @@ +function fakeAjax(url,cb) { + var fake_responses = { + "file1": "The first text", + "file2": "The middle text", + "file3": "The last text" + }; + var randomDelay = (Math.round(Math.random() * 1E4) % 8000) + 1000; + + console.log("Requesting: " + url); + + setTimeout(function(){ + cb(fake_responses[url]); + },randomDelay); +} + +function output(text) { + console.log(text); +} + +// ************************************** + +function getFile(file) { + return new Promise(function(resolve){ + fakeAjax(file,resolve); + }); +} + +// Request all files at once in +// "parallel" via `getFile(..)`. +var p1 = getFile("file1"); +var p2 = getFile("file2"); +var p3 = getFile("file3"); + +// Render as each one finishes, +// but only once previous rendering +// is done. +p1 +.then(output) +.then(function(){ + return p2; +}) +.then(output) +.then(function(){ + return p3; +}) +.then(output) +.then(function(){ + output("Complete!"); +}); diff --git a/frontend-masters-exercises/exercises/ex3/ex3.html b/frontend-masters-exercises/exercises/ex3/ex3.html new file mode 100755 index 0000000..33e5265 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex3/ex3.html @@ -0,0 +1,14 @@ + + + + +Exercise 3 + + +

Exercise 3

+ + + + + + diff --git a/frontend-masters-exercises/exercises/ex3/ex3.js b/frontend-masters-exercises/exercises/ex3/ex3.js new file mode 100755 index 0000000..0d738b0 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex3/ex3.js @@ -0,0 +1,27 @@ +function fakeAjax(url,cb) { + var fake_responses = { + "file1": "The first text", + "file2": "The middle text", + "file3": "The last text" + }; + var randomDelay = (Math.round(Math.random() * 1E4) % 8000) + 1000; + + console.log("Requesting: " + url); + + setTimeout(function(){ + cb(fake_responses[url]); + },randomDelay); +} + +function output(text) { + console.log(text); +} + +// ************************************** + +function getFile(file) { + // what do we do here? +} + +// request all files at once in "parallel" +// ??? diff --git a/frontend-masters-exercises/exercises/ex3/npo.js b/frontend-masters-exercises/exercises/ex3/npo.js new file mode 100755 index 0000000..c363ed4 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex3/npo.js @@ -0,0 +1,5 @@ +/*! Native Promise Only + v0.8.1 (c) Kyle Simpson + MIT License: http://getify.mit-license.org +*/ +!function(t,n,e){n[t]=n[t]||e(),"undefined"!=typeof module&&module.exports?module.exports=n[t]:"function"==typeof define&&define.amd&&define(function(){return n[t]})}("Promise","undefined"!=typeof global?global:this,function(){"use strict";function t(t,n){l.add(t,n),h||(h=y(l.drain))}function n(t){var n,e=typeof t;return null==t||"object"!=e&&"function"!=e||(n=t.then),"function"==typeof n?n:!1}function e(){for(var t=0;t0&&t(e,u))}catch(a){i.call(new f(u),a)}}}function i(n){var o=this;o.triggered||(o.triggered=!0,o.def&&(o=o.def),o.msg=n,o.state=2,o.chain.length>0&&t(e,o))}function c(t,n,e,o){for(var r=0;r + + + +Exercise 4 - Fixed + + +

Exercise 4 - Fixed

+ + + + + diff --git a/frontend-masters-exercises/exercises/ex4/ex4-fixed.js b/frontend-masters-exercises/exercises/ex4/ex4-fixed.js new file mode 100755 index 0000000..5dd3575 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex4/ex4-fixed.js @@ -0,0 +1,48 @@ +function fakeAjax(url,cb) { + var fake_responses = { + "file1": "The first text", + "file2": "The middle text", + "file3": "The last text" + }; + var randomDelay = (Math.round(Math.random() * 1E4) % 8000) + 1000; + + console.log("Requesting: " + url); + + setTimeout(function(){ + cb(fake_responses[url]); + },randomDelay); +} + +function output(text) { + console.log(text); +} + +// ************************************** + +function getFile(file) { + return new Promise(function(resolve){ + fakeAjax(file,resolve); + }); +} + +// Request all files at once in +// "parallel" via `getFile(..)`. +// +// Render as each one finishes, +// but only once previous rendering +// is done. +["file1","file2","file3"] +.map(getFile) +.reduce( + function(chain,filePromise){ + return chain + .then(function(){ + return filePromise; + }) + .then(output); + }, + Promise.resolve() // fulfilled promise to start chain +) +.then(function() { + output("Complete!"); +}); diff --git a/frontend-masters-exercises/exercises/ex4/ex4.html b/frontend-masters-exercises/exercises/ex4/ex4.html new file mode 100755 index 0000000..1d96dfb --- /dev/null +++ b/frontend-masters-exercises/exercises/ex4/ex4.html @@ -0,0 +1,13 @@ + + + + +Exercise 4 + + +

Exercise 4

+ + + + + diff --git a/frontend-masters-exercises/exercises/ex4/ex4.js b/frontend-masters-exercises/exercises/ex4/ex4.js new file mode 100755 index 0000000..341ad9c --- /dev/null +++ b/frontend-masters-exercises/exercises/ex4/ex4.js @@ -0,0 +1,36 @@ +function fakeAjax(url,cb) { + var fake_responses = { + "file1": "The first text", + "file2": "The middle text", + "file3": "The last text" + }; + var randomDelay = (Math.round(Math.random() * 1E4) % 8000) + 1000; + + console.log("Requesting: " + url); + + setTimeout(function(){ + cb(fake_responses[url]); + },randomDelay); +} + +function output(text) { + console.log(text); +} + +// ************************************** +// The old-n-busted callback way + +function getFile(file) { + return new Promise(function(resolve){ + fakeAjax(file,resolve); + }); +} + +// Request all files at once in +// "parallel" via `getFile(..)`. +// +// Render as each one finishes, +// but only once previous rendering +// is done. + +// ??? diff --git a/frontend-masters-exercises/exercises/ex4/npo.js b/frontend-masters-exercises/exercises/ex4/npo.js new file mode 100755 index 0000000..c363ed4 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex4/npo.js @@ -0,0 +1,5 @@ +/*! Native Promise Only + v0.8.1 (c) Kyle Simpson + MIT License: http://getify.mit-license.org +*/ +!function(t,n,e){n[t]=n[t]||e(),"undefined"!=typeof module&&module.exports?module.exports=n[t]:"function"==typeof define&&define.amd&&define(function(){return n[t]})}("Promise","undefined"!=typeof global?global:this,function(){"use strict";function t(t,n){l.add(t,n),h||(h=y(l.drain))}function n(t){var n,e=typeof t;return null==t||"object"!=e&&"function"!=e||(n=t.then),"function"==typeof n?n:!1}function e(){for(var t=0;t0&&t(e,u))}catch(a){i.call(new f(u),a)}}}function i(n){var o=this;o.triggered||(o.triggered=!0,o.def&&(o=o.def),o.msg=n,o.state=2,o.chain.length>0&&t(e,o))}function c(t,n,e,o){for(var r=0;r0){u=!1,a=s.shift(),c=g.slice(),g.length=0,c.unshift(createStepCompletion());try{a.apply(h,c)}catch(i){l(i)?$=$.concat(i):$.push(i),n=!0,scheduleSequenceTick()}}}function createStepCompletion(){function done(){n||r||u||(u=!0,g.push.apply(g,arguments),$.length=0,scheduleSequenceTick())}return done.fail=function $$step$fail(){n||r||u||(n=!0,g.length=0,$.push.apply($,arguments),scheduleSequenceTick())},done.abort=function $$step$abort(){n||r||(u=!1,r=!0,g.length=$.length=0,scheduleSequenceTick())},done.errfcb=function $$step$errfcb(e){e?done.fail(e):done.apply(h,f.call(arguments,1))},done}function createGate(e,t,u){function resetGate(){clearTimeout(s),s=d=m=o=null}function scheduleGateTick(){return g?gateTick():void(s||(s=schedule(gateTick)))}function gateTick(){if(!(n||r||$)){var t=[];s=null,p?(e.fail.apply(h,o),resetGate()):g?(e.abort(),resetGate()):checkGate()&&($=!0,d.forEach(function $$each(e,n){t.push(m["s"+n])}),e.apply(h,t),resetGate())}}function checkGate(){if(0!==d.length){var e=!0;return d.some(function $$some(n){return null===n?(e=!1,!0):void 0}),e}}function createSegmentCompletion(){function done(){if(!(n||r||p||g||$||d[e])){var t=c.apply(h,arguments);m["s"+e]=t.length>1?t:t[0],d[e]=!0,scheduleGateTick()}}var e=d.length;return done.fail=function $$segment$fail(){n||r||p||g||$||d[e]||(p=!0,o=f.call(arguments),scheduleGateTick())},done.abort=function $$segment$abort(){n||r||p||g||$||(g=!0,gateTick())},done.errfcb=function $$segment$errfcb(e){e?done.fail(e):done.apply(h,f.call(arguments,1))},d[e]=null,done}var a,i,o,s,p=!1,g=!1,$=!1,d=[],m={};t.some(function $$some(e){if(p||g)return!0;a=u.slice(),a.unshift(createSegmentCompletion());try{e.apply(h,a)}catch(n){return i=n,p=!0,!0}}),i&&(l(i)?e.fail.apply(h,i):e.fail(i))}function then(){return n||r||0===arguments.length?d:(wrapArgs(arguments,thenWrapper).forEach(function $$each(e){i(e)?seq(e):s.push(e)}),scheduleSequenceTick(),d)}function or(){return r||0===arguments.length?d:(p.push.apply(p,arguments),scheduleSequenceTick(),d)}function gate(){if(n||r||0===arguments.length)return d;var e=f.call(arguments).map(function $$map(e){var n;return i(e)?(n={seq:e},tapSequence(n),function $$segment(e){n.seq.pipe(e)}):e});return then(function $$then(n){var t=f.call(arguments,1);createGate(n,e,t)}),d}function pipe(){return r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){then(function $$then(n){e.apply(h,f.call(arguments,1)),n()}).or(e.fail)}),d)}function seq(){return n||r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){var n={seq:e};i(e)&&tapSequence(n),then(function $$then(e){var t=n.seq;i(t)||(t=n.seq.apply(h,f.call(arguments,1))),t.pipe(e)})}),d)}function val(){return n||r||0===arguments.length?d:(f.call(wrapArgs(arguments,valWrapper)).forEach(function $$each(e){then(function $$then(n){var t=e.apply(h,f.call(arguments,1));l(t)||(t=c(t)),n.apply(h,t)})}),d)}function promise(){function wrap(e){return function $$fn(){e.apply(h,l(arguments[0])?arguments[0]:arguments)}}return n||r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){then(function $$then(n){var t=e;"function"==typeof e&&"function"!=typeof e.then&&(t=e.apply(h,f.call(arguments,1))),t.then(wrap(n),wrap(n.fail))})}),d)}function fork(){var e;return val(function $$val(){return e?e.apply(h,arguments):e=createSequence.apply(h,arguments).defer(),c.apply(h,arguments)}),or(function $$or(){if(e)e.fail.apply(h,arguments);else{var n=f.call(arguments);e=createSequence().then(function $$then(e){e.fail.apply(h,n)}).defer()}}),createSequence().then(function $$then(n){e?e.pipe(n):e=n}).defer()}function abort(){return n?d:(r=!0,sequenceTick(),d)}function duplicate(){var e;return a={then_queue:s.slice(),or_queue:p.slice()},e=createSequence(),a=null,e}function unpause(){g.push.apply(g,arguments),e===!0&&(e=null),scheduleSequenceTick()}function defer(){return p.push(function ignored(){}),d}function internals(e,t){var a=arguments.length>1;switch(e){case"seq_error":if(!a)return n;n=t;break;case"seq_aborted":if(!a)return r;r=t;break;case"then_ready":if(!a)return u;u=t;break;case"then_queue":return s;case"or_queue":return p;case"sequence_messages":return g;case"sequence_errors":return $}}function includeExtensions(){Object.keys(o).forEach(function $$each(e){d[e]=o[e](d,internals)})}var e,n=!1,t=!1,r=!1,u=!0,s=[],p=[],g=[],$=[],d=brandIt({then:then,or:or,onerror:or,gate:gate,all:gate,pipe:pipe,seq:seq,val:val,promise:promise,fork:fork,abort:abort,duplicate:duplicate,defer:defer});return includeExtensions(),a&&(s=a.then_queue.slice(),p=a.or_queue.slice(),d.unpause=unpause,e=!0),d.then.apply(h,arguments),d}function brandIt(e){return Object.defineProperty(e,p,{enumerable:!1,value:!0})}function checkBranding(e){return!(null==e||"object"!=typeof e||!e[p])}function valWrapper(e){return c.apply(h,f.call(arguments).slice(1,e+1))}function thenWrapper(e){arguments[e+1].apply(h,f.call(arguments).slice(1,e+1))}function wrapArgs(e,n){var t,r;for(e=f.call(e),t=0;t 1 ? + ARRAY_SLICE.call(arguments,1) : + void 0 + ; + num = +num || 0; + + api.then(function $$then(done){ + var args = orig_args || ARRAY_SLICE.call(arguments,1); + + setTimeout(function $$set$timeout(){ + done.apply(ø,args); + },num); + }); + + return api; + }; +}); + +ASQ.after = function $$after() { + return ASQ().after.apply(ø,arguments); +}; +// "any" +ASQ.extend("any",function $$extend(api,internals){ + return function $$any() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + function reset() { + finished = true; + error_messages.length = 0; + success_messages.length = 0; + } + + function complete(trigger) { + if (success_messages.length > 0) { + // any successful segment's message(s) sent + // to main sequence to proceed as success + success_messages.length = fns.length; + trigger.apply(ø,success_messages); + } + else { + // send errors into main sequence + error_messages.length = fns.length; + trigger.fail.apply(ø,error_messages); + } + + reset(); + } + + function success(trigger,idx,args) { + if (!finished) { + completed++; + success_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + + // all segments complete? + if (completed === fns.length) { + finished = true; + + complete(trigger); + } + } + } + + function failure(trigger,idx,args) { + if (!finished && + !(idx in error_messages) + ) { + completed++; + error_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + } + + // all segments complete? + if (!finished && + completed === fns.length + ) { + finished = true; + + complete(trigger); + } + } + + var completed = 0, error_messages = [], finished = false, + success_messages = [], + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)) + ; + + wrapGate(sq,fns,success,failure,reset); + + sq.pipe(done); + }); + + return api; + }; +}); +// "errfcb" +ASQ.extend("errfcb",function $$extend(api,internals){ + return function $$errfcb() { + // create a fake sequence to extract the callbacks + var sq = { + val: function $$then(cb){ sq.val_cb = cb; return sq; }, + or: function $$or(cb){ sq.or_cb = cb; return sq; } + }; + + // trick `seq(..)`s checks for a sequence + sq[brand] = true; + + // immediately register our fake sequence on the + // main sequence + api.seq(sq); + + // provide the "error-first" callback + return function $$errorfirst$callback(err) { + if (err) { + sq.or_cb(err); + } + else { + sq.val_cb.apply(ø,ARRAY_SLICE.call(arguments,1)); + } + }; + }; +}); +// "failAfter" +ASQ.extend("failAfter",function $$extend(api,internals){ + return function $$failAfter(num) { + var args = arguments.length > 1 ? + ARRAY_SLICE.call(arguments,1) : + void 0 + ; + num = +num || 0; + + api.then(function $$then(done){ + setTimeout(function $$set$timeout(){ + done.fail.apply(ø,args); + },num); + }); + + return api; + }; +}); + +ASQ.failAfter = function $$fail$after() { + return ASQ().failAfter.apply(ø,arguments); +}; +// "first" +ASQ.extend("first",function $$extend(api,internals){ + return function $$first() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + function reset() { + error_messages.length = 0; + } + + function success(trigger,idx,args) { + if (!finished) { + finished = true; + + // first successful segment triggers + // main sequence to proceed as success + trigger( + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ); + + reset(); + } + } + + function failure(trigger,idx,args) { + if (!finished && + !(idx in error_messages) + ) { + completed++; + error_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + + // all segments complete without success? + if (completed === fns.length) { + finished = true; + + // send errors into main sequence + error_messages.length = fns.length; + trigger.fail.apply(ø,error_messages); + + reset(); + } + } + } + + var completed = 0, error_messages = [], finished = false, + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)) + ; + + wrapGate(sq,fns,success,failure,reset); + + sq.pipe(done); + }); + + return api; + }; +}); +// "go-style CSP" +(function IIFE(){ + + // filter out already-resolved queue entries + function filterResolved(queue) { + return queue.filter(function $$filter(entry){ + return !entry.resolved; + }); + } + + function closeQueue(queue,finalValue) { + queue.forEach(function $$each(iter){ + if (!iter.resolved) { + iter.next(); + iter.next(finalValue); + } + }); + queue.length = 0; + } + + function channel(bufSize) { + var ch = { + close: function $$close(){ + ch.closed = true; + closeQueue(ch.put_queue,false); + closeQueue(ch.take_queue,ASQ.csp.CLOSED); + }, + closed: false, + messages: [], + put_queue: [], + take_queue: [], + buffer_size: +bufSize || 0 + }; + return ch; + } + + function unblock(iter) { + if (iter && !iter.resolved) { + iter.next(iter.next().value); + } + } + + function put(channel,value) { + var ret; + + if (channel.closed) { + return false; + } + + // remove already-resolved entries + channel.put_queue = filterResolved(channel.put_queue); + channel.take_queue = filterResolved(channel.take_queue); + + // immediate put? + if (channel.messages.length < channel.buffer_size) { + channel.messages.push(value); + unblock(channel.take_queue.shift()); + return true; + } + // queued put + else { + channel.put_queue.push( + // make a notifiable iterable for 'put' blocking + ASQ.iterable() + .then(function $$then(){ + if (!channel.closed) { + channel.messages.push(value); + return true; + } + else { + return false; + } + }) + ); + + // wrap a sequence/promise around the iterable + ret = ASQ( + channel.put_queue[channel.put_queue.length - 1] + ); + + // take waiting on this queued put? + if (channel.take_queue.length > 0) { + unblock(channel.put_queue.shift()); + unblock(channel.take_queue.shift()); + } + + return ret; + } + } + + function putAsync(channel,value,cb) { + var ret = ASQ(put(channel,value)); + + if (cb && typeof cb == "function") { + ret.val(cb); + } + else { + return ret; + } + } + + function take(channel) { + var ret; + + try { + ret = takem(channel); + } + catch (err) { + ret = err; + } + + if (ASQ.isSequence(ret)) { + ret.pCatch(function $$pcatch(err){ + return err; + }); + } + + return ret; + } + + function takeAsync(channel,cb) { + var ret = ASQ(take(channel)); + + if (cb && typeof cb == "function") { + ret.val(cb); + } + else { + return ret; + } + } + + function takem(channel) { + var msg; + + if (channel.closed) { + return ASQ.csp.CLOSED; + } + + // remove already-resolved entries + channel.put_queue = filterResolved(channel.put_queue); + channel.take_queue = filterResolved(channel.take_queue); + + // immediate take? + if (channel.messages.length > 0) { + msg = channel.messages.shift(); + unblock(channel.put_queue.shift()); + if (msg instanceof Error) { + throw msg; + } + return msg; + } + // queued take + else { + channel.take_queue.push( + // make a notifiable iterable for 'take' blocking + ASQ.iterable() + .then(function $$then(){ + if (!channel.closed) { + var v = channel.messages.shift(); + if (v instanceof Error) { + throw v; + } + return v; + } + else { + return ASQ.csp.CLOSED; + } + }) + ); + + // wrap a sequence/promise around the iterable + msg = ASQ( + channel.take_queue[channel.take_queue.length - 1] + ); + + // put waiting on this take? + if (channel.put_queue.length > 0) { + unblock(channel.put_queue.shift()); + unblock(channel.take_queue.shift()); + } + + return msg; + } + } + + function takemAsync(channel,cb) { + var ret = ASQ(takem(channel)); + + if (cb && typeof cb == "function") { + ret.pThen(cb,cb); + } + else { + return ret.val(function $$val(v){ + if (v instanceof Error) { + throw v; + } + return v; + }); + } + } + + function alts(actions) { + var closed, open, handlers, i, isq, ret, resolved = false; + + // used `alts(..)` incorrectly? + if (!Array.isArray(actions) || actions.length == 0) { + throw Error("Invalid usage"); + } + + closed = []; + open = []; + handlers = []; + + // separate actions by open/closed channel status + actions.forEach(function $$each(action){ + var channel = Array.isArray(action) ? action[0] : action; + + // remove already-resolved entries + channel.put_queue = filterResolved(channel.put_queue); + channel.take_queue = filterResolved(channel.take_queue); + + if (channel.closed) { + closed.push(channel); + } + else { + open.push(action); + } + }); + + // if no channels are still open, we're done + if (open.length == 0) { + return { value: ASQ.csp.CLOSED, channel: closed }; + } + + // can any channel action be executed immediately? + for (i=0; i 0) { + return { value: take(open[i]), channel: open[i] }; + } + } + + isq = ASQ.iterable(); + var ret = ASQ(isq); + + // setup channel action handlers + for (i=0; i 0) { + schedule(function handleUnblocking(){ + if (!resolved) { + unblock(channel.put_queue.shift()); + unblock(channel.take_queue.shift()); + } + },0); + } + } + // take action? + else { + channel = action; + + // define take handler + handlers.push( + ASQ.iterable() + .then(function $$then(){ + resolved = true; + + // mark all handlers across this `alts(..)` as resolved now + handlers = handlers.filter(function $$filter(handler){ + return !(handler.resolved = true); + }); + + // channel still open? + if (!channel.closed) { + isq.next({ value: channel.messages.shift(), channel: channel }); + } + // channel already closed? + else { + isq.next({ value: ASQ.csp.CLOSED, channel: channel }); + } + }) + ); + + // queue up take handler + channel.take_queue.push(handlers[handlers.length-1]); + + // put waiting on this queued take? + if (channel.put_queue.length > 0) { + schedule(function handleUnblocking(){ + if (!resolved) { + unblock(channel.put_queue.shift()); + unblock(channel.take_queue.shift()); + } + }); + } + } + })(open[i]); + } + + return ret; + } + + function altsAsync(chans,cb) { + var ret = ASQ(alts(chans)); + + if (cb && typeof cb == "function") { + ret.pThen(cb,cb); + } + else { + return ret; + } + } + + function timeout(delay) { + var ch = channel(); + setTimeout(ch.close,delay); + return ch; + } + + function go(gen,args) { + // goroutine arguments passed? + if (arguments.length > 1) { + if (!args || !Array.isArray(args)) { + args = [args]; + } + } + else { + args = []; + } + + return function *$$go(token) { + + // unblock the overall goroutine handling + function unblock() { + token.unblock_count++; + + if (token.block && !token.block.marked) { + token.block.marked = true; + token.block.next(); + } + } + + var ret, msg, err, type, done = false, it; + + // keep track of how many requests for unblocking + // have occurred + token.unblock_count = (token.unblock_count || 0); + + // keep track of how many goroutines are running + // so we can infer when we're done go'ing + token.go_count = (token.go_count || 0) + 1; + + // need to initialize a set of goroutines? + if (token.go_count === 1) { + // create a default channel for these goroutines + token.channel = channel(); + token.channel.messages = token.messages; + token.channel.go = function $$go(){ + // unblock the goroutine handling for this + // new goroutine + unblock(); + // add the goroutine (called with any args) to + // the handling queue + token.add( go.apply(ø,arguments) ); + }; + // starting out with initial channel messages? + if (token.channel.messages.length > 0) { + // fake back-pressure blocking for each + token.channel.put_queue = token.channel.messages.map(function $$map(){ + // make a notifiable iterable for 'put' blocking + return ASQ.iterable() + .then(function $$then(){ + unblock(token.channel.take_queue.shift()); + return !token.channel.closed; + }); + }); + } + } + + // initialize the generator + it = gen.apply(ø,[token.channel].concat(args)); + + (function iterate(){ + + function next() { + // keep going with next step in goroutine? + if (!done) { + iterate(); + } + // unblock overall goroutine handling to + // continue with other goroutines + else { + unblock(); + } + } + + // has a resumption value been achieved yet? + if (!ret) { + // try to resume the goroutine + try { + // resume with injected exception? + if (err) { + ret = it.throw(err); + err = null; + } + // resume normally + else { + ret = it.next(msg); + } + } + // resumption failed, so bail + catch (e) { + done = true; + err = e; + msg = null; + unblock(); + return; + } + + // keep track of the result of the resumption + done = ret.done; + ret = ret.value; + type = typeof ret; + + // if this goroutine is complete, unblock the + // overall goroutine handling + if (done) { + unblock(); + } + + // received a thenable/promise back? + if (isPromise(ret)) { + ret = ASQ().promise(ret); + } + + // wait for the value? + if (ASQ.isSequence(ret)) { + ret.val(function $$val(){ + ret = null; + msg = arguments.length > 1 ? + ASQ.messages.apply(ø,arguments) : + arguments[0] + ; + next(); + }) + .or(function $$or(){ + ret = null; + msg = arguments.length > 1 ? + ASQ.messages.apply(ø,arguments) : + arguments[0] + ; + if (msg instanceof Error) { + err = msg; + msg = null; + } + next(); + }); + } + // immediate value, prepare it to go right back in + else { + msg = ret; + ret = null; + next(); + } + } + })(); + + // keep this goroutine alive until completion + while (!done) { + // transfer control to another goroutine + yield token; + + // need to block overall goroutine handling + // while idle? + if (!done && !token.block && token.unblock_count === 0) { + // wait here while idle + yield (token.block = ASQ.iterable()); + + token.block = false; + } + + if (token.unblock_count > 0) token.unblock_count--; + } + + // this goroutine is done now + token.go_count--; + + // all goroutines done? + if (token.go_count === 0) { + // any lingering blocking need to be cleaned up? + unblock(); + + // capture any untaken messages + msg = ASQ.messages.apply(ø,token.messages); + + // need to implicitly force-close channel? + if (token.channel && !token.channel.closed) { + token.channel.closed = true; + token.channel.put_queue.length = token.channel.take_queue.length = 0; + token.channel.close = token.channel.go = token.channel.messages = null; + } + token.channel = null; + } + + // make sure leftover error or message are + // passed along + if (err) { + throw err; + } + else if (token.go_count === 0) { + return msg; + } + else { + return token; + } + }; + } + + ASQ.csp = { + chan: channel, + put: put, + putAsync: putAsync, + take: take, + takeAsync: takeAsync, + takem: takem, + takemAsync: takemAsync, + alts: alts, + altsAsync: altsAsync, + timeout: timeout, + go: go, + CLOSED: {} + }; + +})(); +// "ASQ.iterable()" +(function IIFE(){ + var template; + + ASQ.iterable = function $$iterable() { + function throwSequenceErrors() { + throw (sequence_errors.length === 1 ? sequence_errors[0] : sequence_errors); + } + + function notifyErrors() { + var fn; + + seq_tick = null; + + if (seq_error) { + if (or_queue.length === 0 && !error_reported) { + error_reported = true; + throwSequenceErrors(); + } + + while (or_queue.length > 0) { + error_reported = true; + fn = or_queue.shift(); + try { + fn.apply(ø,sequence_errors); + } + catch (err) { + if (checkBranding(err)) { + sequence_errors = sequence_errors.concat(err); + } + else { + sequence_errors.push(err); + } + if (or_queue.length === 0) { + throwSequenceErrors(); + } + } + } + } + } + + function val() { + if (seq_error || seq_aborted || arguments.length === 0) { + return sequence_api; + } + + var args = ARRAY_SLICE.call(arguments).map(function mapper(arg){ + if (typeof arg != "function") return function $$val() { return arg; }; + else return arg; + }); + + val_queue.push.apply(val_queue,args); + + return sequence_api; + } + + function or() { + if (seq_aborted || arguments.length === 0) { + return sequence_api; + } + + or_queue.push.apply(or_queue,arguments); + + if (!seq_tick) { + seq_tick = schedule(notifyErrors); + } + + return sequence_api; + } + + function pipe() { + if (seq_aborted || arguments.length === 0) { + return sequence_api; + } + + ARRAY_SLICE.call(arguments) + .forEach(function $$each(fn){ + val(fn).or(fn.fail); + }); + + return sequence_api; + } + + function next() { + if (seq_error || seq_aborted || val_queue.length === 0) { + if (val_queue.length > 0) { + $throw$("Sequence cannot be iterated"); + } + return { done: true }; + } + + try { + return { value: val_queue.shift().apply(ø,arguments) }; + } + catch (err) { + if (ASQ.isMessageWrapper(err)) { + $throw$.apply(ø,err); + } + else { + $throw$(err); + } + + return {}; + } + } + + function $throw$() { + if (seq_error || seq_aborted) { + return sequence_api; + } + + sequence_errors.push.apply(sequence_errors,arguments); + seq_error = true; + if (!seq_tick) { + seq_tick = schedule(notifyErrors); + } + + return sequence_api; + } + + function $return$(val) { + if (seq_error || seq_aborted) { + val = void 0; + } + + abort(); + + return { done: true, value: val }; + } + + function abort() { + if (seq_error || seq_aborted) { + return; + } + + seq_aborted = true; + + clearTimeout(seq_tick); + seq_tick = null; + val_queue.length = or_queue.length = sequence_errors.length = 0; + } + + function duplicate() { + var isq; + + template = { + val_queue: val_queue.slice(), + or_queue: or_queue.slice() + }; + isq = ASQ.iterable(); + template = null; + + return isq; + } + + // opt-out of global error reporting for this sequence + function defer() { + or_queue.push(function $$ignored(){}); + return sequence_api; + } + + // *********************************************** + // Object branding utilities + // *********************************************** + function brandIt(obj) { + Object.defineProperty(obj,brand,{ + enumerable: false, + value: true + }); + + return obj; + } + + var sequence_api, + + seq_error = false, + error_reported = false, + seq_aborted = false, + + seq_tick, + + val_queue = [], + or_queue = [], + + sequence_errors = [] + ; + + // *********************************************** + // Setup the ASQ.iterable() public API + // *********************************************** + sequence_api = brandIt({ + val: val, + then: val, + or: or, + pipe: pipe, + next: next, + "throw": $throw$, + "return": $return$, + abort: abort, + duplicate: duplicate, + defer: defer + }); + + // useful for ES6 `for..of` loops, + // add `@@iterator` to simply hand back + // our iterable sequence itself! + sequence_api[(typeof Symbol == "function" && Symbol.iterator) || "@@iterator"] = function $$iter() { + return sequence_api; + }; + + // templating the iterable-sequence setup? + if (template) { + val_queue = template.val_queue.slice(0); + or_queue = template.or_queue.slice(0); + } + + // treat ASQ.iterable() constructor parameters as having been + // passed to `val()` + sequence_api.val.apply(ø,arguments); + + return sequence_api; + }; + +})(); +// "last" +ASQ.extend("last",function $$extend(api,internals){ + return function $$last() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + function reset() { + finished = true; + error_messages.length = 0; + success_messages = null; + } + + function complete(trigger) { + if (success_messages != null) { + // last successful segment's message(s) sent + // to main sequence to proceed as success + trigger( + success_messages.length > 1 ? + ASQ.messages.apply(ø,success_messages) : + success_messages[0] + ); + } + else { + // send errors into main sequence + error_messages.length = fns.length; + trigger.fail.apply(ø,error_messages); + } + + reset(); + } + + function success(trigger,idx,args) { + if (!finished) { + completed++; + success_messages = args; + + // all segments complete? + if (completed === fns.length) { + finished = true; + + complete(trigger); + } + } + } + + function failure(trigger,idx,args) { + if (!finished && + !(idx in error_messages) + ) { + completed++; + error_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + } + + // all segments complete? + if (!finished && + completed === fns.length + ) { + finished = true; + + complete(trigger); + } + } + + var completed = 0, error_messages = [], finished = false, + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)), + success_messages + ; + + wrapGate(sq,fns,success,failure,reset); + + sq.pipe(done); + }); + + return api; + }; +}); +// "map" +ASQ.extend("map",function $$extend(api,internals){ + return function $$map(pArr,pEach) { + if (internals("seq_error") || internals("seq_aborted")) { + return api; + } + + api.seq(function $$seq(){ + var tmp, args = ARRAY_SLICE.call(arguments), + arr = pArr, each = pEach; + + // if missing `map(..)` args, use value-messages (if any) + if (!each) each = args.shift(); + if (!arr) arr = args.shift(); + + // if arg types in reverse order (each,arr), swap + if (typeof arr === "function" && Array.isArray(each)) { + tmp = arr; + arr = each; + each = tmp; + } + + return ASQ.apply(ø,args) + .gate.apply(ø,arr.map(function $$map(item){ + return function $$segment(){ + each.apply(ø,[item].concat(ARRAY_SLICE.call(arguments))); + }; + })); + }) + .val(function $$val(){ + // collect all gate segment output into one value-message + // Note: return a normal array here, not a message wrapper! + return ARRAY_SLICE.call(arguments); + }); + + return api; + }; +}); +// "none" +ASQ.extend("none",function $$extend(api,internals){ + return function $$none() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + function reset() { + finished = true; + error_messages.length = 0; + success_messages.length = 0; + } + + function complete(trigger) { + if (success_messages.length > 0) { + // any successful segment's message(s) sent + // to main sequence to proceed as **error** + success_messages.length = fns.length; + trigger.fail.apply(ø,success_messages); + } + else { + // send errors as **success** to main sequence + error_messages.length = fns.length; + trigger.apply(ø,error_messages); + } + + reset(); + } + + function success(trigger,idx,args) { + if (!finished) { + completed++; + success_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + + // all segments complete? + if (completed === fns.length) { + finished = true; + + complete(trigger); + } + } + } + + function failure(trigger,idx,args) { + if (!finished && + !(idx in error_messages) + ) { + completed++; + error_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + } + + // all segments complete? + if (!finished && + completed === fns.length + ) { + finished = true; + + complete(trigger); + } + } + + var completed = 0, error_messages = [], finished = false, + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)), + success_messages = [] + ; + + wrapGate(sq,fns,success,failure,reset); + + sq.pipe(done); + }); + + return api; + }; +}); +// "pThen" +ASQ.extend("pThen",function $$extend(api,internals){ + return function $$pthen(success,failure) { + if (internals("seq_aborted")) { + return api; + } + + var ignore_success_handler = false, ignore_failure_handler = false; + + if (typeof success === "function") { + api.then(function $$then(done){ + if (!ignore_success_handler) { + var ret, msgs = ASQ.messages.apply(ø,arguments); + msgs.shift(); + + if (msgs.length === 1) { + msgs = msgs[0]; + } + + ignore_failure_handler = true; + + try { + ret = success(msgs); + } + catch (err) { + if (!ASQ.isMessageWrapper(err)) { + err = [err]; + } + done.fail.apply(ø,err); + return; + } + + // returned a sequence? + if (ASQ.isSequence(ret)) { + ret.pipe(done); + } + // returned a message wrapper? + else if (ASQ.isMessageWrapper(ret)) { + done.apply(ø,ret); + } + // returned a promise/thenable? + else if (isPromise(ret)) { + ret.then(done,done.fail); + } + // just a normal value to pass along + else { + done(ret); + } + } + else { + done.apply(ø,ARRAY_SLICE.call(arguments,1)); + } + }); + } + if (typeof failure === "function") { + api.or(function $$or(){ + if (!ignore_failure_handler) { + var ret, msgs = ASQ.messages.apply(ø,arguments), smgs, + or_queue = ARRAY_SLICE.call(internals("or_queue")) + ; + + if (msgs.length === 1) { + msgs = msgs[0]; + } + + ignore_success_handler = true; + + // NOTE: if this call throws, that'll automatically + // be handled by core as we'd want it to be + ret = failure(msgs); + + // if we get this far: + // first, inject return value (if any) as + // next step's sequence messages + smgs = internals("sequence_messages"); + smgs.length = 0; + if (typeof ret !== "undefined") { + if (!ASQ.isMessageWrapper(ret)) { + ret = [ret]; + } + smgs.push.apply(smgs,ret); + } + + // reset internal error state, because we've exclusively + // handled any errors up to this point of the sequence + internals("sequence_errors").length = 0; + internals("seq_error",false); + internals("then_ready",true); + + // temporarily empty the or-queue + internals("or_queue").length = 0; + + // make sure to schedule success-procession on the chain + api.val(function $$val(){ + // pass thru messages + return ASQ.messages.apply(ø,arguments); + }); + + // at next cycle, reinstate the or-queue (if any) + if (or_queue.length > 0) { + schedule(function $$schedule(){ + api.or.apply(ø,or_queue); + }); + } + } + }); + } + return api; + }; +}); + +// "pCatch" +ASQ.extend("pCatch",function $$extend(api,internals){ + return function $$pcatch(failure) { + if (internals("seq_aborted")) { + return api; + } + + api.pThen(void 0,failure); + + return api; + }; +}); +// "race" +ASQ.extend("race",function $$extend(api,internals){ + return function $$race() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments) + .map(function $$map(v){ + var def; + // tap any directly-provided sequences immediately + if (ASQ.isSequence(v)) { + def = { seq: v }; + tapSequence(def); + return function $$fn(done) { + def.seq.pipe(done); + }; + } + else return v; + }); + + api.then(function $$then(done){ + var args = ARRAY_SLICE.call(arguments); + + fns.forEach(function $$each(fn){ + fn.apply(ø,args); + }); + }); + + return api; + }; +}); +// "react" (reactive sequences) +ASQ.react = function $$react(reactor) { + function next() { + if (!paused) { + if (template) { + var sq = template.duplicate(); + sq.unpause.apply(ø,arguments); + return sq; + } + return ASQ(function $$asq(){ throw "Disabled Sequence"; }); + } + } + + function registerTeardown(fn) { + if (template && typeof fn === "function") { + teardowns.push(fn); + } + } + + var template = ASQ().duplicate(), + teardowns = [], paused = false + ; + + // add reactive sequence kill switch + template.stop = function $$stop() { + if (template) { + template = null; + teardowns.forEach(Function.call,Function.call); + teardowns.length = 0; + } + }; + + template.pause = function $$pause() { + if (!paused && template) { + paused = true; + teardowns.forEach(Function.call,Function.call); + teardowns.length = 0; + } + }; + + template.resume = function $$resume() { + if (paused && template) { + paused = false; + reactor.call(template,next,registerTeardown); + } + }; + + template.push = next; + + next.onStream = function $$onStream() { + ARRAY_SLICE.call(arguments) + .forEach(function $$each(stream){ + stream.on("data",next); + stream.on("error",next); + }); + }; + + next.unStream = function $$unStream() { + ARRAY_SLICE.call(arguments) + .forEach(function $$each(stream){ + stream.removeListener("data",next); + stream.removeListener("error",next); + }); + }; + + // make sure `reactor(..)` is called async + ASQ.__schedule(function $$schedule(){ + reactor.call(template,next,registerTeardown); + }); + + return template; +}; +// "react" helpers +(function IIFE(){ + + var Ar = ASQ.react; + + Ar.of = function $$react$of() { + function reactor(next) { + if (!started) { + started = true; + if (args.length > 0) { + args.shift().val(function val(){ + next.apply(ø,arguments); + if (args.length > 0) { + args.shift().val(val); + } + }); + } + } + } + + var started, args = ARRAY_SLICE.call(arguments) + .map(function wrapper(arg){ + if (!ASQ.isSequence(arg)) arg = ASQ(arg); + return arg; + }); + + return Ar(reactor); + }; + + Ar.all = Ar.zip = makeReactOperator(/*buffer=*/true); + Ar.allLatest = makeReactOperator(/*buffer=false*/); + Ar.latest = Ar.combineLatest = makeReactOperator(/*buffer=*/false,/*keep=*/true); + + Ar.any = Ar.merge = function $$react$any(){ + function reactor(next,registerTeardown){ + function processSequence(def){ + function trigger(){ + var args = ASQ.messages.apply(ø,arguments); + // still observing sequence-streams? + if (seqs && seqs.length > 0) { + // fire off reactive sequence instance + next.apply(ø,args); + } + // keep sequence going + return args; + } + + // sequence-stream event listener + def.seq.val(trigger); + } + + // observe all sequence-streams + seqs.forEach(processSequence); + + // listen for stop() of reactive sequence + registerTeardown(function $$teardown(){ + seqs = null; + }); + } + + // observe all sequence-streams + var seqs = tapSequences.apply(null,arguments); + + if (seqs.length == 0) return; + + return Ar(reactor); + }; + + Ar.distinct = function $$react$distinct(seq){ + return Ar.filter(seq,makeDistinctFilterer(/*keepAll=*/true)); + }; + + Ar.distinctConsecutive = Ar.distinctUntilChanged = function $$react$distinct$consecutive(seq) { + return Ar.filter(seq,makeDistinctFilterer(/*keepAll=*/false)); + }; + + Ar.filter = function $$react$filter(seq,filterer){ + function reactor(next,registerTeardown) { + function trigger(){ + var messages = ASQ.messages.apply(ø,arguments); + + if (filterer && filterer.apply(ø,messages)) { + // fire off reactive sequence instance + next.apply(ø,messages); + } + + // keep sequence going + return messages; + } + + // sequence-stream event listener + def.seq.val(trigger); + + // listen for stop() of reactive sequence + registerTeardown(function $$teardown(){ + def = filterer = null; + }); + } + + // observe sequence-stream + var def = tapSequences(seq)[0]; + + if (!def) return; + + return Ar(reactor); + }; + + Ar.fromObservable = function $$react$from$observable(obsv){ + function reactor(next,registerTeardown){ + // process buffer (if any) + buffer.forEach(next); + buffer.length = 0; + + // start non-buffered notifications? + if (!buffer.complete) { + notify = next; + } + + registerTeardown(function $$teardown(){ + obsv.dispose(); + }); + } + + function notify(v) { + buffer.push(v); + } + + var buffer = []; + + obsv.subscribe( + function $$on$next(v){ + notify(v); + }, + function $$on$error(){}, + function $$on$complete(){ + buffer.complete = true; + obsv.dispose(); + } + ); + + return Ar(reactor); + }; + + ASQ.extend("toObservable",function $$extend(api,internals){ + return function $$to$observable(){ + function init(observer) { + function define(pair){ + function listen(){ + var args = ASQ.messages.apply(ø,arguments); + observer[pair[1]].apply(observer, + args.length == 1 ? [args[0]] : args + ); + return args; + } + + api[pair[0]](listen); + } + + [["val","onNext"],["or","onError"]] + .forEach(define); + } + + return Rx.Observable.create(init); + }; + }); + + function tapSequences() { + function tapSequence(seq) { + // temporary `trigger` which, if called before being replaced + // below, creates replacement proxy sequence with the + // event message(s) re-fired + function trigger() { + var args = ARRAY_SLICE.call(arguments); + def.seq = Ar(function $$react(next){ + next.apply(ø,args); + }); + } + + if (ASQ.isSequence(seq)) { + var def = { seq: seq }; + + // listen for events from the sequence-stream + seq.val(function $$val(){ + trigger.apply(ø,arguments); + return ASQ.messages.apply(ø,arguments); + }); + + // make a reactive sequence to act as a proxy to the original + // sequence + def.seq = Ar(function $$react(next){ + // replace the temporary trigger (created above) + // with this proxy's trigger + trigger = next; + }); + + return def; + } + } + + return ARRAY_SLICE.call(arguments) + .map(tapSequence) + .filter(Boolean); + } + + function makeReactOperator(buffer,keep) { + return function $$react$operator(){ + function reactor(next,registerTeardown){ + function processSequence(def) { + // sequence-stream event listener + function trigger() { + var args = ASQ.messages.apply(ø,arguments); + // still observing sequence-streams? + if (seqs && seqs.length > 0) { + // store event message(s), if any + seq_events[seq_id] = + (buffer ? seq_events[seq_id] : []).concat( + args.length > 0 ? (args.length > 1 ? [args] : args[0]) : undefined + ); + + // collect event message(s) across the + // sequence-stream sources + var messages = seq_events.reduce(function reducer(msgs,eventList,idx){ + if (eventList.length > 0) msgs.push(eventList[0]); + return msgs; + },[]); + + // did all sequence-streams get an event? + if (messages.length == seq_events.length) { + if (messages.length == 1) messages = messages[0]; + + // fire off reactive sequence instance + next.apply(ø,messages); + + // discard stored event message(s)? + if (!keep) { + seq_events.forEach(function $$each(eventList){ + eventList.shift(); + }); + } + } + } + // keep sequence going + return args; + } + + var seq_id = seq_events.length; + seq_events.push([]); + def.seq.val(trigger); + } + + // process all sequence-streams + seqs.forEach(processSequence); + + // listen for stop() of reactive sequence + registerTeardown(function $$teardown(){ + seqs = seq_events = null; + }); + } + + var seq_events = [], + // observe all sequence-streams + seqs = tapSequences.apply(null,arguments) + ; + + if (seqs.length == 0) return; + + return Ar(reactor); + }; + } + + function makeDistinctFilterer(keepAll) { + function filterer() { + function isDuplicate(msgSet) { + return ( + msgSet.length == message_set.length && + msgSet.every(function $$every(val,idx){ + return val === message_set[idx]; + }) + ); + } + + var message_set = ASQ.messages.apply(ø,arguments); + + // any messages in message-set to check against? + if (message_set.length > 0) { + // duplicate message-set? + if (msg_sets.some(isDuplicate)) { + return false; + } + + // remember all message-sets for future distinct checking? + if (keepAll) { + msg_sets.push(message_set); + } + // only keep the last message-set for distinct-consecutive + // checking + else { + msg_sets[0] = message_set; + } + } + + // allow distinct non-duplicate value through + return true; + } + + var msg_sets = []; + + return filterer; + } + +})(); +// "runner" +ASQ.extend("runner",function $$extend(api,internals){ + + return function $$runner() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var args = ARRAY_SLICE.call(arguments); + + api + .then(function $$then(mainDone){ + + function wrap(v) { + // function? expected to produce an iterator + // (like a generator) or a promise + if (typeof v === "function") { + // call function passing in the control token + // note: neutralize `this` in call to prevent + // unexpected behavior + v = v.call(ø,token); + + // promise returned (ie, from async function)? + if (isPromise(v)) { + // wrap it in iterable sequence + v = ASQ.iterable(v); + } + } + // an iterable sequence? duplicate it (in case of multiple runs) + else if (ASQ.isSequence(v) && "next" in v) { + v = v.duplicate(); + } + // wrap anything else in iterable sequence + else { + v = ASQ.iterable(v); + } + + // a sequence to tap for errors? + if (ASQ.isSequence(v)) { + // listen for any sequence failures + v.or(function $$or(){ + // signal iteration-error + mainDone.fail.apply(ø,arguments); + }); + } + + return v; + } + + function addWrapped() { + iterators.push.apply( + iterators, + ARRAY_SLICE.call(arguments).map(wrap) + ); + } + + function iterateOrQuit(iterFn,now) { + // still have some co-routine runs to process? + if (iterators.length > 0) { + if (now) iterFn(); + else schedule(iterFn); + } + // all done! + else { + // previous value message? + if (typeof next_val !== "undefined") { + // not a message wrapper array? + if (!ASQ.isMessageWrapper(next_val)) { + // wrap value for the subsequent `apply(..)` + next_val = [next_val]; + } + } + else { + // nothing to affirmatively pass along + next_val = []; + } + + // signal done with all co-routine runs + mainDone.apply(ø,next_val); + } + } + + var iterators = args, + token = { + messages: ARRAY_SLICE.call(arguments,1), + add: addWrapped + }, + iter, ret, next_val = token + ; + + // map co-routines to round-robin list of iterators + iterators = iterators.map(wrap); + + // async iteration of round-robin list + (function iterate(){ + // get next co-routine in list + iter = iterators.shift(); + + // process the iteration + try { + // multiple messages to send to an iterable + // sequence? + if (ASQ.isMessageWrapper(next_val) && + ASQ.isSequence(iter) + ) { + ret = iter.next.apply(iter,next_val); + } + else { + ret = iter.next(next_val); + } + } + catch (err) { + return mainDone.fail(err); + } + + // bail on run in aborted sequence + if (internals("seq_aborted")) return; + + // was the control token yielded? + if (ret.value === token) { + // round-robin: put co-routine back into the list + // at the end where it was so it can be processed + // again on next loop-iteration + if (!ret.done) { + iterators.push(iter); + } + next_val = token; + iterateOrQuit(iterate,/*now=*/false); + } + else { + // not a recognized ASQ instance returned? + if (!ASQ.isSequence(ret.value)) { + // received a thenable/promise back? + if (isPromise(ret.value)) { + // wrap in a sequence + ret.value = ASQ().promise(ret.value); + } + // thunk yielded? + else if (typeof ret.value === "function") { + // wrap thunk call in a sequence + var fn = ret.value; + ret.value = ASQ(function $$ASQ(done){ + fn(done.errfcb); + }); + } + // message wrapper returned? + else if (ASQ.isMessageWrapper(ret.value)) { + // wrap message(s) in a sequence + ret.value = ASQ.apply(ø, + // don't let `apply(..)` discard an empty message + // wrapper! instead, pass it along as its own value + // itself. + ret.value.length > 0 ? ret.value : ASQ.messages(undefined) + ); + } + // non-undefined value returned? + else if (typeof ret.value !== "undefined") { + // wrap the value in a sequence + ret.value = ASQ(ret.value); + } + else { + // make an empty sequence + ret.value = ASQ(); + } + } + + ret.value + .val(function $$val(){ + // bail on run in aborted sequence + if (internals("seq_aborted")) return; + + if (arguments.length > 0) { + // save any return messages for input + // to next iteration + next_val = arguments.length > 1 ? + ASQ.messages.apply(ø,arguments) : + arguments[0] + ; + } + + // still more to iterate? + if (!ret.done) { + // was the control token passed along? + if (next_val === token) { + // round-robin: put co-routine back into the list + // at the end, so that the the next iterator can be + // processed on next loop-iteration + iterators.push(iter); + } + else { + // put co-routine back in where it just + // was so it can be processed again on + // next loop-iteration + iterators.unshift(iter); + } + } + + iterateOrQuit(iterate,/*now=*/true); + }) + .or(function $$or(){ + // bail on run in aborted sequence + if (internals("seq_aborted")) return; + + try { + // if an error occurs in the step-continuation + // promise or sequence, throw it back into the + // generator or iterable-sequence + iter["throw"].apply(iter,arguments); + } + catch (err) { + // if an error comes back out of after the throw, + // pass it out to the main sequence, as iteration + // must now be complete + mainDone.fail(err); + } + }); + } + })(); + }); + + return api; + }; +}); +// "toPromise" +ASQ.extend("toPromise",function $$extend(api,internals){ + return function $$to$promise() { + return new Promise(function $$executor(resolve,reject){ + api + .val(function $$val(){ + var args = ARRAY_SLICE.call(arguments); + resolve.call(ø,args.length > 1 ? args : args[0]); + return ASQ.messages.apply(ø,args); + }) + .or(function $$or(){ + var args = ARRAY_SLICE.call(arguments); + reject.call(ø,args.length > 1 ? args : args[0]); + }); + }); + }; +}); +// "try" +ASQ.extend("try",function $$extend(api,internals){ + return function $$try() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments) + .map(function $$map(fn){ + return function $$then(mainDone) { + var main_args = ARRAY_SLICE.call(arguments), + sq = ASQ.apply(ø,main_args.slice(1)) + ; + + sq + .then(function $$inner$then(){ + fn.apply(ø,arguments); + }) + .val(function $$val(){ + mainDone.apply(ø,arguments); + }) + .or(function $$inner$or(){ + var msgs = ASQ.messages.apply(ø,arguments); + // failed, so map error(s) as `catch` + mainDone({ + "catch": msgs.length > 1 ? msgs : msgs[0] + }); + }); + }; + }); + + api.then.apply(ø,fns); + + return api; + }; +}); +// "until" +ASQ.extend("until",function $$extend(api,internals){ + return function $$until() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments) + .map(function $$map(fn){ + return function $$then(mainDone) { + var main_args = ARRAY_SLICE.call(arguments), + sq = ASQ.apply(ø,main_args.slice(1)) + ; + + sq + .then(function $$inner$then(){ + var args = ARRAY_SLICE.call(arguments); + args[0]["break"] = function $$break(){ + mainDone.fail.apply(ø,arguments); + sq.abort(); + }; + + fn.apply(ø,args); + }) + .val(function $$val(){ + mainDone.apply(ø,arguments); + }) + .or(function $$inner$or(){ + // failed, retry + $$then.apply(ø,main_args); + }); + }; + }); + + api.then.apply(ø,fns); + + return api; + }; +}); +// "waterfall" +ASQ.extend("waterfall",function $$extend(api,internals){ + return function $$waterfall() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + var msgs = ASQ.messages(), + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)) + ; + + fns.forEach(function $$each(fn){ + sq.then(fn) + .val(function $$val(){ + var args = ASQ.messages.apply(ø,arguments); + msgs.push(args.length > 1 ? args : args[0]); + return msgs; + }); + }); + + sq.pipe(done); + }); + + return api; + }; +}); +// "wrap" +ASQ.wrap = function $$wrap(fn,opts) { + function checkThis(t,o) { + return (!t || + (typeof window != "undefined" && t === window) || + (typeof global != "undefined" && t === global) + ) ? o : t; + } + + function paramSpread(gen) { + return function *paramSpread(token) { + yield *gen.apply(this,token.messages); + }; + } + + var errfcb, params_first, act, this_obj; + + opts = (opts && typeof opts == "object") ? opts : {}; + + if ( + (opts.errfcb && opts.splitcb) || + (opts.errfcb && opts.simplecb) || + (opts.splitcb && opts.simplecb) || + ("errfcb" in opts && !opts.errfcb && !opts.splitcb && !opts.simplecb) || + (opts.params_first && opts.params_last) || + (opts.spread && !opts.gen) + ) { + throw Error("Invalid options"); + } + + // initialize default flags + this_obj = (opts["this"] && typeof opts["this"] == "object") ? opts["this"] : ø; + errfcb = opts.errfcb || !(opts.splitcb || opts.simplecb); + params_first = !!opts.params_first || + (!opts.params_last && !("params_first" in opts || opts.params_first)) || + ("params_last" in opts && !opts.params_first && !opts.params_last) + ; + + if (params_first) { + act = "push"; + } + else { + act = "unshift"; + } + + if (opts.gen) { + if (opts.spread) { + fn = paramSpread(fn); + } + return function $$wrapped$gen() { + return ASQ.apply(ø,arguments).runner(fn); + }; + } + if (errfcb) { + return function $$wrapped$errfcb() { + var args = ARRAY_SLICE.call(arguments), + _this = checkThis(this,this_obj) + ; + + return ASQ(function $$asq(done){ + args[act](done.errfcb); + fn.apply(_this,args); + }); + }; + } + if (opts.splitcb) { + return function $$wrapped$splitcb() { + var args = ARRAY_SLICE.call(arguments), + _this = checkThis(this,this_obj) + ; + + return ASQ(function $$asq(done){ + args[act](done,done.fail); + fn.apply(_this,args); + }); + }; + } + if (opts.simplecb) { + return function $$wrapped$simplecb() { + var args = ARRAY_SLICE.call(arguments), + _this = checkThis(this,this_obj) + ; + + return ASQ(function $$asq(done){ + args[act](done); + fn.apply(_this,args); + }); + }; + } +}; + + + // just return `ASQ` itself for convenience sake + return ASQ; +}); diff --git a/frontend-masters-exercises/exercises/ex5/ex5-fixed.html b/frontend-masters-exercises/exercises/ex5/ex5-fixed.html new file mode 100755 index 0000000..1b24ff3 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex5/ex5-fixed.html @@ -0,0 +1,14 @@ + + + + +Exercise 5 - Fixed + + +

Exercise 5 - Fixed

+ + + + + + diff --git a/frontend-masters-exercises/exercises/ex5/ex5-fixed.js b/frontend-masters-exercises/exercises/ex5/ex5-fixed.js new file mode 100755 index 0000000..3ba5bbb --- /dev/null +++ b/frontend-masters-exercises/exercises/ex5/ex5-fixed.js @@ -0,0 +1,43 @@ +function fakeAjax(url,cb) { + var fake_responses = { + "file1": "The first text", + "file2": "The middle text", + "file3": "The last text" + }; + var randomDelay = (Math.round(Math.random() * 1E4) % 8000) + 1000; + + console.log("Requesting: " + url); + + setTimeout(function(){ + cb(fake_responses[url]); + },randomDelay); +} + +function output(text) { + console.log(text); +} + +// ************************************** + +function getFile(file) { + return ASQ(function(done){ + fakeAjax(file,done); + }); +} + +// Request all files at once in +// "parallel" via `getFile(..)`. +// +// Render as each one finishes, +// but only once previous rendering +// is done. +ASQ() +.seq( getFile("file1") ) +.val( output ) +.seq( getFile("file2") ) +.val( output ) +.seq( getFile("file3") ) +.val( output ) +.val(function(){ + output("Complete!"); +}); diff --git a/frontend-masters-exercises/exercises/ex5/ex5.html b/frontend-masters-exercises/exercises/ex5/ex5.html new file mode 100755 index 0000000..04171dd --- /dev/null +++ b/frontend-masters-exercises/exercises/ex5/ex5.html @@ -0,0 +1,14 @@ + + + + +Exercise 5 + + +

Exercise 5

+ + + + + + diff --git a/frontend-masters-exercises/exercises/ex5/ex5.js b/frontend-masters-exercises/exercises/ex5/ex5.js new file mode 100755 index 0000000..9a5f8e3 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex5/ex5.js @@ -0,0 +1,27 @@ +function fakeAjax(url,cb) { + var fake_responses = { + "file1": "The first text", + "file2": "The middle text", + "file3": "The last text" + }; + var randomDelay = (Math.round(Math.random() * 1E4) % 8000) + 1000; + + console.log("Requesting: " + url); + + setTimeout(function(){ + cb(fake_responses[url]); + },randomDelay); +} + +function output(text) { + console.log(text); +} + +// ************************************** + +function getFile(file) { + // what do we do here? +} + +// request an array of files at once in "parallel" +// ??? diff --git a/frontend-masters-exercises/exercises/ex6/README.md b/frontend-masters-exercises/exercises/ex6/README.md new file mode 100755 index 0000000..476a277 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex6/README.md @@ -0,0 +1,9 @@ +# Instructions + +1. You'll do the same thing as the previous exercise(s), but now you should use map/reduce, asynquence, and an array of files. + +2. Expected behavior: + - Request all 3 files at the same time (in "parallel"). + - Render them ASAP (don't just blindly wait for all to finish loading) + - BUT, render them in proper (obvious) order: "file1", "file2", "file3". + - After all 3 are done, output "Complete!". diff --git a/frontend-masters-exercises/exercises/ex6/asq.bundle.js b/frontend-masters-exercises/exercises/ex6/asq.bundle.js new file mode 100755 index 0000000..93c9ada --- /dev/null +++ b/frontend-masters-exercises/exercises/ex6/asq.bundle.js @@ -0,0 +1,2333 @@ +/*! asynquence + v0.8.2 (c) Kyle Simpson + MIT License: http://getify.mit-license.org +*/ +!function UMD(e,n,t){"function"==typeof define&&define.amd?define(t):"undefined"!=typeof module&&module.exports?module.exports=t():n[e]=t(e,n)}("ASQ",this,function DEF(e,n){"use strict";function Queue(){function Item(e){this.fn=e,this.next=void 0}var e,n,r;return{add:function $$add(t){r=new Item(t),n?n.next=r:e=r,n=r,r=void 0},drain:function $$drain(){var r=e;for(e=n=t=null;r;)r.fn(),r=r.next}}}function schedule(e){r.add(e),t||(t=u(r.drain))}function tapSequence(e){function trigger(){e.seq=createSequence.apply(h,arguments).defer()}trigger.fail=function $$trigger$fail(){var n=f.call(arguments);e.seq=createSequence(function $$create$sequence(e){e.fail.apply(h,n)}).defer()},e.seq.val(function $$val(){return trigger.apply(h,arguments),c.apply(h,arguments)}).or(function $$or(){trigger.fail.apply(h,arguments)}),e.seq=createSequence(function $$create$sequence(e){trigger=e}).defer()}function createSequence(){function scheduleSequenceTick(){r?sequenceTick():e||(e=schedule(sequenceTick))}function throwSequenceErrors(){throw 1===$.length?$[0]:$}function sequenceTick(){var a,c;if(e=null,delete d.unpause,r)clearTimeout(e),e=null,s.length=p.length=g.length=$.length=0;else if(n)for(0!==p.length||t||(t=!0,throwSequenceErrors());p.length;){t=!0,a=p.shift();try{a.apply(h,$)}catch(i){l(i)?$=$.concat(i):($.push(i),i.stack&&$.push(i.stack)),0===p.length&&throwSequenceErrors()}}else if(u&&s.length>0){u=!1,a=s.shift(),c=g.slice(),g.length=0,c.unshift(createStepCompletion());try{a.apply(h,c)}catch(i){l(i)?$=$.concat(i):$.push(i),n=!0,scheduleSequenceTick()}}}function createStepCompletion(){function done(){n||r||u||(u=!0,g.push.apply(g,arguments),$.length=0,scheduleSequenceTick())}return done.fail=function $$step$fail(){n||r||u||(n=!0,g.length=0,$.push.apply($,arguments),scheduleSequenceTick())},done.abort=function $$step$abort(){n||r||(u=!1,r=!0,g.length=$.length=0,scheduleSequenceTick())},done.errfcb=function $$step$errfcb(e){e?done.fail(e):done.apply(h,f.call(arguments,1))},done}function createGate(e,t,u){function resetGate(){clearTimeout(s),s=d=m=o=null}function scheduleGateTick(){return g?gateTick():void(s||(s=schedule(gateTick)))}function gateTick(){if(!(n||r||$)){var t=[];s=null,p?(e.fail.apply(h,o),resetGate()):g?(e.abort(),resetGate()):checkGate()&&($=!0,d.forEach(function $$each(e,n){t.push(m["s"+n])}),e.apply(h,t),resetGate())}}function checkGate(){if(0!==d.length){var e=!0;return d.some(function $$some(n){return null===n?(e=!1,!0):void 0}),e}}function createSegmentCompletion(){function done(){if(!(n||r||p||g||$||d[e])){var t=c.apply(h,arguments);m["s"+e]=t.length>1?t:t[0],d[e]=!0,scheduleGateTick()}}var e=d.length;return done.fail=function $$segment$fail(){n||r||p||g||$||d[e]||(p=!0,o=f.call(arguments),scheduleGateTick())},done.abort=function $$segment$abort(){n||r||p||g||$||(g=!0,gateTick())},done.errfcb=function $$segment$errfcb(e){e?done.fail(e):done.apply(h,f.call(arguments,1))},d[e]=null,done}var a,i,o,s,p=!1,g=!1,$=!1,d=[],m={};t.some(function $$some(e){if(p||g)return!0;a=u.slice(),a.unshift(createSegmentCompletion());try{e.apply(h,a)}catch(n){return i=n,p=!0,!0}}),i&&(l(i)?e.fail.apply(h,i):e.fail(i))}function then(){return n||r||0===arguments.length?d:(wrapArgs(arguments,thenWrapper).forEach(function $$each(e){i(e)?seq(e):s.push(e)}),scheduleSequenceTick(),d)}function or(){return r||0===arguments.length?d:(p.push.apply(p,arguments),scheduleSequenceTick(),d)}function gate(){if(n||r||0===arguments.length)return d;var e=f.call(arguments).map(function $$map(e){var n;return i(e)?(n={seq:e},tapSequence(n),function $$segment(e){n.seq.pipe(e)}):e});return then(function $$then(n){var t=f.call(arguments,1);createGate(n,e,t)}),d}function pipe(){return r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){then(function $$then(n){e.apply(h,f.call(arguments,1)),n()}).or(e.fail)}),d)}function seq(){return n||r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){var n={seq:e};i(e)&&tapSequence(n),then(function $$then(e){var t=n.seq;i(t)||(t=n.seq.apply(h,f.call(arguments,1))),t.pipe(e)})}),d)}function val(){return n||r||0===arguments.length?d:(f.call(wrapArgs(arguments,valWrapper)).forEach(function $$each(e){then(function $$then(n){var t=e.apply(h,f.call(arguments,1));l(t)||(t=c(t)),n.apply(h,t)})}),d)}function promise(){function wrap(e){return function $$fn(){e.apply(h,l(arguments[0])?arguments[0]:arguments)}}return n||r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){then(function $$then(n){var t=e;"function"==typeof e&&"function"!=typeof e.then&&(t=e.apply(h,f.call(arguments,1))),t.then(wrap(n),wrap(n.fail))})}),d)}function fork(){var e;return val(function $$val(){return e?e.apply(h,arguments):e=createSequence.apply(h,arguments).defer(),c.apply(h,arguments)}),or(function $$or(){if(e)e.fail.apply(h,arguments);else{var n=f.call(arguments);e=createSequence().then(function $$then(e){e.fail.apply(h,n)}).defer()}}),createSequence().then(function $$then(n){e?e.pipe(n):e=n}).defer()}function abort(){return n?d:(r=!0,sequenceTick(),d)}function duplicate(){var e;return a={then_queue:s.slice(),or_queue:p.slice()},e=createSequence(),a=null,e}function unpause(){g.push.apply(g,arguments),e===!0&&(e=null),scheduleSequenceTick()}function defer(){return p.push(function ignored(){}),d}function internals(e,t){var a=arguments.length>1;switch(e){case"seq_error":if(!a)return n;n=t;break;case"seq_aborted":if(!a)return r;r=t;break;case"then_ready":if(!a)return u;u=t;break;case"then_queue":return s;case"or_queue":return p;case"sequence_messages":return g;case"sequence_errors":return $}}function includeExtensions(){Object.keys(o).forEach(function $$each(e){d[e]=o[e](d,internals)})}var e,n=!1,t=!1,r=!1,u=!0,s=[],p=[],g=[],$=[],d=brandIt({then:then,or:or,onerror:or,gate:gate,all:gate,pipe:pipe,seq:seq,val:val,promise:promise,fork:fork,abort:abort,duplicate:duplicate,defer:defer});return includeExtensions(),a&&(s=a.then_queue.slice(),p=a.or_queue.slice(),d.unpause=unpause,e=!0),d.then.apply(h,arguments),d}function brandIt(e){return Object.defineProperty(e,p,{enumerable:!1,value:!0})}function checkBranding(e){return!(null==e||"object"!=typeof e||!e[p])}function valWrapper(e){return c.apply(h,f.call(arguments).slice(1,e+1))}function thenWrapper(e){arguments[e+1].apply(h,f.call(arguments).slice(1,e+1))}function wrapArgs(e,n){var t,r;for(e=f.call(e),t=0;t 1 ? + ARRAY_SLICE.call(arguments,1) : + void 0 + ; + num = +num || 0; + + api.then(function $$then(done){ + var args = orig_args || ARRAY_SLICE.call(arguments,1); + + setTimeout(function $$set$timeout(){ + done.apply(ø,args); + },num); + }); + + return api; + }; +}); + +ASQ.after = function $$after() { + return ASQ().after.apply(ø,arguments); +}; +// "any" +ASQ.extend("any",function $$extend(api,internals){ + return function $$any() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + function reset() { + finished = true; + error_messages.length = 0; + success_messages.length = 0; + } + + function complete(trigger) { + if (success_messages.length > 0) { + // any successful segment's message(s) sent + // to main sequence to proceed as success + success_messages.length = fns.length; + trigger.apply(ø,success_messages); + } + else { + // send errors into main sequence + error_messages.length = fns.length; + trigger.fail.apply(ø,error_messages); + } + + reset(); + } + + function success(trigger,idx,args) { + if (!finished) { + completed++; + success_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + + // all segments complete? + if (completed === fns.length) { + finished = true; + + complete(trigger); + } + } + } + + function failure(trigger,idx,args) { + if (!finished && + !(idx in error_messages) + ) { + completed++; + error_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + } + + // all segments complete? + if (!finished && + completed === fns.length + ) { + finished = true; + + complete(trigger); + } + } + + var completed = 0, error_messages = [], finished = false, + success_messages = [], + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)) + ; + + wrapGate(sq,fns,success,failure,reset); + + sq.pipe(done); + }); + + return api; + }; +}); +// "errfcb" +ASQ.extend("errfcb",function $$extend(api,internals){ + return function $$errfcb() { + // create a fake sequence to extract the callbacks + var sq = { + val: function $$then(cb){ sq.val_cb = cb; return sq; }, + or: function $$or(cb){ sq.or_cb = cb; return sq; } + }; + + // trick `seq(..)`s checks for a sequence + sq[brand] = true; + + // immediately register our fake sequence on the + // main sequence + api.seq(sq); + + // provide the "error-first" callback + return function $$errorfirst$callback(err) { + if (err) { + sq.or_cb(err); + } + else { + sq.val_cb.apply(ø,ARRAY_SLICE.call(arguments,1)); + } + }; + }; +}); +// "failAfter" +ASQ.extend("failAfter",function $$extend(api,internals){ + return function $$failAfter(num) { + var args = arguments.length > 1 ? + ARRAY_SLICE.call(arguments,1) : + void 0 + ; + num = +num || 0; + + api.then(function $$then(done){ + setTimeout(function $$set$timeout(){ + done.fail.apply(ø,args); + },num); + }); + + return api; + }; +}); + +ASQ.failAfter = function $$fail$after() { + return ASQ().failAfter.apply(ø,arguments); +}; +// "first" +ASQ.extend("first",function $$extend(api,internals){ + return function $$first() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + function reset() { + error_messages.length = 0; + } + + function success(trigger,idx,args) { + if (!finished) { + finished = true; + + // first successful segment triggers + // main sequence to proceed as success + trigger( + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ); + + reset(); + } + } + + function failure(trigger,idx,args) { + if (!finished && + !(idx in error_messages) + ) { + completed++; + error_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + + // all segments complete without success? + if (completed === fns.length) { + finished = true; + + // send errors into main sequence + error_messages.length = fns.length; + trigger.fail.apply(ø,error_messages); + + reset(); + } + } + } + + var completed = 0, error_messages = [], finished = false, + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)) + ; + + wrapGate(sq,fns,success,failure,reset); + + sq.pipe(done); + }); + + return api; + }; +}); +// "go-style CSP" +(function IIFE(){ + + // filter out already-resolved queue entries + function filterResolved(queue) { + return queue.filter(function $$filter(entry){ + return !entry.resolved; + }); + } + + function closeQueue(queue,finalValue) { + queue.forEach(function $$each(iter){ + if (!iter.resolved) { + iter.next(); + iter.next(finalValue); + } + }); + queue.length = 0; + } + + function channel(bufSize) { + var ch = { + close: function $$close(){ + ch.closed = true; + closeQueue(ch.put_queue,false); + closeQueue(ch.take_queue,ASQ.csp.CLOSED); + }, + closed: false, + messages: [], + put_queue: [], + take_queue: [], + buffer_size: +bufSize || 0 + }; + return ch; + } + + function unblock(iter) { + if (iter && !iter.resolved) { + iter.next(iter.next().value); + } + } + + function put(channel,value) { + var ret; + + if (channel.closed) { + return false; + } + + // remove already-resolved entries + channel.put_queue = filterResolved(channel.put_queue); + channel.take_queue = filterResolved(channel.take_queue); + + // immediate put? + if (channel.messages.length < channel.buffer_size) { + channel.messages.push(value); + unblock(channel.take_queue.shift()); + return true; + } + // queued put + else { + channel.put_queue.push( + // make a notifiable iterable for 'put' blocking + ASQ.iterable() + .then(function $$then(){ + if (!channel.closed) { + channel.messages.push(value); + return true; + } + else { + return false; + } + }) + ); + + // wrap a sequence/promise around the iterable + ret = ASQ( + channel.put_queue[channel.put_queue.length - 1] + ); + + // take waiting on this queued put? + if (channel.take_queue.length > 0) { + unblock(channel.put_queue.shift()); + unblock(channel.take_queue.shift()); + } + + return ret; + } + } + + function putAsync(channel,value,cb) { + var ret = ASQ(put(channel,value)); + + if (cb && typeof cb == "function") { + ret.val(cb); + } + else { + return ret; + } + } + + function take(channel) { + var ret; + + try { + ret = takem(channel); + } + catch (err) { + ret = err; + } + + if (ASQ.isSequence(ret)) { + ret.pCatch(function $$pcatch(err){ + return err; + }); + } + + return ret; + } + + function takeAsync(channel,cb) { + var ret = ASQ(take(channel)); + + if (cb && typeof cb == "function") { + ret.val(cb); + } + else { + return ret; + } + } + + function takem(channel) { + var msg; + + if (channel.closed) { + return ASQ.csp.CLOSED; + } + + // remove already-resolved entries + channel.put_queue = filterResolved(channel.put_queue); + channel.take_queue = filterResolved(channel.take_queue); + + // immediate take? + if (channel.messages.length > 0) { + msg = channel.messages.shift(); + unblock(channel.put_queue.shift()); + if (msg instanceof Error) { + throw msg; + } + return msg; + } + // queued take + else { + channel.take_queue.push( + // make a notifiable iterable for 'take' blocking + ASQ.iterable() + .then(function $$then(){ + if (!channel.closed) { + var v = channel.messages.shift(); + if (v instanceof Error) { + throw v; + } + return v; + } + else { + return ASQ.csp.CLOSED; + } + }) + ); + + // wrap a sequence/promise around the iterable + msg = ASQ( + channel.take_queue[channel.take_queue.length - 1] + ); + + // put waiting on this take? + if (channel.put_queue.length > 0) { + unblock(channel.put_queue.shift()); + unblock(channel.take_queue.shift()); + } + + return msg; + } + } + + function takemAsync(channel,cb) { + var ret = ASQ(takem(channel)); + + if (cb && typeof cb == "function") { + ret.pThen(cb,cb); + } + else { + return ret.val(function $$val(v){ + if (v instanceof Error) { + throw v; + } + return v; + }); + } + } + + function alts(actions) { + var closed, open, handlers, i, isq, ret, resolved = false; + + // used `alts(..)` incorrectly? + if (!Array.isArray(actions) || actions.length == 0) { + throw Error("Invalid usage"); + } + + closed = []; + open = []; + handlers = []; + + // separate actions by open/closed channel status + actions.forEach(function $$each(action){ + var channel = Array.isArray(action) ? action[0] : action; + + // remove already-resolved entries + channel.put_queue = filterResolved(channel.put_queue); + channel.take_queue = filterResolved(channel.take_queue); + + if (channel.closed) { + closed.push(channel); + } + else { + open.push(action); + } + }); + + // if no channels are still open, we're done + if (open.length == 0) { + return { value: ASQ.csp.CLOSED, channel: closed }; + } + + // can any channel action be executed immediately? + for (i=0; i 0) { + return { value: take(open[i]), channel: open[i] }; + } + } + + isq = ASQ.iterable(); + var ret = ASQ(isq); + + // setup channel action handlers + for (i=0; i 0) { + schedule(function handleUnblocking(){ + if (!resolved) { + unblock(channel.put_queue.shift()); + unblock(channel.take_queue.shift()); + } + },0); + } + } + // take action? + else { + channel = action; + + // define take handler + handlers.push( + ASQ.iterable() + .then(function $$then(){ + resolved = true; + + // mark all handlers across this `alts(..)` as resolved now + handlers = handlers.filter(function $$filter(handler){ + return !(handler.resolved = true); + }); + + // channel still open? + if (!channel.closed) { + isq.next({ value: channel.messages.shift(), channel: channel }); + } + // channel already closed? + else { + isq.next({ value: ASQ.csp.CLOSED, channel: channel }); + } + }) + ); + + // queue up take handler + channel.take_queue.push(handlers[handlers.length-1]); + + // put waiting on this queued take? + if (channel.put_queue.length > 0) { + schedule(function handleUnblocking(){ + if (!resolved) { + unblock(channel.put_queue.shift()); + unblock(channel.take_queue.shift()); + } + }); + } + } + })(open[i]); + } + + return ret; + } + + function altsAsync(chans,cb) { + var ret = ASQ(alts(chans)); + + if (cb && typeof cb == "function") { + ret.pThen(cb,cb); + } + else { + return ret; + } + } + + function timeout(delay) { + var ch = channel(); + setTimeout(ch.close,delay); + return ch; + } + + function go(gen,args) { + // goroutine arguments passed? + if (arguments.length > 1) { + if (!args || !Array.isArray(args)) { + args = [args]; + } + } + else { + args = []; + } + + return function *$$go(token) { + + // unblock the overall goroutine handling + function unblock() { + token.unblock_count++; + + if (token.block && !token.block.marked) { + token.block.marked = true; + token.block.next(); + } + } + + var ret, msg, err, type, done = false, it; + + // keep track of how many requests for unblocking + // have occurred + token.unblock_count = (token.unblock_count || 0); + + // keep track of how many goroutines are running + // so we can infer when we're done go'ing + token.go_count = (token.go_count || 0) + 1; + + // need to initialize a set of goroutines? + if (token.go_count === 1) { + // create a default channel for these goroutines + token.channel = channel(); + token.channel.messages = token.messages; + token.channel.go = function $$go(){ + // unblock the goroutine handling for this + // new goroutine + unblock(); + // add the goroutine (called with any args) to + // the handling queue + token.add( go.apply(ø,arguments) ); + }; + // starting out with initial channel messages? + if (token.channel.messages.length > 0) { + // fake back-pressure blocking for each + token.channel.put_queue = token.channel.messages.map(function $$map(){ + // make a notifiable iterable for 'put' blocking + return ASQ.iterable() + .then(function $$then(){ + unblock(token.channel.take_queue.shift()); + return !token.channel.closed; + }); + }); + } + } + + // initialize the generator + it = gen.apply(ø,[token.channel].concat(args)); + + (function iterate(){ + + function next() { + // keep going with next step in goroutine? + if (!done) { + iterate(); + } + // unblock overall goroutine handling to + // continue with other goroutines + else { + unblock(); + } + } + + // has a resumption value been achieved yet? + if (!ret) { + // try to resume the goroutine + try { + // resume with injected exception? + if (err) { + ret = it.throw(err); + err = null; + } + // resume normally + else { + ret = it.next(msg); + } + } + // resumption failed, so bail + catch (e) { + done = true; + err = e; + msg = null; + unblock(); + return; + } + + // keep track of the result of the resumption + done = ret.done; + ret = ret.value; + type = typeof ret; + + // if this goroutine is complete, unblock the + // overall goroutine handling + if (done) { + unblock(); + } + + // received a thenable/promise back? + if (isPromise(ret)) { + ret = ASQ().promise(ret); + } + + // wait for the value? + if (ASQ.isSequence(ret)) { + ret.val(function $$val(){ + ret = null; + msg = arguments.length > 1 ? + ASQ.messages.apply(ø,arguments) : + arguments[0] + ; + next(); + }) + .or(function $$or(){ + ret = null; + msg = arguments.length > 1 ? + ASQ.messages.apply(ø,arguments) : + arguments[0] + ; + if (msg instanceof Error) { + err = msg; + msg = null; + } + next(); + }); + } + // immediate value, prepare it to go right back in + else { + msg = ret; + ret = null; + next(); + } + } + })(); + + // keep this goroutine alive until completion + while (!done) { + // transfer control to another goroutine + yield token; + + // need to block overall goroutine handling + // while idle? + if (!done && !token.block && token.unblock_count === 0) { + // wait here while idle + yield (token.block = ASQ.iterable()); + + token.block = false; + } + + if (token.unblock_count > 0) token.unblock_count--; + } + + // this goroutine is done now + token.go_count--; + + // all goroutines done? + if (token.go_count === 0) { + // any lingering blocking need to be cleaned up? + unblock(); + + // capture any untaken messages + msg = ASQ.messages.apply(ø,token.messages); + + // need to implicitly force-close channel? + if (token.channel && !token.channel.closed) { + token.channel.closed = true; + token.channel.put_queue.length = token.channel.take_queue.length = 0; + token.channel.close = token.channel.go = token.channel.messages = null; + } + token.channel = null; + } + + // make sure leftover error or message are + // passed along + if (err) { + throw err; + } + else if (token.go_count === 0) { + return msg; + } + else { + return token; + } + }; + } + + ASQ.csp = { + chan: channel, + put: put, + putAsync: putAsync, + take: take, + takeAsync: takeAsync, + takem: takem, + takemAsync: takemAsync, + alts: alts, + altsAsync: altsAsync, + timeout: timeout, + go: go, + CLOSED: {} + }; + +})(); +// "ASQ.iterable()" +(function IIFE(){ + var template; + + ASQ.iterable = function $$iterable() { + function throwSequenceErrors() { + throw (sequence_errors.length === 1 ? sequence_errors[0] : sequence_errors); + } + + function notifyErrors() { + var fn; + + seq_tick = null; + + if (seq_error) { + if (or_queue.length === 0 && !error_reported) { + error_reported = true; + throwSequenceErrors(); + } + + while (or_queue.length > 0) { + error_reported = true; + fn = or_queue.shift(); + try { + fn.apply(ø,sequence_errors); + } + catch (err) { + if (checkBranding(err)) { + sequence_errors = sequence_errors.concat(err); + } + else { + sequence_errors.push(err); + } + if (or_queue.length === 0) { + throwSequenceErrors(); + } + } + } + } + } + + function val() { + if (seq_error || seq_aborted || arguments.length === 0) { + return sequence_api; + } + + var args = ARRAY_SLICE.call(arguments).map(function mapper(arg){ + if (typeof arg != "function") return function $$val() { return arg; }; + else return arg; + }); + + val_queue.push.apply(val_queue,args); + + return sequence_api; + } + + function or() { + if (seq_aborted || arguments.length === 0) { + return sequence_api; + } + + or_queue.push.apply(or_queue,arguments); + + if (!seq_tick) { + seq_tick = schedule(notifyErrors); + } + + return sequence_api; + } + + function pipe() { + if (seq_aborted || arguments.length === 0) { + return sequence_api; + } + + ARRAY_SLICE.call(arguments) + .forEach(function $$each(fn){ + val(fn).or(fn.fail); + }); + + return sequence_api; + } + + function next() { + if (seq_error || seq_aborted || val_queue.length === 0) { + if (val_queue.length > 0) { + $throw$("Sequence cannot be iterated"); + } + return { done: true }; + } + + try { + return { value: val_queue.shift().apply(ø,arguments) }; + } + catch (err) { + if (ASQ.isMessageWrapper(err)) { + $throw$.apply(ø,err); + } + else { + $throw$(err); + } + + return {}; + } + } + + function $throw$() { + if (seq_error || seq_aborted) { + return sequence_api; + } + + sequence_errors.push.apply(sequence_errors,arguments); + seq_error = true; + if (!seq_tick) { + seq_tick = schedule(notifyErrors); + } + + return sequence_api; + } + + function $return$(val) { + if (seq_error || seq_aborted) { + val = void 0; + } + + abort(); + + return { done: true, value: val }; + } + + function abort() { + if (seq_error || seq_aborted) { + return; + } + + seq_aborted = true; + + clearTimeout(seq_tick); + seq_tick = null; + val_queue.length = or_queue.length = sequence_errors.length = 0; + } + + function duplicate() { + var isq; + + template = { + val_queue: val_queue.slice(), + or_queue: or_queue.slice() + }; + isq = ASQ.iterable(); + template = null; + + return isq; + } + + // opt-out of global error reporting for this sequence + function defer() { + or_queue.push(function $$ignored(){}); + return sequence_api; + } + + // *********************************************** + // Object branding utilities + // *********************************************** + function brandIt(obj) { + Object.defineProperty(obj,brand,{ + enumerable: false, + value: true + }); + + return obj; + } + + var sequence_api, + + seq_error = false, + error_reported = false, + seq_aborted = false, + + seq_tick, + + val_queue = [], + or_queue = [], + + sequence_errors = [] + ; + + // *********************************************** + // Setup the ASQ.iterable() public API + // *********************************************** + sequence_api = brandIt({ + val: val, + then: val, + or: or, + pipe: pipe, + next: next, + "throw": $throw$, + "return": $return$, + abort: abort, + duplicate: duplicate, + defer: defer + }); + + // useful for ES6 `for..of` loops, + // add `@@iterator` to simply hand back + // our iterable sequence itself! + sequence_api[(typeof Symbol == "function" && Symbol.iterator) || "@@iterator"] = function $$iter() { + return sequence_api; + }; + + // templating the iterable-sequence setup? + if (template) { + val_queue = template.val_queue.slice(0); + or_queue = template.or_queue.slice(0); + } + + // treat ASQ.iterable() constructor parameters as having been + // passed to `val()` + sequence_api.val.apply(ø,arguments); + + return sequence_api; + }; + +})(); +// "last" +ASQ.extend("last",function $$extend(api,internals){ + return function $$last() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + function reset() { + finished = true; + error_messages.length = 0; + success_messages = null; + } + + function complete(trigger) { + if (success_messages != null) { + // last successful segment's message(s) sent + // to main sequence to proceed as success + trigger( + success_messages.length > 1 ? + ASQ.messages.apply(ø,success_messages) : + success_messages[0] + ); + } + else { + // send errors into main sequence + error_messages.length = fns.length; + trigger.fail.apply(ø,error_messages); + } + + reset(); + } + + function success(trigger,idx,args) { + if (!finished) { + completed++; + success_messages = args; + + // all segments complete? + if (completed === fns.length) { + finished = true; + + complete(trigger); + } + } + } + + function failure(trigger,idx,args) { + if (!finished && + !(idx in error_messages) + ) { + completed++; + error_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + } + + // all segments complete? + if (!finished && + completed === fns.length + ) { + finished = true; + + complete(trigger); + } + } + + var completed = 0, error_messages = [], finished = false, + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)), + success_messages + ; + + wrapGate(sq,fns,success,failure,reset); + + sq.pipe(done); + }); + + return api; + }; +}); +// "map" +ASQ.extend("map",function $$extend(api,internals){ + return function $$map(pArr,pEach) { + if (internals("seq_error") || internals("seq_aborted")) { + return api; + } + + api.seq(function $$seq(){ + var tmp, args = ARRAY_SLICE.call(arguments), + arr = pArr, each = pEach; + + // if missing `map(..)` args, use value-messages (if any) + if (!each) each = args.shift(); + if (!arr) arr = args.shift(); + + // if arg types in reverse order (each,arr), swap + if (typeof arr === "function" && Array.isArray(each)) { + tmp = arr; + arr = each; + each = tmp; + } + + return ASQ.apply(ø,args) + .gate.apply(ø,arr.map(function $$map(item){ + return function $$segment(){ + each.apply(ø,[item].concat(ARRAY_SLICE.call(arguments))); + }; + })); + }) + .val(function $$val(){ + // collect all gate segment output into one value-message + // Note: return a normal array here, not a message wrapper! + return ARRAY_SLICE.call(arguments); + }); + + return api; + }; +}); +// "none" +ASQ.extend("none",function $$extend(api,internals){ + return function $$none() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + function reset() { + finished = true; + error_messages.length = 0; + success_messages.length = 0; + } + + function complete(trigger) { + if (success_messages.length > 0) { + // any successful segment's message(s) sent + // to main sequence to proceed as **error** + success_messages.length = fns.length; + trigger.fail.apply(ø,success_messages); + } + else { + // send errors as **success** to main sequence + error_messages.length = fns.length; + trigger.apply(ø,error_messages); + } + + reset(); + } + + function success(trigger,idx,args) { + if (!finished) { + completed++; + success_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + + // all segments complete? + if (completed === fns.length) { + finished = true; + + complete(trigger); + } + } + } + + function failure(trigger,idx,args) { + if (!finished && + !(idx in error_messages) + ) { + completed++; + error_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + } + + // all segments complete? + if (!finished && + completed === fns.length + ) { + finished = true; + + complete(trigger); + } + } + + var completed = 0, error_messages = [], finished = false, + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)), + success_messages = [] + ; + + wrapGate(sq,fns,success,failure,reset); + + sq.pipe(done); + }); + + return api; + }; +}); +// "pThen" +ASQ.extend("pThen",function $$extend(api,internals){ + return function $$pthen(success,failure) { + if (internals("seq_aborted")) { + return api; + } + + var ignore_success_handler = false, ignore_failure_handler = false; + + if (typeof success === "function") { + api.then(function $$then(done){ + if (!ignore_success_handler) { + var ret, msgs = ASQ.messages.apply(ø,arguments); + msgs.shift(); + + if (msgs.length === 1) { + msgs = msgs[0]; + } + + ignore_failure_handler = true; + + try { + ret = success(msgs); + } + catch (err) { + if (!ASQ.isMessageWrapper(err)) { + err = [err]; + } + done.fail.apply(ø,err); + return; + } + + // returned a sequence? + if (ASQ.isSequence(ret)) { + ret.pipe(done); + } + // returned a message wrapper? + else if (ASQ.isMessageWrapper(ret)) { + done.apply(ø,ret); + } + // returned a promise/thenable? + else if (isPromise(ret)) { + ret.then(done,done.fail); + } + // just a normal value to pass along + else { + done(ret); + } + } + else { + done.apply(ø,ARRAY_SLICE.call(arguments,1)); + } + }); + } + if (typeof failure === "function") { + api.or(function $$or(){ + if (!ignore_failure_handler) { + var ret, msgs = ASQ.messages.apply(ø,arguments), smgs, + or_queue = ARRAY_SLICE.call(internals("or_queue")) + ; + + if (msgs.length === 1) { + msgs = msgs[0]; + } + + ignore_success_handler = true; + + // NOTE: if this call throws, that'll automatically + // be handled by core as we'd want it to be + ret = failure(msgs); + + // if we get this far: + // first, inject return value (if any) as + // next step's sequence messages + smgs = internals("sequence_messages"); + smgs.length = 0; + if (typeof ret !== "undefined") { + if (!ASQ.isMessageWrapper(ret)) { + ret = [ret]; + } + smgs.push.apply(smgs,ret); + } + + // reset internal error state, because we've exclusively + // handled any errors up to this point of the sequence + internals("sequence_errors").length = 0; + internals("seq_error",false); + internals("then_ready",true); + + // temporarily empty the or-queue + internals("or_queue").length = 0; + + // make sure to schedule success-procession on the chain + api.val(function $$val(){ + // pass thru messages + return ASQ.messages.apply(ø,arguments); + }); + + // at next cycle, reinstate the or-queue (if any) + if (or_queue.length > 0) { + schedule(function $$schedule(){ + api.or.apply(ø,or_queue); + }); + } + } + }); + } + return api; + }; +}); + +// "pCatch" +ASQ.extend("pCatch",function $$extend(api,internals){ + return function $$pcatch(failure) { + if (internals("seq_aborted")) { + return api; + } + + api.pThen(void 0,failure); + + return api; + }; +}); +// "race" +ASQ.extend("race",function $$extend(api,internals){ + return function $$race() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments) + .map(function $$map(v){ + var def; + // tap any directly-provided sequences immediately + if (ASQ.isSequence(v)) { + def = { seq: v }; + tapSequence(def); + return function $$fn(done) { + def.seq.pipe(done); + }; + } + else return v; + }); + + api.then(function $$then(done){ + var args = ARRAY_SLICE.call(arguments); + + fns.forEach(function $$each(fn){ + fn.apply(ø,args); + }); + }); + + return api; + }; +}); +// "react" (reactive sequences) +ASQ.react = function $$react(reactor) { + function next() { + if (!paused) { + if (template) { + var sq = template.duplicate(); + sq.unpause.apply(ø,arguments); + return sq; + } + return ASQ(function $$asq(){ throw "Disabled Sequence"; }); + } + } + + function registerTeardown(fn) { + if (template && typeof fn === "function") { + teardowns.push(fn); + } + } + + var template = ASQ().duplicate(), + teardowns = [], paused = false + ; + + // add reactive sequence kill switch + template.stop = function $$stop() { + if (template) { + template = null; + teardowns.forEach(Function.call,Function.call); + teardowns.length = 0; + } + }; + + template.pause = function $$pause() { + if (!paused && template) { + paused = true; + teardowns.forEach(Function.call,Function.call); + teardowns.length = 0; + } + }; + + template.resume = function $$resume() { + if (paused && template) { + paused = false; + reactor.call(template,next,registerTeardown); + } + }; + + template.push = next; + + next.onStream = function $$onStream() { + ARRAY_SLICE.call(arguments) + .forEach(function $$each(stream){ + stream.on("data",next); + stream.on("error",next); + }); + }; + + next.unStream = function $$unStream() { + ARRAY_SLICE.call(arguments) + .forEach(function $$each(stream){ + stream.removeListener("data",next); + stream.removeListener("error",next); + }); + }; + + // make sure `reactor(..)` is called async + ASQ.__schedule(function $$schedule(){ + reactor.call(template,next,registerTeardown); + }); + + return template; +}; +// "react" helpers +(function IIFE(){ + + var Ar = ASQ.react; + + Ar.of = function $$react$of() { + function reactor(next) { + if (!started) { + started = true; + if (args.length > 0) { + args.shift().val(function val(){ + next.apply(ø,arguments); + if (args.length > 0) { + args.shift().val(val); + } + }); + } + } + } + + var started, args = ARRAY_SLICE.call(arguments) + .map(function wrapper(arg){ + if (!ASQ.isSequence(arg)) arg = ASQ(arg); + return arg; + }); + + return Ar(reactor); + }; + + Ar.all = Ar.zip = makeReactOperator(/*buffer=*/true); + Ar.allLatest = makeReactOperator(/*buffer=false*/); + Ar.latest = Ar.combineLatest = makeReactOperator(/*buffer=*/false,/*keep=*/true); + + Ar.any = Ar.merge = function $$react$any(){ + function reactor(next,registerTeardown){ + function processSequence(def){ + function trigger(){ + var args = ASQ.messages.apply(ø,arguments); + // still observing sequence-streams? + if (seqs && seqs.length > 0) { + // fire off reactive sequence instance + next.apply(ø,args); + } + // keep sequence going + return args; + } + + // sequence-stream event listener + def.seq.val(trigger); + } + + // observe all sequence-streams + seqs.forEach(processSequence); + + // listen for stop() of reactive sequence + registerTeardown(function $$teardown(){ + seqs = null; + }); + } + + // observe all sequence-streams + var seqs = tapSequences.apply(null,arguments); + + if (seqs.length == 0) return; + + return Ar(reactor); + }; + + Ar.distinct = function $$react$distinct(seq){ + return Ar.filter(seq,makeDistinctFilterer(/*keepAll=*/true)); + }; + + Ar.distinctConsecutive = Ar.distinctUntilChanged = function $$react$distinct$consecutive(seq) { + return Ar.filter(seq,makeDistinctFilterer(/*keepAll=*/false)); + }; + + Ar.filter = function $$react$filter(seq,filterer){ + function reactor(next,registerTeardown) { + function trigger(){ + var messages = ASQ.messages.apply(ø,arguments); + + if (filterer && filterer.apply(ø,messages)) { + // fire off reactive sequence instance + next.apply(ø,messages); + } + + // keep sequence going + return messages; + } + + // sequence-stream event listener + def.seq.val(trigger); + + // listen for stop() of reactive sequence + registerTeardown(function $$teardown(){ + def = filterer = null; + }); + } + + // observe sequence-stream + var def = tapSequences(seq)[0]; + + if (!def) return; + + return Ar(reactor); + }; + + Ar.fromObservable = function $$react$from$observable(obsv){ + function reactor(next,registerTeardown){ + // process buffer (if any) + buffer.forEach(next); + buffer.length = 0; + + // start non-buffered notifications? + if (!buffer.complete) { + notify = next; + } + + registerTeardown(function $$teardown(){ + obsv.dispose(); + }); + } + + function notify(v) { + buffer.push(v); + } + + var buffer = []; + + obsv.subscribe( + function $$on$next(v){ + notify(v); + }, + function $$on$error(){}, + function $$on$complete(){ + buffer.complete = true; + obsv.dispose(); + } + ); + + return Ar(reactor); + }; + + ASQ.extend("toObservable",function $$extend(api,internals){ + return function $$to$observable(){ + function init(observer) { + function define(pair){ + function listen(){ + var args = ASQ.messages.apply(ø,arguments); + observer[pair[1]].apply(observer, + args.length == 1 ? [args[0]] : args + ); + return args; + } + + api[pair[0]](listen); + } + + [["val","onNext"],["or","onError"]] + .forEach(define); + } + + return Rx.Observable.create(init); + }; + }); + + function tapSequences() { + function tapSequence(seq) { + // temporary `trigger` which, if called before being replaced + // below, creates replacement proxy sequence with the + // event message(s) re-fired + function trigger() { + var args = ARRAY_SLICE.call(arguments); + def.seq = Ar(function $$react(next){ + next.apply(ø,args); + }); + } + + if (ASQ.isSequence(seq)) { + var def = { seq: seq }; + + // listen for events from the sequence-stream + seq.val(function $$val(){ + trigger.apply(ø,arguments); + return ASQ.messages.apply(ø,arguments); + }); + + // make a reactive sequence to act as a proxy to the original + // sequence + def.seq = Ar(function $$react(next){ + // replace the temporary trigger (created above) + // with this proxy's trigger + trigger = next; + }); + + return def; + } + } + + return ARRAY_SLICE.call(arguments) + .map(tapSequence) + .filter(Boolean); + } + + function makeReactOperator(buffer,keep) { + return function $$react$operator(){ + function reactor(next,registerTeardown){ + function processSequence(def) { + // sequence-stream event listener + function trigger() { + var args = ASQ.messages.apply(ø,arguments); + // still observing sequence-streams? + if (seqs && seqs.length > 0) { + // store event message(s), if any + seq_events[seq_id] = + (buffer ? seq_events[seq_id] : []).concat( + args.length > 0 ? (args.length > 1 ? [args] : args[0]) : undefined + ); + + // collect event message(s) across the + // sequence-stream sources + var messages = seq_events.reduce(function reducer(msgs,eventList,idx){ + if (eventList.length > 0) msgs.push(eventList[0]); + return msgs; + },[]); + + // did all sequence-streams get an event? + if (messages.length == seq_events.length) { + if (messages.length == 1) messages = messages[0]; + + // fire off reactive sequence instance + next.apply(ø,messages); + + // discard stored event message(s)? + if (!keep) { + seq_events.forEach(function $$each(eventList){ + eventList.shift(); + }); + } + } + } + // keep sequence going + return args; + } + + var seq_id = seq_events.length; + seq_events.push([]); + def.seq.val(trigger); + } + + // process all sequence-streams + seqs.forEach(processSequence); + + // listen for stop() of reactive sequence + registerTeardown(function $$teardown(){ + seqs = seq_events = null; + }); + } + + var seq_events = [], + // observe all sequence-streams + seqs = tapSequences.apply(null,arguments) + ; + + if (seqs.length == 0) return; + + return Ar(reactor); + }; + } + + function makeDistinctFilterer(keepAll) { + function filterer() { + function isDuplicate(msgSet) { + return ( + msgSet.length == message_set.length && + msgSet.every(function $$every(val,idx){ + return val === message_set[idx]; + }) + ); + } + + var message_set = ASQ.messages.apply(ø,arguments); + + // any messages in message-set to check against? + if (message_set.length > 0) { + // duplicate message-set? + if (msg_sets.some(isDuplicate)) { + return false; + } + + // remember all message-sets for future distinct checking? + if (keepAll) { + msg_sets.push(message_set); + } + // only keep the last message-set for distinct-consecutive + // checking + else { + msg_sets[0] = message_set; + } + } + + // allow distinct non-duplicate value through + return true; + } + + var msg_sets = []; + + return filterer; + } + +})(); +// "runner" +ASQ.extend("runner",function $$extend(api,internals){ + + return function $$runner() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var args = ARRAY_SLICE.call(arguments); + + api + .then(function $$then(mainDone){ + + function wrap(v) { + // function? expected to produce an iterator + // (like a generator) or a promise + if (typeof v === "function") { + // call function passing in the control token + // note: neutralize `this` in call to prevent + // unexpected behavior + v = v.call(ø,token); + + // promise returned (ie, from async function)? + if (isPromise(v)) { + // wrap it in iterable sequence + v = ASQ.iterable(v); + } + } + // an iterable sequence? duplicate it (in case of multiple runs) + else if (ASQ.isSequence(v) && "next" in v) { + v = v.duplicate(); + } + // wrap anything else in iterable sequence + else { + v = ASQ.iterable(v); + } + + // a sequence to tap for errors? + if (ASQ.isSequence(v)) { + // listen for any sequence failures + v.or(function $$or(){ + // signal iteration-error + mainDone.fail.apply(ø,arguments); + }); + } + + return v; + } + + function addWrapped() { + iterators.push.apply( + iterators, + ARRAY_SLICE.call(arguments).map(wrap) + ); + } + + function iterateOrQuit(iterFn,now) { + // still have some co-routine runs to process? + if (iterators.length > 0) { + if (now) iterFn(); + else schedule(iterFn); + } + // all done! + else { + // previous value message? + if (typeof next_val !== "undefined") { + // not a message wrapper array? + if (!ASQ.isMessageWrapper(next_val)) { + // wrap value for the subsequent `apply(..)` + next_val = [next_val]; + } + } + else { + // nothing to affirmatively pass along + next_val = []; + } + + // signal done with all co-routine runs + mainDone.apply(ø,next_val); + } + } + + var iterators = args, + token = { + messages: ARRAY_SLICE.call(arguments,1), + add: addWrapped + }, + iter, ret, next_val = token + ; + + // map co-routines to round-robin list of iterators + iterators = iterators.map(wrap); + + // async iteration of round-robin list + (function iterate(){ + // get next co-routine in list + iter = iterators.shift(); + + // process the iteration + try { + // multiple messages to send to an iterable + // sequence? + if (ASQ.isMessageWrapper(next_val) && + ASQ.isSequence(iter) + ) { + ret = iter.next.apply(iter,next_val); + } + else { + ret = iter.next(next_val); + } + } + catch (err) { + return mainDone.fail(err); + } + + // bail on run in aborted sequence + if (internals("seq_aborted")) return; + + // was the control token yielded? + if (ret.value === token) { + // round-robin: put co-routine back into the list + // at the end where it was so it can be processed + // again on next loop-iteration + if (!ret.done) { + iterators.push(iter); + } + next_val = token; + iterateOrQuit(iterate,/*now=*/false); + } + else { + // not a recognized ASQ instance returned? + if (!ASQ.isSequence(ret.value)) { + // received a thenable/promise back? + if (isPromise(ret.value)) { + // wrap in a sequence + ret.value = ASQ().promise(ret.value); + } + // thunk yielded? + else if (typeof ret.value === "function") { + // wrap thunk call in a sequence + var fn = ret.value; + ret.value = ASQ(function $$ASQ(done){ + fn(done.errfcb); + }); + } + // message wrapper returned? + else if (ASQ.isMessageWrapper(ret.value)) { + // wrap message(s) in a sequence + ret.value = ASQ.apply(ø, + // don't let `apply(..)` discard an empty message + // wrapper! instead, pass it along as its own value + // itself. + ret.value.length > 0 ? ret.value : ASQ.messages(undefined) + ); + } + // non-undefined value returned? + else if (typeof ret.value !== "undefined") { + // wrap the value in a sequence + ret.value = ASQ(ret.value); + } + else { + // make an empty sequence + ret.value = ASQ(); + } + } + + ret.value + .val(function $$val(){ + // bail on run in aborted sequence + if (internals("seq_aborted")) return; + + if (arguments.length > 0) { + // save any return messages for input + // to next iteration + next_val = arguments.length > 1 ? + ASQ.messages.apply(ø,arguments) : + arguments[0] + ; + } + + // still more to iterate? + if (!ret.done) { + // was the control token passed along? + if (next_val === token) { + // round-robin: put co-routine back into the list + // at the end, so that the the next iterator can be + // processed on next loop-iteration + iterators.push(iter); + } + else { + // put co-routine back in where it just + // was so it can be processed again on + // next loop-iteration + iterators.unshift(iter); + } + } + + iterateOrQuit(iterate,/*now=*/true); + }) + .or(function $$or(){ + // bail on run in aborted sequence + if (internals("seq_aborted")) return; + + try { + // if an error occurs in the step-continuation + // promise or sequence, throw it back into the + // generator or iterable-sequence + iter["throw"].apply(iter,arguments); + } + catch (err) { + // if an error comes back out of after the throw, + // pass it out to the main sequence, as iteration + // must now be complete + mainDone.fail(err); + } + }); + } + })(); + }); + + return api; + }; +}); +// "toPromise" +ASQ.extend("toPromise",function $$extend(api,internals){ + return function $$to$promise() { + return new Promise(function $$executor(resolve,reject){ + api + .val(function $$val(){ + var args = ARRAY_SLICE.call(arguments); + resolve.call(ø,args.length > 1 ? args : args[0]); + return ASQ.messages.apply(ø,args); + }) + .or(function $$or(){ + var args = ARRAY_SLICE.call(arguments); + reject.call(ø,args.length > 1 ? args : args[0]); + }); + }); + }; +}); +// "try" +ASQ.extend("try",function $$extend(api,internals){ + return function $$try() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments) + .map(function $$map(fn){ + return function $$then(mainDone) { + var main_args = ARRAY_SLICE.call(arguments), + sq = ASQ.apply(ø,main_args.slice(1)) + ; + + sq + .then(function $$inner$then(){ + fn.apply(ø,arguments); + }) + .val(function $$val(){ + mainDone.apply(ø,arguments); + }) + .or(function $$inner$or(){ + var msgs = ASQ.messages.apply(ø,arguments); + // failed, so map error(s) as `catch` + mainDone({ + "catch": msgs.length > 1 ? msgs : msgs[0] + }); + }); + }; + }); + + api.then.apply(ø,fns); + + return api; + }; +}); +// "until" +ASQ.extend("until",function $$extend(api,internals){ + return function $$until() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments) + .map(function $$map(fn){ + return function $$then(mainDone) { + var main_args = ARRAY_SLICE.call(arguments), + sq = ASQ.apply(ø,main_args.slice(1)) + ; + + sq + .then(function $$inner$then(){ + var args = ARRAY_SLICE.call(arguments); + args[0]["break"] = function $$break(){ + mainDone.fail.apply(ø,arguments); + sq.abort(); + }; + + fn.apply(ø,args); + }) + .val(function $$val(){ + mainDone.apply(ø,arguments); + }) + .or(function $$inner$or(){ + // failed, retry + $$then.apply(ø,main_args); + }); + }; + }); + + api.then.apply(ø,fns); + + return api; + }; +}); +// "waterfall" +ASQ.extend("waterfall",function $$extend(api,internals){ + return function $$waterfall() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + var msgs = ASQ.messages(), + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)) + ; + + fns.forEach(function $$each(fn){ + sq.then(fn) + .val(function $$val(){ + var args = ASQ.messages.apply(ø,arguments); + msgs.push(args.length > 1 ? args : args[0]); + return msgs; + }); + }); + + sq.pipe(done); + }); + + return api; + }; +}); +// "wrap" +ASQ.wrap = function $$wrap(fn,opts) { + function checkThis(t,o) { + return (!t || + (typeof window != "undefined" && t === window) || + (typeof global != "undefined" && t === global) + ) ? o : t; + } + + function paramSpread(gen) { + return function *paramSpread(token) { + yield *gen.apply(this,token.messages); + }; + } + + var errfcb, params_first, act, this_obj; + + opts = (opts && typeof opts == "object") ? opts : {}; + + if ( + (opts.errfcb && opts.splitcb) || + (opts.errfcb && opts.simplecb) || + (opts.splitcb && opts.simplecb) || + ("errfcb" in opts && !opts.errfcb && !opts.splitcb && !opts.simplecb) || + (opts.params_first && opts.params_last) || + (opts.spread && !opts.gen) + ) { + throw Error("Invalid options"); + } + + // initialize default flags + this_obj = (opts["this"] && typeof opts["this"] == "object") ? opts["this"] : ø; + errfcb = opts.errfcb || !(opts.splitcb || opts.simplecb); + params_first = !!opts.params_first || + (!opts.params_last && !("params_first" in opts || opts.params_first)) || + ("params_last" in opts && !opts.params_first && !opts.params_last) + ; + + if (params_first) { + act = "push"; + } + else { + act = "unshift"; + } + + if (opts.gen) { + if (opts.spread) { + fn = paramSpread(fn); + } + return function $$wrapped$gen() { + return ASQ.apply(ø,arguments).runner(fn); + }; + } + if (errfcb) { + return function $$wrapped$errfcb() { + var args = ARRAY_SLICE.call(arguments), + _this = checkThis(this,this_obj) + ; + + return ASQ(function $$asq(done){ + args[act](done.errfcb); + fn.apply(_this,args); + }); + }; + } + if (opts.splitcb) { + return function $$wrapped$splitcb() { + var args = ARRAY_SLICE.call(arguments), + _this = checkThis(this,this_obj) + ; + + return ASQ(function $$asq(done){ + args[act](done,done.fail); + fn.apply(_this,args); + }); + }; + } + if (opts.simplecb) { + return function $$wrapped$simplecb() { + var args = ARRAY_SLICE.call(arguments), + _this = checkThis(this,this_obj) + ; + + return ASQ(function $$asq(done){ + args[act](done); + fn.apply(_this,args); + }); + }; + } +}; + + + // just return `ASQ` itself for convenience sake + return ASQ; +}); diff --git a/frontend-masters-exercises/exercises/ex6/ex6-fixed.html b/frontend-masters-exercises/exercises/ex6/ex6-fixed.html new file mode 100755 index 0000000..4c627e8 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex6/ex6-fixed.html @@ -0,0 +1,14 @@ + + + + +Exercise 6 - Fixed + + +

Exercise 6 - Fixed

+ + + + + + diff --git a/frontend-masters-exercises/exercises/ex6/ex6-fixed.js b/frontend-masters-exercises/exercises/ex6/ex6-fixed.js new file mode 100755 index 0000000..0d36482 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex6/ex6-fixed.js @@ -0,0 +1,49 @@ +function fakeAjax(url,cb) { + var fake_responses = { + "file1": "The first text", + "file2": "The middle text", + "file3": "The last text" + }; + var randomDelay = (Math.round(Math.random() * 1E4) % 8000) + 1000; + + console.log("Requesting: " + url); + + setTimeout(function(){ + cb(fake_responses[url]); + },randomDelay); +} + +function output(text) { + console.log(text); +} + +// ************************************** + +function getFile(file) { + return ASQ(function(done){ + fakeAjax(file,done); + }); +} + +// Request all files at once in +// "parallel" via `getFile(..)`. +// +// Render as each one finishes, +// but only once previous rendering +// is done. +ASQ() +.seq.apply(null, + ["file1","file2","file3"] + // Request all files at once in "parallel" + .map(getFile) + // Render output as each file finishes, but + // only once previous rendering is done + .map(function(sq){ + return function(){ + return sq.val(output); + }; + }) +) +.val(function(){ + output("Complete!"); +}); diff --git a/frontend-masters-exercises/exercises/ex6/ex6.html b/frontend-masters-exercises/exercises/ex6/ex6.html new file mode 100755 index 0000000..2b24736 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex6/ex6.html @@ -0,0 +1,14 @@ + + + + +Exercise 6 + + +

Exercise 6

+ + + + + + diff --git a/frontend-masters-exercises/exercises/ex6/ex6.js b/frontend-masters-exercises/exercises/ex6/ex6.js new file mode 100755 index 0000000..a76785a --- /dev/null +++ b/frontend-masters-exercises/exercises/ex6/ex6.js @@ -0,0 +1,35 @@ +function fakeAjax(url,cb) { + var fake_responses = { + "file1": "The first text", + "file2": "The middle text", + "file3": "The last text" + }; + var randomDelay = (Math.round(Math.random() * 1E4) % 8000) + 1000; + + console.log("Requesting: " + url); + + setTimeout(function(){ + cb(fake_responses[url]); + },randomDelay); +} + +function output(text) { + console.log(text); +} + +// ************************************** + +function getFile(file) { + return ASQ(function(done){ + fakeAjax(file,done); + }); +} + +// Request all files at once in +// "parallel" via `getFile(..)`. +// +// Render as each one finishes, +// but only once previous rendering +// is done. + +// ??? diff --git a/frontend-masters-exercises/exercises/ex7/README.md b/frontend-masters-exercises/exercises/ex7/README.md new file mode 100755 index 0000000..97ca804 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex7/README.md @@ -0,0 +1,9 @@ +# Instructions + +1. You'll do the same thing as the previous exercise(s), but now you should use asynquence and a generator. + +2. Expected behavior: + - Request all 3 files at the same time (in "parallel"). + - Render them ASAP (don't just blindly wait for all to finish loading) + - BUT, render them in proper (obvious) order: "file1", "file2", "file3". + - After all 3 are done, output "Complete!". diff --git a/frontend-masters-exercises/exercises/ex7/asq.bundle.js b/frontend-masters-exercises/exercises/ex7/asq.bundle.js new file mode 100755 index 0000000..93c9ada --- /dev/null +++ b/frontend-masters-exercises/exercises/ex7/asq.bundle.js @@ -0,0 +1,2333 @@ +/*! asynquence + v0.8.2 (c) Kyle Simpson + MIT License: http://getify.mit-license.org +*/ +!function UMD(e,n,t){"function"==typeof define&&define.amd?define(t):"undefined"!=typeof module&&module.exports?module.exports=t():n[e]=t(e,n)}("ASQ",this,function DEF(e,n){"use strict";function Queue(){function Item(e){this.fn=e,this.next=void 0}var e,n,r;return{add:function $$add(t){r=new Item(t),n?n.next=r:e=r,n=r,r=void 0},drain:function $$drain(){var r=e;for(e=n=t=null;r;)r.fn(),r=r.next}}}function schedule(e){r.add(e),t||(t=u(r.drain))}function tapSequence(e){function trigger(){e.seq=createSequence.apply(h,arguments).defer()}trigger.fail=function $$trigger$fail(){var n=f.call(arguments);e.seq=createSequence(function $$create$sequence(e){e.fail.apply(h,n)}).defer()},e.seq.val(function $$val(){return trigger.apply(h,arguments),c.apply(h,arguments)}).or(function $$or(){trigger.fail.apply(h,arguments)}),e.seq=createSequence(function $$create$sequence(e){trigger=e}).defer()}function createSequence(){function scheduleSequenceTick(){r?sequenceTick():e||(e=schedule(sequenceTick))}function throwSequenceErrors(){throw 1===$.length?$[0]:$}function sequenceTick(){var a,c;if(e=null,delete d.unpause,r)clearTimeout(e),e=null,s.length=p.length=g.length=$.length=0;else if(n)for(0!==p.length||t||(t=!0,throwSequenceErrors());p.length;){t=!0,a=p.shift();try{a.apply(h,$)}catch(i){l(i)?$=$.concat(i):($.push(i),i.stack&&$.push(i.stack)),0===p.length&&throwSequenceErrors()}}else if(u&&s.length>0){u=!1,a=s.shift(),c=g.slice(),g.length=0,c.unshift(createStepCompletion());try{a.apply(h,c)}catch(i){l(i)?$=$.concat(i):$.push(i),n=!0,scheduleSequenceTick()}}}function createStepCompletion(){function done(){n||r||u||(u=!0,g.push.apply(g,arguments),$.length=0,scheduleSequenceTick())}return done.fail=function $$step$fail(){n||r||u||(n=!0,g.length=0,$.push.apply($,arguments),scheduleSequenceTick())},done.abort=function $$step$abort(){n||r||(u=!1,r=!0,g.length=$.length=0,scheduleSequenceTick())},done.errfcb=function $$step$errfcb(e){e?done.fail(e):done.apply(h,f.call(arguments,1))},done}function createGate(e,t,u){function resetGate(){clearTimeout(s),s=d=m=o=null}function scheduleGateTick(){return g?gateTick():void(s||(s=schedule(gateTick)))}function gateTick(){if(!(n||r||$)){var t=[];s=null,p?(e.fail.apply(h,o),resetGate()):g?(e.abort(),resetGate()):checkGate()&&($=!0,d.forEach(function $$each(e,n){t.push(m["s"+n])}),e.apply(h,t),resetGate())}}function checkGate(){if(0!==d.length){var e=!0;return d.some(function $$some(n){return null===n?(e=!1,!0):void 0}),e}}function createSegmentCompletion(){function done(){if(!(n||r||p||g||$||d[e])){var t=c.apply(h,arguments);m["s"+e]=t.length>1?t:t[0],d[e]=!0,scheduleGateTick()}}var e=d.length;return done.fail=function $$segment$fail(){n||r||p||g||$||d[e]||(p=!0,o=f.call(arguments),scheduleGateTick())},done.abort=function $$segment$abort(){n||r||p||g||$||(g=!0,gateTick())},done.errfcb=function $$segment$errfcb(e){e?done.fail(e):done.apply(h,f.call(arguments,1))},d[e]=null,done}var a,i,o,s,p=!1,g=!1,$=!1,d=[],m={};t.some(function $$some(e){if(p||g)return!0;a=u.slice(),a.unshift(createSegmentCompletion());try{e.apply(h,a)}catch(n){return i=n,p=!0,!0}}),i&&(l(i)?e.fail.apply(h,i):e.fail(i))}function then(){return n||r||0===arguments.length?d:(wrapArgs(arguments,thenWrapper).forEach(function $$each(e){i(e)?seq(e):s.push(e)}),scheduleSequenceTick(),d)}function or(){return r||0===arguments.length?d:(p.push.apply(p,arguments),scheduleSequenceTick(),d)}function gate(){if(n||r||0===arguments.length)return d;var e=f.call(arguments).map(function $$map(e){var n;return i(e)?(n={seq:e},tapSequence(n),function $$segment(e){n.seq.pipe(e)}):e});return then(function $$then(n){var t=f.call(arguments,1);createGate(n,e,t)}),d}function pipe(){return r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){then(function $$then(n){e.apply(h,f.call(arguments,1)),n()}).or(e.fail)}),d)}function seq(){return n||r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){var n={seq:e};i(e)&&tapSequence(n),then(function $$then(e){var t=n.seq;i(t)||(t=n.seq.apply(h,f.call(arguments,1))),t.pipe(e)})}),d)}function val(){return n||r||0===arguments.length?d:(f.call(wrapArgs(arguments,valWrapper)).forEach(function $$each(e){then(function $$then(n){var t=e.apply(h,f.call(arguments,1));l(t)||(t=c(t)),n.apply(h,t)})}),d)}function promise(){function wrap(e){return function $$fn(){e.apply(h,l(arguments[0])?arguments[0]:arguments)}}return n||r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){then(function $$then(n){var t=e;"function"==typeof e&&"function"!=typeof e.then&&(t=e.apply(h,f.call(arguments,1))),t.then(wrap(n),wrap(n.fail))})}),d)}function fork(){var e;return val(function $$val(){return e?e.apply(h,arguments):e=createSequence.apply(h,arguments).defer(),c.apply(h,arguments)}),or(function $$or(){if(e)e.fail.apply(h,arguments);else{var n=f.call(arguments);e=createSequence().then(function $$then(e){e.fail.apply(h,n)}).defer()}}),createSequence().then(function $$then(n){e?e.pipe(n):e=n}).defer()}function abort(){return n?d:(r=!0,sequenceTick(),d)}function duplicate(){var e;return a={then_queue:s.slice(),or_queue:p.slice()},e=createSequence(),a=null,e}function unpause(){g.push.apply(g,arguments),e===!0&&(e=null),scheduleSequenceTick()}function defer(){return p.push(function ignored(){}),d}function internals(e,t){var a=arguments.length>1;switch(e){case"seq_error":if(!a)return n;n=t;break;case"seq_aborted":if(!a)return r;r=t;break;case"then_ready":if(!a)return u;u=t;break;case"then_queue":return s;case"or_queue":return p;case"sequence_messages":return g;case"sequence_errors":return $}}function includeExtensions(){Object.keys(o).forEach(function $$each(e){d[e]=o[e](d,internals)})}var e,n=!1,t=!1,r=!1,u=!0,s=[],p=[],g=[],$=[],d=brandIt({then:then,or:or,onerror:or,gate:gate,all:gate,pipe:pipe,seq:seq,val:val,promise:promise,fork:fork,abort:abort,duplicate:duplicate,defer:defer});return includeExtensions(),a&&(s=a.then_queue.slice(),p=a.or_queue.slice(),d.unpause=unpause,e=!0),d.then.apply(h,arguments),d}function brandIt(e){return Object.defineProperty(e,p,{enumerable:!1,value:!0})}function checkBranding(e){return!(null==e||"object"!=typeof e||!e[p])}function valWrapper(e){return c.apply(h,f.call(arguments).slice(1,e+1))}function thenWrapper(e){arguments[e+1].apply(h,f.call(arguments).slice(1,e+1))}function wrapArgs(e,n){var t,r;for(e=f.call(e),t=0;t 1 ? + ARRAY_SLICE.call(arguments,1) : + void 0 + ; + num = +num || 0; + + api.then(function $$then(done){ + var args = orig_args || ARRAY_SLICE.call(arguments,1); + + setTimeout(function $$set$timeout(){ + done.apply(ø,args); + },num); + }); + + return api; + }; +}); + +ASQ.after = function $$after() { + return ASQ().after.apply(ø,arguments); +}; +// "any" +ASQ.extend("any",function $$extend(api,internals){ + return function $$any() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + function reset() { + finished = true; + error_messages.length = 0; + success_messages.length = 0; + } + + function complete(trigger) { + if (success_messages.length > 0) { + // any successful segment's message(s) sent + // to main sequence to proceed as success + success_messages.length = fns.length; + trigger.apply(ø,success_messages); + } + else { + // send errors into main sequence + error_messages.length = fns.length; + trigger.fail.apply(ø,error_messages); + } + + reset(); + } + + function success(trigger,idx,args) { + if (!finished) { + completed++; + success_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + + // all segments complete? + if (completed === fns.length) { + finished = true; + + complete(trigger); + } + } + } + + function failure(trigger,idx,args) { + if (!finished && + !(idx in error_messages) + ) { + completed++; + error_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + } + + // all segments complete? + if (!finished && + completed === fns.length + ) { + finished = true; + + complete(trigger); + } + } + + var completed = 0, error_messages = [], finished = false, + success_messages = [], + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)) + ; + + wrapGate(sq,fns,success,failure,reset); + + sq.pipe(done); + }); + + return api; + }; +}); +// "errfcb" +ASQ.extend("errfcb",function $$extend(api,internals){ + return function $$errfcb() { + // create a fake sequence to extract the callbacks + var sq = { + val: function $$then(cb){ sq.val_cb = cb; return sq; }, + or: function $$or(cb){ sq.or_cb = cb; return sq; } + }; + + // trick `seq(..)`s checks for a sequence + sq[brand] = true; + + // immediately register our fake sequence on the + // main sequence + api.seq(sq); + + // provide the "error-first" callback + return function $$errorfirst$callback(err) { + if (err) { + sq.or_cb(err); + } + else { + sq.val_cb.apply(ø,ARRAY_SLICE.call(arguments,1)); + } + }; + }; +}); +// "failAfter" +ASQ.extend("failAfter",function $$extend(api,internals){ + return function $$failAfter(num) { + var args = arguments.length > 1 ? + ARRAY_SLICE.call(arguments,1) : + void 0 + ; + num = +num || 0; + + api.then(function $$then(done){ + setTimeout(function $$set$timeout(){ + done.fail.apply(ø,args); + },num); + }); + + return api; + }; +}); + +ASQ.failAfter = function $$fail$after() { + return ASQ().failAfter.apply(ø,arguments); +}; +// "first" +ASQ.extend("first",function $$extend(api,internals){ + return function $$first() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + function reset() { + error_messages.length = 0; + } + + function success(trigger,idx,args) { + if (!finished) { + finished = true; + + // first successful segment triggers + // main sequence to proceed as success + trigger( + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ); + + reset(); + } + } + + function failure(trigger,idx,args) { + if (!finished && + !(idx in error_messages) + ) { + completed++; + error_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + + // all segments complete without success? + if (completed === fns.length) { + finished = true; + + // send errors into main sequence + error_messages.length = fns.length; + trigger.fail.apply(ø,error_messages); + + reset(); + } + } + } + + var completed = 0, error_messages = [], finished = false, + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)) + ; + + wrapGate(sq,fns,success,failure,reset); + + sq.pipe(done); + }); + + return api; + }; +}); +// "go-style CSP" +(function IIFE(){ + + // filter out already-resolved queue entries + function filterResolved(queue) { + return queue.filter(function $$filter(entry){ + return !entry.resolved; + }); + } + + function closeQueue(queue,finalValue) { + queue.forEach(function $$each(iter){ + if (!iter.resolved) { + iter.next(); + iter.next(finalValue); + } + }); + queue.length = 0; + } + + function channel(bufSize) { + var ch = { + close: function $$close(){ + ch.closed = true; + closeQueue(ch.put_queue,false); + closeQueue(ch.take_queue,ASQ.csp.CLOSED); + }, + closed: false, + messages: [], + put_queue: [], + take_queue: [], + buffer_size: +bufSize || 0 + }; + return ch; + } + + function unblock(iter) { + if (iter && !iter.resolved) { + iter.next(iter.next().value); + } + } + + function put(channel,value) { + var ret; + + if (channel.closed) { + return false; + } + + // remove already-resolved entries + channel.put_queue = filterResolved(channel.put_queue); + channel.take_queue = filterResolved(channel.take_queue); + + // immediate put? + if (channel.messages.length < channel.buffer_size) { + channel.messages.push(value); + unblock(channel.take_queue.shift()); + return true; + } + // queued put + else { + channel.put_queue.push( + // make a notifiable iterable for 'put' blocking + ASQ.iterable() + .then(function $$then(){ + if (!channel.closed) { + channel.messages.push(value); + return true; + } + else { + return false; + } + }) + ); + + // wrap a sequence/promise around the iterable + ret = ASQ( + channel.put_queue[channel.put_queue.length - 1] + ); + + // take waiting on this queued put? + if (channel.take_queue.length > 0) { + unblock(channel.put_queue.shift()); + unblock(channel.take_queue.shift()); + } + + return ret; + } + } + + function putAsync(channel,value,cb) { + var ret = ASQ(put(channel,value)); + + if (cb && typeof cb == "function") { + ret.val(cb); + } + else { + return ret; + } + } + + function take(channel) { + var ret; + + try { + ret = takem(channel); + } + catch (err) { + ret = err; + } + + if (ASQ.isSequence(ret)) { + ret.pCatch(function $$pcatch(err){ + return err; + }); + } + + return ret; + } + + function takeAsync(channel,cb) { + var ret = ASQ(take(channel)); + + if (cb && typeof cb == "function") { + ret.val(cb); + } + else { + return ret; + } + } + + function takem(channel) { + var msg; + + if (channel.closed) { + return ASQ.csp.CLOSED; + } + + // remove already-resolved entries + channel.put_queue = filterResolved(channel.put_queue); + channel.take_queue = filterResolved(channel.take_queue); + + // immediate take? + if (channel.messages.length > 0) { + msg = channel.messages.shift(); + unblock(channel.put_queue.shift()); + if (msg instanceof Error) { + throw msg; + } + return msg; + } + // queued take + else { + channel.take_queue.push( + // make a notifiable iterable for 'take' blocking + ASQ.iterable() + .then(function $$then(){ + if (!channel.closed) { + var v = channel.messages.shift(); + if (v instanceof Error) { + throw v; + } + return v; + } + else { + return ASQ.csp.CLOSED; + } + }) + ); + + // wrap a sequence/promise around the iterable + msg = ASQ( + channel.take_queue[channel.take_queue.length - 1] + ); + + // put waiting on this take? + if (channel.put_queue.length > 0) { + unblock(channel.put_queue.shift()); + unblock(channel.take_queue.shift()); + } + + return msg; + } + } + + function takemAsync(channel,cb) { + var ret = ASQ(takem(channel)); + + if (cb && typeof cb == "function") { + ret.pThen(cb,cb); + } + else { + return ret.val(function $$val(v){ + if (v instanceof Error) { + throw v; + } + return v; + }); + } + } + + function alts(actions) { + var closed, open, handlers, i, isq, ret, resolved = false; + + // used `alts(..)` incorrectly? + if (!Array.isArray(actions) || actions.length == 0) { + throw Error("Invalid usage"); + } + + closed = []; + open = []; + handlers = []; + + // separate actions by open/closed channel status + actions.forEach(function $$each(action){ + var channel = Array.isArray(action) ? action[0] : action; + + // remove already-resolved entries + channel.put_queue = filterResolved(channel.put_queue); + channel.take_queue = filterResolved(channel.take_queue); + + if (channel.closed) { + closed.push(channel); + } + else { + open.push(action); + } + }); + + // if no channels are still open, we're done + if (open.length == 0) { + return { value: ASQ.csp.CLOSED, channel: closed }; + } + + // can any channel action be executed immediately? + for (i=0; i 0) { + return { value: take(open[i]), channel: open[i] }; + } + } + + isq = ASQ.iterable(); + var ret = ASQ(isq); + + // setup channel action handlers + for (i=0; i 0) { + schedule(function handleUnblocking(){ + if (!resolved) { + unblock(channel.put_queue.shift()); + unblock(channel.take_queue.shift()); + } + },0); + } + } + // take action? + else { + channel = action; + + // define take handler + handlers.push( + ASQ.iterable() + .then(function $$then(){ + resolved = true; + + // mark all handlers across this `alts(..)` as resolved now + handlers = handlers.filter(function $$filter(handler){ + return !(handler.resolved = true); + }); + + // channel still open? + if (!channel.closed) { + isq.next({ value: channel.messages.shift(), channel: channel }); + } + // channel already closed? + else { + isq.next({ value: ASQ.csp.CLOSED, channel: channel }); + } + }) + ); + + // queue up take handler + channel.take_queue.push(handlers[handlers.length-1]); + + // put waiting on this queued take? + if (channel.put_queue.length > 0) { + schedule(function handleUnblocking(){ + if (!resolved) { + unblock(channel.put_queue.shift()); + unblock(channel.take_queue.shift()); + } + }); + } + } + })(open[i]); + } + + return ret; + } + + function altsAsync(chans,cb) { + var ret = ASQ(alts(chans)); + + if (cb && typeof cb == "function") { + ret.pThen(cb,cb); + } + else { + return ret; + } + } + + function timeout(delay) { + var ch = channel(); + setTimeout(ch.close,delay); + return ch; + } + + function go(gen,args) { + // goroutine arguments passed? + if (arguments.length > 1) { + if (!args || !Array.isArray(args)) { + args = [args]; + } + } + else { + args = []; + } + + return function *$$go(token) { + + // unblock the overall goroutine handling + function unblock() { + token.unblock_count++; + + if (token.block && !token.block.marked) { + token.block.marked = true; + token.block.next(); + } + } + + var ret, msg, err, type, done = false, it; + + // keep track of how many requests for unblocking + // have occurred + token.unblock_count = (token.unblock_count || 0); + + // keep track of how many goroutines are running + // so we can infer when we're done go'ing + token.go_count = (token.go_count || 0) + 1; + + // need to initialize a set of goroutines? + if (token.go_count === 1) { + // create a default channel for these goroutines + token.channel = channel(); + token.channel.messages = token.messages; + token.channel.go = function $$go(){ + // unblock the goroutine handling for this + // new goroutine + unblock(); + // add the goroutine (called with any args) to + // the handling queue + token.add( go.apply(ø,arguments) ); + }; + // starting out with initial channel messages? + if (token.channel.messages.length > 0) { + // fake back-pressure blocking for each + token.channel.put_queue = token.channel.messages.map(function $$map(){ + // make a notifiable iterable for 'put' blocking + return ASQ.iterable() + .then(function $$then(){ + unblock(token.channel.take_queue.shift()); + return !token.channel.closed; + }); + }); + } + } + + // initialize the generator + it = gen.apply(ø,[token.channel].concat(args)); + + (function iterate(){ + + function next() { + // keep going with next step in goroutine? + if (!done) { + iterate(); + } + // unblock overall goroutine handling to + // continue with other goroutines + else { + unblock(); + } + } + + // has a resumption value been achieved yet? + if (!ret) { + // try to resume the goroutine + try { + // resume with injected exception? + if (err) { + ret = it.throw(err); + err = null; + } + // resume normally + else { + ret = it.next(msg); + } + } + // resumption failed, so bail + catch (e) { + done = true; + err = e; + msg = null; + unblock(); + return; + } + + // keep track of the result of the resumption + done = ret.done; + ret = ret.value; + type = typeof ret; + + // if this goroutine is complete, unblock the + // overall goroutine handling + if (done) { + unblock(); + } + + // received a thenable/promise back? + if (isPromise(ret)) { + ret = ASQ().promise(ret); + } + + // wait for the value? + if (ASQ.isSequence(ret)) { + ret.val(function $$val(){ + ret = null; + msg = arguments.length > 1 ? + ASQ.messages.apply(ø,arguments) : + arguments[0] + ; + next(); + }) + .or(function $$or(){ + ret = null; + msg = arguments.length > 1 ? + ASQ.messages.apply(ø,arguments) : + arguments[0] + ; + if (msg instanceof Error) { + err = msg; + msg = null; + } + next(); + }); + } + // immediate value, prepare it to go right back in + else { + msg = ret; + ret = null; + next(); + } + } + })(); + + // keep this goroutine alive until completion + while (!done) { + // transfer control to another goroutine + yield token; + + // need to block overall goroutine handling + // while idle? + if (!done && !token.block && token.unblock_count === 0) { + // wait here while idle + yield (token.block = ASQ.iterable()); + + token.block = false; + } + + if (token.unblock_count > 0) token.unblock_count--; + } + + // this goroutine is done now + token.go_count--; + + // all goroutines done? + if (token.go_count === 0) { + // any lingering blocking need to be cleaned up? + unblock(); + + // capture any untaken messages + msg = ASQ.messages.apply(ø,token.messages); + + // need to implicitly force-close channel? + if (token.channel && !token.channel.closed) { + token.channel.closed = true; + token.channel.put_queue.length = token.channel.take_queue.length = 0; + token.channel.close = token.channel.go = token.channel.messages = null; + } + token.channel = null; + } + + // make sure leftover error or message are + // passed along + if (err) { + throw err; + } + else if (token.go_count === 0) { + return msg; + } + else { + return token; + } + }; + } + + ASQ.csp = { + chan: channel, + put: put, + putAsync: putAsync, + take: take, + takeAsync: takeAsync, + takem: takem, + takemAsync: takemAsync, + alts: alts, + altsAsync: altsAsync, + timeout: timeout, + go: go, + CLOSED: {} + }; + +})(); +// "ASQ.iterable()" +(function IIFE(){ + var template; + + ASQ.iterable = function $$iterable() { + function throwSequenceErrors() { + throw (sequence_errors.length === 1 ? sequence_errors[0] : sequence_errors); + } + + function notifyErrors() { + var fn; + + seq_tick = null; + + if (seq_error) { + if (or_queue.length === 0 && !error_reported) { + error_reported = true; + throwSequenceErrors(); + } + + while (or_queue.length > 0) { + error_reported = true; + fn = or_queue.shift(); + try { + fn.apply(ø,sequence_errors); + } + catch (err) { + if (checkBranding(err)) { + sequence_errors = sequence_errors.concat(err); + } + else { + sequence_errors.push(err); + } + if (or_queue.length === 0) { + throwSequenceErrors(); + } + } + } + } + } + + function val() { + if (seq_error || seq_aborted || arguments.length === 0) { + return sequence_api; + } + + var args = ARRAY_SLICE.call(arguments).map(function mapper(arg){ + if (typeof arg != "function") return function $$val() { return arg; }; + else return arg; + }); + + val_queue.push.apply(val_queue,args); + + return sequence_api; + } + + function or() { + if (seq_aborted || arguments.length === 0) { + return sequence_api; + } + + or_queue.push.apply(or_queue,arguments); + + if (!seq_tick) { + seq_tick = schedule(notifyErrors); + } + + return sequence_api; + } + + function pipe() { + if (seq_aborted || arguments.length === 0) { + return sequence_api; + } + + ARRAY_SLICE.call(arguments) + .forEach(function $$each(fn){ + val(fn).or(fn.fail); + }); + + return sequence_api; + } + + function next() { + if (seq_error || seq_aborted || val_queue.length === 0) { + if (val_queue.length > 0) { + $throw$("Sequence cannot be iterated"); + } + return { done: true }; + } + + try { + return { value: val_queue.shift().apply(ø,arguments) }; + } + catch (err) { + if (ASQ.isMessageWrapper(err)) { + $throw$.apply(ø,err); + } + else { + $throw$(err); + } + + return {}; + } + } + + function $throw$() { + if (seq_error || seq_aborted) { + return sequence_api; + } + + sequence_errors.push.apply(sequence_errors,arguments); + seq_error = true; + if (!seq_tick) { + seq_tick = schedule(notifyErrors); + } + + return sequence_api; + } + + function $return$(val) { + if (seq_error || seq_aborted) { + val = void 0; + } + + abort(); + + return { done: true, value: val }; + } + + function abort() { + if (seq_error || seq_aborted) { + return; + } + + seq_aborted = true; + + clearTimeout(seq_tick); + seq_tick = null; + val_queue.length = or_queue.length = sequence_errors.length = 0; + } + + function duplicate() { + var isq; + + template = { + val_queue: val_queue.slice(), + or_queue: or_queue.slice() + }; + isq = ASQ.iterable(); + template = null; + + return isq; + } + + // opt-out of global error reporting for this sequence + function defer() { + or_queue.push(function $$ignored(){}); + return sequence_api; + } + + // *********************************************** + // Object branding utilities + // *********************************************** + function brandIt(obj) { + Object.defineProperty(obj,brand,{ + enumerable: false, + value: true + }); + + return obj; + } + + var sequence_api, + + seq_error = false, + error_reported = false, + seq_aborted = false, + + seq_tick, + + val_queue = [], + or_queue = [], + + sequence_errors = [] + ; + + // *********************************************** + // Setup the ASQ.iterable() public API + // *********************************************** + sequence_api = brandIt({ + val: val, + then: val, + or: or, + pipe: pipe, + next: next, + "throw": $throw$, + "return": $return$, + abort: abort, + duplicate: duplicate, + defer: defer + }); + + // useful for ES6 `for..of` loops, + // add `@@iterator` to simply hand back + // our iterable sequence itself! + sequence_api[(typeof Symbol == "function" && Symbol.iterator) || "@@iterator"] = function $$iter() { + return sequence_api; + }; + + // templating the iterable-sequence setup? + if (template) { + val_queue = template.val_queue.slice(0); + or_queue = template.or_queue.slice(0); + } + + // treat ASQ.iterable() constructor parameters as having been + // passed to `val()` + sequence_api.val.apply(ø,arguments); + + return sequence_api; + }; + +})(); +// "last" +ASQ.extend("last",function $$extend(api,internals){ + return function $$last() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + function reset() { + finished = true; + error_messages.length = 0; + success_messages = null; + } + + function complete(trigger) { + if (success_messages != null) { + // last successful segment's message(s) sent + // to main sequence to proceed as success + trigger( + success_messages.length > 1 ? + ASQ.messages.apply(ø,success_messages) : + success_messages[0] + ); + } + else { + // send errors into main sequence + error_messages.length = fns.length; + trigger.fail.apply(ø,error_messages); + } + + reset(); + } + + function success(trigger,idx,args) { + if (!finished) { + completed++; + success_messages = args; + + // all segments complete? + if (completed === fns.length) { + finished = true; + + complete(trigger); + } + } + } + + function failure(trigger,idx,args) { + if (!finished && + !(idx in error_messages) + ) { + completed++; + error_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + } + + // all segments complete? + if (!finished && + completed === fns.length + ) { + finished = true; + + complete(trigger); + } + } + + var completed = 0, error_messages = [], finished = false, + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)), + success_messages + ; + + wrapGate(sq,fns,success,failure,reset); + + sq.pipe(done); + }); + + return api; + }; +}); +// "map" +ASQ.extend("map",function $$extend(api,internals){ + return function $$map(pArr,pEach) { + if (internals("seq_error") || internals("seq_aborted")) { + return api; + } + + api.seq(function $$seq(){ + var tmp, args = ARRAY_SLICE.call(arguments), + arr = pArr, each = pEach; + + // if missing `map(..)` args, use value-messages (if any) + if (!each) each = args.shift(); + if (!arr) arr = args.shift(); + + // if arg types in reverse order (each,arr), swap + if (typeof arr === "function" && Array.isArray(each)) { + tmp = arr; + arr = each; + each = tmp; + } + + return ASQ.apply(ø,args) + .gate.apply(ø,arr.map(function $$map(item){ + return function $$segment(){ + each.apply(ø,[item].concat(ARRAY_SLICE.call(arguments))); + }; + })); + }) + .val(function $$val(){ + // collect all gate segment output into one value-message + // Note: return a normal array here, not a message wrapper! + return ARRAY_SLICE.call(arguments); + }); + + return api; + }; +}); +// "none" +ASQ.extend("none",function $$extend(api,internals){ + return function $$none() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + function reset() { + finished = true; + error_messages.length = 0; + success_messages.length = 0; + } + + function complete(trigger) { + if (success_messages.length > 0) { + // any successful segment's message(s) sent + // to main sequence to proceed as **error** + success_messages.length = fns.length; + trigger.fail.apply(ø,success_messages); + } + else { + // send errors as **success** to main sequence + error_messages.length = fns.length; + trigger.apply(ø,error_messages); + } + + reset(); + } + + function success(trigger,idx,args) { + if (!finished) { + completed++; + success_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + + // all segments complete? + if (completed === fns.length) { + finished = true; + + complete(trigger); + } + } + } + + function failure(trigger,idx,args) { + if (!finished && + !(idx in error_messages) + ) { + completed++; + error_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + } + + // all segments complete? + if (!finished && + completed === fns.length + ) { + finished = true; + + complete(trigger); + } + } + + var completed = 0, error_messages = [], finished = false, + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)), + success_messages = [] + ; + + wrapGate(sq,fns,success,failure,reset); + + sq.pipe(done); + }); + + return api; + }; +}); +// "pThen" +ASQ.extend("pThen",function $$extend(api,internals){ + return function $$pthen(success,failure) { + if (internals("seq_aborted")) { + return api; + } + + var ignore_success_handler = false, ignore_failure_handler = false; + + if (typeof success === "function") { + api.then(function $$then(done){ + if (!ignore_success_handler) { + var ret, msgs = ASQ.messages.apply(ø,arguments); + msgs.shift(); + + if (msgs.length === 1) { + msgs = msgs[0]; + } + + ignore_failure_handler = true; + + try { + ret = success(msgs); + } + catch (err) { + if (!ASQ.isMessageWrapper(err)) { + err = [err]; + } + done.fail.apply(ø,err); + return; + } + + // returned a sequence? + if (ASQ.isSequence(ret)) { + ret.pipe(done); + } + // returned a message wrapper? + else if (ASQ.isMessageWrapper(ret)) { + done.apply(ø,ret); + } + // returned a promise/thenable? + else if (isPromise(ret)) { + ret.then(done,done.fail); + } + // just a normal value to pass along + else { + done(ret); + } + } + else { + done.apply(ø,ARRAY_SLICE.call(arguments,1)); + } + }); + } + if (typeof failure === "function") { + api.or(function $$or(){ + if (!ignore_failure_handler) { + var ret, msgs = ASQ.messages.apply(ø,arguments), smgs, + or_queue = ARRAY_SLICE.call(internals("or_queue")) + ; + + if (msgs.length === 1) { + msgs = msgs[0]; + } + + ignore_success_handler = true; + + // NOTE: if this call throws, that'll automatically + // be handled by core as we'd want it to be + ret = failure(msgs); + + // if we get this far: + // first, inject return value (if any) as + // next step's sequence messages + smgs = internals("sequence_messages"); + smgs.length = 0; + if (typeof ret !== "undefined") { + if (!ASQ.isMessageWrapper(ret)) { + ret = [ret]; + } + smgs.push.apply(smgs,ret); + } + + // reset internal error state, because we've exclusively + // handled any errors up to this point of the sequence + internals("sequence_errors").length = 0; + internals("seq_error",false); + internals("then_ready",true); + + // temporarily empty the or-queue + internals("or_queue").length = 0; + + // make sure to schedule success-procession on the chain + api.val(function $$val(){ + // pass thru messages + return ASQ.messages.apply(ø,arguments); + }); + + // at next cycle, reinstate the or-queue (if any) + if (or_queue.length > 0) { + schedule(function $$schedule(){ + api.or.apply(ø,or_queue); + }); + } + } + }); + } + return api; + }; +}); + +// "pCatch" +ASQ.extend("pCatch",function $$extend(api,internals){ + return function $$pcatch(failure) { + if (internals("seq_aborted")) { + return api; + } + + api.pThen(void 0,failure); + + return api; + }; +}); +// "race" +ASQ.extend("race",function $$extend(api,internals){ + return function $$race() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments) + .map(function $$map(v){ + var def; + // tap any directly-provided sequences immediately + if (ASQ.isSequence(v)) { + def = { seq: v }; + tapSequence(def); + return function $$fn(done) { + def.seq.pipe(done); + }; + } + else return v; + }); + + api.then(function $$then(done){ + var args = ARRAY_SLICE.call(arguments); + + fns.forEach(function $$each(fn){ + fn.apply(ø,args); + }); + }); + + return api; + }; +}); +// "react" (reactive sequences) +ASQ.react = function $$react(reactor) { + function next() { + if (!paused) { + if (template) { + var sq = template.duplicate(); + sq.unpause.apply(ø,arguments); + return sq; + } + return ASQ(function $$asq(){ throw "Disabled Sequence"; }); + } + } + + function registerTeardown(fn) { + if (template && typeof fn === "function") { + teardowns.push(fn); + } + } + + var template = ASQ().duplicate(), + teardowns = [], paused = false + ; + + // add reactive sequence kill switch + template.stop = function $$stop() { + if (template) { + template = null; + teardowns.forEach(Function.call,Function.call); + teardowns.length = 0; + } + }; + + template.pause = function $$pause() { + if (!paused && template) { + paused = true; + teardowns.forEach(Function.call,Function.call); + teardowns.length = 0; + } + }; + + template.resume = function $$resume() { + if (paused && template) { + paused = false; + reactor.call(template,next,registerTeardown); + } + }; + + template.push = next; + + next.onStream = function $$onStream() { + ARRAY_SLICE.call(arguments) + .forEach(function $$each(stream){ + stream.on("data",next); + stream.on("error",next); + }); + }; + + next.unStream = function $$unStream() { + ARRAY_SLICE.call(arguments) + .forEach(function $$each(stream){ + stream.removeListener("data",next); + stream.removeListener("error",next); + }); + }; + + // make sure `reactor(..)` is called async + ASQ.__schedule(function $$schedule(){ + reactor.call(template,next,registerTeardown); + }); + + return template; +}; +// "react" helpers +(function IIFE(){ + + var Ar = ASQ.react; + + Ar.of = function $$react$of() { + function reactor(next) { + if (!started) { + started = true; + if (args.length > 0) { + args.shift().val(function val(){ + next.apply(ø,arguments); + if (args.length > 0) { + args.shift().val(val); + } + }); + } + } + } + + var started, args = ARRAY_SLICE.call(arguments) + .map(function wrapper(arg){ + if (!ASQ.isSequence(arg)) arg = ASQ(arg); + return arg; + }); + + return Ar(reactor); + }; + + Ar.all = Ar.zip = makeReactOperator(/*buffer=*/true); + Ar.allLatest = makeReactOperator(/*buffer=false*/); + Ar.latest = Ar.combineLatest = makeReactOperator(/*buffer=*/false,/*keep=*/true); + + Ar.any = Ar.merge = function $$react$any(){ + function reactor(next,registerTeardown){ + function processSequence(def){ + function trigger(){ + var args = ASQ.messages.apply(ø,arguments); + // still observing sequence-streams? + if (seqs && seqs.length > 0) { + // fire off reactive sequence instance + next.apply(ø,args); + } + // keep sequence going + return args; + } + + // sequence-stream event listener + def.seq.val(trigger); + } + + // observe all sequence-streams + seqs.forEach(processSequence); + + // listen for stop() of reactive sequence + registerTeardown(function $$teardown(){ + seqs = null; + }); + } + + // observe all sequence-streams + var seqs = tapSequences.apply(null,arguments); + + if (seqs.length == 0) return; + + return Ar(reactor); + }; + + Ar.distinct = function $$react$distinct(seq){ + return Ar.filter(seq,makeDistinctFilterer(/*keepAll=*/true)); + }; + + Ar.distinctConsecutive = Ar.distinctUntilChanged = function $$react$distinct$consecutive(seq) { + return Ar.filter(seq,makeDistinctFilterer(/*keepAll=*/false)); + }; + + Ar.filter = function $$react$filter(seq,filterer){ + function reactor(next,registerTeardown) { + function trigger(){ + var messages = ASQ.messages.apply(ø,arguments); + + if (filterer && filterer.apply(ø,messages)) { + // fire off reactive sequence instance + next.apply(ø,messages); + } + + // keep sequence going + return messages; + } + + // sequence-stream event listener + def.seq.val(trigger); + + // listen for stop() of reactive sequence + registerTeardown(function $$teardown(){ + def = filterer = null; + }); + } + + // observe sequence-stream + var def = tapSequences(seq)[0]; + + if (!def) return; + + return Ar(reactor); + }; + + Ar.fromObservable = function $$react$from$observable(obsv){ + function reactor(next,registerTeardown){ + // process buffer (if any) + buffer.forEach(next); + buffer.length = 0; + + // start non-buffered notifications? + if (!buffer.complete) { + notify = next; + } + + registerTeardown(function $$teardown(){ + obsv.dispose(); + }); + } + + function notify(v) { + buffer.push(v); + } + + var buffer = []; + + obsv.subscribe( + function $$on$next(v){ + notify(v); + }, + function $$on$error(){}, + function $$on$complete(){ + buffer.complete = true; + obsv.dispose(); + } + ); + + return Ar(reactor); + }; + + ASQ.extend("toObservable",function $$extend(api,internals){ + return function $$to$observable(){ + function init(observer) { + function define(pair){ + function listen(){ + var args = ASQ.messages.apply(ø,arguments); + observer[pair[1]].apply(observer, + args.length == 1 ? [args[0]] : args + ); + return args; + } + + api[pair[0]](listen); + } + + [["val","onNext"],["or","onError"]] + .forEach(define); + } + + return Rx.Observable.create(init); + }; + }); + + function tapSequences() { + function tapSequence(seq) { + // temporary `trigger` which, if called before being replaced + // below, creates replacement proxy sequence with the + // event message(s) re-fired + function trigger() { + var args = ARRAY_SLICE.call(arguments); + def.seq = Ar(function $$react(next){ + next.apply(ø,args); + }); + } + + if (ASQ.isSequence(seq)) { + var def = { seq: seq }; + + // listen for events from the sequence-stream + seq.val(function $$val(){ + trigger.apply(ø,arguments); + return ASQ.messages.apply(ø,arguments); + }); + + // make a reactive sequence to act as a proxy to the original + // sequence + def.seq = Ar(function $$react(next){ + // replace the temporary trigger (created above) + // with this proxy's trigger + trigger = next; + }); + + return def; + } + } + + return ARRAY_SLICE.call(arguments) + .map(tapSequence) + .filter(Boolean); + } + + function makeReactOperator(buffer,keep) { + return function $$react$operator(){ + function reactor(next,registerTeardown){ + function processSequence(def) { + // sequence-stream event listener + function trigger() { + var args = ASQ.messages.apply(ø,arguments); + // still observing sequence-streams? + if (seqs && seqs.length > 0) { + // store event message(s), if any + seq_events[seq_id] = + (buffer ? seq_events[seq_id] : []).concat( + args.length > 0 ? (args.length > 1 ? [args] : args[0]) : undefined + ); + + // collect event message(s) across the + // sequence-stream sources + var messages = seq_events.reduce(function reducer(msgs,eventList,idx){ + if (eventList.length > 0) msgs.push(eventList[0]); + return msgs; + },[]); + + // did all sequence-streams get an event? + if (messages.length == seq_events.length) { + if (messages.length == 1) messages = messages[0]; + + // fire off reactive sequence instance + next.apply(ø,messages); + + // discard stored event message(s)? + if (!keep) { + seq_events.forEach(function $$each(eventList){ + eventList.shift(); + }); + } + } + } + // keep sequence going + return args; + } + + var seq_id = seq_events.length; + seq_events.push([]); + def.seq.val(trigger); + } + + // process all sequence-streams + seqs.forEach(processSequence); + + // listen for stop() of reactive sequence + registerTeardown(function $$teardown(){ + seqs = seq_events = null; + }); + } + + var seq_events = [], + // observe all sequence-streams + seqs = tapSequences.apply(null,arguments) + ; + + if (seqs.length == 0) return; + + return Ar(reactor); + }; + } + + function makeDistinctFilterer(keepAll) { + function filterer() { + function isDuplicate(msgSet) { + return ( + msgSet.length == message_set.length && + msgSet.every(function $$every(val,idx){ + return val === message_set[idx]; + }) + ); + } + + var message_set = ASQ.messages.apply(ø,arguments); + + // any messages in message-set to check against? + if (message_set.length > 0) { + // duplicate message-set? + if (msg_sets.some(isDuplicate)) { + return false; + } + + // remember all message-sets for future distinct checking? + if (keepAll) { + msg_sets.push(message_set); + } + // only keep the last message-set for distinct-consecutive + // checking + else { + msg_sets[0] = message_set; + } + } + + // allow distinct non-duplicate value through + return true; + } + + var msg_sets = []; + + return filterer; + } + +})(); +// "runner" +ASQ.extend("runner",function $$extend(api,internals){ + + return function $$runner() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var args = ARRAY_SLICE.call(arguments); + + api + .then(function $$then(mainDone){ + + function wrap(v) { + // function? expected to produce an iterator + // (like a generator) or a promise + if (typeof v === "function") { + // call function passing in the control token + // note: neutralize `this` in call to prevent + // unexpected behavior + v = v.call(ø,token); + + // promise returned (ie, from async function)? + if (isPromise(v)) { + // wrap it in iterable sequence + v = ASQ.iterable(v); + } + } + // an iterable sequence? duplicate it (in case of multiple runs) + else if (ASQ.isSequence(v) && "next" in v) { + v = v.duplicate(); + } + // wrap anything else in iterable sequence + else { + v = ASQ.iterable(v); + } + + // a sequence to tap for errors? + if (ASQ.isSequence(v)) { + // listen for any sequence failures + v.or(function $$or(){ + // signal iteration-error + mainDone.fail.apply(ø,arguments); + }); + } + + return v; + } + + function addWrapped() { + iterators.push.apply( + iterators, + ARRAY_SLICE.call(arguments).map(wrap) + ); + } + + function iterateOrQuit(iterFn,now) { + // still have some co-routine runs to process? + if (iterators.length > 0) { + if (now) iterFn(); + else schedule(iterFn); + } + // all done! + else { + // previous value message? + if (typeof next_val !== "undefined") { + // not a message wrapper array? + if (!ASQ.isMessageWrapper(next_val)) { + // wrap value for the subsequent `apply(..)` + next_val = [next_val]; + } + } + else { + // nothing to affirmatively pass along + next_val = []; + } + + // signal done with all co-routine runs + mainDone.apply(ø,next_val); + } + } + + var iterators = args, + token = { + messages: ARRAY_SLICE.call(arguments,1), + add: addWrapped + }, + iter, ret, next_val = token + ; + + // map co-routines to round-robin list of iterators + iterators = iterators.map(wrap); + + // async iteration of round-robin list + (function iterate(){ + // get next co-routine in list + iter = iterators.shift(); + + // process the iteration + try { + // multiple messages to send to an iterable + // sequence? + if (ASQ.isMessageWrapper(next_val) && + ASQ.isSequence(iter) + ) { + ret = iter.next.apply(iter,next_val); + } + else { + ret = iter.next(next_val); + } + } + catch (err) { + return mainDone.fail(err); + } + + // bail on run in aborted sequence + if (internals("seq_aborted")) return; + + // was the control token yielded? + if (ret.value === token) { + // round-robin: put co-routine back into the list + // at the end where it was so it can be processed + // again on next loop-iteration + if (!ret.done) { + iterators.push(iter); + } + next_val = token; + iterateOrQuit(iterate,/*now=*/false); + } + else { + // not a recognized ASQ instance returned? + if (!ASQ.isSequence(ret.value)) { + // received a thenable/promise back? + if (isPromise(ret.value)) { + // wrap in a sequence + ret.value = ASQ().promise(ret.value); + } + // thunk yielded? + else if (typeof ret.value === "function") { + // wrap thunk call in a sequence + var fn = ret.value; + ret.value = ASQ(function $$ASQ(done){ + fn(done.errfcb); + }); + } + // message wrapper returned? + else if (ASQ.isMessageWrapper(ret.value)) { + // wrap message(s) in a sequence + ret.value = ASQ.apply(ø, + // don't let `apply(..)` discard an empty message + // wrapper! instead, pass it along as its own value + // itself. + ret.value.length > 0 ? ret.value : ASQ.messages(undefined) + ); + } + // non-undefined value returned? + else if (typeof ret.value !== "undefined") { + // wrap the value in a sequence + ret.value = ASQ(ret.value); + } + else { + // make an empty sequence + ret.value = ASQ(); + } + } + + ret.value + .val(function $$val(){ + // bail on run in aborted sequence + if (internals("seq_aborted")) return; + + if (arguments.length > 0) { + // save any return messages for input + // to next iteration + next_val = arguments.length > 1 ? + ASQ.messages.apply(ø,arguments) : + arguments[0] + ; + } + + // still more to iterate? + if (!ret.done) { + // was the control token passed along? + if (next_val === token) { + // round-robin: put co-routine back into the list + // at the end, so that the the next iterator can be + // processed on next loop-iteration + iterators.push(iter); + } + else { + // put co-routine back in where it just + // was so it can be processed again on + // next loop-iteration + iterators.unshift(iter); + } + } + + iterateOrQuit(iterate,/*now=*/true); + }) + .or(function $$or(){ + // bail on run in aborted sequence + if (internals("seq_aborted")) return; + + try { + // if an error occurs in the step-continuation + // promise or sequence, throw it back into the + // generator or iterable-sequence + iter["throw"].apply(iter,arguments); + } + catch (err) { + // if an error comes back out of after the throw, + // pass it out to the main sequence, as iteration + // must now be complete + mainDone.fail(err); + } + }); + } + })(); + }); + + return api; + }; +}); +// "toPromise" +ASQ.extend("toPromise",function $$extend(api,internals){ + return function $$to$promise() { + return new Promise(function $$executor(resolve,reject){ + api + .val(function $$val(){ + var args = ARRAY_SLICE.call(arguments); + resolve.call(ø,args.length > 1 ? args : args[0]); + return ASQ.messages.apply(ø,args); + }) + .or(function $$or(){ + var args = ARRAY_SLICE.call(arguments); + reject.call(ø,args.length > 1 ? args : args[0]); + }); + }); + }; +}); +// "try" +ASQ.extend("try",function $$extend(api,internals){ + return function $$try() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments) + .map(function $$map(fn){ + return function $$then(mainDone) { + var main_args = ARRAY_SLICE.call(arguments), + sq = ASQ.apply(ø,main_args.slice(1)) + ; + + sq + .then(function $$inner$then(){ + fn.apply(ø,arguments); + }) + .val(function $$val(){ + mainDone.apply(ø,arguments); + }) + .or(function $$inner$or(){ + var msgs = ASQ.messages.apply(ø,arguments); + // failed, so map error(s) as `catch` + mainDone({ + "catch": msgs.length > 1 ? msgs : msgs[0] + }); + }); + }; + }); + + api.then.apply(ø,fns); + + return api; + }; +}); +// "until" +ASQ.extend("until",function $$extend(api,internals){ + return function $$until() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments) + .map(function $$map(fn){ + return function $$then(mainDone) { + var main_args = ARRAY_SLICE.call(arguments), + sq = ASQ.apply(ø,main_args.slice(1)) + ; + + sq + .then(function $$inner$then(){ + var args = ARRAY_SLICE.call(arguments); + args[0]["break"] = function $$break(){ + mainDone.fail.apply(ø,arguments); + sq.abort(); + }; + + fn.apply(ø,args); + }) + .val(function $$val(){ + mainDone.apply(ø,arguments); + }) + .or(function $$inner$or(){ + // failed, retry + $$then.apply(ø,main_args); + }); + }; + }); + + api.then.apply(ø,fns); + + return api; + }; +}); +// "waterfall" +ASQ.extend("waterfall",function $$extend(api,internals){ + return function $$waterfall() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + var msgs = ASQ.messages(), + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)) + ; + + fns.forEach(function $$each(fn){ + sq.then(fn) + .val(function $$val(){ + var args = ASQ.messages.apply(ø,arguments); + msgs.push(args.length > 1 ? args : args[0]); + return msgs; + }); + }); + + sq.pipe(done); + }); + + return api; + }; +}); +// "wrap" +ASQ.wrap = function $$wrap(fn,opts) { + function checkThis(t,o) { + return (!t || + (typeof window != "undefined" && t === window) || + (typeof global != "undefined" && t === global) + ) ? o : t; + } + + function paramSpread(gen) { + return function *paramSpread(token) { + yield *gen.apply(this,token.messages); + }; + } + + var errfcb, params_first, act, this_obj; + + opts = (opts && typeof opts == "object") ? opts : {}; + + if ( + (opts.errfcb && opts.splitcb) || + (opts.errfcb && opts.simplecb) || + (opts.splitcb && opts.simplecb) || + ("errfcb" in opts && !opts.errfcb && !opts.splitcb && !opts.simplecb) || + (opts.params_first && opts.params_last) || + (opts.spread && !opts.gen) + ) { + throw Error("Invalid options"); + } + + // initialize default flags + this_obj = (opts["this"] && typeof opts["this"] == "object") ? opts["this"] : ø; + errfcb = opts.errfcb || !(opts.splitcb || opts.simplecb); + params_first = !!opts.params_first || + (!opts.params_last && !("params_first" in opts || opts.params_first)) || + ("params_last" in opts && !opts.params_first && !opts.params_last) + ; + + if (params_first) { + act = "push"; + } + else { + act = "unshift"; + } + + if (opts.gen) { + if (opts.spread) { + fn = paramSpread(fn); + } + return function $$wrapped$gen() { + return ASQ.apply(ø,arguments).runner(fn); + }; + } + if (errfcb) { + return function $$wrapped$errfcb() { + var args = ARRAY_SLICE.call(arguments), + _this = checkThis(this,this_obj) + ; + + return ASQ(function $$asq(done){ + args[act](done.errfcb); + fn.apply(_this,args); + }); + }; + } + if (opts.splitcb) { + return function $$wrapped$splitcb() { + var args = ARRAY_SLICE.call(arguments), + _this = checkThis(this,this_obj) + ; + + return ASQ(function $$asq(done){ + args[act](done,done.fail); + fn.apply(_this,args); + }); + }; + } + if (opts.simplecb) { + return function $$wrapped$simplecb() { + var args = ARRAY_SLICE.call(arguments), + _this = checkThis(this,this_obj) + ; + + return ASQ(function $$asq(done){ + args[act](done); + fn.apply(_this,args); + }); + }; + } +}; + + + // just return `ASQ` itself for convenience sake + return ASQ; +}); diff --git a/frontend-masters-exercises/exercises/ex7/ex7-fixed.html b/frontend-masters-exercises/exercises/ex7/ex7-fixed.html new file mode 100755 index 0000000..b740d48 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex7/ex7-fixed.html @@ -0,0 +1,15 @@ + + + + +Exercise 7 - Fixed + + +

Exercise 7 - Fixed

+ + + + + + + diff --git a/frontend-masters-exercises/exercises/ex7/ex7-fixed.js b/frontend-masters-exercises/exercises/ex7/ex7-fixed.js new file mode 100755 index 0000000..00ff999 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex7/ex7-fixed.js @@ -0,0 +1,51 @@ +function fakeAjax(url,cb) { + var fake_responses = { + "file1": "The first text", + "file2": "The middle text", + "file3": "The last text" + }; + var randomDelay = (Math.round(Math.random() * 1E4) % 8000) + 1000; + + console.log("Requesting: " + url); + + setTimeout(function(){ + cb(fake_responses[url]); + },randomDelay); +} + +function output(text) { + console.log(text); +} + +// ************************************** + +function getFile(file) { + return ASQ(function(done){ + fakeAjax(file,done); + }); +} + +// function getFile(file) { +// return new Promise(function(resolve){ +// fakeAjax(file,resolve); +// }); +// } + +ASQ() +.runner(function *loadFiles(){ + // Request all files at once in + // "parallel" via `getFile(..)`. + var p1 = getFile("file1"); + var p2 = getFile("file2"); + var p3 = getFile("file3"); + + // Render as each one finishes, + // but only once previous rendering + // is done. + output( yield p1 ); + output( yield p2 ); + output( yield p3 ); +}) +.val(function(){ + output("Complete!"); +}); diff --git a/frontend-masters-exercises/exercises/ex7/ex7.html b/frontend-masters-exercises/exercises/ex7/ex7.html new file mode 100755 index 0000000..9f98a79 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex7/ex7.html @@ -0,0 +1,15 @@ + + + + +Exercise 7 + + +

Exercise 7

+ + + + + + + diff --git a/frontend-masters-exercises/exercises/ex7/ex7.js b/frontend-masters-exercises/exercises/ex7/ex7.js new file mode 100755 index 0000000..a76785a --- /dev/null +++ b/frontend-masters-exercises/exercises/ex7/ex7.js @@ -0,0 +1,35 @@ +function fakeAjax(url,cb) { + var fake_responses = { + "file1": "The first text", + "file2": "The middle text", + "file3": "The last text" + }; + var randomDelay = (Math.round(Math.random() * 1E4) % 8000) + 1000; + + console.log("Requesting: " + url); + + setTimeout(function(){ + cb(fake_responses[url]); + },randomDelay); +} + +function output(text) { + console.log(text); +} + +// ************************************** + +function getFile(file) { + return ASQ(function(done){ + fakeAjax(file,done); + }); +} + +// Request all files at once in +// "parallel" via `getFile(..)`. +// +// Render as each one finishes, +// but only once previous rendering +// is done. + +// ??? diff --git a/frontend-masters-exercises/exercises/ex7/npo.js b/frontend-masters-exercises/exercises/ex7/npo.js new file mode 100755 index 0000000..c363ed4 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex7/npo.js @@ -0,0 +1,5 @@ +/*! Native Promise Only + v0.8.1 (c) Kyle Simpson + MIT License: http://getify.mit-license.org +*/ +!function(t,n,e){n[t]=n[t]||e(),"undefined"!=typeof module&&module.exports?module.exports=n[t]:"function"==typeof define&&define.amd&&define(function(){return n[t]})}("Promise","undefined"!=typeof global?global:this,function(){"use strict";function t(t,n){l.add(t,n),h||(h=y(l.drain))}function n(t){var n,e=typeof t;return null==t||"object"!=e&&"function"!=e||(n=t.then),"function"==typeof n?n:!1}function e(){for(var t=0;t0&&t(e,u))}catch(a){i.call(new f(u),a)}}}function i(n){var o=this;o.triggered||(o.triggered=!0,o.def&&(o=o.def),o.msg=n,o.state=2,o.chain.length>0&&t(e,o))}function c(t,n,e,o){for(var r=0;r0){u=!1,a=s.shift(),c=g.slice(),g.length=0,c.unshift(createStepCompletion());try{a.apply(h,c)}catch(i){l(i)?$=$.concat(i):$.push(i),n=!0,scheduleSequenceTick()}}}function createStepCompletion(){function done(){n||r||u||(u=!0,g.push.apply(g,arguments),$.length=0,scheduleSequenceTick())}return done.fail=function $$step$fail(){n||r||u||(n=!0,g.length=0,$.push.apply($,arguments),scheduleSequenceTick())},done.abort=function $$step$abort(){n||r||(u=!1,r=!0,g.length=$.length=0,scheduleSequenceTick())},done.errfcb=function $$step$errfcb(e){e?done.fail(e):done.apply(h,f.call(arguments,1))},done}function createGate(e,t,u){function resetGate(){clearTimeout(s),s=d=m=o=null}function scheduleGateTick(){return g?gateTick():void(s||(s=schedule(gateTick)))}function gateTick(){if(!(n||r||$)){var t=[];s=null,p?(e.fail.apply(h,o),resetGate()):g?(e.abort(),resetGate()):checkGate()&&($=!0,d.forEach(function $$each(e,n){t.push(m["s"+n])}),e.apply(h,t),resetGate())}}function checkGate(){if(0!==d.length){var e=!0;return d.some(function $$some(n){return null===n?(e=!1,!0):void 0}),e}}function createSegmentCompletion(){function done(){if(!(n||r||p||g||$||d[e])){var t=c.apply(h,arguments);m["s"+e]=t.length>1?t:t[0],d[e]=!0,scheduleGateTick()}}var e=d.length;return done.fail=function $$segment$fail(){n||r||p||g||$||d[e]||(p=!0,o=f.call(arguments),scheduleGateTick())},done.abort=function $$segment$abort(){n||r||p||g||$||(g=!0,gateTick())},done.errfcb=function $$segment$errfcb(e){e?done.fail(e):done.apply(h,f.call(arguments,1))},d[e]=null,done}var a,i,o,s,p=!1,g=!1,$=!1,d=[],m={};t.some(function $$some(e){if(p||g)return!0;a=u.slice(),a.unshift(createSegmentCompletion());try{e.apply(h,a)}catch(n){return i=n,p=!0,!0}}),i&&(l(i)?e.fail.apply(h,i):e.fail(i))}function then(){return n||r||0===arguments.length?d:(wrapArgs(arguments,thenWrapper).forEach(function $$each(e){i(e)?seq(e):s.push(e)}),scheduleSequenceTick(),d)}function or(){return r||0===arguments.length?d:(p.push.apply(p,arguments),scheduleSequenceTick(),d)}function gate(){if(n||r||0===arguments.length)return d;var e=f.call(arguments).map(function $$map(e){var n;return i(e)?(n={seq:e},tapSequence(n),function $$segment(e){n.seq.pipe(e)}):e});return then(function $$then(n){var t=f.call(arguments,1);createGate(n,e,t)}),d}function pipe(){return r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){then(function $$then(n){e.apply(h,f.call(arguments,1)),n()}).or(e.fail)}),d)}function seq(){return n||r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){var n={seq:e};i(e)&&tapSequence(n),then(function $$then(e){var t=n.seq;i(t)||(t=n.seq.apply(h,f.call(arguments,1))),t.pipe(e)})}),d)}function val(){return n||r||0===arguments.length?d:(f.call(wrapArgs(arguments,valWrapper)).forEach(function $$each(e){then(function $$then(n){var t=e.apply(h,f.call(arguments,1));l(t)||(t=c(t)),n.apply(h,t)})}),d)}function promise(){function wrap(e){return function $$fn(){e.apply(h,l(arguments[0])?arguments[0]:arguments)}}return n||r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){then(function $$then(n){var t=e;"function"==typeof e&&"function"!=typeof e.then&&(t=e.apply(h,f.call(arguments,1))),t.then(wrap(n),wrap(n.fail))})}),d)}function fork(){var e;return val(function $$val(){return e?e.apply(h,arguments):e=createSequence.apply(h,arguments).defer(),c.apply(h,arguments)}),or(function $$or(){if(e)e.fail.apply(h,arguments);else{var n=f.call(arguments);e=createSequence().then(function $$then(e){e.fail.apply(h,n)}).defer()}}),createSequence().then(function $$then(n){e?e.pipe(n):e=n}).defer()}function abort(){return n?d:(r=!0,sequenceTick(),d)}function duplicate(){var e;return a={then_queue:s.slice(),or_queue:p.slice()},e=createSequence(),a=null,e}function unpause(){g.push.apply(g,arguments),e===!0&&(e=null),scheduleSequenceTick()}function defer(){return p.push(function ignored(){}),d}function internals(e,t){var a=arguments.length>1;switch(e){case"seq_error":if(!a)return n;n=t;break;case"seq_aborted":if(!a)return r;r=t;break;case"then_ready":if(!a)return u;u=t;break;case"then_queue":return s;case"or_queue":return p;case"sequence_messages":return g;case"sequence_errors":return $}}function includeExtensions(){Object.keys(o).forEach(function $$each(e){d[e]=o[e](d,internals)})}var e,n=!1,t=!1,r=!1,u=!0,s=[],p=[],g=[],$=[],d=brandIt({then:then,or:or,onerror:or,gate:gate,all:gate,pipe:pipe,seq:seq,val:val,promise:promise,fork:fork,abort:abort,duplicate:duplicate,defer:defer});return includeExtensions(),a&&(s=a.then_queue.slice(),p=a.or_queue.slice(),d.unpause=unpause,e=!0),d.then.apply(h,arguments),d}function brandIt(e){return Object.defineProperty(e,p,{enumerable:!1,value:!0})}function checkBranding(e){return!(null==e||"object"!=typeof e||!e[p])}function valWrapper(e){return c.apply(h,f.call(arguments).slice(1,e+1))}function thenWrapper(e){arguments[e+1].apply(h,f.call(arguments).slice(1,e+1))}function wrapArgs(e,n){var t,r;for(e=f.call(e),t=0;t 1 ? + ARRAY_SLICE.call(arguments,1) : + void 0 + ; + num = +num || 0; + + api.then(function $$then(done){ + var args = orig_args || ARRAY_SLICE.call(arguments,1); + + setTimeout(function $$set$timeout(){ + done.apply(ø,args); + },num); + }); + + return api; + }; +}); + +ASQ.after = function $$after() { + return ASQ().after.apply(ø,arguments); +}; +// "any" +ASQ.extend("any",function $$extend(api,internals){ + return function $$any() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + function reset() { + finished = true; + error_messages.length = 0; + success_messages.length = 0; + } + + function complete(trigger) { + if (success_messages.length > 0) { + // any successful segment's message(s) sent + // to main sequence to proceed as success + success_messages.length = fns.length; + trigger.apply(ø,success_messages); + } + else { + // send errors into main sequence + error_messages.length = fns.length; + trigger.fail.apply(ø,error_messages); + } + + reset(); + } + + function success(trigger,idx,args) { + if (!finished) { + completed++; + success_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + + // all segments complete? + if (completed === fns.length) { + finished = true; + + complete(trigger); + } + } + } + + function failure(trigger,idx,args) { + if (!finished && + !(idx in error_messages) + ) { + completed++; + error_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + } + + // all segments complete? + if (!finished && + completed === fns.length + ) { + finished = true; + + complete(trigger); + } + } + + var completed = 0, error_messages = [], finished = false, + success_messages = [], + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)) + ; + + wrapGate(sq,fns,success,failure,reset); + + sq.pipe(done); + }); + + return api; + }; +}); +// "errfcb" +ASQ.extend("errfcb",function $$extend(api,internals){ + return function $$errfcb() { + // create a fake sequence to extract the callbacks + var sq = { + val: function $$then(cb){ sq.val_cb = cb; return sq; }, + or: function $$or(cb){ sq.or_cb = cb; return sq; } + }; + + // trick `seq(..)`s checks for a sequence + sq[brand] = true; + + // immediately register our fake sequence on the + // main sequence + api.seq(sq); + + // provide the "error-first" callback + return function $$errorfirst$callback(err) { + if (err) { + sq.or_cb(err); + } + else { + sq.val_cb.apply(ø,ARRAY_SLICE.call(arguments,1)); + } + }; + }; +}); +// "failAfter" +ASQ.extend("failAfter",function $$extend(api,internals){ + return function $$failAfter(num) { + var args = arguments.length > 1 ? + ARRAY_SLICE.call(arguments,1) : + void 0 + ; + num = +num || 0; + + api.then(function $$then(done){ + setTimeout(function $$set$timeout(){ + done.fail.apply(ø,args); + },num); + }); + + return api; + }; +}); + +ASQ.failAfter = function $$fail$after() { + return ASQ().failAfter.apply(ø,arguments); +}; +// "first" +ASQ.extend("first",function $$extend(api,internals){ + return function $$first() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + function reset() { + error_messages.length = 0; + } + + function success(trigger,idx,args) { + if (!finished) { + finished = true; + + // first successful segment triggers + // main sequence to proceed as success + trigger( + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ); + + reset(); + } + } + + function failure(trigger,idx,args) { + if (!finished && + !(idx in error_messages) + ) { + completed++; + error_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + + // all segments complete without success? + if (completed === fns.length) { + finished = true; + + // send errors into main sequence + error_messages.length = fns.length; + trigger.fail.apply(ø,error_messages); + + reset(); + } + } + } + + var completed = 0, error_messages = [], finished = false, + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)) + ; + + wrapGate(sq,fns,success,failure,reset); + + sq.pipe(done); + }); + + return api; + }; +}); +// "go-style CSP" +(function IIFE(){ + + // filter out already-resolved queue entries + function filterResolved(queue) { + return queue.filter(function $$filter(entry){ + return !entry.resolved; + }); + } + + function closeQueue(queue,finalValue) { + queue.forEach(function $$each(iter){ + if (!iter.resolved) { + iter.next(); + iter.next(finalValue); + } + }); + queue.length = 0; + } + + function channel(bufSize) { + var ch = { + close: function $$close(){ + ch.closed = true; + closeQueue(ch.put_queue,false); + closeQueue(ch.take_queue,ASQ.csp.CLOSED); + }, + closed: false, + messages: [], + put_queue: [], + take_queue: [], + buffer_size: +bufSize || 0 + }; + return ch; + } + + function unblock(iter) { + if (iter && !iter.resolved) { + iter.next(iter.next().value); + } + } + + function put(channel,value) { + var ret; + + if (channel.closed) { + return false; + } + + // remove already-resolved entries + channel.put_queue = filterResolved(channel.put_queue); + channel.take_queue = filterResolved(channel.take_queue); + + // immediate put? + if (channel.messages.length < channel.buffer_size) { + channel.messages.push(value); + unblock(channel.take_queue.shift()); + return true; + } + // queued put + else { + channel.put_queue.push( + // make a notifiable iterable for 'put' blocking + ASQ.iterable() + .then(function $$then(){ + if (!channel.closed) { + channel.messages.push(value); + return true; + } + else { + return false; + } + }) + ); + + // wrap a sequence/promise around the iterable + ret = ASQ( + channel.put_queue[channel.put_queue.length - 1] + ); + + // take waiting on this queued put? + if (channel.take_queue.length > 0) { + unblock(channel.put_queue.shift()); + unblock(channel.take_queue.shift()); + } + + return ret; + } + } + + function putAsync(channel,value,cb) { + var ret = ASQ(put(channel,value)); + + if (cb && typeof cb == "function") { + ret.val(cb); + } + else { + return ret; + } + } + + function take(channel) { + var ret; + + try { + ret = takem(channel); + } + catch (err) { + ret = err; + } + + if (ASQ.isSequence(ret)) { + ret.pCatch(function $$pcatch(err){ + return err; + }); + } + + return ret; + } + + function takeAsync(channel,cb) { + var ret = ASQ(take(channel)); + + if (cb && typeof cb == "function") { + ret.val(cb); + } + else { + return ret; + } + } + + function takem(channel) { + var msg; + + if (channel.closed) { + return ASQ.csp.CLOSED; + } + + // remove already-resolved entries + channel.put_queue = filterResolved(channel.put_queue); + channel.take_queue = filterResolved(channel.take_queue); + + // immediate take? + if (channel.messages.length > 0) { + msg = channel.messages.shift(); + unblock(channel.put_queue.shift()); + if (msg instanceof Error) { + throw msg; + } + return msg; + } + // queued take + else { + channel.take_queue.push( + // make a notifiable iterable for 'take' blocking + ASQ.iterable() + .then(function $$then(){ + if (!channel.closed) { + var v = channel.messages.shift(); + if (v instanceof Error) { + throw v; + } + return v; + } + else { + return ASQ.csp.CLOSED; + } + }) + ); + + // wrap a sequence/promise around the iterable + msg = ASQ( + channel.take_queue[channel.take_queue.length - 1] + ); + + // put waiting on this take? + if (channel.put_queue.length > 0) { + unblock(channel.put_queue.shift()); + unblock(channel.take_queue.shift()); + } + + return msg; + } + } + + function takemAsync(channel,cb) { + var ret = ASQ(takem(channel)); + + if (cb && typeof cb == "function") { + ret.pThen(cb,cb); + } + else { + return ret.val(function $$val(v){ + if (v instanceof Error) { + throw v; + } + return v; + }); + } + } + + function alts(actions) { + var closed, open, handlers, i, isq, ret, resolved = false; + + // used `alts(..)` incorrectly? + if (!Array.isArray(actions) || actions.length == 0) { + throw Error("Invalid usage"); + } + + closed = []; + open = []; + handlers = []; + + // separate actions by open/closed channel status + actions.forEach(function $$each(action){ + var channel = Array.isArray(action) ? action[0] : action; + + // remove already-resolved entries + channel.put_queue = filterResolved(channel.put_queue); + channel.take_queue = filterResolved(channel.take_queue); + + if (channel.closed) { + closed.push(channel); + } + else { + open.push(action); + } + }); + + // if no channels are still open, we're done + if (open.length == 0) { + return { value: ASQ.csp.CLOSED, channel: closed }; + } + + // can any channel action be executed immediately? + for (i=0; i 0) { + return { value: take(open[i]), channel: open[i] }; + } + } + + isq = ASQ.iterable(); + var ret = ASQ(isq); + + // setup channel action handlers + for (i=0; i 0) { + schedule(function handleUnblocking(){ + if (!resolved) { + unblock(channel.put_queue.shift()); + unblock(channel.take_queue.shift()); + } + },0); + } + } + // take action? + else { + channel = action; + + // define take handler + handlers.push( + ASQ.iterable() + .then(function $$then(){ + resolved = true; + + // mark all handlers across this `alts(..)` as resolved now + handlers = handlers.filter(function $$filter(handler){ + return !(handler.resolved = true); + }); + + // channel still open? + if (!channel.closed) { + isq.next({ value: channel.messages.shift(), channel: channel }); + } + // channel already closed? + else { + isq.next({ value: ASQ.csp.CLOSED, channel: channel }); + } + }) + ); + + // queue up take handler + channel.take_queue.push(handlers[handlers.length-1]); + + // put waiting on this queued take? + if (channel.put_queue.length > 0) { + schedule(function handleUnblocking(){ + if (!resolved) { + unblock(channel.put_queue.shift()); + unblock(channel.take_queue.shift()); + } + }); + } + } + })(open[i]); + } + + return ret; + } + + function altsAsync(chans,cb) { + var ret = ASQ(alts(chans)); + + if (cb && typeof cb == "function") { + ret.pThen(cb,cb); + } + else { + return ret; + } + } + + function timeout(delay) { + var ch = channel(); + setTimeout(ch.close,delay); + return ch; + } + + function go(gen,args) { + // goroutine arguments passed? + if (arguments.length > 1) { + if (!args || !Array.isArray(args)) { + args = [args]; + } + } + else { + args = []; + } + + return function *$$go(token) { + + // unblock the overall goroutine handling + function unblock() { + token.unblock_count++; + + if (token.block && !token.block.marked) { + token.block.marked = true; + token.block.next(); + } + } + + var ret, msg, err, type, done = false, it; + + // keep track of how many requests for unblocking + // have occurred + token.unblock_count = (token.unblock_count || 0); + + // keep track of how many goroutines are running + // so we can infer when we're done go'ing + token.go_count = (token.go_count || 0) + 1; + + // need to initialize a set of goroutines? + if (token.go_count === 1) { + // create a default channel for these goroutines + token.channel = channel(); + token.channel.messages = token.messages; + token.channel.go = function $$go(){ + // unblock the goroutine handling for this + // new goroutine + unblock(); + // add the goroutine (called with any args) to + // the handling queue + token.add( go.apply(ø,arguments) ); + }; + // starting out with initial channel messages? + if (token.channel.messages.length > 0) { + // fake back-pressure blocking for each + token.channel.put_queue = token.channel.messages.map(function $$map(){ + // make a notifiable iterable for 'put' blocking + return ASQ.iterable() + .then(function $$then(){ + unblock(token.channel.take_queue.shift()); + return !token.channel.closed; + }); + }); + } + } + + // initialize the generator + it = gen.apply(ø,[token.channel].concat(args)); + + (function iterate(){ + + function next() { + // keep going with next step in goroutine? + if (!done) { + iterate(); + } + // unblock overall goroutine handling to + // continue with other goroutines + else { + unblock(); + } + } + + // has a resumption value been achieved yet? + if (!ret) { + // try to resume the goroutine + try { + // resume with injected exception? + if (err) { + ret = it.throw(err); + err = null; + } + // resume normally + else { + ret = it.next(msg); + } + } + // resumption failed, so bail + catch (e) { + done = true; + err = e; + msg = null; + unblock(); + return; + } + + // keep track of the result of the resumption + done = ret.done; + ret = ret.value; + type = typeof ret; + + // if this goroutine is complete, unblock the + // overall goroutine handling + if (done) { + unblock(); + } + + // received a thenable/promise back? + if (isPromise(ret)) { + ret = ASQ().promise(ret); + } + + // wait for the value? + if (ASQ.isSequence(ret)) { + ret.val(function $$val(){ + ret = null; + msg = arguments.length > 1 ? + ASQ.messages.apply(ø,arguments) : + arguments[0] + ; + next(); + }) + .or(function $$or(){ + ret = null; + msg = arguments.length > 1 ? + ASQ.messages.apply(ø,arguments) : + arguments[0] + ; + if (msg instanceof Error) { + err = msg; + msg = null; + } + next(); + }); + } + // immediate value, prepare it to go right back in + else { + msg = ret; + ret = null; + next(); + } + } + })(); + + // keep this goroutine alive until completion + while (!done) { + // transfer control to another goroutine + yield token; + + // need to block overall goroutine handling + // while idle? + if (!done && !token.block && token.unblock_count === 0) { + // wait here while idle + yield (token.block = ASQ.iterable()); + + token.block = false; + } + + if (token.unblock_count > 0) token.unblock_count--; + } + + // this goroutine is done now + token.go_count--; + + // all goroutines done? + if (token.go_count === 0) { + // any lingering blocking need to be cleaned up? + unblock(); + + // capture any untaken messages + msg = ASQ.messages.apply(ø,token.messages); + + // need to implicitly force-close channel? + if (token.channel && !token.channel.closed) { + token.channel.closed = true; + token.channel.put_queue.length = token.channel.take_queue.length = 0; + token.channel.close = token.channel.go = token.channel.messages = null; + } + token.channel = null; + } + + // make sure leftover error or message are + // passed along + if (err) { + throw err; + } + else if (token.go_count === 0) { + return msg; + } + else { + return token; + } + }; + } + + ASQ.csp = { + chan: channel, + put: put, + putAsync: putAsync, + take: take, + takeAsync: takeAsync, + takem: takem, + takemAsync: takemAsync, + alts: alts, + altsAsync: altsAsync, + timeout: timeout, + go: go, + CLOSED: {} + }; + +})(); +// "ASQ.iterable()" +(function IIFE(){ + var template; + + ASQ.iterable = function $$iterable() { + function throwSequenceErrors() { + throw (sequence_errors.length === 1 ? sequence_errors[0] : sequence_errors); + } + + function notifyErrors() { + var fn; + + seq_tick = null; + + if (seq_error) { + if (or_queue.length === 0 && !error_reported) { + error_reported = true; + throwSequenceErrors(); + } + + while (or_queue.length > 0) { + error_reported = true; + fn = or_queue.shift(); + try { + fn.apply(ø,sequence_errors); + } + catch (err) { + if (checkBranding(err)) { + sequence_errors = sequence_errors.concat(err); + } + else { + sequence_errors.push(err); + } + if (or_queue.length === 0) { + throwSequenceErrors(); + } + } + } + } + } + + function val() { + if (seq_error || seq_aborted || arguments.length === 0) { + return sequence_api; + } + + var args = ARRAY_SLICE.call(arguments).map(function mapper(arg){ + if (typeof arg != "function") return function $$val() { return arg; }; + else return arg; + }); + + val_queue.push.apply(val_queue,args); + + return sequence_api; + } + + function or() { + if (seq_aborted || arguments.length === 0) { + return sequence_api; + } + + or_queue.push.apply(or_queue,arguments); + + if (!seq_tick) { + seq_tick = schedule(notifyErrors); + } + + return sequence_api; + } + + function pipe() { + if (seq_aborted || arguments.length === 0) { + return sequence_api; + } + + ARRAY_SLICE.call(arguments) + .forEach(function $$each(fn){ + val(fn).or(fn.fail); + }); + + return sequence_api; + } + + function next() { + if (seq_error || seq_aborted || val_queue.length === 0) { + if (val_queue.length > 0) { + $throw$("Sequence cannot be iterated"); + } + return { done: true }; + } + + try { + return { value: val_queue.shift().apply(ø,arguments) }; + } + catch (err) { + if (ASQ.isMessageWrapper(err)) { + $throw$.apply(ø,err); + } + else { + $throw$(err); + } + + return {}; + } + } + + function $throw$() { + if (seq_error || seq_aborted) { + return sequence_api; + } + + sequence_errors.push.apply(sequence_errors,arguments); + seq_error = true; + if (!seq_tick) { + seq_tick = schedule(notifyErrors); + } + + return sequence_api; + } + + function $return$(val) { + if (seq_error || seq_aborted) { + val = void 0; + } + + abort(); + + return { done: true, value: val }; + } + + function abort() { + if (seq_error || seq_aborted) { + return; + } + + seq_aborted = true; + + clearTimeout(seq_tick); + seq_tick = null; + val_queue.length = or_queue.length = sequence_errors.length = 0; + } + + function duplicate() { + var isq; + + template = { + val_queue: val_queue.slice(), + or_queue: or_queue.slice() + }; + isq = ASQ.iterable(); + template = null; + + return isq; + } + + // opt-out of global error reporting for this sequence + function defer() { + or_queue.push(function $$ignored(){}); + return sequence_api; + } + + // *********************************************** + // Object branding utilities + // *********************************************** + function brandIt(obj) { + Object.defineProperty(obj,brand,{ + enumerable: false, + value: true + }); + + return obj; + } + + var sequence_api, + + seq_error = false, + error_reported = false, + seq_aborted = false, + + seq_tick, + + val_queue = [], + or_queue = [], + + sequence_errors = [] + ; + + // *********************************************** + // Setup the ASQ.iterable() public API + // *********************************************** + sequence_api = brandIt({ + val: val, + then: val, + or: or, + pipe: pipe, + next: next, + "throw": $throw$, + "return": $return$, + abort: abort, + duplicate: duplicate, + defer: defer + }); + + // useful for ES6 `for..of` loops, + // add `@@iterator` to simply hand back + // our iterable sequence itself! + sequence_api[(typeof Symbol == "function" && Symbol.iterator) || "@@iterator"] = function $$iter() { + return sequence_api; + }; + + // templating the iterable-sequence setup? + if (template) { + val_queue = template.val_queue.slice(0); + or_queue = template.or_queue.slice(0); + } + + // treat ASQ.iterable() constructor parameters as having been + // passed to `val()` + sequence_api.val.apply(ø,arguments); + + return sequence_api; + }; + +})(); +// "last" +ASQ.extend("last",function $$extend(api,internals){ + return function $$last() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + function reset() { + finished = true; + error_messages.length = 0; + success_messages = null; + } + + function complete(trigger) { + if (success_messages != null) { + // last successful segment's message(s) sent + // to main sequence to proceed as success + trigger( + success_messages.length > 1 ? + ASQ.messages.apply(ø,success_messages) : + success_messages[0] + ); + } + else { + // send errors into main sequence + error_messages.length = fns.length; + trigger.fail.apply(ø,error_messages); + } + + reset(); + } + + function success(trigger,idx,args) { + if (!finished) { + completed++; + success_messages = args; + + // all segments complete? + if (completed === fns.length) { + finished = true; + + complete(trigger); + } + } + } + + function failure(trigger,idx,args) { + if (!finished && + !(idx in error_messages) + ) { + completed++; + error_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + } + + // all segments complete? + if (!finished && + completed === fns.length + ) { + finished = true; + + complete(trigger); + } + } + + var completed = 0, error_messages = [], finished = false, + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)), + success_messages + ; + + wrapGate(sq,fns,success,failure,reset); + + sq.pipe(done); + }); + + return api; + }; +}); +// "map" +ASQ.extend("map",function $$extend(api,internals){ + return function $$map(pArr,pEach) { + if (internals("seq_error") || internals("seq_aborted")) { + return api; + } + + api.seq(function $$seq(){ + var tmp, args = ARRAY_SLICE.call(arguments), + arr = pArr, each = pEach; + + // if missing `map(..)` args, use value-messages (if any) + if (!each) each = args.shift(); + if (!arr) arr = args.shift(); + + // if arg types in reverse order (each,arr), swap + if (typeof arr === "function" && Array.isArray(each)) { + tmp = arr; + arr = each; + each = tmp; + } + + return ASQ.apply(ø,args) + .gate.apply(ø,arr.map(function $$map(item){ + return function $$segment(){ + each.apply(ø,[item].concat(ARRAY_SLICE.call(arguments))); + }; + })); + }) + .val(function $$val(){ + // collect all gate segment output into one value-message + // Note: return a normal array here, not a message wrapper! + return ARRAY_SLICE.call(arguments); + }); + + return api; + }; +}); +// "none" +ASQ.extend("none",function $$extend(api,internals){ + return function $$none() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + function reset() { + finished = true; + error_messages.length = 0; + success_messages.length = 0; + } + + function complete(trigger) { + if (success_messages.length > 0) { + // any successful segment's message(s) sent + // to main sequence to proceed as **error** + success_messages.length = fns.length; + trigger.fail.apply(ø,success_messages); + } + else { + // send errors as **success** to main sequence + error_messages.length = fns.length; + trigger.apply(ø,error_messages); + } + + reset(); + } + + function success(trigger,idx,args) { + if (!finished) { + completed++; + success_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + + // all segments complete? + if (completed === fns.length) { + finished = true; + + complete(trigger); + } + } + } + + function failure(trigger,idx,args) { + if (!finished && + !(idx in error_messages) + ) { + completed++; + error_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + } + + // all segments complete? + if (!finished && + completed === fns.length + ) { + finished = true; + + complete(trigger); + } + } + + var completed = 0, error_messages = [], finished = false, + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)), + success_messages = [] + ; + + wrapGate(sq,fns,success,failure,reset); + + sq.pipe(done); + }); + + return api; + }; +}); +// "pThen" +ASQ.extend("pThen",function $$extend(api,internals){ + return function $$pthen(success,failure) { + if (internals("seq_aborted")) { + return api; + } + + var ignore_success_handler = false, ignore_failure_handler = false; + + if (typeof success === "function") { + api.then(function $$then(done){ + if (!ignore_success_handler) { + var ret, msgs = ASQ.messages.apply(ø,arguments); + msgs.shift(); + + if (msgs.length === 1) { + msgs = msgs[0]; + } + + ignore_failure_handler = true; + + try { + ret = success(msgs); + } + catch (err) { + if (!ASQ.isMessageWrapper(err)) { + err = [err]; + } + done.fail.apply(ø,err); + return; + } + + // returned a sequence? + if (ASQ.isSequence(ret)) { + ret.pipe(done); + } + // returned a message wrapper? + else if (ASQ.isMessageWrapper(ret)) { + done.apply(ø,ret); + } + // returned a promise/thenable? + else if (isPromise(ret)) { + ret.then(done,done.fail); + } + // just a normal value to pass along + else { + done(ret); + } + } + else { + done.apply(ø,ARRAY_SLICE.call(arguments,1)); + } + }); + } + if (typeof failure === "function") { + api.or(function $$or(){ + if (!ignore_failure_handler) { + var ret, msgs = ASQ.messages.apply(ø,arguments), smgs, + or_queue = ARRAY_SLICE.call(internals("or_queue")) + ; + + if (msgs.length === 1) { + msgs = msgs[0]; + } + + ignore_success_handler = true; + + // NOTE: if this call throws, that'll automatically + // be handled by core as we'd want it to be + ret = failure(msgs); + + // if we get this far: + // first, inject return value (if any) as + // next step's sequence messages + smgs = internals("sequence_messages"); + smgs.length = 0; + if (typeof ret !== "undefined") { + if (!ASQ.isMessageWrapper(ret)) { + ret = [ret]; + } + smgs.push.apply(smgs,ret); + } + + // reset internal error state, because we've exclusively + // handled any errors up to this point of the sequence + internals("sequence_errors").length = 0; + internals("seq_error",false); + internals("then_ready",true); + + // temporarily empty the or-queue + internals("or_queue").length = 0; + + // make sure to schedule success-procession on the chain + api.val(function $$val(){ + // pass thru messages + return ASQ.messages.apply(ø,arguments); + }); + + // at next cycle, reinstate the or-queue (if any) + if (or_queue.length > 0) { + schedule(function $$schedule(){ + api.or.apply(ø,or_queue); + }); + } + } + }); + } + return api; + }; +}); + +// "pCatch" +ASQ.extend("pCatch",function $$extend(api,internals){ + return function $$pcatch(failure) { + if (internals("seq_aborted")) { + return api; + } + + api.pThen(void 0,failure); + + return api; + }; +}); +// "race" +ASQ.extend("race",function $$extend(api,internals){ + return function $$race() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments) + .map(function $$map(v){ + var def; + // tap any directly-provided sequences immediately + if (ASQ.isSequence(v)) { + def = { seq: v }; + tapSequence(def); + return function $$fn(done) { + def.seq.pipe(done); + }; + } + else return v; + }); + + api.then(function $$then(done){ + var args = ARRAY_SLICE.call(arguments); + + fns.forEach(function $$each(fn){ + fn.apply(ø,args); + }); + }); + + return api; + }; +}); +// "react" (reactive sequences) +ASQ.react = function $$react(reactor) { + function next() { + if (!paused) { + if (template) { + var sq = template.duplicate(); + sq.unpause.apply(ø,arguments); + return sq; + } + return ASQ(function $$asq(){ throw "Disabled Sequence"; }); + } + } + + function registerTeardown(fn) { + if (template && typeof fn === "function") { + teardowns.push(fn); + } + } + + var template = ASQ().duplicate(), + teardowns = [], paused = false + ; + + // add reactive sequence kill switch + template.stop = function $$stop() { + if (template) { + template = null; + teardowns.forEach(Function.call,Function.call); + teardowns.length = 0; + } + }; + + template.pause = function $$pause() { + if (!paused && template) { + paused = true; + teardowns.forEach(Function.call,Function.call); + teardowns.length = 0; + } + }; + + template.resume = function $$resume() { + if (paused && template) { + paused = false; + reactor.call(template,next,registerTeardown); + } + }; + + template.push = next; + + next.onStream = function $$onStream() { + ARRAY_SLICE.call(arguments) + .forEach(function $$each(stream){ + stream.on("data",next); + stream.on("error",next); + }); + }; + + next.unStream = function $$unStream() { + ARRAY_SLICE.call(arguments) + .forEach(function $$each(stream){ + stream.removeListener("data",next); + stream.removeListener("error",next); + }); + }; + + // make sure `reactor(..)` is called async + ASQ.__schedule(function $$schedule(){ + reactor.call(template,next,registerTeardown); + }); + + return template; +}; +// "react" helpers +(function IIFE(){ + + var Ar = ASQ.react; + + Ar.of = function $$react$of() { + function reactor(next) { + if (!started) { + started = true; + if (args.length > 0) { + args.shift().val(function val(){ + next.apply(ø,arguments); + if (args.length > 0) { + args.shift().val(val); + } + }); + } + } + } + + var started, args = ARRAY_SLICE.call(arguments) + .map(function wrapper(arg){ + if (!ASQ.isSequence(arg)) arg = ASQ(arg); + return arg; + }); + + return Ar(reactor); + }; + + Ar.all = Ar.zip = makeReactOperator(/*buffer=*/true); + Ar.allLatest = makeReactOperator(/*buffer=false*/); + Ar.latest = Ar.combineLatest = makeReactOperator(/*buffer=*/false,/*keep=*/true); + + Ar.any = Ar.merge = function $$react$any(){ + function reactor(next,registerTeardown){ + function processSequence(def){ + function trigger(){ + var args = ASQ.messages.apply(ø,arguments); + // still observing sequence-streams? + if (seqs && seqs.length > 0) { + // fire off reactive sequence instance + next.apply(ø,args); + } + // keep sequence going + return args; + } + + // sequence-stream event listener + def.seq.val(trigger); + } + + // observe all sequence-streams + seqs.forEach(processSequence); + + // listen for stop() of reactive sequence + registerTeardown(function $$teardown(){ + seqs = null; + }); + } + + // observe all sequence-streams + var seqs = tapSequences.apply(null,arguments); + + if (seqs.length == 0) return; + + return Ar(reactor); + }; + + Ar.distinct = function $$react$distinct(seq){ + return Ar.filter(seq,makeDistinctFilterer(/*keepAll=*/true)); + }; + + Ar.distinctConsecutive = Ar.distinctUntilChanged = function $$react$distinct$consecutive(seq) { + return Ar.filter(seq,makeDistinctFilterer(/*keepAll=*/false)); + }; + + Ar.filter = function $$react$filter(seq,filterer){ + function reactor(next,registerTeardown) { + function trigger(){ + var messages = ASQ.messages.apply(ø,arguments); + + if (filterer && filterer.apply(ø,messages)) { + // fire off reactive sequence instance + next.apply(ø,messages); + } + + // keep sequence going + return messages; + } + + // sequence-stream event listener + def.seq.val(trigger); + + // listen for stop() of reactive sequence + registerTeardown(function $$teardown(){ + def = filterer = null; + }); + } + + // observe sequence-stream + var def = tapSequences(seq)[0]; + + if (!def) return; + + return Ar(reactor); + }; + + Ar.fromObservable = function $$react$from$observable(obsv){ + function reactor(next,registerTeardown){ + // process buffer (if any) + buffer.forEach(next); + buffer.length = 0; + + // start non-buffered notifications? + if (!buffer.complete) { + notify = next; + } + + registerTeardown(function $$teardown(){ + obsv.dispose(); + }); + } + + function notify(v) { + buffer.push(v); + } + + var buffer = []; + + obsv.subscribe( + function $$on$next(v){ + notify(v); + }, + function $$on$error(){}, + function $$on$complete(){ + buffer.complete = true; + obsv.dispose(); + } + ); + + return Ar(reactor); + }; + + ASQ.extend("toObservable",function $$extend(api,internals){ + return function $$to$observable(){ + function init(observer) { + function define(pair){ + function listen(){ + var args = ASQ.messages.apply(ø,arguments); + observer[pair[1]].apply(observer, + args.length == 1 ? [args[0]] : args + ); + return args; + } + + api[pair[0]](listen); + } + + [["val","onNext"],["or","onError"]] + .forEach(define); + } + + return Rx.Observable.create(init); + }; + }); + + function tapSequences() { + function tapSequence(seq) { + // temporary `trigger` which, if called before being replaced + // below, creates replacement proxy sequence with the + // event message(s) re-fired + function trigger() { + var args = ARRAY_SLICE.call(arguments); + def.seq = Ar(function $$react(next){ + next.apply(ø,args); + }); + } + + if (ASQ.isSequence(seq)) { + var def = { seq: seq }; + + // listen for events from the sequence-stream + seq.val(function $$val(){ + trigger.apply(ø,arguments); + return ASQ.messages.apply(ø,arguments); + }); + + // make a reactive sequence to act as a proxy to the original + // sequence + def.seq = Ar(function $$react(next){ + // replace the temporary trigger (created above) + // with this proxy's trigger + trigger = next; + }); + + return def; + } + } + + return ARRAY_SLICE.call(arguments) + .map(tapSequence) + .filter(Boolean); + } + + function makeReactOperator(buffer,keep) { + return function $$react$operator(){ + function reactor(next,registerTeardown){ + function processSequence(def) { + // sequence-stream event listener + function trigger() { + var args = ASQ.messages.apply(ø,arguments); + // still observing sequence-streams? + if (seqs && seqs.length > 0) { + // store event message(s), if any + seq_events[seq_id] = + (buffer ? seq_events[seq_id] : []).concat( + args.length > 0 ? (args.length > 1 ? [args] : args[0]) : undefined + ); + + // collect event message(s) across the + // sequence-stream sources + var messages = seq_events.reduce(function reducer(msgs,eventList,idx){ + if (eventList.length > 0) msgs.push(eventList[0]); + return msgs; + },[]); + + // did all sequence-streams get an event? + if (messages.length == seq_events.length) { + if (messages.length == 1) messages = messages[0]; + + // fire off reactive sequence instance + next.apply(ø,messages); + + // discard stored event message(s)? + if (!keep) { + seq_events.forEach(function $$each(eventList){ + eventList.shift(); + }); + } + } + } + // keep sequence going + return args; + } + + var seq_id = seq_events.length; + seq_events.push([]); + def.seq.val(trigger); + } + + // process all sequence-streams + seqs.forEach(processSequence); + + // listen for stop() of reactive sequence + registerTeardown(function $$teardown(){ + seqs = seq_events = null; + }); + } + + var seq_events = [], + // observe all sequence-streams + seqs = tapSequences.apply(null,arguments) + ; + + if (seqs.length == 0) return; + + return Ar(reactor); + }; + } + + function makeDistinctFilterer(keepAll) { + function filterer() { + function isDuplicate(msgSet) { + return ( + msgSet.length == message_set.length && + msgSet.every(function $$every(val,idx){ + return val === message_set[idx]; + }) + ); + } + + var message_set = ASQ.messages.apply(ø,arguments); + + // any messages in message-set to check against? + if (message_set.length > 0) { + // duplicate message-set? + if (msg_sets.some(isDuplicate)) { + return false; + } + + // remember all message-sets for future distinct checking? + if (keepAll) { + msg_sets.push(message_set); + } + // only keep the last message-set for distinct-consecutive + // checking + else { + msg_sets[0] = message_set; + } + } + + // allow distinct non-duplicate value through + return true; + } + + var msg_sets = []; + + return filterer; + } + +})(); +// "runner" +ASQ.extend("runner",function $$extend(api,internals){ + + return function $$runner() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var args = ARRAY_SLICE.call(arguments); + + api + .then(function $$then(mainDone){ + + function wrap(v) { + // function? expected to produce an iterator + // (like a generator) or a promise + if (typeof v === "function") { + // call function passing in the control token + // note: neutralize `this` in call to prevent + // unexpected behavior + v = v.call(ø,token); + + // promise returned (ie, from async function)? + if (isPromise(v)) { + // wrap it in iterable sequence + v = ASQ.iterable(v); + } + } + // an iterable sequence? duplicate it (in case of multiple runs) + else if (ASQ.isSequence(v) && "next" in v) { + v = v.duplicate(); + } + // wrap anything else in iterable sequence + else { + v = ASQ.iterable(v); + } + + // a sequence to tap for errors? + if (ASQ.isSequence(v)) { + // listen for any sequence failures + v.or(function $$or(){ + // signal iteration-error + mainDone.fail.apply(ø,arguments); + }); + } + + return v; + } + + function addWrapped() { + iterators.push.apply( + iterators, + ARRAY_SLICE.call(arguments).map(wrap) + ); + } + + function iterateOrQuit(iterFn,now) { + // still have some co-routine runs to process? + if (iterators.length > 0) { + if (now) iterFn(); + else schedule(iterFn); + } + // all done! + else { + // previous value message? + if (typeof next_val !== "undefined") { + // not a message wrapper array? + if (!ASQ.isMessageWrapper(next_val)) { + // wrap value for the subsequent `apply(..)` + next_val = [next_val]; + } + } + else { + // nothing to affirmatively pass along + next_val = []; + } + + // signal done with all co-routine runs + mainDone.apply(ø,next_val); + } + } + + var iterators = args, + token = { + messages: ARRAY_SLICE.call(arguments,1), + add: addWrapped + }, + iter, ret, next_val = token + ; + + // map co-routines to round-robin list of iterators + iterators = iterators.map(wrap); + + // async iteration of round-robin list + (function iterate(){ + // get next co-routine in list + iter = iterators.shift(); + + // process the iteration + try { + // multiple messages to send to an iterable + // sequence? + if (ASQ.isMessageWrapper(next_val) && + ASQ.isSequence(iter) + ) { + ret = iter.next.apply(iter,next_val); + } + else { + ret = iter.next(next_val); + } + } + catch (err) { + return mainDone.fail(err); + } + + // bail on run in aborted sequence + if (internals("seq_aborted")) return; + + // was the control token yielded? + if (ret.value === token) { + // round-robin: put co-routine back into the list + // at the end where it was so it can be processed + // again on next loop-iteration + if (!ret.done) { + iterators.push(iter); + } + next_val = token; + iterateOrQuit(iterate,/*now=*/false); + } + else { + // not a recognized ASQ instance returned? + if (!ASQ.isSequence(ret.value)) { + // received a thenable/promise back? + if (isPromise(ret.value)) { + // wrap in a sequence + ret.value = ASQ().promise(ret.value); + } + // thunk yielded? + else if (typeof ret.value === "function") { + // wrap thunk call in a sequence + var fn = ret.value; + ret.value = ASQ(function $$ASQ(done){ + fn(done.errfcb); + }); + } + // message wrapper returned? + else if (ASQ.isMessageWrapper(ret.value)) { + // wrap message(s) in a sequence + ret.value = ASQ.apply(ø, + // don't let `apply(..)` discard an empty message + // wrapper! instead, pass it along as its own value + // itself. + ret.value.length > 0 ? ret.value : ASQ.messages(undefined) + ); + } + // non-undefined value returned? + else if (typeof ret.value !== "undefined") { + // wrap the value in a sequence + ret.value = ASQ(ret.value); + } + else { + // make an empty sequence + ret.value = ASQ(); + } + } + + ret.value + .val(function $$val(){ + // bail on run in aborted sequence + if (internals("seq_aborted")) return; + + if (arguments.length > 0) { + // save any return messages for input + // to next iteration + next_val = arguments.length > 1 ? + ASQ.messages.apply(ø,arguments) : + arguments[0] + ; + } + + // still more to iterate? + if (!ret.done) { + // was the control token passed along? + if (next_val === token) { + // round-robin: put co-routine back into the list + // at the end, so that the the next iterator can be + // processed on next loop-iteration + iterators.push(iter); + } + else { + // put co-routine back in where it just + // was so it can be processed again on + // next loop-iteration + iterators.unshift(iter); + } + } + + iterateOrQuit(iterate,/*now=*/true); + }) + .or(function $$or(){ + // bail on run in aborted sequence + if (internals("seq_aborted")) return; + + try { + // if an error occurs in the step-continuation + // promise or sequence, throw it back into the + // generator or iterable-sequence + iter["throw"].apply(iter,arguments); + } + catch (err) { + // if an error comes back out of after the throw, + // pass it out to the main sequence, as iteration + // must now be complete + mainDone.fail(err); + } + }); + } + })(); + }); + + return api; + }; +}); +// "toPromise" +ASQ.extend("toPromise",function $$extend(api,internals){ + return function $$to$promise() { + return new Promise(function $$executor(resolve,reject){ + api + .val(function $$val(){ + var args = ARRAY_SLICE.call(arguments); + resolve.call(ø,args.length > 1 ? args : args[0]); + return ASQ.messages.apply(ø,args); + }) + .or(function $$or(){ + var args = ARRAY_SLICE.call(arguments); + reject.call(ø,args.length > 1 ? args : args[0]); + }); + }); + }; +}); +// "try" +ASQ.extend("try",function $$extend(api,internals){ + return function $$try() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments) + .map(function $$map(fn){ + return function $$then(mainDone) { + var main_args = ARRAY_SLICE.call(arguments), + sq = ASQ.apply(ø,main_args.slice(1)) + ; + + sq + .then(function $$inner$then(){ + fn.apply(ø,arguments); + }) + .val(function $$val(){ + mainDone.apply(ø,arguments); + }) + .or(function $$inner$or(){ + var msgs = ASQ.messages.apply(ø,arguments); + // failed, so map error(s) as `catch` + mainDone({ + "catch": msgs.length > 1 ? msgs : msgs[0] + }); + }); + }; + }); + + api.then.apply(ø,fns); + + return api; + }; +}); +// "until" +ASQ.extend("until",function $$extend(api,internals){ + return function $$until() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments) + .map(function $$map(fn){ + return function $$then(mainDone) { + var main_args = ARRAY_SLICE.call(arguments), + sq = ASQ.apply(ø,main_args.slice(1)) + ; + + sq + .then(function $$inner$then(){ + var args = ARRAY_SLICE.call(arguments); + args[0]["break"] = function $$break(){ + mainDone.fail.apply(ø,arguments); + sq.abort(); + }; + + fn.apply(ø,args); + }) + .val(function $$val(){ + mainDone.apply(ø,arguments); + }) + .or(function $$inner$or(){ + // failed, retry + $$then.apply(ø,main_args); + }); + }; + }); + + api.then.apply(ø,fns); + + return api; + }; +}); +// "waterfall" +ASQ.extend("waterfall",function $$extend(api,internals){ + return function $$waterfall() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + var msgs = ASQ.messages(), + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)) + ; + + fns.forEach(function $$each(fn){ + sq.then(fn) + .val(function $$val(){ + var args = ASQ.messages.apply(ø,arguments); + msgs.push(args.length > 1 ? args : args[0]); + return msgs; + }); + }); + + sq.pipe(done); + }); + + return api; + }; +}); +// "wrap" +ASQ.wrap = function $$wrap(fn,opts) { + function checkThis(t,o) { + return (!t || + (typeof window != "undefined" && t === window) || + (typeof global != "undefined" && t === global) + ) ? o : t; + } + + function paramSpread(gen) { + return function *paramSpread(token) { + yield *gen.apply(this,token.messages); + }; + } + + var errfcb, params_first, act, this_obj; + + opts = (opts && typeof opts == "object") ? opts : {}; + + if ( + (opts.errfcb && opts.splitcb) || + (opts.errfcb && opts.simplecb) || + (opts.splitcb && opts.simplecb) || + ("errfcb" in opts && !opts.errfcb && !opts.splitcb && !opts.simplecb) || + (opts.params_first && opts.params_last) || + (opts.spread && !opts.gen) + ) { + throw Error("Invalid options"); + } + + // initialize default flags + this_obj = (opts["this"] && typeof opts["this"] == "object") ? opts["this"] : ø; + errfcb = opts.errfcb || !(opts.splitcb || opts.simplecb); + params_first = !!opts.params_first || + (!opts.params_last && !("params_first" in opts || opts.params_first)) || + ("params_last" in opts && !opts.params_first && !opts.params_last) + ; + + if (params_first) { + act = "push"; + } + else { + act = "unshift"; + } + + if (opts.gen) { + if (opts.spread) { + fn = paramSpread(fn); + } + return function $$wrapped$gen() { + return ASQ.apply(ø,arguments).runner(fn); + }; + } + if (errfcb) { + return function $$wrapped$errfcb() { + var args = ARRAY_SLICE.call(arguments), + _this = checkThis(this,this_obj) + ; + + return ASQ(function $$asq(done){ + args[act](done.errfcb); + fn.apply(_this,args); + }); + }; + } + if (opts.splitcb) { + return function $$wrapped$splitcb() { + var args = ARRAY_SLICE.call(arguments), + _this = checkThis(this,this_obj) + ; + + return ASQ(function $$asq(done){ + args[act](done,done.fail); + fn.apply(_this,args); + }); + }; + } + if (opts.simplecb) { + return function $$wrapped$simplecb() { + var args = ARRAY_SLICE.call(arguments), + _this = checkThis(this,this_obj) + ; + + return ASQ(function $$asq(done){ + args[act](done); + fn.apply(_this,args); + }); + }; + } +}; + + + // just return `ASQ` itself for convenience sake + return ASQ; +}); diff --git a/frontend-masters-exercises/exercises/ex8/ex8-fixed.html b/frontend-masters-exercises/exercises/ex8/ex8-fixed.html new file mode 100755 index 0000000..be423fb --- /dev/null +++ b/frontend-masters-exercises/exercises/ex8/ex8-fixed.html @@ -0,0 +1,18 @@ + + + + +Exercise 8 - Fixed + + +

Exercise 8 - Fixed

+ +

+
+ + + + + + + diff --git a/frontend-masters-exercises/exercises/ex8/ex8-fixed.js b/frontend-masters-exercises/exercises/ex8/ex8-fixed.js new file mode 100755 index 0000000..5ef75cd --- /dev/null +++ b/frontend-masters-exercises/exercises/ex8/ex8-fixed.js @@ -0,0 +1,30 @@ +$(document).ready(function(){ + var $btn = $("#btn"), + $list = $("#list"), + clicks = ASQ.react.of(), + msgs = ASQ.react.of(), + latest; + + $btn.click(function(evt){ + // push click event messages into stream + clicks.push(evt); + }); + + // sample clicks stream + setInterval(function(){ + if (latest) { + msgs.push("clicked!"); + latest = null; + } + },1000); + + // subscribe to click stream + clicks.val(function(evt){ + latest = evt; + }); + + // subscribe to sampled message stream + msgs.val(function(msg){ + $list.append($("
" + msg + "
")); + }); +}); diff --git a/frontend-masters-exercises/exercises/ex8/ex8.html b/frontend-masters-exercises/exercises/ex8/ex8.html new file mode 100755 index 0000000..55b403a --- /dev/null +++ b/frontend-masters-exercises/exercises/ex8/ex8.html @@ -0,0 +1,18 @@ + + + + +Exercise 8 + + +

Exercise 8

+ +

+
+ + + + + + + diff --git a/frontend-masters-exercises/exercises/ex8/ex8.js b/frontend-masters-exercises/exercises/ex8/ex8.js new file mode 100755 index 0000000..3335f25 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex8/ex8.js @@ -0,0 +1,10 @@ +$(document).ready(function(){ + var $btn = $("#btn"), + $list = $("#list"); + + $btn.click(function(evt){ + // TODO + }); + + // TODO: setup sampled sequence, populate $list +}); diff --git a/frontend-masters-exercises/exercises/ex8/jquery.js b/frontend-masters-exercises/exercises/ex8/jquery.js new file mode 100755 index 0000000..3883779 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex8/jquery.js @@ -0,0 +1,2 @@ +/*! jQuery v1.8.3 jquery.com | jquery.org/license */ +(function(e,t){function _(e){var t=M[e]={};return v.each(e.split(y),function(e,n){t[n]=!0}),t}function H(e,n,r){if(r===t&&e.nodeType===1){var i="data-"+n.replace(P,"-$1").toLowerCase();r=e.getAttribute(i);if(typeof r=="string"){try{r=r==="true"?!0:r==="false"?!1:r==="null"?null:+r+""===r?+r:D.test(r)?v.parseJSON(r):r}catch(s){}v.data(e,n,r)}else r=t}return r}function B(e){var t;for(t in e){if(t==="data"&&v.isEmptyObject(e[t]))continue;if(t!=="toJSON")return!1}return!0}function et(){return!1}function tt(){return!0}function ut(e){return!e||!e.parentNode||e.parentNode.nodeType===11}function at(e,t){do e=e[t];while(e&&e.nodeType!==1);return e}function ft(e,t,n){t=t||0;if(v.isFunction(t))return v.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return v.grep(e,function(e,r){return e===t===n});if(typeof t=="string"){var r=v.grep(e,function(e){return e.nodeType===1});if(it.test(t))return v.filter(t,r,!n);t=v.filter(t,r)}return v.grep(e,function(e,r){return v.inArray(e,t)>=0===n})}function lt(e){var t=ct.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function At(e,t){if(t.nodeType!==1||!v.hasData(e))return;var n,r,i,s=v._data(e),o=v._data(t,s),u=s.events;if(u){delete o.handle,o.events={};for(n in u)for(r=0,i=u[n].length;r").appendTo(i.body),n=t.css("display");t.remove();if(n==="none"||n===""){Pt=i.body.appendChild(Pt||v.extend(i.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!Ht||!Pt.createElement)Ht=(Pt.contentWindow||Pt.contentDocument).document,Ht.write(""),Ht.close();t=Ht.body.appendChild(Ht.createElement(e)),n=Dt(t,"display"),i.body.removeChild(Pt)}return Wt[e]=n,n}function fn(e,t,n,r){var i;if(v.isArray(t))v.each(t,function(t,i){n||sn.test(e)?r(e,i):fn(e+"["+(typeof i=="object"?t:"")+"]",i,n,r)});else if(!n&&v.type(t)==="object")for(i in t)fn(e+"["+i+"]",t[i],n,r);else r(e,t)}function Cn(e){return function(t,n){typeof t!="string"&&(n=t,t="*");var r,i,s,o=t.toLowerCase().split(y),u=0,a=o.length;if(v.isFunction(n))for(;u)[^>]*$|#([\w\-]*)$)/,E=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,S=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,T=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,N=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,C=/^-ms-/,k=/-([\da-z])/gi,L=function(e,t){return(t+"").toUpperCase()},A=function(){i.addEventListener?(i.removeEventListener("DOMContentLoaded",A,!1),v.ready()):i.readyState==="complete"&&(i.detachEvent("onreadystatechange",A),v.ready())},O={};v.fn=v.prototype={constructor:v,init:function(e,n,r){var s,o,u,a;if(!e)return this;if(e.nodeType)return this.context=this[0]=e,this.length=1,this;if(typeof e=="string"){e.charAt(0)==="<"&&e.charAt(e.length-1)===">"&&e.length>=3?s=[null,e,null]:s=w.exec(e);if(s&&(s[1]||!n)){if(s[1])return n=n instanceof v?n[0]:n,a=n&&n.nodeType?n.ownerDocument||n:i,e=v.parseHTML(s[1],a,!0),E.test(s[1])&&v.isPlainObject(n)&&this.attr.call(e,n,!0),v.merge(this,e);o=i.getElementById(s[2]);if(o&&o.parentNode){if(o.id!==s[2])return r.find(e);this.length=1,this[0]=o}return this.context=i,this.selector=e,this}return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e)}return v.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),v.makeArray(e,this))},selector:"",jquery:"1.8.3",length:0,size:function(){return this.length},toArray:function(){return l.call(this)},get:function(e){return e==null?this.toArray():e<0?this[this.length+e]:this[e]},pushStack:function(e,t,n){var r=v.merge(this.constructor(),e);return r.prevObject=this,r.context=this.context,t==="find"?r.selector=this.selector+(this.selector?" ":"")+n:t&&(r.selector=this.selector+"."+t+"("+n+")"),r},each:function(e,t){return v.each(this,e,t)},ready:function(e){return v.ready.promise().done(e),this},eq:function(e){return e=+e,e===-1?this.slice(e):this.slice(e,e+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(l.apply(this,arguments),"slice",l.call(arguments).join(","))},map:function(e){return this.pushStack(v.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:[].sort,splice:[].splice},v.fn.init.prototype=v.fn,v.extend=v.fn.extend=function(){var e,n,r,i,s,o,u=arguments[0]||{},a=1,f=arguments.length,l=!1;typeof u=="boolean"&&(l=u,u=arguments[1]||{},a=2),typeof u!="object"&&!v.isFunction(u)&&(u={}),f===a&&(u=this,--a);for(;a0)return;r.resolveWith(i,[v]),v.fn.trigger&&v(i).trigger("ready").off("ready")},isFunction:function(e){return v.type(e)==="function"},isArray:Array.isArray||function(e){return v.type(e)==="array"},isWindow:function(e){return e!=null&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return e==null?String(e):O[h.call(e)]||"object"},isPlainObject:function(e){if(!e||v.type(e)!=="object"||e.nodeType||v.isWindow(e))return!1;try{if(e.constructor&&!p.call(e,"constructor")&&!p.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||p.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw new Error(e)},parseHTML:function(e,t,n){var r;return!e||typeof e!="string"?null:(typeof t=="boolean"&&(n=t,t=0),t=t||i,(r=E.exec(e))?[t.createElement(r[1])]:(r=v.buildFragment([e],t,n?null:[]),v.merge([],(r.cacheable?v.clone(r.fragment):r.fragment).childNodes)))},parseJSON:function(t){if(!t||typeof t!="string")return null;t=v.trim(t);if(e.JSON&&e.JSON.parse)return e.JSON.parse(t);if(S.test(t.replace(T,"@").replace(N,"]").replace(x,"")))return(new Function("return "+t))();v.error("Invalid JSON: "+t)},parseXML:function(n){var r,i;if(!n||typeof n!="string")return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(s){r=t}return(!r||!r.documentElement||r.getElementsByTagName("parsererror").length)&&v.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&g.test(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(C,"ms-").replace(k,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,n,r){var i,s=0,o=e.length,u=o===t||v.isFunction(e);if(r){if(u){for(i in e)if(n.apply(e[i],r)===!1)break}else for(;s0&&e[0]&&e[a-1]||a===0||v.isArray(e));if(f)for(;u-1)a.splice(n,1),i&&(n<=o&&o--,n<=u&&u--)}),this},has:function(e){return v.inArray(e,a)>-1},empty:function(){return a=[],this},disable:function(){return a=f=n=t,this},disabled:function(){return!a},lock:function(){return f=t,n||c.disable(),this},locked:function(){return!f},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],a&&(!r||f)&&(i?f.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},v.extend({Deferred:function(e){var t=[["resolve","done",v.Callbacks("once memory"),"resolved"],["reject","fail",v.Callbacks("once memory"),"rejected"],["notify","progress",v.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return v.Deferred(function(n){v.each(t,function(t,r){var s=r[0],o=e[t];i[r[1]](v.isFunction(o)?function(){var e=o.apply(this,arguments);e&&v.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===i?n:this,[e])}:n[s])}),e=null}).promise()},promise:function(e){return e!=null?v.extend(e,r):r}},i={};return r.pipe=r.then,v.each(t,function(e,s){var o=s[2],u=s[3];r[s[1]]=o.add,u&&o.add(function(){n=u},t[e^1][2].disable,t[2][2].lock),i[s[0]]=o.fire,i[s[0]+"With"]=o.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=l.call(arguments),r=n.length,i=r!==1||e&&v.isFunction(e.promise)?r:0,s=i===1?e:v.Deferred(),o=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?l.call(arguments):r,n===u?s.notifyWith(t,n):--i||s.resolveWith(t,n)}},u,a,f;if(r>1){u=new Array(r),a=new Array(r),f=new Array(r);for(;t
a",n=p.getElementsByTagName("*"),r=p.getElementsByTagName("a")[0];if(!n||!r||!n.length)return{};s=i.createElement("select"),o=s.appendChild(i.createElement("option")),u=p.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:r.getAttribute("href")==="/a",opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:u.value==="on",optSelected:o.selected,getSetAttribute:p.className!=="t",enctype:!!i.createElement("form").enctype,html5Clone:i.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",boxModel:i.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},u.checked=!0,t.noCloneChecked=u.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!o.disabled;try{delete p.test}catch(d){t.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",h=function(){t.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick"),p.detachEvent("onclick",h)),u=i.createElement("input"),u.value="t",u.setAttribute("type","radio"),t.radioValue=u.value==="t",u.setAttribute("checked","checked"),u.setAttribute("name","t"),p.appendChild(u),a=i.createDocumentFragment(),a.appendChild(p.lastChild),t.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,t.appendChecked=u.checked,a.removeChild(u),a.appendChild(p);if(p.attachEvent)for(l in{submit:!0,change:!0,focusin:!0})f="on"+l,c=f in p,c||(p.setAttribute(f,"return;"),c=typeof p[f]=="function"),t[l+"Bubbles"]=c;return v(function(){var n,r,s,o,u="padding:0;margin:0;border:0;display:block;overflow:hidden;",a=i.getElementsByTagName("body")[0];if(!a)return;n=i.createElement("div"),n.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",a.insertBefore(n,a.firstChild),r=i.createElement("div"),n.appendChild(r),r.innerHTML="
t
",s=r.getElementsByTagName("td"),s[0].style.cssText="padding:0;margin:0;border:0;display:none",c=s[0].offsetHeight===0,s[0].style.display="",s[1].style.display="none",t.reliableHiddenOffsets=c&&s[0].offsetHeight===0,r.innerHTML="",r.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=r.offsetWidth===4,t.doesNotIncludeMarginInBodyOffset=a.offsetTop!==1,e.getComputedStyle&&(t.pixelPosition=(e.getComputedStyle(r,null)||{}).top!=="1%",t.boxSizingReliable=(e.getComputedStyle(r,null)||{width:"4px"}).width==="4px",o=i.createElement("div"),o.style.cssText=r.style.cssText=u,o.style.marginRight=o.style.width="0",r.style.width="1px",r.appendChild(o),t.reliableMarginRight=!parseFloat((e.getComputedStyle(o,null)||{}).marginRight)),typeof r.style.zoom!="undefined"&&(r.innerHTML="",r.style.cssText=u+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=r.offsetWidth===3,r.style.display="block",r.style.overflow="visible",r.innerHTML="
",r.firstChild.style.width="5px",t.shrinkWrapBlocks=r.offsetWidth!==3,n.style.zoom=1),a.removeChild(n),n=r=s=o=null}),a.removeChild(p),n=r=s=o=u=a=p=null,t}();var D=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;v.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(v.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?v.cache[e[v.expando]]:e[v.expando],!!e&&!B(e)},data:function(e,n,r,i){if(!v.acceptData(e))return;var s,o,u=v.expando,a=typeof n=="string",f=e.nodeType,l=f?v.cache:e,c=f?e[u]:e[u]&&u;if((!c||!l[c]||!i&&!l[c].data)&&a&&r===t)return;c||(f?e[u]=c=v.deletedIds.pop()||v.guid++:c=u),l[c]||(l[c]={},f||(l[c].toJSON=v.noop));if(typeof n=="object"||typeof n=="function")i?l[c]=v.extend(l[c],n):l[c].data=v.extend(l[c].data,n);return s=l[c],i||(s.data||(s.data={}),s=s.data),r!==t&&(s[v.camelCase(n)]=r),a?(o=s[n],o==null&&(o=s[v.camelCase(n)])):o=s,o},removeData:function(e,t,n){if(!v.acceptData(e))return;var r,i,s,o=e.nodeType,u=o?v.cache:e,a=o?e[v.expando]:v.expando;if(!u[a])return;if(t){r=n?u[a]:u[a].data;if(r){v.isArray(t)||(t in r?t=[t]:(t=v.camelCase(t),t in r?t=[t]:t=t.split(" ")));for(i=0,s=t.length;i1,null,!1))},removeData:function(e){return this.each(function(){v.removeData(this,e)})}}),v.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=v._data(e,t),n&&(!r||v.isArray(n)?r=v._data(e,t,v.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=v.queue(e,t),r=n.length,i=n.shift(),s=v._queueHooks(e,t),o=function(){v.dequeue(e,t)};i==="inprogress"&&(i=n.shift(),r--),i&&(t==="fx"&&n.unshift("inprogress"),delete s.stop,i.call(e,o,s)),!r&&s&&s.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return v._data(e,n)||v._data(e,n,{empty:v.Callbacks("once memory").add(function(){v.removeData(e,t+"queue",!0),v.removeData(e,n,!0)})})}}),v.fn.extend({queue:function(e,n){var r=2;return typeof e!="string"&&(n=e,e="fx",r--),arguments.length1)},removeAttr:function(e){return this.each(function(){v.removeAttr(this,e)})},prop:function(e,t){return v.access(this,v.prop,e,t,arguments.length>1)},removeProp:function(e){return e=v.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,s,o,u;if(v.isFunction(e))return this.each(function(t){v(this).addClass(e.call(this,t,this.className))});if(e&&typeof e=="string"){t=e.split(y);for(n=0,r=this.length;n=0)r=r.replace(" "+n[s]+" "," ");i.className=e?v.trim(r):""}}}return this},toggleClass:function(e,t){var n=typeof e,r=typeof t=="boolean";return v.isFunction(e)?this.each(function(n){v(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if(n==="string"){var i,s=0,o=v(this),u=t,a=e.split(y);while(i=a[s++])u=r?u:!o.hasClass(i),o[u?"addClass":"removeClass"](i)}else if(n==="undefined"||n==="boolean")this.className&&v._data(this,"__className__",this.className),this.className=this.className||e===!1?"":v._data(this,"__className__")||""})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;n=0)return!0;return!1},val:function(e){var n,r,i,s=this[0];if(!arguments.length){if(s)return n=v.valHooks[s.type]||v.valHooks[s.nodeName.toLowerCase()],n&&"get"in n&&(r=n.get(s,"value"))!==t?r:(r=s.value,typeof r=="string"?r.replace(R,""):r==null?"":r);return}return i=v.isFunction(e),this.each(function(r){var s,o=v(this);if(this.nodeType!==1)return;i?s=e.call(this,r,o.val()):s=e,s==null?s="":typeof s=="number"?s+="":v.isArray(s)&&(s=v.map(s,function(e){return e==null?"":e+""})),n=v.valHooks[this.type]||v.valHooks[this.nodeName.toLowerCase()];if(!n||!("set"in n)||n.set(this,s,"value")===t)this.value=s})}}),v.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,s=e.type==="select-one"||i<0,o=s?null:[],u=s?i+1:r.length,a=i<0?u:s?i:0;for(;a=0}),n.length||(e.selectedIndex=-1),n}}},attrFn:{},attr:function(e,n,r,i){var s,o,u,a=e.nodeType;if(!e||a===3||a===8||a===2)return;if(i&&v.isFunction(v.fn[n]))return v(e)[n](r);if(typeof e.getAttribute=="undefined")return v.prop(e,n,r);u=a!==1||!v.isXMLDoc(e),u&&(n=n.toLowerCase(),o=v.attrHooks[n]||(X.test(n)?F:j));if(r!==t){if(r===null){v.removeAttr(e,n);return}return o&&"set"in o&&u&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r)}return o&&"get"in o&&u&&(s=o.get(e,n))!==null?s:(s=e.getAttribute(n),s===null?t:s)},removeAttr:function(e,t){var n,r,i,s,o=0;if(t&&e.nodeType===1){r=t.split(y);for(;o=0}})});var $=/^(?:textarea|input|select)$/i,J=/^([^\.]*|)(?:\.(.+)|)$/,K=/(?:^|\s)hover(\.\S+|)\b/,Q=/^key/,G=/^(?:mouse|contextmenu)|click/,Y=/^(?:focusinfocus|focusoutblur)$/,Z=function(e){return v.event.special.hover?e:e.replace(K,"mouseenter$1 mouseleave$1")};v.event={add:function(e,n,r,i,s){var o,u,a,f,l,c,h,p,d,m,g;if(e.nodeType===3||e.nodeType===8||!n||!r||!(o=v._data(e)))return;r.handler&&(d=r,r=d.handler,s=d.selector),r.guid||(r.guid=v.guid++),a=o.events,a||(o.events=a={}),u=o.handle,u||(o.handle=u=function(e){return typeof v=="undefined"||!!e&&v.event.triggered===e.type?t:v.event.dispatch.apply(u.elem,arguments)},u.elem=e),n=v.trim(Z(n)).split(" ");for(f=0;f=0&&(y=y.slice(0,-1),a=!0),y.indexOf(".")>=0&&(b=y.split("."),y=b.shift(),b.sort());if((!s||v.event.customEvent[y])&&!v.event.global[y])return;n=typeof n=="object"?n[v.expando]?n:new v.Event(y,n):new v.Event(y),n.type=y,n.isTrigger=!0,n.exclusive=a,n.namespace=b.join("."),n.namespace_re=n.namespace?new RegExp("(^|\\.)"+b.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,h=y.indexOf(":")<0?"on"+y:"";if(!s){u=v.cache;for(f in u)u[f].events&&u[f].events[y]&&v.event.trigger(n,r,u[f].handle.elem,!0);return}n.result=t,n.target||(n.target=s),r=r!=null?v.makeArray(r):[],r.unshift(n),p=v.event.special[y]||{};if(p.trigger&&p.trigger.apply(s,r)===!1)return;m=[[s,p.bindType||y]];if(!o&&!p.noBubble&&!v.isWindow(s)){g=p.delegateType||y,l=Y.test(g+y)?s:s.parentNode;for(c=s;l;l=l.parentNode)m.push([l,g]),c=l;c===(s.ownerDocument||i)&&m.push([c.defaultView||c.parentWindow||e,g])}for(f=0;f=0:v.find(h,this,null,[s]).length),u[h]&&f.push(c);f.length&&w.push({elem:s,matches:f})}d.length>m&&w.push({elem:this,matches:d.slice(m)});for(r=0;r0?this.on(t,null,e,n):this.trigger(t)},Q.test(t)&&(v.event.fixHooks[t]=v.event.keyHooks),G.test(t)&&(v.event.fixHooks[t]=v.event.mouseHooks)}),function(e,t){function nt(e,t,n,r){n=n||[],t=t||g;var i,s,a,f,l=t.nodeType;if(!e||typeof e!="string")return n;if(l!==1&&l!==9)return[];a=o(t);if(!a&&!r)if(i=R.exec(e))if(f=i[1]){if(l===9){s=t.getElementById(f);if(!s||!s.parentNode)return n;if(s.id===f)return n.push(s),n}else if(t.ownerDocument&&(s=t.ownerDocument.getElementById(f))&&u(t,s)&&s.id===f)return n.push(s),n}else{if(i[2])return S.apply(n,x.call(t.getElementsByTagName(e),0)),n;if((f=i[3])&&Z&&t.getElementsByClassName)return S.apply(n,x.call(t.getElementsByClassName(f),0)),n}return vt(e.replace(j,"$1"),t,n,r,a)}function rt(e){return function(t){var n=t.nodeName.toLowerCase();return n==="input"&&t.type===e}}function it(e){return function(t){var n=t.nodeName.toLowerCase();return(n==="input"||n==="button")&&t.type===e}}function st(e){return N(function(t){return t=+t,N(function(n,r){var i,s=e([],n.length,t),o=s.length;while(o--)n[i=s[o]]&&(n[i]=!(r[i]=n[i]))})})}function ot(e,t,n){if(e===t)return n;var r=e.nextSibling;while(r){if(r===t)return-1;r=r.nextSibling}return 1}function ut(e,t){var n,r,s,o,u,a,f,l=L[d][e+" "];if(l)return t?0:l.slice(0);u=e,a=[],f=i.preFilter;while(u){if(!n||(r=F.exec(u)))r&&(u=u.slice(r[0].length)||u),a.push(s=[]);n=!1;if(r=I.exec(u))s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=r[0].replace(j," ");for(o in i.filter)(r=J[o].exec(u))&&(!f[o]||(r=f[o](r)))&&(s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=o,n.matches=r);if(!n)break}return t?u.length:u?nt.error(e):L(e,a).slice(0)}function at(e,t,r){var i=t.dir,s=r&&t.dir==="parentNode",o=w++;return t.first?function(t,n,r){while(t=t[i])if(s||t.nodeType===1)return e(t,n,r)}:function(t,r,u){if(!u){var a,f=b+" "+o+" ",l=f+n;while(t=t[i])if(s||t.nodeType===1){if((a=t[d])===l)return t.sizset;if(typeof a=="string"&&a.indexOf(f)===0){if(t.sizset)return t}else{t[d]=l;if(e(t,r,u))return t.sizset=!0,t;t.sizset=!1}}}else while(t=t[i])if(s||t.nodeType===1)if(e(t,r,u))return t}}function ft(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function lt(e,t,n,r,i){var s,o=[],u=0,a=e.length,f=t!=null;for(;u-1&&(s[f]=!(o[f]=c))}}else g=lt(g===o?g.splice(d,g.length):g),i?i(null,o,g,a):S.apply(o,g)})}function ht(e){var t,n,r,s=e.length,o=i.relative[e[0].type],u=o||i.relative[" "],a=o?1:0,f=at(function(e){return e===t},u,!0),l=at(function(e){return T.call(t,e)>-1},u,!0),h=[function(e,n,r){return!o&&(r||n!==c)||((t=n).nodeType?f(e,n,r):l(e,n,r))}];for(;a1&&ft(h),a>1&&e.slice(0,a-1).join("").replace(j,"$1"),n,a0,s=e.length>0,o=function(u,a,f,l,h){var p,d,v,m=[],y=0,w="0",x=u&&[],T=h!=null,N=c,C=u||s&&i.find.TAG("*",h&&a.parentNode||a),k=b+=N==null?1:Math.E;T&&(c=a!==g&&a,n=o.el);for(;(p=C[w])!=null;w++){if(s&&p){for(d=0;v=e[d];d++)if(v(p,a,f)){l.push(p);break}T&&(b=k,n=++o.el)}r&&((p=!v&&p)&&y--,u&&x.push(p))}y+=w;if(r&&w!==y){for(d=0;v=t[d];d++)v(x,m,a,f);if(u){if(y>0)while(w--)!x[w]&&!m[w]&&(m[w]=E.call(l));m=lt(m)}S.apply(l,m),T&&!u&&m.length>0&&y+t.length>1&&nt.uniqueSort(l)}return T&&(b=k,c=N),x};return o.el=0,r?N(o):o}function dt(e,t,n){var r=0,i=t.length;for(;r2&&(f=u[0]).type==="ID"&&t.nodeType===9&&!s&&i.relative[u[1].type]){t=i.find.ID(f.matches[0].replace($,""),t,s)[0];if(!t)return n;e=e.slice(u.shift().length)}for(o=J.POS.test(e)?-1:u.length-1;o>=0;o--){f=u[o];if(i.relative[l=f.type])break;if(c=i.find[l])if(r=c(f.matches[0].replace($,""),z.test(u[0].type)&&t.parentNode||t,s)){u.splice(o,1),e=r.length&&u.join("");if(!e)return S.apply(n,x.call(r,0)),n;break}}}return a(e,h)(r,t,s,n,z.test(e)),n}function mt(){}var n,r,i,s,o,u,a,f,l,c,h=!0,p="undefined",d=("sizcache"+Math.random()).replace(".",""),m=String,g=e.document,y=g.documentElement,b=0,w=0,E=[].pop,S=[].push,x=[].slice,T=[].indexOf||function(e){var t=0,n=this.length;for(;ti.cacheLength&&delete e[t.shift()],e[n+" "]=r},e)},k=C(),L=C(),A=C(),O="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",_=M.replace("w","w#"),D="([*^$|!~]?=)",P="\\["+O+"*("+M+")"+O+"*(?:"+D+O+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+_+")|)|)"+O+"*\\]",H=":("+M+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+P+")|[^:]|\\\\.)*|.*))\\)|)",B=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+O+"*((?:-\\d)?\\d*)"+O+"*\\)|)(?=[^-]|$)",j=new RegExp("^"+O+"+|((?:^|[^\\\\])(?:\\\\.)*)"+O+"+$","g"),F=new RegExp("^"+O+"*,"+O+"*"),I=new RegExp("^"+O+"*([\\x20\\t\\r\\n\\f>+~])"+O+"*"),q=new RegExp(H),R=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,U=/^:not/,z=/[\x20\t\r\n\f]*[+~]/,W=/:not\($/,X=/h\d/i,V=/input|select|textarea|button/i,$=/\\(?!\\)/g,J={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),NAME:new RegExp("^\\[name=['\"]?("+M+")['\"]?\\]"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+H),POS:new RegExp(B,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+O+"*(even|odd|(([+-]|)(\\d*)n|)"+O+"*(?:([+-]|)"+O+"*(\\d+)|))"+O+"*\\)|)","i"),needsContext:new RegExp("^"+O+"*[>+~]|"+B,"i")},K=function(e){var t=g.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}},Q=K(function(e){return e.appendChild(g.createComment("")),!e.getElementsByTagName("*").length}),G=K(function(e){return e.innerHTML="",e.firstChild&&typeof e.firstChild.getAttribute!==p&&e.firstChild.getAttribute("href")==="#"}),Y=K(function(e){e.innerHTML="";var t=typeof e.lastChild.getAttribute("multiple");return t!=="boolean"&&t!=="string"}),Z=K(function(e){return e.innerHTML="",!e.getElementsByClassName||!e.getElementsByClassName("e").length?!1:(e.lastChild.className="e",e.getElementsByClassName("e").length===2)}),et=K(function(e){e.id=d+0,e.innerHTML="
",y.insertBefore(e,y.firstChild);var t=g.getElementsByName&&g.getElementsByName(d).length===2+g.getElementsByName(d+0).length;return r=!g.getElementById(d),y.removeChild(e),t});try{x.call(y.childNodes,0)[0].nodeType}catch(tt){x=function(e){var t,n=[];for(;t=this[e];e++)n.push(t);return n}}nt.matches=function(e,t){return nt(e,null,null,t)},nt.matchesSelector=function(e,t){return nt(t,null,null,[e]).length>0},s=nt.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(i===1||i===9||i===11){if(typeof e.textContent=="string")return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=s(e)}else if(i===3||i===4)return e.nodeValue}else for(;t=e[r];r++)n+=s(t);return n},o=nt.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?t.nodeName!=="HTML":!1},u=nt.contains=y.contains?function(e,t){var n=e.nodeType===9?e.documentElement:e,r=t&&t.parentNode;return e===r||!!(r&&r.nodeType===1&&n.contains&&n.contains(r))}:y.compareDocumentPosition?function(e,t){return t&&!!(e.compareDocumentPosition(t)&16)}:function(e,t){while(t=t.parentNode)if(t===e)return!0;return!1},nt.attr=function(e,t){var n,r=o(e);return r||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):r||Y?e.getAttribute(t):(n=e.getAttributeNode(t),n?typeof e[t]=="boolean"?e[t]?t:null:n.specified?n.value:null:null)},i=nt.selectors={cacheLength:50,createPseudo:N,match:J,attrHandle:G?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},find:{ID:r?function(e,t,n){if(typeof t.getElementById!==p&&!n){var r=t.getElementById(e);return r&&r.parentNode?[r]:[]}}:function(e,n,r){if(typeof n.getElementById!==p&&!r){var i=n.getElementById(e);return i?i.id===e||typeof i.getAttributeNode!==p&&i.getAttributeNode("id").value===e?[i]:t:[]}},TAG:Q?function(e,t){if(typeof t.getElementsByTagName!==p)return t.getElementsByTagName(e)}:function(e,t){var n=t.getElementsByTagName(e);if(e==="*"){var r,i=[],s=0;for(;r=n[s];s++)r.nodeType===1&&i.push(r);return i}return n},NAME:et&&function(e,t){if(typeof t.getElementsByName!==p)return t.getElementsByName(name)},CLASS:Z&&function(e,t,n){if(typeof t.getElementsByClassName!==p&&!n)return t.getElementsByClassName(e)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace($,""),e[3]=(e[4]||e[5]||"").replace($,""),e[2]==="~="&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),e[1]==="nth"?(e[2]||nt.error(e[0]),e[3]=+(e[3]?e[4]+(e[5]||1):2*(e[2]==="even"||e[2]==="odd")),e[4]=+(e[6]+e[7]||e[2]==="odd")):e[2]&&nt.error(e[0]),e},PSEUDO:function(e){var t,n;if(J.CHILD.test(e[0]))return null;if(e[3])e[2]=e[3];else if(t=e[4])q.test(t)&&(n=ut(t,!0))&&(n=t.indexOf(")",t.length-n)-t.length)&&(t=t.slice(0,n),e[0]=e[0].slice(0,n)),e[2]=t;return e.slice(0,3)}},filter:{ID:r?function(e){return e=e.replace($,""),function(t){return t.getAttribute("id")===e}}:function(e){return e=e.replace($,""),function(t){var n=typeof t.getAttributeNode!==p&&t.getAttributeNode("id");return n&&n.value===e}},TAG:function(e){return e==="*"?function(){return!0}:(e=e.replace($,"").toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[d][e+" "];return t||(t=new RegExp("(^|"+O+")"+e+"("+O+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==p&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r,i){var s=nt.attr(r,e);return s==null?t==="!=":t?(s+="",t==="="?s===n:t==="!="?s!==n:t==="^="?n&&s.indexOf(n)===0:t==="*="?n&&s.indexOf(n)>-1:t==="$="?n&&s.substr(s.length-n.length)===n:t==="~="?(" "+s+" ").indexOf(n)>-1:t==="|="?s===n||s.substr(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r){return e==="nth"?function(e){var t,i,s=e.parentNode;if(n===1&&r===0)return!0;if(s){i=0;for(t=s.firstChild;t;t=t.nextSibling)if(t.nodeType===1){i++;if(e===t)break}}return i-=r,i===n||i%n===0&&i/n>=0}:function(t){var n=t;switch(e){case"only":case"first":while(n=n.previousSibling)if(n.nodeType===1)return!1;if(e==="first")return!0;n=t;case"last":while(n=n.nextSibling)if(n.nodeType===1)return!1;return!0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||nt.error("unsupported pseudo: "+e);return r[d]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?N(function(e,n){var i,s=r(e,t),o=s.length;while(o--)i=T.call(e,s[o]),e[i]=!(n[i]=s[o])}):function(e){return r(e,0,n)}):r}},pseudos:{not:N(function(e){var t=[],n=[],r=a(e.replace(j,"$1"));return r[d]?N(function(e,t,n,i){var s,o=r(e,null,i,[]),u=e.length;while(u--)if(s=o[u])e[u]=!(t[u]=s)}):function(e,i,s){return t[0]=e,r(t,null,s,n),!n.pop()}}),has:N(function(e){return function(t){return nt(e,t).length>0}}),contains:N(function(e){return function(t){return(t.textContent||t.innerText||s(t)).indexOf(e)>-1}}),enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&!!e.checked||t==="option"&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},parent:function(e){return!i.pseudos.empty(e)},empty:function(e){var t;e=e.firstChild;while(e){if(e.nodeName>"@"||(t=e.nodeType)===3||t===4)return!1;e=e.nextSibling}return!0},header:function(e){return X.test(e.nodeName)},text:function(e){var t,n;return e.nodeName.toLowerCase()==="input"&&(t=e.type)==="text"&&((n=e.getAttribute("type"))==null||n.toLowerCase()===t)},radio:rt("radio"),checkbox:rt("checkbox"),file:rt("file"),password:rt("password"),image:rt("image"),submit:it("submit"),reset:it("reset"),button:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&e.type==="button"||t==="button"},input:function(e){return V.test(e.nodeName)},focus:function(e){var t=e.ownerDocument;return e===t.activeElement&&(!t.hasFocus||t.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},active:function(e){return e===e.ownerDocument.activeElement},first:st(function(){return[0]}),last:st(function(e,t){return[t-1]}),eq:st(function(e,t,n){return[n<0?n+t:n]}),even:st(function(e,t){for(var n=0;n=0;)e.push(r);return e}),gt:st(function(e,t,n){for(var r=n<0?n+t:n;++r",e.querySelectorAll("[selected]").length||i.push("\\["+O+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||i.push(":checked")}),K(function(e){e.innerHTML="

",e.querySelectorAll("[test^='']").length&&i.push("[*^$]="+O+"*(?:\"\"|'')"),e.innerHTML="",e.querySelectorAll(":enabled").length||i.push(":enabled",":disabled")}),i=new RegExp(i.join("|")),vt=function(e,r,s,o,u){if(!o&&!u&&!i.test(e)){var a,f,l=!0,c=d,h=r,p=r.nodeType===9&&e;if(r.nodeType===1&&r.nodeName.toLowerCase()!=="object"){a=ut(e),(l=r.getAttribute("id"))?c=l.replace(n,"\\$&"):r.setAttribute("id",c),c="[id='"+c+"'] ",f=a.length;while(f--)a[f]=c+a[f].join("");h=z.test(e)&&r.parentNode||r,p=a.join(",")}if(p)try{return S.apply(s,x.call(h.querySelectorAll(p),0)),s}catch(v){}finally{l||r.removeAttribute("id")}}return t(e,r,s,o,u)},u&&(K(function(t){e=u.call(t,"div");try{u.call(t,"[test!='']:sizzle"),s.push("!=",H)}catch(n){}}),s=new RegExp(s.join("|")),nt.matchesSelector=function(t,n){n=n.replace(r,"='$1']");if(!o(t)&&!s.test(n)&&!i.test(n))try{var a=u.call(t,n);if(a||e||t.document&&t.document.nodeType!==11)return a}catch(f){}return nt(n,null,null,[t]).length>0})}(),i.pseudos.nth=i.pseudos.eq,i.filters=mt.prototype=i.pseudos,i.setFilters=new mt,nt.attr=v.attr,v.find=nt,v.expr=nt.selectors,v.expr[":"]=v.expr.pseudos,v.unique=nt.uniqueSort,v.text=nt.getText,v.isXMLDoc=nt.isXML,v.contains=nt.contains}(e);var nt=/Until$/,rt=/^(?:parents|prev(?:Until|All))/,it=/^.[^:#\[\.,]*$/,st=v.expr.match.needsContext,ot={children:!0,contents:!0,next:!0,prev:!0};v.fn.extend({find:function(e){var t,n,r,i,s,o,u=this;if(typeof e!="string")return v(e).filter(function(){for(t=0,n=u.length;t0)for(i=r;i=0:v.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,s=[],o=st.test(e)||typeof e!="string"?v(e,t||this.context):0;for(;r-1:v.find.matchesSelector(n,e)){s.push(n);break}n=n.parentNode}}return s=s.length>1?v.unique(s):s,this.pushStack(s,"closest",e)},index:function(e){return e?typeof e=="string"?v.inArray(this[0],v(e)):v.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(e,t){var n=typeof e=="string"?v(e,t):v.makeArray(e&&e.nodeType?[e]:e),r=v.merge(this.get(),n);return this.pushStack(ut(n[0])||ut(r[0])?r:v.unique(r))},addBack:function(e){return this.add(e==null?this.prevObject:this.prevObject.filter(e))}}),v.fn.andSelf=v.fn.addBack,v.each({parent:function(e){var t=e.parentNode;return t&&t.nodeType!==11?t:null},parents:function(e){return v.dir(e,"parentNode")},parentsUntil:function(e,t,n){return v.dir(e,"parentNode",n)},next:function(e){return at(e,"nextSibling")},prev:function(e){return at(e,"previousSibling")},nextAll:function(e){return v.dir(e,"nextSibling")},prevAll:function(e){return v.dir(e,"previousSibling")},nextUntil:function(e,t,n){return v.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return v.dir(e,"previousSibling",n)},siblings:function(e){return v.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return v.sibling(e.firstChild)},contents:function(e){return v.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:v.merge([],e.childNodes)}},function(e,t){v.fn[e]=function(n,r){var i=v.map(this,t,n);return nt.test(e)||(r=n),r&&typeof r=="string"&&(i=v.filter(r,i)),i=this.length>1&&!ot[e]?v.unique(i):i,this.length>1&&rt.test(e)&&(i=i.reverse()),this.pushStack(i,e,l.call(arguments).join(","))}}),v.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),t.length===1?v.find.matchesSelector(t[0],e)?[t[0]]:[]:v.find.matches(e,t)},dir:function(e,n,r){var i=[],s=e[n];while(s&&s.nodeType!==9&&(r===t||s.nodeType!==1||!v(s).is(r)))s.nodeType===1&&i.push(s),s=s[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)e.nodeType===1&&e!==t&&n.push(e);return n}});var ct="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ht=/ jQuery\d+="(?:null|\d+)"/g,pt=/^\s+/,dt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,vt=/<([\w:]+)/,mt=/]","i"),Et=/^(?:checkbox|radio)$/,St=/checked\s*(?:[^=]|=\s*.checked.)/i,xt=/\/(java|ecma)script/i,Tt=/^\s*\s*$/g,Nt={option:[1,""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},Ct=lt(i),kt=Ct.appendChild(i.createElement("div"));Nt.optgroup=Nt.option,Nt.tbody=Nt.tfoot=Nt.colgroup=Nt.caption=Nt.thead,Nt.th=Nt.td,v.support.htmlSerialize||(Nt._default=[1,"X
","
"]),v.fn.extend({text:function(e){return v.access(this,function(e){return e===t?v.text(this):this.empty().append((this[0]&&this[0].ownerDocument||i).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(v.isFunction(e))return this.each(function(t){v(this).wrapAll(e.call(this,t))});if(this[0]){var t=v(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&e.firstChild.nodeType===1)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return v.isFunction(e)?this.each(function(t){v(this).wrapInner(e.call(this,t))}):this.each(function(){var t=v(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=v.isFunction(e);return this.each(function(n){v(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){v.nodeName(this,"body")||v(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(e,this.firstChild)})},before:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(e,this),"before",this.selector)}},after:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this.nextSibling)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(this,e),"after",this.selector)}},remove:function(e,t){var n,r=0;for(;(n=this[r])!=null;r++)if(!e||v.filter(e,[n]).length)!t&&n.nodeType===1&&(v.cleanData(n.getElementsByTagName("*")),v.cleanData([n])),n.parentNode&&n.parentNode.removeChild(n);return this},empty:function(){var e,t=0;for(;(e=this[t])!=null;t++){e.nodeType===1&&v.cleanData(e.getElementsByTagName("*"));while(e.firstChild)e.removeChild(e.firstChild)}return this},clone:function(e,t){return e=e==null?!1:e,t=t==null?e:t,this.map(function(){return v.clone(this,e,t)})},html:function(e){return v.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return n.nodeType===1?n.innerHTML.replace(ht,""):t;if(typeof e=="string"&&!yt.test(e)&&(v.support.htmlSerialize||!wt.test(e))&&(v.support.leadingWhitespace||!pt.test(e))&&!Nt[(vt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(dt,"<$1>");try{for(;r1&&typeof f=="string"&&St.test(f))return this.each(function(){v(this).domManip(e,n,r)});if(v.isFunction(f))return this.each(function(i){var s=v(this);e[0]=f.call(this,i,n?s.html():t),s.domManip(e,n,r)});if(this[0]){i=v.buildFragment(e,this,l),o=i.fragment,s=o.firstChild,o.childNodes.length===1&&(o=s);if(s){n=n&&v.nodeName(s,"tr");for(u=i.cacheable||c-1;a0?this.clone(!0):this).get(),v(o[i])[t](r),s=s.concat(r);return this.pushStack(s,e,o.selector)}}),v.extend({clone:function(e,t,n){var r,i,s,o;v.support.html5Clone||v.isXMLDoc(e)||!wt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(kt.innerHTML=e.outerHTML,kt.removeChild(o=kt.firstChild));if((!v.support.noCloneEvent||!v.support.noCloneChecked)&&(e.nodeType===1||e.nodeType===11)&&!v.isXMLDoc(e)){Ot(e,o),r=Mt(e),i=Mt(o);for(s=0;r[s];++s)i[s]&&Ot(r[s],i[s])}if(t){At(e,o);if(n){r=Mt(e),i=Mt(o);for(s=0;r[s];++s)At(r[s],i[s])}}return r=i=null,o},clean:function(e,t,n,r){var s,o,u,a,f,l,c,h,p,d,m,g,y=t===i&&Ct,b=[];if(!t||typeof t.createDocumentFragment=="undefined")t=i;for(s=0;(u=e[s])!=null;s++){typeof u=="number"&&(u+="");if(!u)continue;if(typeof u=="string")if(!gt.test(u))u=t.createTextNode(u);else{y=y||lt(t),c=t.createElement("div"),y.appendChild(c),u=u.replace(dt,"<$1>"),a=(vt.exec(u)||["",""])[1].toLowerCase(),f=Nt[a]||Nt._default,l=f[0],c.innerHTML=f[1]+u+f[2];while(l--)c=c.lastChild;if(!v.support.tbody){h=mt.test(u),p=a==="table"&&!h?c.firstChild&&c.firstChild.childNodes:f[1]===""&&!h?c.childNodes:[];for(o=p.length-1;o>=0;--o)v.nodeName(p[o],"tbody")&&!p[o].childNodes.length&&p[o].parentNode.removeChild(p[o])}!v.support.leadingWhitespace&&pt.test(u)&&c.insertBefore(t.createTextNode(pt.exec(u)[0]),c.firstChild),u=c.childNodes,c.parentNode.removeChild(c)}u.nodeType?b.push(u):v.merge(b,u)}c&&(u=c=y=null);if(!v.support.appendChecked)for(s=0;(u=b[s])!=null;s++)v.nodeName(u,"input")?_t(u):typeof u.getElementsByTagName!="undefined"&&v.grep(u.getElementsByTagName("input"),_t);if(n){m=function(e){if(!e.type||xt.test(e.type))return r?r.push(e.parentNode?e.parentNode.removeChild(e):e):n.appendChild(e)};for(s=0;(u=b[s])!=null;s++)if(!v.nodeName(u,"script")||!m(u))n.appendChild(u),typeof u.getElementsByTagName!="undefined"&&(g=v.grep(v.merge([],u.getElementsByTagName("script")),m),b.splice.apply(b,[s+1,0].concat(g)),s+=g.length)}return b},cleanData:function(e,t){var n,r,i,s,o=0,u=v.expando,a=v.cache,f=v.support.deleteExpando,l=v.event.special;for(;(i=e[o])!=null;o++)if(t||v.acceptData(i)){r=i[u],n=r&&a[r];if(n){if(n.events)for(s in n.events)l[s]?v.event.remove(i,s):v.removeEvent(i,s,n.handle);a[r]&&(delete a[r],f?delete i[u]:i.removeAttribute?i.removeAttribute(u):i[u]=null,v.deletedIds.push(r))}}}}),function(){var e,t;v.uaMatch=function(e){e=e.toLowerCase();var t=/(chrome)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+)/.exec(e)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(e)||/(msie) ([\w.]+)/.exec(e)||e.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(e)||[];return{browser:t[1]||"",version:t[2]||"0"}},e=v.uaMatch(o.userAgent),t={},e.browser&&(t[e.browser]=!0,t.version=e.version),t.chrome?t.webkit=!0:t.webkit&&(t.safari=!0),v.browser=t,v.sub=function(){function e(t,n){return new e.fn.init(t,n)}v.extend(!0,e,this),e.superclass=this,e.fn=e.prototype=this(),e.fn.constructor=e,e.sub=this.sub,e.fn.init=function(r,i){return i&&i instanceof v&&!(i instanceof e)&&(i=e(i)),v.fn.init.call(this,r,i,t)},e.fn.init.prototype=e.fn;var t=e(i);return e}}();var Dt,Pt,Ht,Bt=/alpha\([^)]*\)/i,jt=/opacity=([^)]*)/,Ft=/^(top|right|bottom|left)$/,It=/^(none|table(?!-c[ea]).+)/,qt=/^margin/,Rt=new RegExp("^("+m+")(.*)$","i"),Ut=new RegExp("^("+m+")(?!px)[a-z%]+$","i"),zt=new RegExp("^([-+])=("+m+")","i"),Wt={BODY:"block"},Xt={position:"absolute",visibility:"hidden",display:"block"},Vt={letterSpacing:0,fontWeight:400},$t=["Top","Right","Bottom","Left"],Jt=["Webkit","O","Moz","ms"],Kt=v.fn.toggle;v.fn.extend({css:function(e,n){return v.access(this,function(e,n,r){return r!==t?v.style(e,n,r):v.css(e,n)},e,n,arguments.length>1)},show:function(){return Yt(this,!0)},hide:function(){return Yt(this)},toggle:function(e,t){var n=typeof e=="boolean";return v.isFunction(e)&&v.isFunction(t)?Kt.apply(this,arguments):this.each(function(){(n?e:Gt(this))?v(this).show():v(this).hide()})}}),v.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Dt(e,"opacity");return n===""?"1":n}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":v.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(!e||e.nodeType===3||e.nodeType===8||!e.style)return;var s,o,u,a=v.camelCase(n),f=e.style;n=v.cssProps[a]||(v.cssProps[a]=Qt(f,a)),u=v.cssHooks[n]||v.cssHooks[a];if(r===t)return u&&"get"in u&&(s=u.get(e,!1,i))!==t?s:f[n];o=typeof r,o==="string"&&(s=zt.exec(r))&&(r=(s[1]+1)*s[2]+parseFloat(v.css(e,n)),o="number");if(r==null||o==="number"&&isNaN(r))return;o==="number"&&!v.cssNumber[a]&&(r+="px");if(!u||!("set"in u)||(r=u.set(e,r,i))!==t)try{f[n]=r}catch(l){}},css:function(e,n,r,i){var s,o,u,a=v.camelCase(n);return n=v.cssProps[a]||(v.cssProps[a]=Qt(e.style,a)),u=v.cssHooks[n]||v.cssHooks[a],u&&"get"in u&&(s=u.get(e,!0,i)),s===t&&(s=Dt(e,n)),s==="normal"&&n in Vt&&(s=Vt[n]),r||i!==t?(o=parseFloat(s),r||v.isNumeric(o)?o||0:s):s},swap:function(e,t,n){var r,i,s={};for(i in t)s[i]=e.style[i],e.style[i]=t[i];r=n.call(e);for(i in t)e.style[i]=s[i];return r}}),e.getComputedStyle?Dt=function(t,n){var r,i,s,o,u=e.getComputedStyle(t,null),a=t.style;return u&&(r=u.getPropertyValue(n)||u[n],r===""&&!v.contains(t.ownerDocument,t)&&(r=v.style(t,n)),Ut.test(r)&&qt.test(n)&&(i=a.width,s=a.minWidth,o=a.maxWidth,a.minWidth=a.maxWidth=a.width=r,r=u.width,a.width=i,a.minWidth=s,a.maxWidth=o)),r}:i.documentElement.currentStyle&&(Dt=function(e,t){var n,r,i=e.currentStyle&&e.currentStyle[t],s=e.style;return i==null&&s&&s[t]&&(i=s[t]),Ut.test(i)&&!Ft.test(t)&&(n=s.left,r=e.runtimeStyle&&e.runtimeStyle.left,r&&(e.runtimeStyle.left=e.currentStyle.left),s.left=t==="fontSize"?"1em":i,i=s.pixelLeft+"px",s.left=n,r&&(e.runtimeStyle.left=r)),i===""?"auto":i}),v.each(["height","width"],function(e,t){v.cssHooks[t]={get:function(e,n,r){if(n)return e.offsetWidth===0&&It.test(Dt(e,"display"))?v.swap(e,Xt,function(){return tn(e,t,r)}):tn(e,t,r)},set:function(e,n,r){return Zt(e,n,r?en(e,t,r,v.support.boxSizing&&v.css(e,"boxSizing")==="border-box"):0)}}}),v.support.opacity||(v.cssHooks.opacity={get:function(e,t){return jt.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=v.isNumeric(t)?"alpha(opacity="+t*100+")":"",s=r&&r.filter||n.filter||"";n.zoom=1;if(t>=1&&v.trim(s.replace(Bt,""))===""&&n.removeAttribute){n.removeAttribute("filter");if(r&&!r.filter)return}n.filter=Bt.test(s)?s.replace(Bt,i):s+" "+i}}),v(function(){v.support.reliableMarginRight||(v.cssHooks.marginRight={get:function(e,t){return v.swap(e,{display:"inline-block"},function(){if(t)return Dt(e,"marginRight")})}}),!v.support.pixelPosition&&v.fn.position&&v.each(["top","left"],function(e,t){v.cssHooks[t]={get:function(e,n){if(n){var r=Dt(e,t);return Ut.test(r)?v(e).position()[t]+"px":r}}}})}),v.expr&&v.expr.filters&&(v.expr.filters.hidden=function(e){return e.offsetWidth===0&&e.offsetHeight===0||!v.support.reliableHiddenOffsets&&(e.style&&e.style.display||Dt(e,"display"))==="none"},v.expr.filters.visible=function(e){return!v.expr.filters.hidden(e)}),v.each({margin:"",padding:"",border:"Width"},function(e,t){v.cssHooks[e+t]={expand:function(n){var r,i=typeof n=="string"?n.split(" "):[n],s={};for(r=0;r<4;r++)s[e+$t[r]+t]=i[r]||i[r-2]||i[0];return s}},qt.test(e)||(v.cssHooks[e+t].set=Zt)});var rn=/%20/g,sn=/\[\]$/,on=/\r?\n/g,un=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,an=/^(?:select|textarea)/i;v.fn.extend({serialize:function(){return v.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?v.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||an.test(this.nodeName)||un.test(this.type))}).map(function(e,t){var n=v(this).val();return n==null?null:v.isArray(n)?v.map(n,function(e,n){return{name:t.name,value:e.replace(on,"\r\n")}}):{name:t.name,value:n.replace(on,"\r\n")}}).get()}}),v.param=function(e,n){var r,i=[],s=function(e,t){t=v.isFunction(t)?t():t==null?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};n===t&&(n=v.ajaxSettings&&v.ajaxSettings.traditional);if(v.isArray(e)||e.jquery&&!v.isPlainObject(e))v.each(e,function(){s(this.name,this.value)});else for(r in e)fn(r,e[r],n,s);return i.join("&").replace(rn,"+")};var ln,cn,hn=/#.*$/,pn=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,dn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,vn=/^(?:GET|HEAD)$/,mn=/^\/\//,gn=/\?/,yn=/)<[^<]*)*<\/script>/gi,bn=/([?&])_=[^&]*/,wn=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,En=v.fn.load,Sn={},xn={},Tn=["*/"]+["*"];try{cn=s.href}catch(Nn){cn=i.createElement("a"),cn.href="",cn=cn.href}ln=wn.exec(cn.toLowerCase())||[],v.fn.load=function(e,n,r){if(typeof e!="string"&&En)return En.apply(this,arguments);if(!this.length)return this;var i,s,o,u=this,a=e.indexOf(" ");return a>=0&&(i=e.slice(a,e.length),e=e.slice(0,a)),v.isFunction(n)?(r=n,n=t):n&&typeof n=="object"&&(s="POST"),v.ajax({url:e,type:s,dataType:"html",data:n,complete:function(e,t){r&&u.each(r,o||[e.responseText,t,e])}}).done(function(e){o=arguments,u.html(i?v("
").append(e.replace(yn,"")).find(i):e)}),this},v.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,t){v.fn[t]=function(e){return this.on(t,e)}}),v.each(["get","post"],function(e,n){v[n]=function(e,r,i,s){return v.isFunction(r)&&(s=s||i,i=r,r=t),v.ajax({type:n,url:e,data:r,success:i,dataType:s})}}),v.extend({getScript:function(e,n){return v.get(e,t,n,"script")},getJSON:function(e,t,n){return v.get(e,t,n,"json")},ajaxSetup:function(e,t){return t?Ln(e,v.ajaxSettings):(t=e,e=v.ajaxSettings),Ln(e,t),e},ajaxSettings:{url:cn,isLocal:dn.test(ln[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":Tn},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":v.parseJSON,"text xml":v.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:Cn(Sn),ajaxTransport:Cn(xn),ajax:function(e,n){function T(e,n,s,a){var l,y,b,w,S,T=n;if(E===2)return;E=2,u&&clearTimeout(u),o=t,i=a||"",x.readyState=e>0?4:0,s&&(w=An(c,x,s));if(e>=200&&e<300||e===304)c.ifModified&&(S=x.getResponseHeader("Last-Modified"),S&&(v.lastModified[r]=S),S=x.getResponseHeader("Etag"),S&&(v.etag[r]=S)),e===304?(T="notmodified",l=!0):(l=On(c,w),T=l.state,y=l.data,b=l.error,l=!b);else{b=T;if(!T||e)T="error",e<0&&(e=0)}x.status=e,x.statusText=(n||T)+"",l?d.resolveWith(h,[y,T,x]):d.rejectWith(h,[x,T,b]),x.statusCode(g),g=t,f&&p.trigger("ajax"+(l?"Success":"Error"),[x,c,l?y:b]),m.fireWith(h,[x,T]),f&&(p.trigger("ajaxComplete",[x,c]),--v.active||v.event.trigger("ajaxStop"))}typeof e=="object"&&(n=e,e=t),n=n||{};var r,i,s,o,u,a,f,l,c=v.ajaxSetup({},n),h=c.context||c,p=h!==c&&(h.nodeType||h instanceof v)?v(h):v.event,d=v.Deferred(),m=v.Callbacks("once memory"),g=c.statusCode||{},b={},w={},E=0,S="canceled",x={readyState:0,setRequestHeader:function(e,t){if(!E){var n=e.toLowerCase();e=w[n]=w[n]||e,b[e]=t}return this},getAllResponseHeaders:function(){return E===2?i:null},getResponseHeader:function(e){var n;if(E===2){if(!s){s={};while(n=pn.exec(i))s[n[1].toLowerCase()]=n[2]}n=s[e.toLowerCase()]}return n===t?null:n},overrideMimeType:function(e){return E||(c.mimeType=e),this},abort:function(e){return e=e||S,o&&o.abort(e),T(0,e),this}};d.promise(x),x.success=x.done,x.error=x.fail,x.complete=m.add,x.statusCode=function(e){if(e){var t;if(E<2)for(t in e)g[t]=[g[t],e[t]];else t=e[x.status],x.always(t)}return this},c.url=((e||c.url)+"").replace(hn,"").replace(mn,ln[1]+"//"),c.dataTypes=v.trim(c.dataType||"*").toLowerCase().split(y),c.crossDomain==null&&(a=wn.exec(c.url.toLowerCase()),c.crossDomain=!(!a||a[1]===ln[1]&&a[2]===ln[2]&&(a[3]||(a[1]==="http:"?80:443))==(ln[3]||(ln[1]==="http:"?80:443)))),c.data&&c.processData&&typeof c.data!="string"&&(c.data=v.param(c.data,c.traditional)),kn(Sn,c,n,x);if(E===2)return x;f=c.global,c.type=c.type.toUpperCase(),c.hasContent=!vn.test(c.type),f&&v.active++===0&&v.event.trigger("ajaxStart");if(!c.hasContent){c.data&&(c.url+=(gn.test(c.url)?"&":"?")+c.data,delete c.data),r=c.url;if(c.cache===!1){var N=v.now(),C=c.url.replace(bn,"$1_="+N);c.url=C+(C===c.url?(gn.test(c.url)?"&":"?")+"_="+N:"")}}(c.data&&c.hasContent&&c.contentType!==!1||n.contentType)&&x.setRequestHeader("Content-Type",c.contentType),c.ifModified&&(r=r||c.url,v.lastModified[r]&&x.setRequestHeader("If-Modified-Since",v.lastModified[r]),v.etag[r]&&x.setRequestHeader("If-None-Match",v.etag[r])),x.setRequestHeader("Accept",c.dataTypes[0]&&c.accepts[c.dataTypes[0]]?c.accepts[c.dataTypes[0]]+(c.dataTypes[0]!=="*"?", "+Tn+"; q=0.01":""):c.accepts["*"]);for(l in c.headers)x.setRequestHeader(l,c.headers[l]);if(!c.beforeSend||c.beforeSend.call(h,x,c)!==!1&&E!==2){S="abort";for(l in{success:1,error:1,complete:1})x[l](c[l]);o=kn(xn,c,n,x);if(!o)T(-1,"No Transport");else{x.readyState=1,f&&p.trigger("ajaxSend",[x,c]),c.async&&c.timeout>0&&(u=setTimeout(function(){x.abort("timeout")},c.timeout));try{E=1,o.send(b,T)}catch(k){if(!(E<2))throw k;T(-1,k)}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var Mn=[],_n=/\?/,Dn=/(=)\?(?=&|$)|\?\?/,Pn=v.now();v.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Mn.pop()||v.expando+"_"+Pn++;return this[e]=!0,e}}),v.ajaxPrefilter("json jsonp",function(n,r,i){var s,o,u,a=n.data,f=n.url,l=n.jsonp!==!1,c=l&&Dn.test(f),h=l&&!c&&typeof a=="string"&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Dn.test(a);if(n.dataTypes[0]==="jsonp"||c||h)return s=n.jsonpCallback=v.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,o=e[s],c?n.url=f.replace(Dn,"$1"+s):h?n.data=a.replace(Dn,"$1"+s):l&&(n.url+=(_n.test(f)?"&":"?")+n.jsonp+"="+s),n.converters["script json"]=function(){return u||v.error(s+" was not called"),u[0]},n.dataTypes[0]="json",e[s]=function(){u=arguments},i.always(function(){e[s]=o,n[s]&&(n.jsonpCallback=r.jsonpCallback,Mn.push(s)),u&&v.isFunction(o)&&o(u[0]),u=o=t}),"script"}),v.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(e){return v.globalEval(e),e}}}),v.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),v.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=i.head||i.getElementsByTagName("head")[0]||i.documentElement;return{send:function(s,o){n=i.createElement("script"),n.async="async",e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,i){if(i||!n.readyState||/loaded|complete/.test(n.readyState))n.onload=n.onreadystatechange=null,r&&n.parentNode&&r.removeChild(n),n=t,i||o(200,"success")},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(0,1)}}}});var Hn,Bn=e.ActiveXObject?function(){for(var e in Hn)Hn[e](0,1)}:!1,jn=0;v.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&Fn()||In()}:Fn,function(e){v.extend(v.support,{ajax:!!e,cors:!!e&&"withCredentials"in e})}(v.ajaxSettings.xhr()),v.support.ajax&&v.ajaxTransport(function(n){if(!n.crossDomain||v.support.cors){var r;return{send:function(i,s){var o,u,a=n.xhr();n.username?a.open(n.type,n.url,n.async,n.username,n.password):a.open(n.type,n.url,n.async);if(n.xhrFields)for(u in n.xhrFields)a[u]=n.xhrFields[u];n.mimeType&&a.overrideMimeType&&a.overrideMimeType(n.mimeType),!n.crossDomain&&!i["X-Requested-With"]&&(i["X-Requested-With"]="XMLHttpRequest");try{for(u in i)a.setRequestHeader(u,i[u])}catch(f){}a.send(n.hasContent&&n.data||null),r=function(e,i){var u,f,l,c,h;try{if(r&&(i||a.readyState===4)){r=t,o&&(a.onreadystatechange=v.noop,Bn&&delete Hn[o]);if(i)a.readyState!==4&&a.abort();else{u=a.status,l=a.getAllResponseHeaders(),c={},h=a.responseXML,h&&h.documentElement&&(c.xml=h);try{c.text=a.responseText}catch(p){}try{f=a.statusText}catch(p){f=""}!u&&n.isLocal&&!n.crossDomain?u=c.text?200:404:u===1223&&(u=204)}}}catch(d){i||s(-1,d)}c&&s(u,f,c,l)},n.async?a.readyState===4?setTimeout(r,0):(o=++jn,Bn&&(Hn||(Hn={},v(e).unload(Bn)),Hn[o]=r),a.onreadystatechange=r):r()},abort:function(){r&&r(0,1)}}}});var qn,Rn,Un=/^(?:toggle|show|hide)$/,zn=new RegExp("^(?:([-+])=|)("+m+")([a-z%]*)$","i"),Wn=/queueHooks$/,Xn=[Gn],Vn={"*":[function(e,t){var n,r,i=this.createTween(e,t),s=zn.exec(t),o=i.cur(),u=+o||0,a=1,f=20;if(s){n=+s[2],r=s[3]||(v.cssNumber[e]?"":"px");if(r!=="px"&&u){u=v.css(i.elem,e,!0)||n||1;do a=a||".5",u/=a,v.style(i.elem,e,u+r);while(a!==(a=i.cur()/o)&&a!==1&&--f)}i.unit=r,i.start=u,i.end=s[1]?u+(s[1]+1)*n:n}return i}]};v.Animation=v.extend(Kn,{tweener:function(e,t){v.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;r-1,f={},l={},c,h;a?(l=i.position(),c=l.top,h=l.left):(c=parseFloat(o)||0,h=parseFloat(u)||0),v.isFunction(t)&&(t=t.call(e,n,s)),t.top!=null&&(f.top=t.top-s.top+c),t.left!=null&&(f.left=t.left-s.left+h),"using"in t?t.using.call(e,f):i.css(f)}},v.fn.extend({position:function(){if(!this[0])return;var e=this[0],t=this.offsetParent(),n=this.offset(),r=er.test(t[0].nodeName)?{top:0,left:0}:t.offset();return n.top-=parseFloat(v.css(e,"marginTop"))||0,n.left-=parseFloat(v.css(e,"marginLeft"))||0,r.top+=parseFloat(v.css(t[0],"borderTopWidth"))||0,r.left+=parseFloat(v.css(t[0],"borderLeftWidth"))||0,{top:n.top-r.top,left:n.left-r.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||i.body;while(e&&!er.test(e.nodeName)&&v.css(e,"position")==="static")e=e.offsetParent;return e||i.body})}}),v.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);v.fn[e]=function(i){return v.access(this,function(e,i,s){var o=tr(e);if(s===t)return o?n in o?o[n]:o.document.documentElement[i]:e[i];o?o.scrollTo(r?v(o).scrollLeft():s,r?s:v(o).scrollTop()):e[i]=s},e,i,arguments.length,null)}}),v.each({Height:"height",Width:"width"},function(e,n){v.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){v.fn[i]=function(i,s){var o=arguments.length&&(r||typeof i!="boolean"),u=r||(i===!0||s===!0?"margin":"border");return v.access(this,function(n,r,i){var s;return v.isWindow(n)?n.document.documentElement["client"+e]:n.nodeType===9?(s=n.documentElement,Math.max(n.body["scroll"+e],s["scroll"+e],n.body["offset"+e],s["offset"+e],s["client"+e])):i===t?v.css(n,r,i,u):v.style(n,r,i,u)},n,o?i:t,o,null)}})}),e.jQuery=e.$=v,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return v})})(window); \ No newline at end of file diff --git a/frontend-masters-exercises/exercises/ex9/README.md b/frontend-masters-exercises/exercises/ex9/README.md new file mode 100755 index 0000000..33c7284 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex9/README.md @@ -0,0 +1,9 @@ +# Instructions + +1. In this exercise, we're going to practice with CSP channel concurrency using asynquence. + +2. Monitor the stream of click events from the button and publish them to a channel if the channel is ready for a message. Hint: `ASQ.csp.putAsync(..)`, which returns a promise + +3. Set up go-routine that samples the channel from (2) once per second. In other words, if you click the button multiple times in a second, you only get one channel message. Hint: `ASQ.csp.take( ASQ.csp.timeout(..) )` + +4. The sampled channel go-routine should add a "clicked!" message to the list. diff --git a/frontend-masters-exercises/exercises/ex9/asq.bundle-es5.js b/frontend-masters-exercises/exercises/ex9/asq.bundle-es5.js new file mode 100755 index 0000000..08c503a --- /dev/null +++ b/frontend-masters-exercises/exercises/ex9/asq.bundle-es5.js @@ -0,0 +1,10 @@ +/*! asynquence + v0.8.2 (c) Kyle Simpson + MIT License: http://getify.mit-license.org +*/ +!function UMD(e,n,t){"function"==typeof define&&define.amd?define(t):"undefined"!=typeof module&&module.exports?module.exports=t():n[e]=t(e,n)}("ASQ",this,function DEF(e,n){"use strict";function Queue(){function Item(e){this.fn=e,this.next=void 0}var e,n,r;return{add:function $$add(t){r=new Item(t),n?n.next=r:e=r,n=r,r=void 0},drain:function $$drain(){var r=e;for(e=n=t=null;r;)r.fn(),r=r.next}}}function schedule(e){r.add(e),t||(t=u(r.drain))}function tapSequence(e){function trigger(){e.seq=createSequence.apply(h,arguments).defer()}trigger.fail=function $$trigger$fail(){var n=f.call(arguments);e.seq=createSequence(function $$create$sequence(e){e.fail.apply(h,n)}).defer()},e.seq.val(function $$val(){return trigger.apply(h,arguments),c.apply(h,arguments)}).or(function $$or(){trigger.fail.apply(h,arguments)}),e.seq=createSequence(function $$create$sequence(e){trigger=e}).defer()}function createSequence(){function scheduleSequenceTick(){r?sequenceTick():e||(e=schedule(sequenceTick))}function throwSequenceErrors(){throw 1===$.length?$[0]:$}function sequenceTick(){var a,c;if(e=null,delete d.unpause,r)clearTimeout(e),e=null,s.length=p.length=g.length=$.length=0;else if(n)for(0!==p.length||t||(t=!0,throwSequenceErrors());p.length;){t=!0,a=p.shift();try{a.apply(h,$)}catch(i){l(i)?$=$.concat(i):($.push(i),i.stack&&$.push(i.stack)),0===p.length&&throwSequenceErrors()}}else if(u&&s.length>0){u=!1,a=s.shift(),c=g.slice(),g.length=0,c.unshift(createStepCompletion());try{a.apply(h,c)}catch(i){l(i)?$=$.concat(i):$.push(i),n=!0,scheduleSequenceTick()}}}function createStepCompletion(){function done(){n||r||u||(u=!0,g.push.apply(g,arguments),$.length=0,scheduleSequenceTick())}return done.fail=function $$step$fail(){n||r||u||(n=!0,g.length=0,$.push.apply($,arguments),scheduleSequenceTick())},done.abort=function $$step$abort(){n||r||(u=!1,r=!0,g.length=$.length=0,scheduleSequenceTick())},done.errfcb=function $$step$errfcb(e){e?done.fail(e):done.apply(h,f.call(arguments,1))},done}function createGate(e,t,u){function resetGate(){clearTimeout(s),s=d=m=o=null}function scheduleGateTick(){return g?gateTick():void(s||(s=schedule(gateTick)))}function gateTick(){if(!(n||r||$)){var t=[];s=null,p?(e.fail.apply(h,o),resetGate()):g?(e.abort(),resetGate()):checkGate()&&($=!0,d.forEach(function $$each(e,n){t.push(m["s"+n])}),e.apply(h,t),resetGate())}}function checkGate(){if(0!==d.length){var e=!0;return d.some(function $$some(n){return null===n?(e=!1,!0):void 0}),e}}function createSegmentCompletion(){function done(){if(!(n||r||p||g||$||d[e])){var t=c.apply(h,arguments);m["s"+e]=t.length>1?t:t[0],d[e]=!0,scheduleGateTick()}}var e=d.length;return done.fail=function $$segment$fail(){n||r||p||g||$||d[e]||(p=!0,o=f.call(arguments),scheduleGateTick())},done.abort=function $$segment$abort(){n||r||p||g||$||(g=!0,gateTick())},done.errfcb=function $$segment$errfcb(e){e?done.fail(e):done.apply(h,f.call(arguments,1))},d[e]=null,done}var a,i,o,s,p=!1,g=!1,$=!1,d=[],m={};t.some(function $$some(e){if(p||g)return!0;a=u.slice(),a.unshift(createSegmentCompletion());try{e.apply(h,a)}catch(n){return i=n,p=!0,!0}}),i&&(l(i)?e.fail.apply(h,i):e.fail(i))}function then(){return n||r||0===arguments.length?d:(wrapArgs(arguments,thenWrapper).forEach(function $$each(e){i(e)?seq(e):s.push(e)}),scheduleSequenceTick(),d)}function or(){return r||0===arguments.length?d:(p.push.apply(p,arguments),scheduleSequenceTick(),d)}function gate(){if(n||r||0===arguments.length)return d;var e=f.call(arguments).map(function $$map(e){var n;return i(e)?(n={seq:e},tapSequence(n),function $$segment(e){n.seq.pipe(e)}):e});return then(function $$then(n){var t=f.call(arguments,1);createGate(n,e,t)}),d}function pipe(){return r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){then(function $$then(n){e.apply(h,f.call(arguments,1)),n()}).or(e.fail)}),d)}function seq(){return n||r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){var n={seq:e};i(e)&&tapSequence(n),then(function $$then(e){var t=n.seq;i(t)||(t=n.seq.apply(h,f.call(arguments,1))),t.pipe(e)})}),d)}function val(){return n||r||0===arguments.length?d:(f.call(wrapArgs(arguments,valWrapper)).forEach(function $$each(e){then(function $$then(n){var t=e.apply(h,f.call(arguments,1));l(t)||(t=c(t)),n.apply(h,t)})}),d)}function promise(){function wrap(e){return function $$fn(){e.apply(h,l(arguments[0])?arguments[0]:arguments)}}return n||r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){then(function $$then(n){var t=e;"function"==typeof e&&"function"!=typeof e.then&&(t=e.apply(h,f.call(arguments,1))),t.then(wrap(n),wrap(n.fail))})}),d)}function fork(){var e;return val(function $$val(){return e?e.apply(h,arguments):e=createSequence.apply(h,arguments).defer(),c.apply(h,arguments)}),or(function $$or(){if(e)e.fail.apply(h,arguments);else{var n=f.call(arguments);e=createSequence().then(function $$then(e){e.fail.apply(h,n)}).defer()}}),createSequence().then(function $$then(n){e?e.pipe(n):e=n}).defer()}function abort(){return n?d:(r=!0,sequenceTick(),d)}function duplicate(){var e;return a={then_queue:s.slice(),or_queue:p.slice()},e=createSequence(),a=null,e}function unpause(){g.push.apply(g,arguments),e===!0&&(e=null),scheduleSequenceTick()}function defer(){return p.push(function ignored(){}),d}function internals(e,t){var a=arguments.length>1;switch(e){case"seq_error":if(!a)return n;n=t;break;case"seq_aborted":if(!a)return r;r=t;break;case"then_ready":if(!a)return u;u=t;break;case"then_queue":return s;case"or_queue":return p;case"sequence_messages":return g;case"sequence_errors":return $}}function includeExtensions(){Object.keys(o).forEach(function $$each(e){d[e]=o[e](d,internals)})}var e,n=!1,t=!1,r=!1,u=!0,s=[],p=[],g=[],$=[],d=brandIt({then:then,or:or,onerror:or,gate:gate,all:gate,pipe:pipe,seq:seq,val:val,promise:promise,fork:fork,abort:abort,duplicate:duplicate,defer:defer});return includeExtensions(),a&&(s=a.then_queue.slice(),p=a.or_queue.slice(),d.unpause=unpause,e=!0),d.then.apply(h,arguments),d}function brandIt(e){return Object.defineProperty(e,p,{enumerable:!1,value:!0})}function checkBranding(e){return!(null==e||"object"!=typeof e||!e[p])}function valWrapper(e){return c.apply(h,f.call(arguments).slice(1,e+1))}function thenWrapper(e){arguments[e+1].apply(h,f.call(arguments).slice(1,e+1))}function wrapArgs(e,n){var t,r;for(e=f.call(e),t=0;t1?n.call(arguments,1):void 0;return r=+r||0,e.then(function $$then(e){var u=a||n.call(arguments,1);setTimeout(function $$set$timeout(){e.apply(t,u)},r)}),e}}),e.after=function $$after(){return e().after.apply(t,arguments)},e.extend("any",function $$extend(r,a){return function $$any(){if(a("seq_error")||a("seq_aborted")||0===arguments.length)return r;var u=n.call(arguments);return r.then(function $$then(r){function reset(){c=!0,l.length=0,s.length=0}function complete(e){s.length>0?(s.length=u.length,e.apply(t,s)):(l.length=u.length,e.fail.apply(t,l)),reset()}function success(n,r,l){c||(a++,s[r]=l.length>1?e.messages.apply(t,l):l[0],a===u.length&&(c=!0,complete(n)))}function failure(n,r,s){c||r in l||(a++,l[r]=s.length>1?e.messages.apply(t,s):s[0]),c||a!==u.length||(c=!0,complete(n))}var a=0,l=[],c=!1,s=[],o=e.apply(t,n.call(arguments,1));wrapGate(o,u,success,failure,reset),o.pipe(r)}),r}}),e.extend("errfcb",function $$extend(e,a){return function $$errfcb(){var a={val:function $$then(e){return a.val_cb=e,a},or:function $$or(e){return a.or_cb=e,a}};return a[r]=!0,e.seq(a),function $$errorfirst$callback(e){e?a.or_cb(e):a.val_cb.apply(t,n.call(arguments,1))}}}),e.extend("failAfter",function $$extend(e,r){return function $$failAfter(r){var a=arguments.length>1?n.call(arguments,1):void 0;return r=+r||0,e.then(function $$then(e){setTimeout(function $$set$timeout(){e.fail.apply(t,a)},r)}),e}}),e.failAfter=function $$fail$after(){return e().failAfter.apply(t,arguments)},e.extend("first",function $$extend(r,a){return function $$first(){if(a("seq_error")||a("seq_aborted")||0===arguments.length)return r;var u=n.call(arguments);return r.then(function $$then(r){function reset(){l.length=0}function success(n,r,a){c||(c=!0,n(a.length>1?e.messages.apply(t,a):a[0]),reset())}function failure(n,r,s){c||r in l||(a++,l[r]=s.length>1?e.messages.apply(t,s):s[0],a===u.length&&(c=!0,l.length=u.length,n.fail.apply(t,l),reset()))}var a=0,l=[],c=!1,s=e.apply(t,n.call(arguments,1));wrapGate(s,u,success,failure,reset),s.pipe(r)}),r}}),function IIFE(){function filterResolved(e){return e.filter(function $$filter(e){return!e.resolved})}function closeQueue(e,n){e.forEach(function $$each(e){e.resolved||(e.next(),e.next(n))}),e.length=0}function channel(n){var t={close:function $$close(){t.closed=!0,closeQueue(t.put_queue,!1),closeQueue(t.take_queue,e.csp.CLOSED)},closed:!1,messages:[],put_queue:[],take_queue:[],buffer_size:+n||0};return t}function unblock(e){e&&!e.resolved&&e.next(e.next().value)}function put(n,t){var r;return n.closed?!1:(n.put_queue=filterResolved(n.put_queue),n.take_queue=filterResolved(n.take_queue),n.messages.length0&&(unblock(n.put_queue.shift()),unblock(n.take_queue.shift())),r))}function putAsync(n,t,r){var a=e(put(n,t));return r&&"function"==typeof r?void a.val(r):a}function take(n){var t;try{t=takem(n)}catch(r){t=r}return e.isSequence(t)&&t.pCatch(function $$pcatch(e){return e}),t}function takeAsync(n,t){var r=e(take(n));return t&&"function"==typeof t?void r.val(t):r}function takem(n){var t;if(n.closed)return e.csp.CLOSED;if(n.put_queue=filterResolved(n.put_queue),n.take_queue=filterResolved(n.take_queue),n.messages.length>0){if(t=n.messages.shift(),unblock(n.put_queue.shift()),t instanceof Error)throw t;return t}return n.take_queue.push(e.iterable().then(function $$then(){if(n.closed)return e.csp.CLOSED;var t=n.messages.shift();if(t instanceof Error)throw t;return t})),t=e(n.take_queue[n.take_queue.length-1]),n.put_queue.length>0&&(unblock(n.put_queue.shift()),unblock(n.take_queue.shift())),t}function takemAsync(n,t){var r=e(takem(n));return t&&"function"==typeof t?void r.pThen(t,t):r.val(function $$val(e){if(e instanceof Error)throw e;return e})}function alts(n){var t,r,u,l,c,s,o=!1;if(!Array.isArray(n)||0==n.length)throw Error("Invalid usage");if(t=[],r=[],u=[],n.forEach(function $$each(e){var n=Array.isArray(e)?e[0]:e;n.put_queue=filterResolved(n.put_queue),n.take_queue=filterResolved(n.take_queue),n.closed?t.push(n):r.push(e)}),0==r.length)return{value:e.csp.CLOSED,channel:t};for(l=0;l0)return{value:take(r[l]),channel:r[l]};c=e.iterable();var s=e(c);for(l=0;l0&&a(function handleUnblocking(){o||(unblock(t.put_queue.shift()),unblock(t.take_queue.shift()))},0)):(t=n,u.push(e.iterable().then(function $$then(){o=!0,u=u.filter(function $$filter(e){return!(e.resolved=!0)}),t.closed?c.next({value:e.csp.CLOSED,channel:t}):c.next({value:t.messages.shift(),channel:t})})),t.take_queue.push(u[u.length-1]),t.put_queue.length>0&&a(function handleUnblocking(){o||(unblock(t.put_queue.shift()),unblock(t.take_queue.shift()))}))}(r[l]);return s}function altsAsync(n,t){var r=e(alts(n));return t&&"function"==typeof t?void r.pThen(t,t):r}function timeout(e){var n=channel();return setTimeout(n.close,e),n}function go(n,r){return arguments.length>1?r&&Array.isArray(r)||(r=[r]):r=[],regeneratorRuntime.mark(function $$go(a){var u,l,c,s,o,i,f;return regeneratorRuntime.wrap(function $$go$(p){for(;;)switch(p.prev=p.next){case 0:u=function unblock(){a.unblock_count++,a.block&&!a.block.marked&&(a.block.marked=!0,a.block.next())},i=!1,a.unblock_count=a.unblock_count||0,a.go_count=(a.go_count||0)+1,1===a.go_count&&(a.channel=channel(),a.channel.messages=a.messages,a.channel.go=function $$go(){u(),a.add(go.apply(t,arguments))},a.channel.messages.length>0&&(a.channel.put_queue=a.channel.messages.map(function $$map(){return e.iterable().then(function $$then(){return u(a.channel.take_queue.shift()),!a.channel.closed})}))),f=n.apply(t,[a.channel].concat(r)),function iterate(){function next(){i?u():iterate()}if(!l){try{s?(l=f["throw"](s),s=null):l=f.next(c)}catch(n){return i=!0,s=n,c=null,void u()}i=l.done,l=l.value,o=typeof l,i&&u(),isPromise(l)&&(l=e().promise(l)),e.isSequence(l)?l.val(function $$val(){l=null,c=arguments.length>1?e.messages.apply(t,arguments):arguments[0],next()}).or(function $$or(){l=null,c=arguments.length>1?e.messages.apply(t,arguments):arguments[0],c instanceof Error&&(s=c,c=null),next()}):(c=l,l=null,next())}}();case 7:if(i){p.next=17;break}return p.next=10,a;case 10:if(i||a.block||0!==a.unblock_count){p.next=14;break}return p.next=13,a.block=e.iterable();case 13:a.block=!1;case 14:a.unblock_count>0&&a.unblock_count--,p.next=7;break;case 17:if(a.go_count--,0===a.go_count&&(u(),c=e.messages.apply(t,a.messages),a.channel&&!a.channel.closed&&(a.channel.closed=!0,a.channel.put_queue.length=a.channel.take_queue.length=0,a.channel.close=a.channel.go=a.channel.messages=null),a.channel=null),!s){p.next=23;break}throw s;case 23:if(0!==a.go_count){p.next=27;break}return p.abrupt("return",c);case 27:return p.abrupt("return",a);case 28:case"end":return p.stop()}},$$go,this)})}e.csp={chan:channel,put:put,putAsync:putAsync,take:take,takeAsync:takeAsync,takem:takem,takemAsync:takemAsync,alts:alts,altsAsync:altsAsync,timeout:timeout,go:go,CLOSED:{}}}(),function IIFE(){var u;e.iterable=function $$iterable(){function throwSequenceErrors(){throw 1===$.length?$[0]:$}function notifyErrors(){var e;if(c=null,s)for(0!==p.length||o||(o=!0,throwSequenceErrors());p.length>0;){o=!0,e=p.shift();try{e.apply(t,$)}catch(n){checkBranding(n)?$=$.concat(n):$.push(n),0===p.length&&throwSequenceErrors()}}}function val(){if(s||i||0===arguments.length)return l;var e=n.call(arguments).map(function mapper(e){return"function"!=typeof e?function $$val(){return e}:e});return f.push.apply(f,e),l}function or(){return i||0===arguments.length?l:(p.push.apply(p,arguments),c||(c=a(notifyErrors)),l)}function pipe(){return i||0===arguments.length?l:(n.call(arguments).forEach(function $$each(e){val(e).or(e.fail)}),l)}function next(){if(s||i||0===f.length)return f.length>0&&$throw$("Sequence cannot be iterated"),{done:!0};try{return{value:f.shift().apply(t,arguments)}}catch(n){return e.isMessageWrapper(n)?$throw$.apply(t,n):$throw$(n),{}}}function $throw$(){return s||i?l:($.push.apply($,arguments),s=!0,c||(c=a(notifyErrors)),l)}function $return$(e){return(s||i)&&(e=void 0),abort(),{done:!0,value:e}}function abort(){s||i||(i=!0,clearTimeout(c),c=null,f.length=p.length=$.length=0)}function duplicate(){var n;return u={val_queue:f.slice(),or_queue:p.slice()},n=e.iterable(),u=null,n}function defer(){return p.push(function $$ignored(){}),l}function brandIt(e){return Object.defineProperty(e,r,{enumerable:!1,value:!0}),e}var l,c,s=!1,o=!1,i=!1,f=[],p=[],$=[];return l=brandIt({val:val,then:val,or:or,pipe:pipe,next:next,"throw":$throw$,"return":$return$,abort:abort,duplicate:duplicate,defer:defer}),l["function"==typeof Symbol&&Symbol.iterator||"@@iterator"]=function $$iter(){return l},u&&(f=u.val_queue.slice(0),p=u.or_queue.slice(0)),l.val.apply(t,arguments),l}}(),e.extend("last",function $$extend(r,a){return function $$last(){if(a("seq_error")||a("seq_aborted")||0===arguments.length)return r;var u=n.call(arguments);return r.then(function $$then(r){function reset(){s=!0,c.length=0,a=null}function complete(n){null!=a?n(a.length>1?e.messages.apply(t,a):a[0]):(c.length=u.length,n.fail.apply(t,c)),reset()}function success(e,n,t){s||(l++,a=t,l===u.length&&(s=!0,complete(e)))}function failure(n,r,a){s||r in c||(l++,c[r]=a.length>1?e.messages.apply(t,a):a[0]),s||l!==u.length||(s=!0,complete(n))}var a,l=0,c=[],s=!1,o=e.apply(t,n.call(arguments,1));wrapGate(o,u,success,failure,reset),o.pipe(r)}),r}}),e.extend("map",function $$extend(r,a){return function $$map(u,l){return a("seq_error")||a("seq_aborted")?r:(r.seq(function $$seq(){var r,a=n.call(arguments),c=u,s=l;return s||(s=a.shift()),c||(c=a.shift()),"function"==typeof c&&Array.isArray(s)&&(r=c,c=s,s=r),e.apply(t,a).gate.apply(t,c.map(function $$map(e){return function $$segment(){s.apply(t,[e].concat(n.call(arguments)))}}))}).val(function $$val(){return n.call(arguments)}),r)}}),e.extend("none",function $$extend(r,a){return function $$none(){if(a("seq_error")||a("seq_aborted")||0===arguments.length)return r;var u=n.call(arguments);return r.then(function $$then(r){function reset(){c=!0,l.length=0,o.length=0}function complete(e){o.length>0?(o.length=u.length,e.fail.apply(t,o)):(l.length=u.length,e.apply(t,l)),reset()}function success(n,r,l){c||(a++,o[r]=l.length>1?e.messages.apply(t,l):l[0],a===u.length&&(c=!0,complete(n)))}function failure(n,r,s){c||r in l||(a++,l[r]=s.length>1?e.messages.apply(t,s):s[0]),c||a!==u.length||(c=!0,complete(n))}var a=0,l=[],c=!1,s=e.apply(t,n.call(arguments,1)),o=[];wrapGate(s,u,success,failure,reset),s.pipe(r)}),r}}),e.extend("pThen",function $$extend(r,u){return function $$pthen(l,c){if(u("seq_aborted"))return r;var s=!1,o=!1;return"function"==typeof l&&r.then(function $$then(r){if(s)r.apply(t,n.call(arguments,1));else{var a,u=e.messages.apply(t,arguments);u.shift(),1===u.length&&(u=u[0]),o=!0;try{a=l(u)}catch(c){return e.isMessageWrapper(c)||(c=[c]),void r.fail.apply(t,c)}e.isSequence(a)?a.pipe(r):e.isMessageWrapper(a)?r.apply(t,a):isPromise(a)?a.then(r,r.fail):r(a)}}),"function"==typeof c&&r.or(function $$or(){if(!o){var l,i,f=e.messages.apply(t,arguments),p=n.call(u("or_queue"));1===f.length&&(f=f[0]),s=!0,l=c(f),i=u("sequence_messages"),i.length=0,"undefined"!=typeof l&&(e.isMessageWrapper(l)||(l=[l]),i.push.apply(i,l)),u("sequence_errors").length=0,u("seq_error",!1),u("then_ready",!0),u("or_queue").length=0,r.val(function $$val(){return e.messages.apply(t,arguments)}),p.length>0&&a(function $$schedule(){r.or.apply(t,p)})}}),r}}),e.extend("pCatch",function $$extend(e,n){return function $$pcatch(t){return n("seq_aborted")?e:(e.pThen(void 0,t),e)}}),e.extend("race",function $$extend(r,a){return function $$race(){if(a("seq_error")||a("seq_aborted")||0===arguments.length)return r;var l=n.call(arguments).map(function $$map(n){var t;return e.isSequence(n)?(t={seq:n},u(t),function $$fn(e){t.seq.pipe(e)}):n});return r.then(function $$then(e){var r=n.call(arguments);l.forEach(function $$each(e){e.apply(t,r)})}),r}}),e.react=function $$react(r){function next(){if(!l){if(a){var n=a.duplicate();return n.unpause.apply(t,arguments),n}return e(function $$asq(){throw"Disabled Sequence"})}}function registerTeardown(e){a&&"function"==typeof e&&u.push(e)}var a=e().duplicate(),u=[],l=!1;return a.stop=function $$stop(){a&&(a=null,u.forEach(Function.call,Function.call),u.length=0)},a.pause=function $$pause(){!l&&a&&(l=!0,u.forEach(Function.call,Function.call),u.length=0)},a.resume=function $$resume(){l&&a&&(l=!1,r.call(a,next,registerTeardown))},a.push=next,next.onStream=function $$onStream(){n.call(arguments).forEach(function $$each(e){e.on("data",next),e.on("error",next)})},next.unStream=function $$unStream(){n.call(arguments).forEach(function $$each(e){e.removeListener("data",next),e.removeListener("error",next)})},e.__schedule(function $$schedule(){r.call(a,next,registerTeardown)}),a},function IIFE(){function tapSequences(){function tapSequence(a){function trigger(){var e=n.call(arguments);u.seq=r(function $$react(n){n.apply(t,e)})}if(e.isSequence(a)){var u={seq:a};return a.val(function $$val(){return trigger.apply(t,arguments),e.messages.apply(t,arguments)}),u.seq=r(function $$react(e){trigger=e}),u}}return n.call(arguments).map(tapSequence).filter(Boolean)}function makeReactOperator(n,a){return function $$react$operator(){function reactor(r,c){function processSequence(c){function trigger(){var c=e.messages.apply(t,arguments);if(l&&l.length>0){u[s]=(n?u[s]:[]).concat(c.length>0?c.length>1?[c]:c[0]:void 0);var o=u.reduce(function reducer(e,n,t){return n.length>0&&e.push(n[0]),e},[]);o.length==u.length&&(1==o.length&&(o=o[0]),r.apply(t,o),a||u.forEach(function $$each(e){e.shift()}))}return c}var s=u.length;u.push([]),c.seq.val(trigger)}l.forEach(processSequence),c(function $$teardown(){l=u=null})}var u=[],l=tapSequences.apply(null,arguments);if(0!=l.length)return r(reactor)}}function makeDistinctFilterer(n){function filterer(){function isDuplicate(e){return e.length==a.length&&e.every(function $$every(e,n){return e===a[n]})}var a=e.messages.apply(t,arguments);if(a.length>0){if(r.some(isDuplicate))return!1;n?r.push(a):r[0]=a}return!0}var r=[];return filterer}var r=e.react;r.of=function $$react$of(){function reactor(e){a||(a=!0,u.length>0&&u.shift().val(function val(){e.apply(t,arguments),u.length>0&&u.shift().val(val)}))}var a,u=n.call(arguments).map(function wrapper(n){return e.isSequence(n)||(n=e(n)),n});return r(reactor)},r.all=r.zip=makeReactOperator(!0),r.allLatest=makeReactOperator(),r.latest=r.combineLatest=makeReactOperator(!1,!0),r.any=r.merge=function $$react$any(){function reactor(r,a){function processSequence(a){function trigger(){var a=e.messages.apply(t,arguments);return n&&n.length>0&&r.apply(t,a),a}a.seq.val(trigger)}n.forEach(processSequence),a(function $$teardown(){n=null})}var n=tapSequences.apply(null,arguments);if(0!=n.length)return r(reactor)},r.distinct=function $$react$distinct(e){return r.filter(e,makeDistinctFilterer(!0))},r.distinctConsecutive=r.distinctUntilChanged=function $$react$distinct$consecutive(e){return r.filter(e,makeDistinctFilterer(!1))},r.filter=function $$react$filter(n,a){function reactor(n,r){function trigger(){var r=e.messages.apply(t,arguments);return a&&a.apply(t,r)&&n.apply(t,r),r}u.seq.val(trigger),r(function $$teardown(){u=a=null})}var u=tapSequences(n)[0];if(u)return r(reactor)},r.fromObservable=function $$react$from$observable(e){function reactor(t,r){n.forEach(t),n.length=0,n.complete||(notify=t),r(function $$teardown(){e.dispose()})}function notify(e){n.push(e)}var n=[];return e.subscribe(function $$on$next(e){notify(e)},function $$on$error(){},function $$on$complete(){n.complete=!0,e.dispose()}),r(reactor)},e.extend("toObservable",function $$extend(n,r){return function $$to$observable(){function init(r){function define(a){function listen(){var n=e.messages.apply(t,arguments);return r[a[1]].apply(r,1==n.length?[n[0]]:n),n}n[a[0]](listen)}[["val","onNext"],["or","onError"]].forEach(define)}return Rx.Observable.create(init)}})}(),e.extend("runner",function $$extend(r,u){return function $$runner(){if(u("seq_error")||u("seq_aborted")||0===arguments.length)return r;var l=n.call(arguments);return r.then(function $$then(r){function wrap(n){return"function"==typeof n?(n=n.call(t,i),isPromise(n)&&(n=e.iterable(n))):n=e.isSequence(n)&&"next"in n?n.duplicate():e.iterable(n),e.isSequence(n)&&n.or(function $$or(){r.fail.apply(t,arguments)}),n}function addWrapped(){o.push.apply(o,n.call(arguments).map(wrap))}function iterateOrQuit(n,u){o.length>0?u?n():a(n):("undefined"!=typeof f?e.isMessageWrapper(f)||(f=[f]):f=[],r.apply(t,f))}var c,s,o=l,i={messages:n.call(arguments,1),add:addWrapped},f=i;o=o.map(wrap),function iterate(){c=o.shift();try{s=e.isMessageWrapper(f)&&e.isSequence(c)?c.next.apply(c,f):c.next(f)}catch(n){return r.fail(n)}if(!u("seq_aborted"))if(s.value===i)s.done||o.push(c),f=i,iterateOrQuit(iterate,!1);else{if(!e.isSequence(s.value))if(isPromise(s.value))s.value=e().promise(s.value);else if("function"==typeof s.value){var a=s.value;s.value=e(function $$ASQ(e){a(e.errfcb)})}else e.isMessageWrapper(s.value)?s.value=e.apply(t,s.value.length>0?s.value:e.messages(void 0)):"undefined"!=typeof s.value?s.value=e(s.value):s.value=e();s.value.val(function $$val(){u("seq_aborted")||(arguments.length>0&&(f=arguments.length>1?e.messages.apply(t,arguments):arguments[0]),s.done||(f===i?o.push(c):o.unshift(c)),iterateOrQuit(iterate,!0))}).or(function $$or(){if(!u("seq_aborted"))try{c["throw"].apply(c,arguments)}catch(e){r.fail(e)}})}}()}),r}}),e.extend("toPromise",function $$extend(r,a){return function $$to$promise(){return new Promise(function $$executor(a,u){r.val(function $$val(){var r=n.call(arguments);return a.call(t,r.length>1?r:r[0]),e.messages.apply(t,r)}).or(function $$or(){var e=n.call(arguments);u.call(t,e.length>1?e:e[0])})})}}),e.extend("try",function $$extend(r,a){return function $$try(){if(a("seq_error")||a("seq_aborted")||0===arguments.length)return r;var u=n.call(arguments).map(function $$map(r){return function $$then(a){var u=n.call(arguments),l=e.apply(t,u.slice(1));l.then(function $$inner$then(){r.apply(t,arguments)}).val(function $$val(){a.apply(t,arguments)}).or(function $$inner$or(){var n=e.messages.apply(t,arguments);a({"catch":n.length>1?n:n[0]})})}});return r.then.apply(t,u),r}}),e.extend("until",function $$extend(r,a){return function $$until(){if(a("seq_error")||a("seq_aborted")||0===arguments.length)return r;var u=n.call(arguments).map(function $$map(r){return function $$then(a){var u=n.call(arguments),l=e.apply(t,u.slice(1));l.then(function $$inner$then(){var e=n.call(arguments);e[0]["break"]=function $$break(){a.fail.apply(t,arguments),l.abort()},r.apply(t,e)}).val(function $$val(){a.apply(t,arguments)}).or(function $$inner$or(){$$then.apply(t,u)})}});return r.then.apply(t,u),r}}),e.extend("waterfall",function $$extend(r,a){return function $$waterfall(){if(a("seq_error")||a("seq_aborted")||0===arguments.length)return r;var u=n.call(arguments);return r.then(function $$then(r){var a=e.messages(),l=e.apply(t,n.call(arguments,1));u.forEach(function $$each(n){l.then(n).val(function $$val(){var n=e.messages.apply(t,arguments);return a.push(n.length>1?n:n[0]),a})}),l.pipe(r)}),r}}),e.wrap=function $$wrap(r,a){function checkThis(e,n){return!e||"undefined"!=typeof window&&e===window||"undefined"!=typeof global&&e===global?n:e}function paramSpread(e){return regeneratorRuntime.mark(function paramSpread(n){return regeneratorRuntime.wrap(function paramSpread$(t){for(;;)switch(t.prev=t.next){case 0:return t.delegateYield(e.apply(this,n.messages),"t0",1);case 1:case"end":return t.stop()}},paramSpread,this)})}var u,l,c,s;if(a=a&&"object"==typeof a?a:{},a.errfcb&&a.splitcb||a.errfcb&&a.simplecb||a.splitcb&&a.simplecb||"errfcb"in a&&!a.errfcb&&!a.splitcb&&!a.simplecb||a.params_first&&a.params_last||a.spread&&!a.gen)throw Error("Invalid options");return s=a["this"]&&"object"==typeof a["this"]?a["this"]:t,u=a.errfcb||!(a.splitcb||a.simplecb),l=!!a.params_first||!a.params_last&&!("params_first"in a||a.params_first)||"params_last"in a&&!a.params_first&&!a.params_last,c=l?"push":"unshift",a.gen?(a.spread&&(r=paramSpread(r)),function $$wrapped$gen(){return e.apply(t,arguments).runner(r)}):u?function $$wrapped$errfcb(){var t=n.call(arguments),a=checkThis(this,s);return e(function $$asq(e){t[c](e.errfcb),r.apply(a,t)})}:a.splitcb?function $$wrapped$splitcb(){var t=n.call(arguments),a=checkThis(this,s);return e(function $$asq(e){t[c](e,e.fail),r.apply(a,t)})}:a.simplecb?function $$wrapped$simplecb(){var t=n.call(arguments),a=checkThis(this,s);return e(function $$asq(e){t[c](e),r.apply(a,t)})}:void 0},e}); diff --git a/frontend-masters-exercises/exercises/ex9/asq.bundle.js b/frontend-masters-exercises/exercises/ex9/asq.bundle.js new file mode 100755 index 0000000..93c9ada --- /dev/null +++ b/frontend-masters-exercises/exercises/ex9/asq.bundle.js @@ -0,0 +1,2333 @@ +/*! asynquence + v0.8.2 (c) Kyle Simpson + MIT License: http://getify.mit-license.org +*/ +!function UMD(e,n,t){"function"==typeof define&&define.amd?define(t):"undefined"!=typeof module&&module.exports?module.exports=t():n[e]=t(e,n)}("ASQ",this,function DEF(e,n){"use strict";function Queue(){function Item(e){this.fn=e,this.next=void 0}var e,n,r;return{add:function $$add(t){r=new Item(t),n?n.next=r:e=r,n=r,r=void 0},drain:function $$drain(){var r=e;for(e=n=t=null;r;)r.fn(),r=r.next}}}function schedule(e){r.add(e),t||(t=u(r.drain))}function tapSequence(e){function trigger(){e.seq=createSequence.apply(h,arguments).defer()}trigger.fail=function $$trigger$fail(){var n=f.call(arguments);e.seq=createSequence(function $$create$sequence(e){e.fail.apply(h,n)}).defer()},e.seq.val(function $$val(){return trigger.apply(h,arguments),c.apply(h,arguments)}).or(function $$or(){trigger.fail.apply(h,arguments)}),e.seq=createSequence(function $$create$sequence(e){trigger=e}).defer()}function createSequence(){function scheduleSequenceTick(){r?sequenceTick():e||(e=schedule(sequenceTick))}function throwSequenceErrors(){throw 1===$.length?$[0]:$}function sequenceTick(){var a,c;if(e=null,delete d.unpause,r)clearTimeout(e),e=null,s.length=p.length=g.length=$.length=0;else if(n)for(0!==p.length||t||(t=!0,throwSequenceErrors());p.length;){t=!0,a=p.shift();try{a.apply(h,$)}catch(i){l(i)?$=$.concat(i):($.push(i),i.stack&&$.push(i.stack)),0===p.length&&throwSequenceErrors()}}else if(u&&s.length>0){u=!1,a=s.shift(),c=g.slice(),g.length=0,c.unshift(createStepCompletion());try{a.apply(h,c)}catch(i){l(i)?$=$.concat(i):$.push(i),n=!0,scheduleSequenceTick()}}}function createStepCompletion(){function done(){n||r||u||(u=!0,g.push.apply(g,arguments),$.length=0,scheduleSequenceTick())}return done.fail=function $$step$fail(){n||r||u||(n=!0,g.length=0,$.push.apply($,arguments),scheduleSequenceTick())},done.abort=function $$step$abort(){n||r||(u=!1,r=!0,g.length=$.length=0,scheduleSequenceTick())},done.errfcb=function $$step$errfcb(e){e?done.fail(e):done.apply(h,f.call(arguments,1))},done}function createGate(e,t,u){function resetGate(){clearTimeout(s),s=d=m=o=null}function scheduleGateTick(){return g?gateTick():void(s||(s=schedule(gateTick)))}function gateTick(){if(!(n||r||$)){var t=[];s=null,p?(e.fail.apply(h,o),resetGate()):g?(e.abort(),resetGate()):checkGate()&&($=!0,d.forEach(function $$each(e,n){t.push(m["s"+n])}),e.apply(h,t),resetGate())}}function checkGate(){if(0!==d.length){var e=!0;return d.some(function $$some(n){return null===n?(e=!1,!0):void 0}),e}}function createSegmentCompletion(){function done(){if(!(n||r||p||g||$||d[e])){var t=c.apply(h,arguments);m["s"+e]=t.length>1?t:t[0],d[e]=!0,scheduleGateTick()}}var e=d.length;return done.fail=function $$segment$fail(){n||r||p||g||$||d[e]||(p=!0,o=f.call(arguments),scheduleGateTick())},done.abort=function $$segment$abort(){n||r||p||g||$||(g=!0,gateTick())},done.errfcb=function $$segment$errfcb(e){e?done.fail(e):done.apply(h,f.call(arguments,1))},d[e]=null,done}var a,i,o,s,p=!1,g=!1,$=!1,d=[],m={};t.some(function $$some(e){if(p||g)return!0;a=u.slice(),a.unshift(createSegmentCompletion());try{e.apply(h,a)}catch(n){return i=n,p=!0,!0}}),i&&(l(i)?e.fail.apply(h,i):e.fail(i))}function then(){return n||r||0===arguments.length?d:(wrapArgs(arguments,thenWrapper).forEach(function $$each(e){i(e)?seq(e):s.push(e)}),scheduleSequenceTick(),d)}function or(){return r||0===arguments.length?d:(p.push.apply(p,arguments),scheduleSequenceTick(),d)}function gate(){if(n||r||0===arguments.length)return d;var e=f.call(arguments).map(function $$map(e){var n;return i(e)?(n={seq:e},tapSequence(n),function $$segment(e){n.seq.pipe(e)}):e});return then(function $$then(n){var t=f.call(arguments,1);createGate(n,e,t)}),d}function pipe(){return r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){then(function $$then(n){e.apply(h,f.call(arguments,1)),n()}).or(e.fail)}),d)}function seq(){return n||r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){var n={seq:e};i(e)&&tapSequence(n),then(function $$then(e){var t=n.seq;i(t)||(t=n.seq.apply(h,f.call(arguments,1))),t.pipe(e)})}),d)}function val(){return n||r||0===arguments.length?d:(f.call(wrapArgs(arguments,valWrapper)).forEach(function $$each(e){then(function $$then(n){var t=e.apply(h,f.call(arguments,1));l(t)||(t=c(t)),n.apply(h,t)})}),d)}function promise(){function wrap(e){return function $$fn(){e.apply(h,l(arguments[0])?arguments[0]:arguments)}}return n||r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){then(function $$then(n){var t=e;"function"==typeof e&&"function"!=typeof e.then&&(t=e.apply(h,f.call(arguments,1))),t.then(wrap(n),wrap(n.fail))})}),d)}function fork(){var e;return val(function $$val(){return e?e.apply(h,arguments):e=createSequence.apply(h,arguments).defer(),c.apply(h,arguments)}),or(function $$or(){if(e)e.fail.apply(h,arguments);else{var n=f.call(arguments);e=createSequence().then(function $$then(e){e.fail.apply(h,n)}).defer()}}),createSequence().then(function $$then(n){e?e.pipe(n):e=n}).defer()}function abort(){return n?d:(r=!0,sequenceTick(),d)}function duplicate(){var e;return a={then_queue:s.slice(),or_queue:p.slice()},e=createSequence(),a=null,e}function unpause(){g.push.apply(g,arguments),e===!0&&(e=null),scheduleSequenceTick()}function defer(){return p.push(function ignored(){}),d}function internals(e,t){var a=arguments.length>1;switch(e){case"seq_error":if(!a)return n;n=t;break;case"seq_aborted":if(!a)return r;r=t;break;case"then_ready":if(!a)return u;u=t;break;case"then_queue":return s;case"or_queue":return p;case"sequence_messages":return g;case"sequence_errors":return $}}function includeExtensions(){Object.keys(o).forEach(function $$each(e){d[e]=o[e](d,internals)})}var e,n=!1,t=!1,r=!1,u=!0,s=[],p=[],g=[],$=[],d=brandIt({then:then,or:or,onerror:or,gate:gate,all:gate,pipe:pipe,seq:seq,val:val,promise:promise,fork:fork,abort:abort,duplicate:duplicate,defer:defer});return includeExtensions(),a&&(s=a.then_queue.slice(),p=a.or_queue.slice(),d.unpause=unpause,e=!0),d.then.apply(h,arguments),d}function brandIt(e){return Object.defineProperty(e,p,{enumerable:!1,value:!0})}function checkBranding(e){return!(null==e||"object"!=typeof e||!e[p])}function valWrapper(e){return c.apply(h,f.call(arguments).slice(1,e+1))}function thenWrapper(e){arguments[e+1].apply(h,f.call(arguments).slice(1,e+1))}function wrapArgs(e,n){var t,r;for(e=f.call(e),t=0;t 1 ? + ARRAY_SLICE.call(arguments,1) : + void 0 + ; + num = +num || 0; + + api.then(function $$then(done){ + var args = orig_args || ARRAY_SLICE.call(arguments,1); + + setTimeout(function $$set$timeout(){ + done.apply(ø,args); + },num); + }); + + return api; + }; +}); + +ASQ.after = function $$after() { + return ASQ().after.apply(ø,arguments); +}; +// "any" +ASQ.extend("any",function $$extend(api,internals){ + return function $$any() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + function reset() { + finished = true; + error_messages.length = 0; + success_messages.length = 0; + } + + function complete(trigger) { + if (success_messages.length > 0) { + // any successful segment's message(s) sent + // to main sequence to proceed as success + success_messages.length = fns.length; + trigger.apply(ø,success_messages); + } + else { + // send errors into main sequence + error_messages.length = fns.length; + trigger.fail.apply(ø,error_messages); + } + + reset(); + } + + function success(trigger,idx,args) { + if (!finished) { + completed++; + success_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + + // all segments complete? + if (completed === fns.length) { + finished = true; + + complete(trigger); + } + } + } + + function failure(trigger,idx,args) { + if (!finished && + !(idx in error_messages) + ) { + completed++; + error_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + } + + // all segments complete? + if (!finished && + completed === fns.length + ) { + finished = true; + + complete(trigger); + } + } + + var completed = 0, error_messages = [], finished = false, + success_messages = [], + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)) + ; + + wrapGate(sq,fns,success,failure,reset); + + sq.pipe(done); + }); + + return api; + }; +}); +// "errfcb" +ASQ.extend("errfcb",function $$extend(api,internals){ + return function $$errfcb() { + // create a fake sequence to extract the callbacks + var sq = { + val: function $$then(cb){ sq.val_cb = cb; return sq; }, + or: function $$or(cb){ sq.or_cb = cb; return sq; } + }; + + // trick `seq(..)`s checks for a sequence + sq[brand] = true; + + // immediately register our fake sequence on the + // main sequence + api.seq(sq); + + // provide the "error-first" callback + return function $$errorfirst$callback(err) { + if (err) { + sq.or_cb(err); + } + else { + sq.val_cb.apply(ø,ARRAY_SLICE.call(arguments,1)); + } + }; + }; +}); +// "failAfter" +ASQ.extend("failAfter",function $$extend(api,internals){ + return function $$failAfter(num) { + var args = arguments.length > 1 ? + ARRAY_SLICE.call(arguments,1) : + void 0 + ; + num = +num || 0; + + api.then(function $$then(done){ + setTimeout(function $$set$timeout(){ + done.fail.apply(ø,args); + },num); + }); + + return api; + }; +}); + +ASQ.failAfter = function $$fail$after() { + return ASQ().failAfter.apply(ø,arguments); +}; +// "first" +ASQ.extend("first",function $$extend(api,internals){ + return function $$first() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + function reset() { + error_messages.length = 0; + } + + function success(trigger,idx,args) { + if (!finished) { + finished = true; + + // first successful segment triggers + // main sequence to proceed as success + trigger( + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ); + + reset(); + } + } + + function failure(trigger,idx,args) { + if (!finished && + !(idx in error_messages) + ) { + completed++; + error_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + + // all segments complete without success? + if (completed === fns.length) { + finished = true; + + // send errors into main sequence + error_messages.length = fns.length; + trigger.fail.apply(ø,error_messages); + + reset(); + } + } + } + + var completed = 0, error_messages = [], finished = false, + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)) + ; + + wrapGate(sq,fns,success,failure,reset); + + sq.pipe(done); + }); + + return api; + }; +}); +// "go-style CSP" +(function IIFE(){ + + // filter out already-resolved queue entries + function filterResolved(queue) { + return queue.filter(function $$filter(entry){ + return !entry.resolved; + }); + } + + function closeQueue(queue,finalValue) { + queue.forEach(function $$each(iter){ + if (!iter.resolved) { + iter.next(); + iter.next(finalValue); + } + }); + queue.length = 0; + } + + function channel(bufSize) { + var ch = { + close: function $$close(){ + ch.closed = true; + closeQueue(ch.put_queue,false); + closeQueue(ch.take_queue,ASQ.csp.CLOSED); + }, + closed: false, + messages: [], + put_queue: [], + take_queue: [], + buffer_size: +bufSize || 0 + }; + return ch; + } + + function unblock(iter) { + if (iter && !iter.resolved) { + iter.next(iter.next().value); + } + } + + function put(channel,value) { + var ret; + + if (channel.closed) { + return false; + } + + // remove already-resolved entries + channel.put_queue = filterResolved(channel.put_queue); + channel.take_queue = filterResolved(channel.take_queue); + + // immediate put? + if (channel.messages.length < channel.buffer_size) { + channel.messages.push(value); + unblock(channel.take_queue.shift()); + return true; + } + // queued put + else { + channel.put_queue.push( + // make a notifiable iterable for 'put' blocking + ASQ.iterable() + .then(function $$then(){ + if (!channel.closed) { + channel.messages.push(value); + return true; + } + else { + return false; + } + }) + ); + + // wrap a sequence/promise around the iterable + ret = ASQ( + channel.put_queue[channel.put_queue.length - 1] + ); + + // take waiting on this queued put? + if (channel.take_queue.length > 0) { + unblock(channel.put_queue.shift()); + unblock(channel.take_queue.shift()); + } + + return ret; + } + } + + function putAsync(channel,value,cb) { + var ret = ASQ(put(channel,value)); + + if (cb && typeof cb == "function") { + ret.val(cb); + } + else { + return ret; + } + } + + function take(channel) { + var ret; + + try { + ret = takem(channel); + } + catch (err) { + ret = err; + } + + if (ASQ.isSequence(ret)) { + ret.pCatch(function $$pcatch(err){ + return err; + }); + } + + return ret; + } + + function takeAsync(channel,cb) { + var ret = ASQ(take(channel)); + + if (cb && typeof cb == "function") { + ret.val(cb); + } + else { + return ret; + } + } + + function takem(channel) { + var msg; + + if (channel.closed) { + return ASQ.csp.CLOSED; + } + + // remove already-resolved entries + channel.put_queue = filterResolved(channel.put_queue); + channel.take_queue = filterResolved(channel.take_queue); + + // immediate take? + if (channel.messages.length > 0) { + msg = channel.messages.shift(); + unblock(channel.put_queue.shift()); + if (msg instanceof Error) { + throw msg; + } + return msg; + } + // queued take + else { + channel.take_queue.push( + // make a notifiable iterable for 'take' blocking + ASQ.iterable() + .then(function $$then(){ + if (!channel.closed) { + var v = channel.messages.shift(); + if (v instanceof Error) { + throw v; + } + return v; + } + else { + return ASQ.csp.CLOSED; + } + }) + ); + + // wrap a sequence/promise around the iterable + msg = ASQ( + channel.take_queue[channel.take_queue.length - 1] + ); + + // put waiting on this take? + if (channel.put_queue.length > 0) { + unblock(channel.put_queue.shift()); + unblock(channel.take_queue.shift()); + } + + return msg; + } + } + + function takemAsync(channel,cb) { + var ret = ASQ(takem(channel)); + + if (cb && typeof cb == "function") { + ret.pThen(cb,cb); + } + else { + return ret.val(function $$val(v){ + if (v instanceof Error) { + throw v; + } + return v; + }); + } + } + + function alts(actions) { + var closed, open, handlers, i, isq, ret, resolved = false; + + // used `alts(..)` incorrectly? + if (!Array.isArray(actions) || actions.length == 0) { + throw Error("Invalid usage"); + } + + closed = []; + open = []; + handlers = []; + + // separate actions by open/closed channel status + actions.forEach(function $$each(action){ + var channel = Array.isArray(action) ? action[0] : action; + + // remove already-resolved entries + channel.put_queue = filterResolved(channel.put_queue); + channel.take_queue = filterResolved(channel.take_queue); + + if (channel.closed) { + closed.push(channel); + } + else { + open.push(action); + } + }); + + // if no channels are still open, we're done + if (open.length == 0) { + return { value: ASQ.csp.CLOSED, channel: closed }; + } + + // can any channel action be executed immediately? + for (i=0; i 0) { + return { value: take(open[i]), channel: open[i] }; + } + } + + isq = ASQ.iterable(); + var ret = ASQ(isq); + + // setup channel action handlers + for (i=0; i 0) { + schedule(function handleUnblocking(){ + if (!resolved) { + unblock(channel.put_queue.shift()); + unblock(channel.take_queue.shift()); + } + },0); + } + } + // take action? + else { + channel = action; + + // define take handler + handlers.push( + ASQ.iterable() + .then(function $$then(){ + resolved = true; + + // mark all handlers across this `alts(..)` as resolved now + handlers = handlers.filter(function $$filter(handler){ + return !(handler.resolved = true); + }); + + // channel still open? + if (!channel.closed) { + isq.next({ value: channel.messages.shift(), channel: channel }); + } + // channel already closed? + else { + isq.next({ value: ASQ.csp.CLOSED, channel: channel }); + } + }) + ); + + // queue up take handler + channel.take_queue.push(handlers[handlers.length-1]); + + // put waiting on this queued take? + if (channel.put_queue.length > 0) { + schedule(function handleUnblocking(){ + if (!resolved) { + unblock(channel.put_queue.shift()); + unblock(channel.take_queue.shift()); + } + }); + } + } + })(open[i]); + } + + return ret; + } + + function altsAsync(chans,cb) { + var ret = ASQ(alts(chans)); + + if (cb && typeof cb == "function") { + ret.pThen(cb,cb); + } + else { + return ret; + } + } + + function timeout(delay) { + var ch = channel(); + setTimeout(ch.close,delay); + return ch; + } + + function go(gen,args) { + // goroutine arguments passed? + if (arguments.length > 1) { + if (!args || !Array.isArray(args)) { + args = [args]; + } + } + else { + args = []; + } + + return function *$$go(token) { + + // unblock the overall goroutine handling + function unblock() { + token.unblock_count++; + + if (token.block && !token.block.marked) { + token.block.marked = true; + token.block.next(); + } + } + + var ret, msg, err, type, done = false, it; + + // keep track of how many requests for unblocking + // have occurred + token.unblock_count = (token.unblock_count || 0); + + // keep track of how many goroutines are running + // so we can infer when we're done go'ing + token.go_count = (token.go_count || 0) + 1; + + // need to initialize a set of goroutines? + if (token.go_count === 1) { + // create a default channel for these goroutines + token.channel = channel(); + token.channel.messages = token.messages; + token.channel.go = function $$go(){ + // unblock the goroutine handling for this + // new goroutine + unblock(); + // add the goroutine (called with any args) to + // the handling queue + token.add( go.apply(ø,arguments) ); + }; + // starting out with initial channel messages? + if (token.channel.messages.length > 0) { + // fake back-pressure blocking for each + token.channel.put_queue = token.channel.messages.map(function $$map(){ + // make a notifiable iterable for 'put' blocking + return ASQ.iterable() + .then(function $$then(){ + unblock(token.channel.take_queue.shift()); + return !token.channel.closed; + }); + }); + } + } + + // initialize the generator + it = gen.apply(ø,[token.channel].concat(args)); + + (function iterate(){ + + function next() { + // keep going with next step in goroutine? + if (!done) { + iterate(); + } + // unblock overall goroutine handling to + // continue with other goroutines + else { + unblock(); + } + } + + // has a resumption value been achieved yet? + if (!ret) { + // try to resume the goroutine + try { + // resume with injected exception? + if (err) { + ret = it.throw(err); + err = null; + } + // resume normally + else { + ret = it.next(msg); + } + } + // resumption failed, so bail + catch (e) { + done = true; + err = e; + msg = null; + unblock(); + return; + } + + // keep track of the result of the resumption + done = ret.done; + ret = ret.value; + type = typeof ret; + + // if this goroutine is complete, unblock the + // overall goroutine handling + if (done) { + unblock(); + } + + // received a thenable/promise back? + if (isPromise(ret)) { + ret = ASQ().promise(ret); + } + + // wait for the value? + if (ASQ.isSequence(ret)) { + ret.val(function $$val(){ + ret = null; + msg = arguments.length > 1 ? + ASQ.messages.apply(ø,arguments) : + arguments[0] + ; + next(); + }) + .or(function $$or(){ + ret = null; + msg = arguments.length > 1 ? + ASQ.messages.apply(ø,arguments) : + arguments[0] + ; + if (msg instanceof Error) { + err = msg; + msg = null; + } + next(); + }); + } + // immediate value, prepare it to go right back in + else { + msg = ret; + ret = null; + next(); + } + } + })(); + + // keep this goroutine alive until completion + while (!done) { + // transfer control to another goroutine + yield token; + + // need to block overall goroutine handling + // while idle? + if (!done && !token.block && token.unblock_count === 0) { + // wait here while idle + yield (token.block = ASQ.iterable()); + + token.block = false; + } + + if (token.unblock_count > 0) token.unblock_count--; + } + + // this goroutine is done now + token.go_count--; + + // all goroutines done? + if (token.go_count === 0) { + // any lingering blocking need to be cleaned up? + unblock(); + + // capture any untaken messages + msg = ASQ.messages.apply(ø,token.messages); + + // need to implicitly force-close channel? + if (token.channel && !token.channel.closed) { + token.channel.closed = true; + token.channel.put_queue.length = token.channel.take_queue.length = 0; + token.channel.close = token.channel.go = token.channel.messages = null; + } + token.channel = null; + } + + // make sure leftover error or message are + // passed along + if (err) { + throw err; + } + else if (token.go_count === 0) { + return msg; + } + else { + return token; + } + }; + } + + ASQ.csp = { + chan: channel, + put: put, + putAsync: putAsync, + take: take, + takeAsync: takeAsync, + takem: takem, + takemAsync: takemAsync, + alts: alts, + altsAsync: altsAsync, + timeout: timeout, + go: go, + CLOSED: {} + }; + +})(); +// "ASQ.iterable()" +(function IIFE(){ + var template; + + ASQ.iterable = function $$iterable() { + function throwSequenceErrors() { + throw (sequence_errors.length === 1 ? sequence_errors[0] : sequence_errors); + } + + function notifyErrors() { + var fn; + + seq_tick = null; + + if (seq_error) { + if (or_queue.length === 0 && !error_reported) { + error_reported = true; + throwSequenceErrors(); + } + + while (or_queue.length > 0) { + error_reported = true; + fn = or_queue.shift(); + try { + fn.apply(ø,sequence_errors); + } + catch (err) { + if (checkBranding(err)) { + sequence_errors = sequence_errors.concat(err); + } + else { + sequence_errors.push(err); + } + if (or_queue.length === 0) { + throwSequenceErrors(); + } + } + } + } + } + + function val() { + if (seq_error || seq_aborted || arguments.length === 0) { + return sequence_api; + } + + var args = ARRAY_SLICE.call(arguments).map(function mapper(arg){ + if (typeof arg != "function") return function $$val() { return arg; }; + else return arg; + }); + + val_queue.push.apply(val_queue,args); + + return sequence_api; + } + + function or() { + if (seq_aborted || arguments.length === 0) { + return sequence_api; + } + + or_queue.push.apply(or_queue,arguments); + + if (!seq_tick) { + seq_tick = schedule(notifyErrors); + } + + return sequence_api; + } + + function pipe() { + if (seq_aborted || arguments.length === 0) { + return sequence_api; + } + + ARRAY_SLICE.call(arguments) + .forEach(function $$each(fn){ + val(fn).or(fn.fail); + }); + + return sequence_api; + } + + function next() { + if (seq_error || seq_aborted || val_queue.length === 0) { + if (val_queue.length > 0) { + $throw$("Sequence cannot be iterated"); + } + return { done: true }; + } + + try { + return { value: val_queue.shift().apply(ø,arguments) }; + } + catch (err) { + if (ASQ.isMessageWrapper(err)) { + $throw$.apply(ø,err); + } + else { + $throw$(err); + } + + return {}; + } + } + + function $throw$() { + if (seq_error || seq_aborted) { + return sequence_api; + } + + sequence_errors.push.apply(sequence_errors,arguments); + seq_error = true; + if (!seq_tick) { + seq_tick = schedule(notifyErrors); + } + + return sequence_api; + } + + function $return$(val) { + if (seq_error || seq_aborted) { + val = void 0; + } + + abort(); + + return { done: true, value: val }; + } + + function abort() { + if (seq_error || seq_aborted) { + return; + } + + seq_aborted = true; + + clearTimeout(seq_tick); + seq_tick = null; + val_queue.length = or_queue.length = sequence_errors.length = 0; + } + + function duplicate() { + var isq; + + template = { + val_queue: val_queue.slice(), + or_queue: or_queue.slice() + }; + isq = ASQ.iterable(); + template = null; + + return isq; + } + + // opt-out of global error reporting for this sequence + function defer() { + or_queue.push(function $$ignored(){}); + return sequence_api; + } + + // *********************************************** + // Object branding utilities + // *********************************************** + function brandIt(obj) { + Object.defineProperty(obj,brand,{ + enumerable: false, + value: true + }); + + return obj; + } + + var sequence_api, + + seq_error = false, + error_reported = false, + seq_aborted = false, + + seq_tick, + + val_queue = [], + or_queue = [], + + sequence_errors = [] + ; + + // *********************************************** + // Setup the ASQ.iterable() public API + // *********************************************** + sequence_api = brandIt({ + val: val, + then: val, + or: or, + pipe: pipe, + next: next, + "throw": $throw$, + "return": $return$, + abort: abort, + duplicate: duplicate, + defer: defer + }); + + // useful for ES6 `for..of` loops, + // add `@@iterator` to simply hand back + // our iterable sequence itself! + sequence_api[(typeof Symbol == "function" && Symbol.iterator) || "@@iterator"] = function $$iter() { + return sequence_api; + }; + + // templating the iterable-sequence setup? + if (template) { + val_queue = template.val_queue.slice(0); + or_queue = template.or_queue.slice(0); + } + + // treat ASQ.iterable() constructor parameters as having been + // passed to `val()` + sequence_api.val.apply(ø,arguments); + + return sequence_api; + }; + +})(); +// "last" +ASQ.extend("last",function $$extend(api,internals){ + return function $$last() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + function reset() { + finished = true; + error_messages.length = 0; + success_messages = null; + } + + function complete(trigger) { + if (success_messages != null) { + // last successful segment's message(s) sent + // to main sequence to proceed as success + trigger( + success_messages.length > 1 ? + ASQ.messages.apply(ø,success_messages) : + success_messages[0] + ); + } + else { + // send errors into main sequence + error_messages.length = fns.length; + trigger.fail.apply(ø,error_messages); + } + + reset(); + } + + function success(trigger,idx,args) { + if (!finished) { + completed++; + success_messages = args; + + // all segments complete? + if (completed === fns.length) { + finished = true; + + complete(trigger); + } + } + } + + function failure(trigger,idx,args) { + if (!finished && + !(idx in error_messages) + ) { + completed++; + error_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + } + + // all segments complete? + if (!finished && + completed === fns.length + ) { + finished = true; + + complete(trigger); + } + } + + var completed = 0, error_messages = [], finished = false, + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)), + success_messages + ; + + wrapGate(sq,fns,success,failure,reset); + + sq.pipe(done); + }); + + return api; + }; +}); +// "map" +ASQ.extend("map",function $$extend(api,internals){ + return function $$map(pArr,pEach) { + if (internals("seq_error") || internals("seq_aborted")) { + return api; + } + + api.seq(function $$seq(){ + var tmp, args = ARRAY_SLICE.call(arguments), + arr = pArr, each = pEach; + + // if missing `map(..)` args, use value-messages (if any) + if (!each) each = args.shift(); + if (!arr) arr = args.shift(); + + // if arg types in reverse order (each,arr), swap + if (typeof arr === "function" && Array.isArray(each)) { + tmp = arr; + arr = each; + each = tmp; + } + + return ASQ.apply(ø,args) + .gate.apply(ø,arr.map(function $$map(item){ + return function $$segment(){ + each.apply(ø,[item].concat(ARRAY_SLICE.call(arguments))); + }; + })); + }) + .val(function $$val(){ + // collect all gate segment output into one value-message + // Note: return a normal array here, not a message wrapper! + return ARRAY_SLICE.call(arguments); + }); + + return api; + }; +}); +// "none" +ASQ.extend("none",function $$extend(api,internals){ + return function $$none() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + function reset() { + finished = true; + error_messages.length = 0; + success_messages.length = 0; + } + + function complete(trigger) { + if (success_messages.length > 0) { + // any successful segment's message(s) sent + // to main sequence to proceed as **error** + success_messages.length = fns.length; + trigger.fail.apply(ø,success_messages); + } + else { + // send errors as **success** to main sequence + error_messages.length = fns.length; + trigger.apply(ø,error_messages); + } + + reset(); + } + + function success(trigger,idx,args) { + if (!finished) { + completed++; + success_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + + // all segments complete? + if (completed === fns.length) { + finished = true; + + complete(trigger); + } + } + } + + function failure(trigger,idx,args) { + if (!finished && + !(idx in error_messages) + ) { + completed++; + error_messages[idx] = + args.length > 1 ? + ASQ.messages.apply(ø,args) : + args[0] + ; + } + + // all segments complete? + if (!finished && + completed === fns.length + ) { + finished = true; + + complete(trigger); + } + } + + var completed = 0, error_messages = [], finished = false, + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)), + success_messages = [] + ; + + wrapGate(sq,fns,success,failure,reset); + + sq.pipe(done); + }); + + return api; + }; +}); +// "pThen" +ASQ.extend("pThen",function $$extend(api,internals){ + return function $$pthen(success,failure) { + if (internals("seq_aborted")) { + return api; + } + + var ignore_success_handler = false, ignore_failure_handler = false; + + if (typeof success === "function") { + api.then(function $$then(done){ + if (!ignore_success_handler) { + var ret, msgs = ASQ.messages.apply(ø,arguments); + msgs.shift(); + + if (msgs.length === 1) { + msgs = msgs[0]; + } + + ignore_failure_handler = true; + + try { + ret = success(msgs); + } + catch (err) { + if (!ASQ.isMessageWrapper(err)) { + err = [err]; + } + done.fail.apply(ø,err); + return; + } + + // returned a sequence? + if (ASQ.isSequence(ret)) { + ret.pipe(done); + } + // returned a message wrapper? + else if (ASQ.isMessageWrapper(ret)) { + done.apply(ø,ret); + } + // returned a promise/thenable? + else if (isPromise(ret)) { + ret.then(done,done.fail); + } + // just a normal value to pass along + else { + done(ret); + } + } + else { + done.apply(ø,ARRAY_SLICE.call(arguments,1)); + } + }); + } + if (typeof failure === "function") { + api.or(function $$or(){ + if (!ignore_failure_handler) { + var ret, msgs = ASQ.messages.apply(ø,arguments), smgs, + or_queue = ARRAY_SLICE.call(internals("or_queue")) + ; + + if (msgs.length === 1) { + msgs = msgs[0]; + } + + ignore_success_handler = true; + + // NOTE: if this call throws, that'll automatically + // be handled by core as we'd want it to be + ret = failure(msgs); + + // if we get this far: + // first, inject return value (if any) as + // next step's sequence messages + smgs = internals("sequence_messages"); + smgs.length = 0; + if (typeof ret !== "undefined") { + if (!ASQ.isMessageWrapper(ret)) { + ret = [ret]; + } + smgs.push.apply(smgs,ret); + } + + // reset internal error state, because we've exclusively + // handled any errors up to this point of the sequence + internals("sequence_errors").length = 0; + internals("seq_error",false); + internals("then_ready",true); + + // temporarily empty the or-queue + internals("or_queue").length = 0; + + // make sure to schedule success-procession on the chain + api.val(function $$val(){ + // pass thru messages + return ASQ.messages.apply(ø,arguments); + }); + + // at next cycle, reinstate the or-queue (if any) + if (or_queue.length > 0) { + schedule(function $$schedule(){ + api.or.apply(ø,or_queue); + }); + } + } + }); + } + return api; + }; +}); + +// "pCatch" +ASQ.extend("pCatch",function $$extend(api,internals){ + return function $$pcatch(failure) { + if (internals("seq_aborted")) { + return api; + } + + api.pThen(void 0,failure); + + return api; + }; +}); +// "race" +ASQ.extend("race",function $$extend(api,internals){ + return function $$race() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments) + .map(function $$map(v){ + var def; + // tap any directly-provided sequences immediately + if (ASQ.isSequence(v)) { + def = { seq: v }; + tapSequence(def); + return function $$fn(done) { + def.seq.pipe(done); + }; + } + else return v; + }); + + api.then(function $$then(done){ + var args = ARRAY_SLICE.call(arguments); + + fns.forEach(function $$each(fn){ + fn.apply(ø,args); + }); + }); + + return api; + }; +}); +// "react" (reactive sequences) +ASQ.react = function $$react(reactor) { + function next() { + if (!paused) { + if (template) { + var sq = template.duplicate(); + sq.unpause.apply(ø,arguments); + return sq; + } + return ASQ(function $$asq(){ throw "Disabled Sequence"; }); + } + } + + function registerTeardown(fn) { + if (template && typeof fn === "function") { + teardowns.push(fn); + } + } + + var template = ASQ().duplicate(), + teardowns = [], paused = false + ; + + // add reactive sequence kill switch + template.stop = function $$stop() { + if (template) { + template = null; + teardowns.forEach(Function.call,Function.call); + teardowns.length = 0; + } + }; + + template.pause = function $$pause() { + if (!paused && template) { + paused = true; + teardowns.forEach(Function.call,Function.call); + teardowns.length = 0; + } + }; + + template.resume = function $$resume() { + if (paused && template) { + paused = false; + reactor.call(template,next,registerTeardown); + } + }; + + template.push = next; + + next.onStream = function $$onStream() { + ARRAY_SLICE.call(arguments) + .forEach(function $$each(stream){ + stream.on("data",next); + stream.on("error",next); + }); + }; + + next.unStream = function $$unStream() { + ARRAY_SLICE.call(arguments) + .forEach(function $$each(stream){ + stream.removeListener("data",next); + stream.removeListener("error",next); + }); + }; + + // make sure `reactor(..)` is called async + ASQ.__schedule(function $$schedule(){ + reactor.call(template,next,registerTeardown); + }); + + return template; +}; +// "react" helpers +(function IIFE(){ + + var Ar = ASQ.react; + + Ar.of = function $$react$of() { + function reactor(next) { + if (!started) { + started = true; + if (args.length > 0) { + args.shift().val(function val(){ + next.apply(ø,arguments); + if (args.length > 0) { + args.shift().val(val); + } + }); + } + } + } + + var started, args = ARRAY_SLICE.call(arguments) + .map(function wrapper(arg){ + if (!ASQ.isSequence(arg)) arg = ASQ(arg); + return arg; + }); + + return Ar(reactor); + }; + + Ar.all = Ar.zip = makeReactOperator(/*buffer=*/true); + Ar.allLatest = makeReactOperator(/*buffer=false*/); + Ar.latest = Ar.combineLatest = makeReactOperator(/*buffer=*/false,/*keep=*/true); + + Ar.any = Ar.merge = function $$react$any(){ + function reactor(next,registerTeardown){ + function processSequence(def){ + function trigger(){ + var args = ASQ.messages.apply(ø,arguments); + // still observing sequence-streams? + if (seqs && seqs.length > 0) { + // fire off reactive sequence instance + next.apply(ø,args); + } + // keep sequence going + return args; + } + + // sequence-stream event listener + def.seq.val(trigger); + } + + // observe all sequence-streams + seqs.forEach(processSequence); + + // listen for stop() of reactive sequence + registerTeardown(function $$teardown(){ + seqs = null; + }); + } + + // observe all sequence-streams + var seqs = tapSequences.apply(null,arguments); + + if (seqs.length == 0) return; + + return Ar(reactor); + }; + + Ar.distinct = function $$react$distinct(seq){ + return Ar.filter(seq,makeDistinctFilterer(/*keepAll=*/true)); + }; + + Ar.distinctConsecutive = Ar.distinctUntilChanged = function $$react$distinct$consecutive(seq) { + return Ar.filter(seq,makeDistinctFilterer(/*keepAll=*/false)); + }; + + Ar.filter = function $$react$filter(seq,filterer){ + function reactor(next,registerTeardown) { + function trigger(){ + var messages = ASQ.messages.apply(ø,arguments); + + if (filterer && filterer.apply(ø,messages)) { + // fire off reactive sequence instance + next.apply(ø,messages); + } + + // keep sequence going + return messages; + } + + // sequence-stream event listener + def.seq.val(trigger); + + // listen for stop() of reactive sequence + registerTeardown(function $$teardown(){ + def = filterer = null; + }); + } + + // observe sequence-stream + var def = tapSequences(seq)[0]; + + if (!def) return; + + return Ar(reactor); + }; + + Ar.fromObservable = function $$react$from$observable(obsv){ + function reactor(next,registerTeardown){ + // process buffer (if any) + buffer.forEach(next); + buffer.length = 0; + + // start non-buffered notifications? + if (!buffer.complete) { + notify = next; + } + + registerTeardown(function $$teardown(){ + obsv.dispose(); + }); + } + + function notify(v) { + buffer.push(v); + } + + var buffer = []; + + obsv.subscribe( + function $$on$next(v){ + notify(v); + }, + function $$on$error(){}, + function $$on$complete(){ + buffer.complete = true; + obsv.dispose(); + } + ); + + return Ar(reactor); + }; + + ASQ.extend("toObservable",function $$extend(api,internals){ + return function $$to$observable(){ + function init(observer) { + function define(pair){ + function listen(){ + var args = ASQ.messages.apply(ø,arguments); + observer[pair[1]].apply(observer, + args.length == 1 ? [args[0]] : args + ); + return args; + } + + api[pair[0]](listen); + } + + [["val","onNext"],["or","onError"]] + .forEach(define); + } + + return Rx.Observable.create(init); + }; + }); + + function tapSequences() { + function tapSequence(seq) { + // temporary `trigger` which, if called before being replaced + // below, creates replacement proxy sequence with the + // event message(s) re-fired + function trigger() { + var args = ARRAY_SLICE.call(arguments); + def.seq = Ar(function $$react(next){ + next.apply(ø,args); + }); + } + + if (ASQ.isSequence(seq)) { + var def = { seq: seq }; + + // listen for events from the sequence-stream + seq.val(function $$val(){ + trigger.apply(ø,arguments); + return ASQ.messages.apply(ø,arguments); + }); + + // make a reactive sequence to act as a proxy to the original + // sequence + def.seq = Ar(function $$react(next){ + // replace the temporary trigger (created above) + // with this proxy's trigger + trigger = next; + }); + + return def; + } + } + + return ARRAY_SLICE.call(arguments) + .map(tapSequence) + .filter(Boolean); + } + + function makeReactOperator(buffer,keep) { + return function $$react$operator(){ + function reactor(next,registerTeardown){ + function processSequence(def) { + // sequence-stream event listener + function trigger() { + var args = ASQ.messages.apply(ø,arguments); + // still observing sequence-streams? + if (seqs && seqs.length > 0) { + // store event message(s), if any + seq_events[seq_id] = + (buffer ? seq_events[seq_id] : []).concat( + args.length > 0 ? (args.length > 1 ? [args] : args[0]) : undefined + ); + + // collect event message(s) across the + // sequence-stream sources + var messages = seq_events.reduce(function reducer(msgs,eventList,idx){ + if (eventList.length > 0) msgs.push(eventList[0]); + return msgs; + },[]); + + // did all sequence-streams get an event? + if (messages.length == seq_events.length) { + if (messages.length == 1) messages = messages[0]; + + // fire off reactive sequence instance + next.apply(ø,messages); + + // discard stored event message(s)? + if (!keep) { + seq_events.forEach(function $$each(eventList){ + eventList.shift(); + }); + } + } + } + // keep sequence going + return args; + } + + var seq_id = seq_events.length; + seq_events.push([]); + def.seq.val(trigger); + } + + // process all sequence-streams + seqs.forEach(processSequence); + + // listen for stop() of reactive sequence + registerTeardown(function $$teardown(){ + seqs = seq_events = null; + }); + } + + var seq_events = [], + // observe all sequence-streams + seqs = tapSequences.apply(null,arguments) + ; + + if (seqs.length == 0) return; + + return Ar(reactor); + }; + } + + function makeDistinctFilterer(keepAll) { + function filterer() { + function isDuplicate(msgSet) { + return ( + msgSet.length == message_set.length && + msgSet.every(function $$every(val,idx){ + return val === message_set[idx]; + }) + ); + } + + var message_set = ASQ.messages.apply(ø,arguments); + + // any messages in message-set to check against? + if (message_set.length > 0) { + // duplicate message-set? + if (msg_sets.some(isDuplicate)) { + return false; + } + + // remember all message-sets for future distinct checking? + if (keepAll) { + msg_sets.push(message_set); + } + // only keep the last message-set for distinct-consecutive + // checking + else { + msg_sets[0] = message_set; + } + } + + // allow distinct non-duplicate value through + return true; + } + + var msg_sets = []; + + return filterer; + } + +})(); +// "runner" +ASQ.extend("runner",function $$extend(api,internals){ + + return function $$runner() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var args = ARRAY_SLICE.call(arguments); + + api + .then(function $$then(mainDone){ + + function wrap(v) { + // function? expected to produce an iterator + // (like a generator) or a promise + if (typeof v === "function") { + // call function passing in the control token + // note: neutralize `this` in call to prevent + // unexpected behavior + v = v.call(ø,token); + + // promise returned (ie, from async function)? + if (isPromise(v)) { + // wrap it in iterable sequence + v = ASQ.iterable(v); + } + } + // an iterable sequence? duplicate it (in case of multiple runs) + else if (ASQ.isSequence(v) && "next" in v) { + v = v.duplicate(); + } + // wrap anything else in iterable sequence + else { + v = ASQ.iterable(v); + } + + // a sequence to tap for errors? + if (ASQ.isSequence(v)) { + // listen for any sequence failures + v.or(function $$or(){ + // signal iteration-error + mainDone.fail.apply(ø,arguments); + }); + } + + return v; + } + + function addWrapped() { + iterators.push.apply( + iterators, + ARRAY_SLICE.call(arguments).map(wrap) + ); + } + + function iterateOrQuit(iterFn,now) { + // still have some co-routine runs to process? + if (iterators.length > 0) { + if (now) iterFn(); + else schedule(iterFn); + } + // all done! + else { + // previous value message? + if (typeof next_val !== "undefined") { + // not a message wrapper array? + if (!ASQ.isMessageWrapper(next_val)) { + // wrap value for the subsequent `apply(..)` + next_val = [next_val]; + } + } + else { + // nothing to affirmatively pass along + next_val = []; + } + + // signal done with all co-routine runs + mainDone.apply(ø,next_val); + } + } + + var iterators = args, + token = { + messages: ARRAY_SLICE.call(arguments,1), + add: addWrapped + }, + iter, ret, next_val = token + ; + + // map co-routines to round-robin list of iterators + iterators = iterators.map(wrap); + + // async iteration of round-robin list + (function iterate(){ + // get next co-routine in list + iter = iterators.shift(); + + // process the iteration + try { + // multiple messages to send to an iterable + // sequence? + if (ASQ.isMessageWrapper(next_val) && + ASQ.isSequence(iter) + ) { + ret = iter.next.apply(iter,next_val); + } + else { + ret = iter.next(next_val); + } + } + catch (err) { + return mainDone.fail(err); + } + + // bail on run in aborted sequence + if (internals("seq_aborted")) return; + + // was the control token yielded? + if (ret.value === token) { + // round-robin: put co-routine back into the list + // at the end where it was so it can be processed + // again on next loop-iteration + if (!ret.done) { + iterators.push(iter); + } + next_val = token; + iterateOrQuit(iterate,/*now=*/false); + } + else { + // not a recognized ASQ instance returned? + if (!ASQ.isSequence(ret.value)) { + // received a thenable/promise back? + if (isPromise(ret.value)) { + // wrap in a sequence + ret.value = ASQ().promise(ret.value); + } + // thunk yielded? + else if (typeof ret.value === "function") { + // wrap thunk call in a sequence + var fn = ret.value; + ret.value = ASQ(function $$ASQ(done){ + fn(done.errfcb); + }); + } + // message wrapper returned? + else if (ASQ.isMessageWrapper(ret.value)) { + // wrap message(s) in a sequence + ret.value = ASQ.apply(ø, + // don't let `apply(..)` discard an empty message + // wrapper! instead, pass it along as its own value + // itself. + ret.value.length > 0 ? ret.value : ASQ.messages(undefined) + ); + } + // non-undefined value returned? + else if (typeof ret.value !== "undefined") { + // wrap the value in a sequence + ret.value = ASQ(ret.value); + } + else { + // make an empty sequence + ret.value = ASQ(); + } + } + + ret.value + .val(function $$val(){ + // bail on run in aborted sequence + if (internals("seq_aborted")) return; + + if (arguments.length > 0) { + // save any return messages for input + // to next iteration + next_val = arguments.length > 1 ? + ASQ.messages.apply(ø,arguments) : + arguments[0] + ; + } + + // still more to iterate? + if (!ret.done) { + // was the control token passed along? + if (next_val === token) { + // round-robin: put co-routine back into the list + // at the end, so that the the next iterator can be + // processed on next loop-iteration + iterators.push(iter); + } + else { + // put co-routine back in where it just + // was so it can be processed again on + // next loop-iteration + iterators.unshift(iter); + } + } + + iterateOrQuit(iterate,/*now=*/true); + }) + .or(function $$or(){ + // bail on run in aborted sequence + if (internals("seq_aborted")) return; + + try { + // if an error occurs in the step-continuation + // promise or sequence, throw it back into the + // generator or iterable-sequence + iter["throw"].apply(iter,arguments); + } + catch (err) { + // if an error comes back out of after the throw, + // pass it out to the main sequence, as iteration + // must now be complete + mainDone.fail(err); + } + }); + } + })(); + }); + + return api; + }; +}); +// "toPromise" +ASQ.extend("toPromise",function $$extend(api,internals){ + return function $$to$promise() { + return new Promise(function $$executor(resolve,reject){ + api + .val(function $$val(){ + var args = ARRAY_SLICE.call(arguments); + resolve.call(ø,args.length > 1 ? args : args[0]); + return ASQ.messages.apply(ø,args); + }) + .or(function $$or(){ + var args = ARRAY_SLICE.call(arguments); + reject.call(ø,args.length > 1 ? args : args[0]); + }); + }); + }; +}); +// "try" +ASQ.extend("try",function $$extend(api,internals){ + return function $$try() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments) + .map(function $$map(fn){ + return function $$then(mainDone) { + var main_args = ARRAY_SLICE.call(arguments), + sq = ASQ.apply(ø,main_args.slice(1)) + ; + + sq + .then(function $$inner$then(){ + fn.apply(ø,arguments); + }) + .val(function $$val(){ + mainDone.apply(ø,arguments); + }) + .or(function $$inner$or(){ + var msgs = ASQ.messages.apply(ø,arguments); + // failed, so map error(s) as `catch` + mainDone({ + "catch": msgs.length > 1 ? msgs : msgs[0] + }); + }); + }; + }); + + api.then.apply(ø,fns); + + return api; + }; +}); +// "until" +ASQ.extend("until",function $$extend(api,internals){ + return function $$until() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments) + .map(function $$map(fn){ + return function $$then(mainDone) { + var main_args = ARRAY_SLICE.call(arguments), + sq = ASQ.apply(ø,main_args.slice(1)) + ; + + sq + .then(function $$inner$then(){ + var args = ARRAY_SLICE.call(arguments); + args[0]["break"] = function $$break(){ + mainDone.fail.apply(ø,arguments); + sq.abort(); + }; + + fn.apply(ø,args); + }) + .val(function $$val(){ + mainDone.apply(ø,arguments); + }) + .or(function $$inner$or(){ + // failed, retry + $$then.apply(ø,main_args); + }); + }; + }); + + api.then.apply(ø,fns); + + return api; + }; +}); +// "waterfall" +ASQ.extend("waterfall",function $$extend(api,internals){ + return function $$waterfall() { + if (internals("seq_error") || internals("seq_aborted") || + arguments.length === 0 + ) { + return api; + } + + var fns = ARRAY_SLICE.call(arguments); + + api.then(function $$then(done){ + var msgs = ASQ.messages(), + sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)) + ; + + fns.forEach(function $$each(fn){ + sq.then(fn) + .val(function $$val(){ + var args = ASQ.messages.apply(ø,arguments); + msgs.push(args.length > 1 ? args : args[0]); + return msgs; + }); + }); + + sq.pipe(done); + }); + + return api; + }; +}); +// "wrap" +ASQ.wrap = function $$wrap(fn,opts) { + function checkThis(t,o) { + return (!t || + (typeof window != "undefined" && t === window) || + (typeof global != "undefined" && t === global) + ) ? o : t; + } + + function paramSpread(gen) { + return function *paramSpread(token) { + yield *gen.apply(this,token.messages); + }; + } + + var errfcb, params_first, act, this_obj; + + opts = (opts && typeof opts == "object") ? opts : {}; + + if ( + (opts.errfcb && opts.splitcb) || + (opts.errfcb && opts.simplecb) || + (opts.splitcb && opts.simplecb) || + ("errfcb" in opts && !opts.errfcb && !opts.splitcb && !opts.simplecb) || + (opts.params_first && opts.params_last) || + (opts.spread && !opts.gen) + ) { + throw Error("Invalid options"); + } + + // initialize default flags + this_obj = (opts["this"] && typeof opts["this"] == "object") ? opts["this"] : ø; + errfcb = opts.errfcb || !(opts.splitcb || opts.simplecb); + params_first = !!opts.params_first || + (!opts.params_last && !("params_first" in opts || opts.params_first)) || + ("params_last" in opts && !opts.params_first && !opts.params_last) + ; + + if (params_first) { + act = "push"; + } + else { + act = "unshift"; + } + + if (opts.gen) { + if (opts.spread) { + fn = paramSpread(fn); + } + return function $$wrapped$gen() { + return ASQ.apply(ø,arguments).runner(fn); + }; + } + if (errfcb) { + return function $$wrapped$errfcb() { + var args = ARRAY_SLICE.call(arguments), + _this = checkThis(this,this_obj) + ; + + return ASQ(function $$asq(done){ + args[act](done.errfcb); + fn.apply(_this,args); + }); + }; + } + if (opts.splitcb) { + return function $$wrapped$splitcb() { + var args = ARRAY_SLICE.call(arguments), + _this = checkThis(this,this_obj) + ; + + return ASQ(function $$asq(done){ + args[act](done,done.fail); + fn.apply(_this,args); + }); + }; + } + if (opts.simplecb) { + return function $$wrapped$simplecb() { + var args = ARRAY_SLICE.call(arguments), + _this = checkThis(this,this_obj) + ; + + return ASQ(function $$asq(done){ + args[act](done); + fn.apply(_this,args); + }); + }; + } +}; + + + // just return `ASQ` itself for convenience sake + return ASQ; +}); diff --git a/frontend-masters-exercises/exercises/ex9/browser-polyfill.min.js b/frontend-masters-exercises/exercises/ex9/browser-polyfill.min.js new file mode 100755 index 0000000..f0683c2 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex9/browser-polyfill.min.js @@ -0,0 +1,3 @@ +(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;oindex){value=O[index++];if(value!=value)return true}else for(;length>index;index++)if(IS_INCLUDES||index in O){if(O[index]===el)return IS_INCLUDES||index}return!IS_INCLUDES&&-1}}},{"./$":24}],4:[function(require,module,exports){var $=require("./$"),ctx=require("./$.ctx");module.exports=function(TYPE){var IS_MAP=TYPE==1,IS_FILTER=TYPE==2,IS_SOME=TYPE==3,IS_EVERY=TYPE==4,IS_FIND_INDEX=TYPE==6,NO_HOLES=TYPE==5||IS_FIND_INDEX;return function($this,callbackfn,that){var O=Object($.assertDefined($this)),self=$.ES5Object(O),f=ctx(callbackfn,that,3),length=$.toLength(self.length),index=0,result=IS_MAP?Array(length):IS_FILTER?[]:undefined,val,res;for(;length>index;index++)if(NO_HOLES||index in self){val=self[index];res=f(val,index,O);if(TYPE){if(IS_MAP)result[index]=res;else if(res)switch(TYPE){case 3:return true;case 5:return val;case 6:return index;case 2:result.push(val)}else if(IS_EVERY)return false}}return IS_FIND_INDEX?-1:IS_SOME||IS_EVERY?IS_EVERY:result}}},{"./$":24,"./$.ctx":12}],5:[function(require,module,exports){var $=require("./$");function assert(condition,msg1,msg2){if(!condition)throw TypeError(msg2?msg1+msg2:msg1)}assert.def=$.assertDefined;assert.fn=function(it){if(!$.isFunction(it))throw TypeError(it+" is not a function!");return it};assert.obj=function(it){if(!$.isObject(it))throw TypeError(it+" is not an object!");return it};assert.inst=function(it,Constructor,name){if(!(it instanceof Constructor))throw TypeError(name+": use the 'new' operator!");return it};module.exports=assert},{"./$":24}],6:[function(require,module,exports){var $=require("./$"),enumKeys=require("./$.enum-keys");module.exports=Object.assign||function assign(target,source){var T=Object($.assertDefined(target)),l=arguments.length,i=1;while(l>i){var S=$.ES5Object(arguments[i++]),keys=enumKeys(S),length=keys.length,j=0,key;while(length>j)T[key=keys[j++]]=S[key]}return T}},{"./$":24,"./$.enum-keys":15}],7:[function(require,module,exports){var $=require("./$"),TAG=require("./$.wks")("toStringTag"),toString={}.toString;function cof(it){return toString.call(it).slice(8,-1)}cof.classof=function(it){var O,T;return it==undefined?it===undefined?"Undefined":"Null":typeof(T=(O=Object(it))[TAG])=="string"?T:cof(O)};cof.set=function(it,tag,stat){if(it&&!$.has(it=stat?it:it.prototype,TAG))$.hide(it,TAG,tag)};module.exports=cof},{"./$":24,"./$.wks":42}],8:[function(require,module,exports){"use strict";var $=require("./$"),ctx=require("./$.ctx"),safe=require("./$.uid").safe,assert=require("./$.assert"),forOf=require("./$.for-of"),step=require("./$.iter").step,$has=$.has,set=$.set,isObject=$.isObject,hide=$.hide,isExtensible=Object.isExtensible||isObject,ID=safe("id"),O1=safe("O1"),LAST=safe("last"),FIRST=safe("first"),ITER=safe("iter"),SIZE=$.DESC?safe("size"):"size",id=0;function fastKey(it,create){if(!isObject(it))return typeof it=="symbol"?it:(typeof it=="string"?"S":"P")+it;if(!$has(it,ID)){if(!isExtensible(it))return"F";if(!create)return"E";hide(it,ID,++id)}return"O"+it[ID]}function getEntry(that,key){var index=fastKey(key),entry;if(index!=="F")return that[O1][index];for(entry=that[FIRST];entry;entry=entry.n){if(entry.k==key)return entry}}module.exports={getConstructor:function(wrapper,NAME,IS_MAP,ADDER){var C=wrapper(function(that,iterable){assert.inst(that,C,NAME);set(that,O1,$.create(null));set(that,SIZE,0);set(that,LAST,undefined);set(that,FIRST,undefined);if(iterable!=undefined)forOf(iterable,IS_MAP,that[ADDER],that)});require("./$.mix")(C.prototype,{clear:function clear(){for(var that=this,data=that[O1],entry=that[FIRST];entry;entry=entry.n){entry.r=true;if(entry.p)entry.p=entry.p.n=undefined;delete data[entry.i]}that[FIRST]=that[LAST]=undefined;that[SIZE]=0},"delete":function(key){var that=this,entry=getEntry(that,key);if(entry){var next=entry.n,prev=entry.p;delete that[O1][entry.i];entry.r=true;if(prev)prev.n=next;if(next)next.p=prev;if(that[FIRST]==entry)that[FIRST]=next;if(that[LAST]==entry)that[LAST]=prev;that[SIZE]--}return!!entry},forEach:function forEach(callbackfn){var f=ctx(callbackfn,arguments[1],3),entry;while(entry=entry?entry.n:this[FIRST]){f(entry.v,entry.k,this);while(entry&&entry.r)entry=entry.p}},has:function has(key){return!!getEntry(this,key)}});if($.DESC)$.setDesc(C.prototype,"size",{get:function(){return assert.def(this[SIZE])}});return C},def:function(that,key,value){var entry=getEntry(that,key),prev,index;if(entry){entry.v=value}else{that[LAST]=entry={i:index=fastKey(key,true),k:key,v:value,p:prev=that[LAST],n:undefined,r:false};if(!that[FIRST])that[FIRST]=entry;if(prev)prev.n=entry;that[SIZE]++;if(index!=="F")that[O1][index]=entry}return that},getEntry:getEntry,setIter:function(C,NAME,IS_MAP){require("./$.iter-define")(C,NAME,function(iterated,kind){set(this,ITER,{o:iterated,k:kind})},function(){var iter=this[ITER],kind=iter.k,entry=iter.l;while(entry&&entry.r)entry=entry.p;if(!iter.o||!(iter.l=entry=entry?entry.n:iter.o[FIRST])){iter.o=undefined;return step(1)}if(kind=="keys")return step(0,entry.k);if(kind=="values")return step(0,entry.v);return step(0,[entry.k,entry.v])},IS_MAP?"entries":"values",!IS_MAP,true)}}},{"./$":24,"./$.assert":5,"./$.ctx":12,"./$.for-of":16,"./$.iter":23,"./$.iter-define":21,"./$.mix":26,"./$.uid":40}],9:[function(require,module,exports){var $def=require("./$.def"),forOf=require("./$.for-of");module.exports=function(NAME){$def($def.P,NAME,{toJSON:function toJSON(){var arr=[];forOf(this,false,arr.push,arr);return arr}})}},{"./$.def":13,"./$.for-of":16}],10:[function(require,module,exports){"use strict";var $=require("./$"),safe=require("./$.uid").safe,assert=require("./$.assert"),forOf=require("./$.for-of"),$has=$.has,isObject=$.isObject,hide=$.hide,isExtensible=Object.isExtensible||isObject,id=0,ID=safe("id"),WEAK=safe("weak"),LEAK=safe("leak"),method=require("./$.array-methods"),find=method(5),findIndex=method(6);function findFrozen(store,key){return find(store.array,function(it){return it[0]===key})}function leakStore(that){return that[LEAK]||hide(that,LEAK,{array:[],get:function(key){var entry=findFrozen(this,key);if(entry)return entry[1]},has:function(key){return!!findFrozen(this,key)},set:function(key,value){var entry=findFrozen(this,key);if(entry)entry[1]=value;else this.array.push([key,value])},"delete":function(key){var index=findIndex(this.array,function(it){return it[0]===key});if(~index)this.array.splice(index,1);return!!~index}})[LEAK]}module.exports={getConstructor:function(wrapper,NAME,IS_MAP,ADDER){var C=wrapper(function(that,iterable){$.set(assert.inst(that,C,NAME),ID,id++);if(iterable!=undefined)forOf(iterable,IS_MAP,that[ADDER],that)});require("./$.mix")(C.prototype,{"delete":function(key){if(!isObject(key))return false;if(!isExtensible(key))return leakStore(this)["delete"](key);return $has(key,WEAK)&&$has(key[WEAK],this[ID])&&delete key[WEAK][this[ID]]},has:function has(key){if(!isObject(key))return false;if(!isExtensible(key))return leakStore(this).has(key);return $has(key,WEAK)&&$has(key[WEAK],this[ID])}});return C},def:function(that,key,value){if(!isExtensible(assert.obj(key))){leakStore(that).set(key,value)}else{$has(key,WEAK)||hide(key,WEAK,{});key[WEAK][that[ID]]=value}return that},leakStore:leakStore,WEAK:WEAK,ID:ID}},{"./$":24,"./$.array-methods":4,"./$.assert":5,"./$.for-of":16,"./$.mix":26,"./$.uid":40}],11:[function(require,module,exports){"use strict";var $=require("./$"),$def=require("./$.def"),BUGGY=require("./$.iter").BUGGY,forOf=require("./$.for-of"),species=require("./$.species"),assertInstance=require("./$.assert").inst;module.exports=function(NAME,wrapper,methods,common,IS_MAP,IS_WEAK){var Base=$.g[NAME],C=Base,ADDER=IS_MAP?"set":"add",proto=C&&C.prototype,O={};function fixMethod(KEY){var fn=proto[KEY];require("./$.redef")(proto,KEY,KEY=="delete"?function(a){return fn.call(this,a===0?0:a)}:KEY=="has"?function has(a){return fn.call(this,a===0?0:a)}:KEY=="get"?function get(a){return fn.call(this,a===0?0:a)}:KEY=="add"?function add(a){fn.call(this,a===0?0:a);return this}:function set(a,b){fn.call(this,a===0?0:a,b);return this})}if(!$.isFunction(C)||!(IS_WEAK||!BUGGY&&proto.forEach&&proto.entries)){C=common.getConstructor(wrapper,NAME,IS_MAP,ADDER);require("./$.mix")(C.prototype,methods)}else{var inst=new C,chain=inst[ADDER](IS_WEAK?{}:-0,1),buggyZero;if(!require("./$.iter-detect")(function(iter){new C(iter)})){C=wrapper(function(target,iterable){assertInstance(target,C,NAME);var that=new Base;if(iterable!=undefined)forOf(iterable,IS_MAP,that[ADDER],that);return that});C.prototype=proto;proto.constructor=C}IS_WEAK||inst.forEach(function(val,key){buggyZero=1/key===-Infinity});if(buggyZero){fixMethod("delete");fixMethod("has");IS_MAP&&fixMethod("get")}if(buggyZero||chain!==inst)fixMethod(ADDER)}require("./$.cof").set(C,NAME);O[NAME]=C;$def($def.G+$def.W+$def.F*(C!=Base),O);species(C);species($.core[NAME]);if(!IS_WEAK)common.setIter(C,NAME,IS_MAP);return C}},{"./$":24,"./$.assert":5,"./$.cof":7,"./$.def":13,"./$.for-of":16,"./$.iter":23,"./$.iter-detect":22,"./$.mix":26,"./$.redef":29,"./$.species":34}],12:[function(require,module,exports){var assertFunction=require("./$.assert").fn;module.exports=function(fn,that,length){assertFunction(fn);if(~length&&that===undefined)return fn;switch(length){case 1:return function(a){return fn.call(that,a)};case 2:return function(a,b){return fn.call(that,a,b)};case 3:return function(a,b,c){return fn.call(that,a,b,c)}}return function(){return fn.apply(that,arguments)}}},{"./$.assert":5}],13:[function(require,module,exports){var $=require("./$"),global=$.g,core=$.core,isFunction=$.isFunction,$redef=require("./$.redef");function ctx(fn,that){return function(){return fn.apply(that,arguments)}}global.core=core;$def.F=1;$def.G=2;$def.S=4;$def.P=8;$def.B=16;$def.W=32;function $def(type,name,source){var key,own,out,exp,isGlobal=type&$def.G,isProto=type&$def.P,target=isGlobal?global:type&$def.S?global[name]:(global[name]||{}).prototype,exports=isGlobal?core:core[name]||(core[name]={});if(isGlobal)source=name;for(key in source){own=!(type&$def.F)&&target&&key in target;out=(own?target:source)[key];if(type&$def.B&&own)exp=ctx(out,global);else exp=isProto&&isFunction(out)?ctx(Function.call,out):out;if(target&&!own)$redef(target,key,out);if(exports[key]!=out)$.hide(exports,key,exp);if(isProto)(exports.prototype||(exports.prototype={}))[key]=out}}module.exports=$def},{"./$":24,"./$.redef":29}],14:[function(require,module,exports){var $=require("./$"),document=$.g.document,isObject=$.isObject,is=isObject(document)&&isObject(document.createElement);module.exports=function(it){return is?document.createElement(it):{}}},{"./$":24}],15:[function(require,module,exports){var $=require("./$");module.exports=function(it){var keys=$.getKeys(it),getDesc=$.getDesc,getSymbols=$.getSymbols;if(getSymbols)$.each.call(getSymbols(it),function(key){if(getDesc(it,key).enumerable)keys.push(key)});return keys}},{"./$":24}],16:[function(require,module,exports){var ctx=require("./$.ctx"),get=require("./$.iter").get,call=require("./$.iter-call");module.exports=function(iterable,entries,fn,that){var iterator=get(iterable),f=ctx(fn,that,entries?2:1),step;while(!(step=iterator.next()).done){if(call(iterator,f,step.value,entries)===false){return call.close(iterator)}}}},{"./$.ctx":12,"./$.iter":23,"./$.iter-call":20}],17:[function(require,module,exports){module.exports=function($){$.FW=true;$.path=$.g;return $}},{}],18:[function(require,module,exports){var $=require("./$"),toString={}.toString,getNames=$.getNames;var windowNames=typeof window=="object"&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[];function getWindowNames(it){try{return getNames(it)}catch(e){return windowNames.slice()}}module.exports.get=function getOwnPropertyNames(it){if(windowNames&&toString.call(it)=="[object Window]")return getWindowNames(it);return getNames($.toObject(it))}},{"./$":24}],19:[function(require,module,exports){module.exports=function(fn,args,that){var un=that===undefined;switch(args.length){case 0:return un?fn():fn.call(that);case 1:return un?fn(args[0]):fn.call(that,args[0]);case 2:return un?fn(args[0],args[1]):fn.call(that,args[0],args[1]);case 3:return un?fn(args[0],args[1],args[2]):fn.call(that,args[0],args[1],args[2]);case 4:return un?fn(args[0],args[1],args[2],args[3]):fn.call(that,args[0],args[1],args[2],args[3]);case 5:return un?fn(args[0],args[1],args[2],args[3],args[4]):fn.call(that,args[0],args[1],args[2],args[3],args[4])}return fn.apply(that,args)}},{}],20:[function(require,module,exports){var assertObject=require("./$.assert").obj;function close(iterator){var ret=iterator["return"];if(ret!==undefined)assertObject(ret.call(iterator))}function call(iterator,fn,value,entries){try{return entries?fn(assertObject(value)[0],value[1]):fn(value)}catch(e){close(iterator);throw e}}call.close=close;module.exports=call},{"./$.assert":5}],21:[function(require,module,exports){var $def=require("./$.def"),$redef=require("./$.redef"),$=require("./$"),cof=require("./$.cof"),$iter=require("./$.iter"),SYMBOL_ITERATOR=require("./$.wks")("iterator"),FF_ITERATOR="@@iterator",KEYS="keys",VALUES="values",Iterators=$iter.Iterators;module.exports=function(Base,NAME,Constructor,next,DEFAULT,IS_SET,FORCE){$iter.create(Constructor,NAME,next);function createMethod(kind){function $$(that){return new Constructor(that,kind)}switch(kind){case KEYS:return function keys(){return $$(this)};case VALUES:return function values(){return $$(this)}}return function entries(){return $$(this)}}var TAG=NAME+" Iterator",proto=Base.prototype,_native=proto[SYMBOL_ITERATOR]||proto[FF_ITERATOR]||DEFAULT&&proto[DEFAULT],_default=_native||createMethod(DEFAULT),methods,key;if(_native){var IteratorPrototype=$.getProto(_default.call(new Base));cof.set(IteratorPrototype,TAG,true);if($.FW&&$.has(proto,FF_ITERATOR))$iter.set(IteratorPrototype,$.that)}if($.FW||FORCE)$iter.set(proto,_default);Iterators[NAME]=_default;Iterators[TAG]=$.that;if(DEFAULT){methods={keys:IS_SET?_default:createMethod(KEYS),values:DEFAULT==VALUES?_default:createMethod(VALUES),entries:DEFAULT!=VALUES?_default:createMethod("entries")};if(FORCE)for(key in methods){if(!(key in proto))$redef(proto,key,methods[key])}else $def($def.P+$def.F*$iter.BUGGY,NAME,methods)}}},{"./$":24,"./$.cof":7,"./$.def":13,"./$.iter":23,"./$.redef":29,"./$.wks":42}],22:[function(require,module,exports){var SYMBOL_ITERATOR=require("./$.wks")("iterator"),SAFE_CLOSING=false;try{var riter=[7][SYMBOL_ITERATOR]();riter["return"]=function(){SAFE_CLOSING=true};Array.from(riter,function(){throw 2})}catch(e){}module.exports=function(exec){if(!SAFE_CLOSING)return false;var safe=false;try{var arr=[7],iter=arr[SYMBOL_ITERATOR]();iter.next=function(){safe=true};arr[SYMBOL_ITERATOR]=function(){return iter};exec(arr)}catch(e){}return safe}},{"./$.wks":42}],23:[function(require,module,exports){"use strict";var $=require("./$"),cof=require("./$.cof"),classof=cof.classof,assert=require("./$.assert"),assertObject=assert.obj,SYMBOL_ITERATOR=require("./$.wks")("iterator"),FF_ITERATOR="@@iterator",Iterators=require("./$.shared")("iterators"),IteratorPrototype={};setIterator(IteratorPrototype,$.that);function setIterator(O,value){$.hide(O,SYMBOL_ITERATOR,value);if(FF_ITERATOR in[])$.hide(O,FF_ITERATOR,value)}module.exports={BUGGY:"keys"in[]&&!("next"in[].keys()),Iterators:Iterators,step:function(done,value){return{value:value,done:!!done}},is:function(it){var O=Object(it),Symbol=$.g.Symbol;return(Symbol&&Symbol.iterator||FF_ITERATOR)in O||SYMBOL_ITERATOR in O||$.has(Iterators,classof(O))},get:function(it){var Symbol=$.g.Symbol,getIter;if(it!=undefined){getIter=it[Symbol&&Symbol.iterator||FF_ITERATOR]||it[SYMBOL_ITERATOR]||Iterators[classof(it)]}assert($.isFunction(getIter),it," is not iterable!");return assertObject(getIter.call(it))},set:setIterator,create:function(Constructor,NAME,next,proto){Constructor.prototype=$.create(proto||IteratorPrototype,{next:$.desc(1,next)});cof.set(Constructor,NAME+" Iterator")}}},{"./$":24,"./$.assert":5,"./$.cof":7,"./$.shared":33,"./$.wks":42}],24:[function(require,module,exports){"use strict";var global=typeof self!="undefined"?self:Function("return this")(),core={},defineProperty=Object.defineProperty,hasOwnProperty={}.hasOwnProperty,ceil=Math.ceil,floor=Math.floor,max=Math.max,min=Math.min;var DESC=!!function(){try{return defineProperty({},"a",{get:function(){return 2}}).a==2}catch(e){}}();var hide=createDefiner(1);function toInteger(it){return isNaN(it=+it)?0:(it>0?floor:ceil)(it)}function desc(bitmap,value){return{enumerable:!(bitmap&1),configurable:!(bitmap&2),writable:!(bitmap&4),value:value}}function simpleSet(object,key,value){object[key]=value;return object}function createDefiner(bitmap){return DESC?function(object,key,value){return $.setDesc(object,key,desc(bitmap,value))}:simpleSet}function isObject(it){return it!==null&&(typeof it=="object"||typeof it=="function")}function isFunction(it){return typeof it=="function"}function assertDefined(it){if(it==undefined)throw TypeError("Can't call method on "+it);return it}var $=module.exports=require("./$.fw")({g:global,core:core,html:global.document&&document.documentElement,isObject:isObject,isFunction:isFunction,that:function(){return this},toInteger:toInteger,toLength:function(it){return it>0?min(toInteger(it),9007199254740991):0},toIndex:function(index,length){index=toInteger(index);return index<0?max(index+length,0):min(index,length)},has:function(it,key){return hasOwnProperty.call(it,key)},create:Object.create,getProto:Object.getPrototypeOf,DESC:DESC,desc:desc,getDesc:Object.getOwnPropertyDescriptor,setDesc:defineProperty,setDescs:Object.defineProperties,getKeys:Object.keys,getNames:Object.getOwnPropertyNames,getSymbols:Object.getOwnPropertySymbols,assertDefined:assertDefined,ES5Object:Object,toObject:function(it){return $.ES5Object(assertDefined(it))},hide:hide,def:createDefiner(0),set:global.Symbol?simpleSet:hide,each:[].forEach});if(typeof __e!="undefined")__e=core;if(typeof __g!="undefined")__g=global},{"./$.fw":17}],25:[function(require,module,exports){var $=require("./$");module.exports=function(object,el){var O=$.toObject(object),keys=$.getKeys(O),length=keys.length,index=0,key;while(length>index)if(O[key=keys[index++]]===el)return key}},{"./$":24}],26:[function(require,module,exports){var $redef=require("./$.redef");module.exports=function(target,src){for(var key in src)$redef(target,key,src[key]);return target}},{"./$.redef":29}],27:[function(require,module,exports){var $=require("./$"),assertObject=require("./$.assert").obj;module.exports=function ownKeys(it){assertObject(it);var keys=$.getNames(it),getSymbols=$.getSymbols;return getSymbols?keys.concat(getSymbols(it)):keys}},{"./$":24,"./$.assert":5}],28:[function(require,module,exports){"use strict";var $=require("./$"),invoke=require("./$.invoke"),assertFunction=require("./$.assert").fn;module.exports=function(){var fn=assertFunction(this),length=arguments.length,pargs=Array(length),i=0,_=$.path._,holder=false;while(length>i)if((pargs[i]=arguments[i++])===_)holder=true;return function(){var that=this,_length=arguments.length,j=0,k=0,args;if(!holder&&!_length)return invoke(fn,pargs,that);args=pargs.slice();if(holder)for(;length>j;j++)if(args[j]===_)args[j]=arguments[k++];while(_length>k)args.push(arguments[k++]);return invoke(fn,args,that)}}},{"./$":24,"./$.assert":5,"./$.invoke":19}],29:[function(require,module,exports){var $=require("./$"),tpl=String({}.hasOwnProperty),SRC=require("./$.uid").safe("src"),_toString=Function.toString;function $redef(O,key,val,safe){if($.isFunction(val)){var base=O[key];$.hide(val,SRC,base?String(base):tpl.replace(/hasOwnProperty/,String(key)));if(!("name"in val))val.name=key}if(O===$.g){O[key]=val}else{if(!safe)delete O[key];$.hide(O,key,val)}}$redef(Function.prototype,"toString",function toString(){return $.has(this,SRC)?this[SRC]:_toString.call(this)});$.core.inspectSource=function(it){return _toString.call(it)};module.exports=$redef},{"./$":24,"./$.uid":40}],30:[function(require,module,exports){"use strict";module.exports=function(regExp,replace,isStatic){var replacer=replace===Object(replace)?function(part){return replace[part]}:replace;return function(it){return String(isStatic?it:this).replace(regExp,replacer)}}},{}],31:[function(require,module,exports){module.exports=Object.is||function is(x,y){return x===y?x!==0||1/x===1/y:x!=x&&y!=y}},{}],32:[function(require,module,exports){var $=require("./$"),assert=require("./$.assert");function check(O,proto){assert.obj(O);assert(proto===null||$.isObject(proto),proto,": can't set as prototype!")}module.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(buggy,set){try{set=require("./$.ctx")(Function.call,$.getDesc(Object.prototype,"__proto__").set,2);set({},[])}catch(e){buggy=true}return function setPrototypeOf(O,proto){check(O,proto);if(buggy)O.__proto__=proto;else set(O,proto);return O}}():undefined),check:check}},{"./$":24,"./$.assert":5,"./$.ctx":12}],33:[function(require,module,exports){var $=require("./$"),SHARED="__core-js_shared__",store=$.g[SHARED]||($.g[SHARED]={});module.exports=function(key){return store[key]||(store[key]={})}},{"./$":24}],34:[function(require,module,exports){var $=require("./$"),SPECIES=require("./$.wks")("species");module.exports=function(C){if($.DESC&&!(SPECIES in C))$.setDesc(C,SPECIES,{configurable:true,get:$.that})}},{"./$":24,"./$.wks":42}],35:[function(require,module,exports){var $=require("./$");module.exports=function(TO_STRING){return function(that,pos){var s=String($.assertDefined(that)),i=$.toInteger(pos),l=s.length,a,b;if(i<0||i>=l)return TO_STRING?"":undefined;a=s.charCodeAt(i);return a<55296||a>56319||i+1===l||(b=s.charCodeAt(i+1))<56320||b>57343?TO_STRING?s.charAt(i):a:TO_STRING?s.slice(i,i+2):(a-55296<<10)+(b-56320)+65536}}},{"./$":24}],36:[function(require,module,exports){var $=require("./$"),repeat=require("./$.string-repeat");module.exports=function(that,minLength,fillChar,left){var S=String($.assertDefined(that));if(minLength===undefined)return S;var intMinLength=$.toInteger(minLength);var fillLen=intMinLength-S.length;if(fillLen<0||fillLen===Infinity){throw new RangeError("Cannot satisfy string length "+minLength+" for string: "+S)}var sFillStr=fillChar===undefined?" ":String(fillChar);var sFillVal=repeat.call(sFillStr,Math.ceil(fillLen/sFillStr.length));if(sFillVal.length>fillLen)sFillVal=left?sFillVal.slice(sFillVal.length-fillLen):sFillVal.slice(0,fillLen);return left?sFillVal.concat(S):S.concat(sFillVal)}},{"./$":24,"./$.string-repeat":37}],37:[function(require,module,exports){"use strict";var $=require("./$");module.exports=function repeat(count){var str=String($.assertDefined(this)),res="",n=$.toInteger(count);if(n<0||n==Infinity)throw RangeError("Count can't be negative");for(;n>0;(n>>>=1)&&(str+=str))if(n&1)res+=str;return res}},{"./$":24}],38:[function(require,module,exports){"use strict";var $=require("./$"),ctx=require("./$.ctx"),cof=require("./$.cof"),invoke=require("./$.invoke"),cel=require("./$.dom-create"),global=$.g,isFunction=$.isFunction,html=$.html,process=global.process,setTask=global.setImmediate,clearTask=global.clearImmediate,MessageChannel=global.MessageChannel,counter=0,queue={},ONREADYSTATECHANGE="onreadystatechange",defer,channel,port;function run(){var id=+this;if($.has(queue,id)){var fn=queue[id];delete queue[id];fn()}}function listner(event){run.call(event.data)}if(!isFunction(setTask)||!isFunction(clearTask)){setTask=function(fn){var args=[],i=1;while(arguments.length>i)args.push(arguments[i++]);queue[++counter]=function(){invoke(isFunction(fn)?fn:Function(fn),args)};defer(counter);return counter};clearTask=function(id){delete queue[id]};if(cof(process)=="process"){defer=function(id){process.nextTick(ctx(run,id,1))}}else if(global.addEventListener&&isFunction(global.postMessage)&&!global.importScripts){defer=function(id){global.postMessage(id,"*")};global.addEventListener("message",listner,false)}else if(isFunction(MessageChannel)){channel=new MessageChannel;port=channel.port2;channel.port1.onmessage=listner;defer=ctx(port.postMessage,port,1)}else if(ONREADYSTATECHANGE in cel("script")){defer=function(id){html.appendChild(cel("script"))[ONREADYSTATECHANGE]=function(){html.removeChild(this);run.call(id)}}}else{defer=function(id){setTimeout(ctx(run,id,1),0)}}}module.exports={set:setTask,clear:clearTask}},{"./$":24,"./$.cof":7,"./$.ctx":12,"./$.dom-create":14,"./$.invoke":19}],39:[function(require,module,exports){module.exports=function(exec){try{exec();return false}catch(e){return true}}},{}],40:[function(require,module,exports){var sid=0;function uid(key){return"Symbol(".concat(key===undefined?"":key,")_",(++sid+Math.random()).toString(36))}uid.safe=require("./$").g.Symbol||uid;module.exports=uid},{"./$":24}],41:[function(require,module,exports){var UNSCOPABLES=require("./$.wks")("unscopables");if(!(UNSCOPABLES in[]))require("./$").hide(Array.prototype,UNSCOPABLES,{});module.exports=function(key){[][UNSCOPABLES][key]=true}},{"./$":24,"./$.wks":42}],42:[function(require,module,exports){var global=require("./$").g,store=require("./$.shared")("wks");module.exports=function(name){return store[name]||(store[name]=global.Symbol&&global.Symbol[name]||require("./$.uid").safe("Symbol."+name))}},{"./$":24,"./$.shared":33,"./$.uid":40}],43:[function(require,module,exports){var $=require("./$"),cel=require("./$.dom-create"),cof=require("./$.cof"),$def=require("./$.def"),invoke=require("./$.invoke"),arrayMethod=require("./$.array-methods"),IE_PROTO=require("./$.uid").safe("__proto__"),assert=require("./$.assert"),assertObject=assert.obj,ObjectProto=Object.prototype,html=$.html,A=[],_slice=A.slice,_join=A.join,classof=cof.classof,has=$.has,defineProperty=$.setDesc,getOwnDescriptor=$.getDesc,defineProperties=$.setDescs,isFunction=$.isFunction,isObject=$.isObject,toObject=$.toObject,toLength=$.toLength,toIndex=$.toIndex,IE8_DOM_DEFINE=false,$indexOf=require("./$.array-includes")(false),$forEach=arrayMethod(0),$map=arrayMethod(1),$filter=arrayMethod(2),$some=arrayMethod(3),$every=arrayMethod(4);if(!$.DESC){try{IE8_DOM_DEFINE=defineProperty(cel("div"),"x",{get:function(){return 8}}).x==8}catch(e){}$.setDesc=function(O,P,Attributes){if(IE8_DOM_DEFINE)try{return defineProperty(O,P,Attributes)}catch(e){}if("get"in Attributes||"set"in Attributes)throw TypeError("Accessors not supported!");if("value"in Attributes)assertObject(O)[P]=Attributes.value;return O};$.getDesc=function(O,P){if(IE8_DOM_DEFINE)try{return getOwnDescriptor(O,P)}catch(e){}if(has(O,P))return $.desc(!ObjectProto.propertyIsEnumerable.call(O,P),O[P])};$.setDescs=defineProperties=function(O,Properties){assertObject(O);var keys=$.getKeys(Properties),length=keys.length,i=0,P;while(length>i)$.setDesc(O,P=keys[i++],Properties[P]);return O}}$def($def.S+$def.F*!$.DESC,"Object",{getOwnPropertyDescriptor:$.getDesc,defineProperty:$.setDesc,defineProperties:defineProperties});var keys1=("constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,"+"toLocaleString,toString,valueOf").split(","),keys2=keys1.concat("length","prototype"),keysLen1=keys1.length;var createDict=function(){var iframe=cel("iframe"),i=keysLen1,gt=">",iframeDocument;iframe.style.display="none";html.appendChild(iframe);iframe.src="javascript:";iframeDocument=iframe.contentWindow.document;iframeDocument.open();iframeDocument.write(" + + + + + + + + diff --git a/frontend-masters-exercises/exercises/ex9/ex9-fixed.js b/frontend-masters-exercises/exercises/ex9/ex9-fixed.js new file mode 100755 index 0000000..fda200f --- /dev/null +++ b/frontend-masters-exercises/exercises/ex9/ex9-fixed.js @@ -0,0 +1,44 @@ +$(document).ready(function(){ + var $btn = $("#btn"), + $list = $("#list"), + clicks = ASQ.csp.chan(), + msgs = ASQ.csp.chan(), + queuedClick; + + $btn.click(listenToClicks); + + // run go-routines + ASQ().runner( + ASQ.csp.go(sampleClicks), + ASQ.csp.go(logClick) + ); + + // push click event messages into channel + function listenToClicks(evt){ + if (!queuedClick) { + queuedClick = ASQ.csp.putAsync(clicks,evt); + queuedClick.then(function(){ + queuedClick = null; + }); + } + } + + // sample clicks channel + function *sampleClicks() { + while (true) { + yield ASQ.csp.take( + ASQ.csp.timeout(1000) + ); + yield ASQ.csp.take(clicks); + yield ASQ.csp.put(msgs,"clicked!"); + } + } + + // subscribe to sampled message channel + function *logClick() { + while (true) { + var msg = yield ASQ.csp.take(msgs); + $list.append($("
" + msg + "
")); + } + } +}); diff --git a/frontend-masters-exercises/exercises/ex9/ex9.html b/frontend-masters-exercises/exercises/ex9/ex9.html new file mode 100755 index 0000000..d67db5e --- /dev/null +++ b/frontend-masters-exercises/exercises/ex9/ex9.html @@ -0,0 +1,18 @@ + + + + +Exercise 9 + + +

Exercise 9

+ +

+
+ + + + + + + diff --git a/frontend-masters-exercises/exercises/ex9/ex9.js b/frontend-masters-exercises/exercises/ex9/ex9.js new file mode 100755 index 0000000..b167571 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex9/ex9.js @@ -0,0 +1,11 @@ +$(document).ready(function(){ + var $btn = $("#btn"), + $list = $("#list"); + + $btn.click(/* TODO */); + + // Hint: ASQ().runner( .. ) + + // TODO: setup sampling go-routine and + // channel, populate $list +}); diff --git a/frontend-masters-exercises/exercises/ex9/jquery.js b/frontend-masters-exercises/exercises/ex9/jquery.js new file mode 100755 index 0000000..3883779 --- /dev/null +++ b/frontend-masters-exercises/exercises/ex9/jquery.js @@ -0,0 +1,2 @@ +/*! jQuery v1.8.3 jquery.com | jquery.org/license */ +(function(e,t){function _(e){var t=M[e]={};return v.each(e.split(y),function(e,n){t[n]=!0}),t}function H(e,n,r){if(r===t&&e.nodeType===1){var i="data-"+n.replace(P,"-$1").toLowerCase();r=e.getAttribute(i);if(typeof r=="string"){try{r=r==="true"?!0:r==="false"?!1:r==="null"?null:+r+""===r?+r:D.test(r)?v.parseJSON(r):r}catch(s){}v.data(e,n,r)}else r=t}return r}function B(e){var t;for(t in e){if(t==="data"&&v.isEmptyObject(e[t]))continue;if(t!=="toJSON")return!1}return!0}function et(){return!1}function tt(){return!0}function ut(e){return!e||!e.parentNode||e.parentNode.nodeType===11}function at(e,t){do e=e[t];while(e&&e.nodeType!==1);return e}function ft(e,t,n){t=t||0;if(v.isFunction(t))return v.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return v.grep(e,function(e,r){return e===t===n});if(typeof t=="string"){var r=v.grep(e,function(e){return e.nodeType===1});if(it.test(t))return v.filter(t,r,!n);t=v.filter(t,r)}return v.grep(e,function(e,r){return v.inArray(e,t)>=0===n})}function lt(e){var t=ct.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function At(e,t){if(t.nodeType!==1||!v.hasData(e))return;var n,r,i,s=v._data(e),o=v._data(t,s),u=s.events;if(u){delete o.handle,o.events={};for(n in u)for(r=0,i=u[n].length;r").appendTo(i.body),n=t.css("display");t.remove();if(n==="none"||n===""){Pt=i.body.appendChild(Pt||v.extend(i.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!Ht||!Pt.createElement)Ht=(Pt.contentWindow||Pt.contentDocument).document,Ht.write(""),Ht.close();t=Ht.body.appendChild(Ht.createElement(e)),n=Dt(t,"display"),i.body.removeChild(Pt)}return Wt[e]=n,n}function fn(e,t,n,r){var i;if(v.isArray(t))v.each(t,function(t,i){n||sn.test(e)?r(e,i):fn(e+"["+(typeof i=="object"?t:"")+"]",i,n,r)});else if(!n&&v.type(t)==="object")for(i in t)fn(e+"["+i+"]",t[i],n,r);else r(e,t)}function Cn(e){return function(t,n){typeof t!="string"&&(n=t,t="*");var r,i,s,o=t.toLowerCase().split(y),u=0,a=o.length;if(v.isFunction(n))for(;u)[^>]*$|#([\w\-]*)$)/,E=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,S=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,T=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,N=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,C=/^-ms-/,k=/-([\da-z])/gi,L=function(e,t){return(t+"").toUpperCase()},A=function(){i.addEventListener?(i.removeEventListener("DOMContentLoaded",A,!1),v.ready()):i.readyState==="complete"&&(i.detachEvent("onreadystatechange",A),v.ready())},O={};v.fn=v.prototype={constructor:v,init:function(e,n,r){var s,o,u,a;if(!e)return this;if(e.nodeType)return this.context=this[0]=e,this.length=1,this;if(typeof e=="string"){e.charAt(0)==="<"&&e.charAt(e.length-1)===">"&&e.length>=3?s=[null,e,null]:s=w.exec(e);if(s&&(s[1]||!n)){if(s[1])return n=n instanceof v?n[0]:n,a=n&&n.nodeType?n.ownerDocument||n:i,e=v.parseHTML(s[1],a,!0),E.test(s[1])&&v.isPlainObject(n)&&this.attr.call(e,n,!0),v.merge(this,e);o=i.getElementById(s[2]);if(o&&o.parentNode){if(o.id!==s[2])return r.find(e);this.length=1,this[0]=o}return this.context=i,this.selector=e,this}return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e)}return v.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),v.makeArray(e,this))},selector:"",jquery:"1.8.3",length:0,size:function(){return this.length},toArray:function(){return l.call(this)},get:function(e){return e==null?this.toArray():e<0?this[this.length+e]:this[e]},pushStack:function(e,t,n){var r=v.merge(this.constructor(),e);return r.prevObject=this,r.context=this.context,t==="find"?r.selector=this.selector+(this.selector?" ":"")+n:t&&(r.selector=this.selector+"."+t+"("+n+")"),r},each:function(e,t){return v.each(this,e,t)},ready:function(e){return v.ready.promise().done(e),this},eq:function(e){return e=+e,e===-1?this.slice(e):this.slice(e,e+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(l.apply(this,arguments),"slice",l.call(arguments).join(","))},map:function(e){return this.pushStack(v.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:[].sort,splice:[].splice},v.fn.init.prototype=v.fn,v.extend=v.fn.extend=function(){var e,n,r,i,s,o,u=arguments[0]||{},a=1,f=arguments.length,l=!1;typeof u=="boolean"&&(l=u,u=arguments[1]||{},a=2),typeof u!="object"&&!v.isFunction(u)&&(u={}),f===a&&(u=this,--a);for(;a0)return;r.resolveWith(i,[v]),v.fn.trigger&&v(i).trigger("ready").off("ready")},isFunction:function(e){return v.type(e)==="function"},isArray:Array.isArray||function(e){return v.type(e)==="array"},isWindow:function(e){return e!=null&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return e==null?String(e):O[h.call(e)]||"object"},isPlainObject:function(e){if(!e||v.type(e)!=="object"||e.nodeType||v.isWindow(e))return!1;try{if(e.constructor&&!p.call(e,"constructor")&&!p.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||p.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw new Error(e)},parseHTML:function(e,t,n){var r;return!e||typeof e!="string"?null:(typeof t=="boolean"&&(n=t,t=0),t=t||i,(r=E.exec(e))?[t.createElement(r[1])]:(r=v.buildFragment([e],t,n?null:[]),v.merge([],(r.cacheable?v.clone(r.fragment):r.fragment).childNodes)))},parseJSON:function(t){if(!t||typeof t!="string")return null;t=v.trim(t);if(e.JSON&&e.JSON.parse)return e.JSON.parse(t);if(S.test(t.replace(T,"@").replace(N,"]").replace(x,"")))return(new Function("return "+t))();v.error("Invalid JSON: "+t)},parseXML:function(n){var r,i;if(!n||typeof n!="string")return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(s){r=t}return(!r||!r.documentElement||r.getElementsByTagName("parsererror").length)&&v.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&g.test(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(C,"ms-").replace(k,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,n,r){var i,s=0,o=e.length,u=o===t||v.isFunction(e);if(r){if(u){for(i in e)if(n.apply(e[i],r)===!1)break}else for(;s0&&e[0]&&e[a-1]||a===0||v.isArray(e));if(f)for(;u-1)a.splice(n,1),i&&(n<=o&&o--,n<=u&&u--)}),this},has:function(e){return v.inArray(e,a)>-1},empty:function(){return a=[],this},disable:function(){return a=f=n=t,this},disabled:function(){return!a},lock:function(){return f=t,n||c.disable(),this},locked:function(){return!f},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],a&&(!r||f)&&(i?f.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},v.extend({Deferred:function(e){var t=[["resolve","done",v.Callbacks("once memory"),"resolved"],["reject","fail",v.Callbacks("once memory"),"rejected"],["notify","progress",v.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return v.Deferred(function(n){v.each(t,function(t,r){var s=r[0],o=e[t];i[r[1]](v.isFunction(o)?function(){var e=o.apply(this,arguments);e&&v.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===i?n:this,[e])}:n[s])}),e=null}).promise()},promise:function(e){return e!=null?v.extend(e,r):r}},i={};return r.pipe=r.then,v.each(t,function(e,s){var o=s[2],u=s[3];r[s[1]]=o.add,u&&o.add(function(){n=u},t[e^1][2].disable,t[2][2].lock),i[s[0]]=o.fire,i[s[0]+"With"]=o.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=l.call(arguments),r=n.length,i=r!==1||e&&v.isFunction(e.promise)?r:0,s=i===1?e:v.Deferred(),o=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?l.call(arguments):r,n===u?s.notifyWith(t,n):--i||s.resolveWith(t,n)}},u,a,f;if(r>1){u=new Array(r),a=new Array(r),f=new Array(r);for(;t
a",n=p.getElementsByTagName("*"),r=p.getElementsByTagName("a")[0];if(!n||!r||!n.length)return{};s=i.createElement("select"),o=s.appendChild(i.createElement("option")),u=p.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:r.getAttribute("href")==="/a",opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:u.value==="on",optSelected:o.selected,getSetAttribute:p.className!=="t",enctype:!!i.createElement("form").enctype,html5Clone:i.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",boxModel:i.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},u.checked=!0,t.noCloneChecked=u.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!o.disabled;try{delete p.test}catch(d){t.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",h=function(){t.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick"),p.detachEvent("onclick",h)),u=i.createElement("input"),u.value="t",u.setAttribute("type","radio"),t.radioValue=u.value==="t",u.setAttribute("checked","checked"),u.setAttribute("name","t"),p.appendChild(u),a=i.createDocumentFragment(),a.appendChild(p.lastChild),t.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,t.appendChecked=u.checked,a.removeChild(u),a.appendChild(p);if(p.attachEvent)for(l in{submit:!0,change:!0,focusin:!0})f="on"+l,c=f in p,c||(p.setAttribute(f,"return;"),c=typeof p[f]=="function"),t[l+"Bubbles"]=c;return v(function(){var n,r,s,o,u="padding:0;margin:0;border:0;display:block;overflow:hidden;",a=i.getElementsByTagName("body")[0];if(!a)return;n=i.createElement("div"),n.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",a.insertBefore(n,a.firstChild),r=i.createElement("div"),n.appendChild(r),r.innerHTML="
t
",s=r.getElementsByTagName("td"),s[0].style.cssText="padding:0;margin:0;border:0;display:none",c=s[0].offsetHeight===0,s[0].style.display="",s[1].style.display="none",t.reliableHiddenOffsets=c&&s[0].offsetHeight===0,r.innerHTML="",r.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=r.offsetWidth===4,t.doesNotIncludeMarginInBodyOffset=a.offsetTop!==1,e.getComputedStyle&&(t.pixelPosition=(e.getComputedStyle(r,null)||{}).top!=="1%",t.boxSizingReliable=(e.getComputedStyle(r,null)||{width:"4px"}).width==="4px",o=i.createElement("div"),o.style.cssText=r.style.cssText=u,o.style.marginRight=o.style.width="0",r.style.width="1px",r.appendChild(o),t.reliableMarginRight=!parseFloat((e.getComputedStyle(o,null)||{}).marginRight)),typeof r.style.zoom!="undefined"&&(r.innerHTML="",r.style.cssText=u+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=r.offsetWidth===3,r.style.display="block",r.style.overflow="visible",r.innerHTML="
",r.firstChild.style.width="5px",t.shrinkWrapBlocks=r.offsetWidth!==3,n.style.zoom=1),a.removeChild(n),n=r=s=o=null}),a.removeChild(p),n=r=s=o=u=a=p=null,t}();var D=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;v.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(v.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?v.cache[e[v.expando]]:e[v.expando],!!e&&!B(e)},data:function(e,n,r,i){if(!v.acceptData(e))return;var s,o,u=v.expando,a=typeof n=="string",f=e.nodeType,l=f?v.cache:e,c=f?e[u]:e[u]&&u;if((!c||!l[c]||!i&&!l[c].data)&&a&&r===t)return;c||(f?e[u]=c=v.deletedIds.pop()||v.guid++:c=u),l[c]||(l[c]={},f||(l[c].toJSON=v.noop));if(typeof n=="object"||typeof n=="function")i?l[c]=v.extend(l[c],n):l[c].data=v.extend(l[c].data,n);return s=l[c],i||(s.data||(s.data={}),s=s.data),r!==t&&(s[v.camelCase(n)]=r),a?(o=s[n],o==null&&(o=s[v.camelCase(n)])):o=s,o},removeData:function(e,t,n){if(!v.acceptData(e))return;var r,i,s,o=e.nodeType,u=o?v.cache:e,a=o?e[v.expando]:v.expando;if(!u[a])return;if(t){r=n?u[a]:u[a].data;if(r){v.isArray(t)||(t in r?t=[t]:(t=v.camelCase(t),t in r?t=[t]:t=t.split(" ")));for(i=0,s=t.length;i1,null,!1))},removeData:function(e){return this.each(function(){v.removeData(this,e)})}}),v.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=v._data(e,t),n&&(!r||v.isArray(n)?r=v._data(e,t,v.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=v.queue(e,t),r=n.length,i=n.shift(),s=v._queueHooks(e,t),o=function(){v.dequeue(e,t)};i==="inprogress"&&(i=n.shift(),r--),i&&(t==="fx"&&n.unshift("inprogress"),delete s.stop,i.call(e,o,s)),!r&&s&&s.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return v._data(e,n)||v._data(e,n,{empty:v.Callbacks("once memory").add(function(){v.removeData(e,t+"queue",!0),v.removeData(e,n,!0)})})}}),v.fn.extend({queue:function(e,n){var r=2;return typeof e!="string"&&(n=e,e="fx",r--),arguments.length1)},removeAttr:function(e){return this.each(function(){v.removeAttr(this,e)})},prop:function(e,t){return v.access(this,v.prop,e,t,arguments.length>1)},removeProp:function(e){return e=v.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,s,o,u;if(v.isFunction(e))return this.each(function(t){v(this).addClass(e.call(this,t,this.className))});if(e&&typeof e=="string"){t=e.split(y);for(n=0,r=this.length;n=0)r=r.replace(" "+n[s]+" "," ");i.className=e?v.trim(r):""}}}return this},toggleClass:function(e,t){var n=typeof e,r=typeof t=="boolean";return v.isFunction(e)?this.each(function(n){v(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if(n==="string"){var i,s=0,o=v(this),u=t,a=e.split(y);while(i=a[s++])u=r?u:!o.hasClass(i),o[u?"addClass":"removeClass"](i)}else if(n==="undefined"||n==="boolean")this.className&&v._data(this,"__className__",this.className),this.className=this.className||e===!1?"":v._data(this,"__className__")||""})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;n=0)return!0;return!1},val:function(e){var n,r,i,s=this[0];if(!arguments.length){if(s)return n=v.valHooks[s.type]||v.valHooks[s.nodeName.toLowerCase()],n&&"get"in n&&(r=n.get(s,"value"))!==t?r:(r=s.value,typeof r=="string"?r.replace(R,""):r==null?"":r);return}return i=v.isFunction(e),this.each(function(r){var s,o=v(this);if(this.nodeType!==1)return;i?s=e.call(this,r,o.val()):s=e,s==null?s="":typeof s=="number"?s+="":v.isArray(s)&&(s=v.map(s,function(e){return e==null?"":e+""})),n=v.valHooks[this.type]||v.valHooks[this.nodeName.toLowerCase()];if(!n||!("set"in n)||n.set(this,s,"value")===t)this.value=s})}}),v.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,s=e.type==="select-one"||i<0,o=s?null:[],u=s?i+1:r.length,a=i<0?u:s?i:0;for(;a=0}),n.length||(e.selectedIndex=-1),n}}},attrFn:{},attr:function(e,n,r,i){var s,o,u,a=e.nodeType;if(!e||a===3||a===8||a===2)return;if(i&&v.isFunction(v.fn[n]))return v(e)[n](r);if(typeof e.getAttribute=="undefined")return v.prop(e,n,r);u=a!==1||!v.isXMLDoc(e),u&&(n=n.toLowerCase(),o=v.attrHooks[n]||(X.test(n)?F:j));if(r!==t){if(r===null){v.removeAttr(e,n);return}return o&&"set"in o&&u&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r)}return o&&"get"in o&&u&&(s=o.get(e,n))!==null?s:(s=e.getAttribute(n),s===null?t:s)},removeAttr:function(e,t){var n,r,i,s,o=0;if(t&&e.nodeType===1){r=t.split(y);for(;o=0}})});var $=/^(?:textarea|input|select)$/i,J=/^([^\.]*|)(?:\.(.+)|)$/,K=/(?:^|\s)hover(\.\S+|)\b/,Q=/^key/,G=/^(?:mouse|contextmenu)|click/,Y=/^(?:focusinfocus|focusoutblur)$/,Z=function(e){return v.event.special.hover?e:e.replace(K,"mouseenter$1 mouseleave$1")};v.event={add:function(e,n,r,i,s){var o,u,a,f,l,c,h,p,d,m,g;if(e.nodeType===3||e.nodeType===8||!n||!r||!(o=v._data(e)))return;r.handler&&(d=r,r=d.handler,s=d.selector),r.guid||(r.guid=v.guid++),a=o.events,a||(o.events=a={}),u=o.handle,u||(o.handle=u=function(e){return typeof v=="undefined"||!!e&&v.event.triggered===e.type?t:v.event.dispatch.apply(u.elem,arguments)},u.elem=e),n=v.trim(Z(n)).split(" ");for(f=0;f=0&&(y=y.slice(0,-1),a=!0),y.indexOf(".")>=0&&(b=y.split("."),y=b.shift(),b.sort());if((!s||v.event.customEvent[y])&&!v.event.global[y])return;n=typeof n=="object"?n[v.expando]?n:new v.Event(y,n):new v.Event(y),n.type=y,n.isTrigger=!0,n.exclusive=a,n.namespace=b.join("."),n.namespace_re=n.namespace?new RegExp("(^|\\.)"+b.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,h=y.indexOf(":")<0?"on"+y:"";if(!s){u=v.cache;for(f in u)u[f].events&&u[f].events[y]&&v.event.trigger(n,r,u[f].handle.elem,!0);return}n.result=t,n.target||(n.target=s),r=r!=null?v.makeArray(r):[],r.unshift(n),p=v.event.special[y]||{};if(p.trigger&&p.trigger.apply(s,r)===!1)return;m=[[s,p.bindType||y]];if(!o&&!p.noBubble&&!v.isWindow(s)){g=p.delegateType||y,l=Y.test(g+y)?s:s.parentNode;for(c=s;l;l=l.parentNode)m.push([l,g]),c=l;c===(s.ownerDocument||i)&&m.push([c.defaultView||c.parentWindow||e,g])}for(f=0;f=0:v.find(h,this,null,[s]).length),u[h]&&f.push(c);f.length&&w.push({elem:s,matches:f})}d.length>m&&w.push({elem:this,matches:d.slice(m)});for(r=0;r0?this.on(t,null,e,n):this.trigger(t)},Q.test(t)&&(v.event.fixHooks[t]=v.event.keyHooks),G.test(t)&&(v.event.fixHooks[t]=v.event.mouseHooks)}),function(e,t){function nt(e,t,n,r){n=n||[],t=t||g;var i,s,a,f,l=t.nodeType;if(!e||typeof e!="string")return n;if(l!==1&&l!==9)return[];a=o(t);if(!a&&!r)if(i=R.exec(e))if(f=i[1]){if(l===9){s=t.getElementById(f);if(!s||!s.parentNode)return n;if(s.id===f)return n.push(s),n}else if(t.ownerDocument&&(s=t.ownerDocument.getElementById(f))&&u(t,s)&&s.id===f)return n.push(s),n}else{if(i[2])return S.apply(n,x.call(t.getElementsByTagName(e),0)),n;if((f=i[3])&&Z&&t.getElementsByClassName)return S.apply(n,x.call(t.getElementsByClassName(f),0)),n}return vt(e.replace(j,"$1"),t,n,r,a)}function rt(e){return function(t){var n=t.nodeName.toLowerCase();return n==="input"&&t.type===e}}function it(e){return function(t){var n=t.nodeName.toLowerCase();return(n==="input"||n==="button")&&t.type===e}}function st(e){return N(function(t){return t=+t,N(function(n,r){var i,s=e([],n.length,t),o=s.length;while(o--)n[i=s[o]]&&(n[i]=!(r[i]=n[i]))})})}function ot(e,t,n){if(e===t)return n;var r=e.nextSibling;while(r){if(r===t)return-1;r=r.nextSibling}return 1}function ut(e,t){var n,r,s,o,u,a,f,l=L[d][e+" "];if(l)return t?0:l.slice(0);u=e,a=[],f=i.preFilter;while(u){if(!n||(r=F.exec(u)))r&&(u=u.slice(r[0].length)||u),a.push(s=[]);n=!1;if(r=I.exec(u))s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=r[0].replace(j," ");for(o in i.filter)(r=J[o].exec(u))&&(!f[o]||(r=f[o](r)))&&(s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=o,n.matches=r);if(!n)break}return t?u.length:u?nt.error(e):L(e,a).slice(0)}function at(e,t,r){var i=t.dir,s=r&&t.dir==="parentNode",o=w++;return t.first?function(t,n,r){while(t=t[i])if(s||t.nodeType===1)return e(t,n,r)}:function(t,r,u){if(!u){var a,f=b+" "+o+" ",l=f+n;while(t=t[i])if(s||t.nodeType===1){if((a=t[d])===l)return t.sizset;if(typeof a=="string"&&a.indexOf(f)===0){if(t.sizset)return t}else{t[d]=l;if(e(t,r,u))return t.sizset=!0,t;t.sizset=!1}}}else while(t=t[i])if(s||t.nodeType===1)if(e(t,r,u))return t}}function ft(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function lt(e,t,n,r,i){var s,o=[],u=0,a=e.length,f=t!=null;for(;u-1&&(s[f]=!(o[f]=c))}}else g=lt(g===o?g.splice(d,g.length):g),i?i(null,o,g,a):S.apply(o,g)})}function ht(e){var t,n,r,s=e.length,o=i.relative[e[0].type],u=o||i.relative[" "],a=o?1:0,f=at(function(e){return e===t},u,!0),l=at(function(e){return T.call(t,e)>-1},u,!0),h=[function(e,n,r){return!o&&(r||n!==c)||((t=n).nodeType?f(e,n,r):l(e,n,r))}];for(;a1&&ft(h),a>1&&e.slice(0,a-1).join("").replace(j,"$1"),n,a0,s=e.length>0,o=function(u,a,f,l,h){var p,d,v,m=[],y=0,w="0",x=u&&[],T=h!=null,N=c,C=u||s&&i.find.TAG("*",h&&a.parentNode||a),k=b+=N==null?1:Math.E;T&&(c=a!==g&&a,n=o.el);for(;(p=C[w])!=null;w++){if(s&&p){for(d=0;v=e[d];d++)if(v(p,a,f)){l.push(p);break}T&&(b=k,n=++o.el)}r&&((p=!v&&p)&&y--,u&&x.push(p))}y+=w;if(r&&w!==y){for(d=0;v=t[d];d++)v(x,m,a,f);if(u){if(y>0)while(w--)!x[w]&&!m[w]&&(m[w]=E.call(l));m=lt(m)}S.apply(l,m),T&&!u&&m.length>0&&y+t.length>1&&nt.uniqueSort(l)}return T&&(b=k,c=N),x};return o.el=0,r?N(o):o}function dt(e,t,n){var r=0,i=t.length;for(;r2&&(f=u[0]).type==="ID"&&t.nodeType===9&&!s&&i.relative[u[1].type]){t=i.find.ID(f.matches[0].replace($,""),t,s)[0];if(!t)return n;e=e.slice(u.shift().length)}for(o=J.POS.test(e)?-1:u.length-1;o>=0;o--){f=u[o];if(i.relative[l=f.type])break;if(c=i.find[l])if(r=c(f.matches[0].replace($,""),z.test(u[0].type)&&t.parentNode||t,s)){u.splice(o,1),e=r.length&&u.join("");if(!e)return S.apply(n,x.call(r,0)),n;break}}}return a(e,h)(r,t,s,n,z.test(e)),n}function mt(){}var n,r,i,s,o,u,a,f,l,c,h=!0,p="undefined",d=("sizcache"+Math.random()).replace(".",""),m=String,g=e.document,y=g.documentElement,b=0,w=0,E=[].pop,S=[].push,x=[].slice,T=[].indexOf||function(e){var t=0,n=this.length;for(;ti.cacheLength&&delete e[t.shift()],e[n+" "]=r},e)},k=C(),L=C(),A=C(),O="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",_=M.replace("w","w#"),D="([*^$|!~]?=)",P="\\["+O+"*("+M+")"+O+"*(?:"+D+O+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+_+")|)|)"+O+"*\\]",H=":("+M+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+P+")|[^:]|\\\\.)*|.*))\\)|)",B=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+O+"*((?:-\\d)?\\d*)"+O+"*\\)|)(?=[^-]|$)",j=new RegExp("^"+O+"+|((?:^|[^\\\\])(?:\\\\.)*)"+O+"+$","g"),F=new RegExp("^"+O+"*,"+O+"*"),I=new RegExp("^"+O+"*([\\x20\\t\\r\\n\\f>+~])"+O+"*"),q=new RegExp(H),R=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,U=/^:not/,z=/[\x20\t\r\n\f]*[+~]/,W=/:not\($/,X=/h\d/i,V=/input|select|textarea|button/i,$=/\\(?!\\)/g,J={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),NAME:new RegExp("^\\[name=['\"]?("+M+")['\"]?\\]"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+H),POS:new RegExp(B,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+O+"*(even|odd|(([+-]|)(\\d*)n|)"+O+"*(?:([+-]|)"+O+"*(\\d+)|))"+O+"*\\)|)","i"),needsContext:new RegExp("^"+O+"*[>+~]|"+B,"i")},K=function(e){var t=g.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}},Q=K(function(e){return e.appendChild(g.createComment("")),!e.getElementsByTagName("*").length}),G=K(function(e){return e.innerHTML="",e.firstChild&&typeof e.firstChild.getAttribute!==p&&e.firstChild.getAttribute("href")==="#"}),Y=K(function(e){e.innerHTML="";var t=typeof e.lastChild.getAttribute("multiple");return t!=="boolean"&&t!=="string"}),Z=K(function(e){return e.innerHTML="",!e.getElementsByClassName||!e.getElementsByClassName("e").length?!1:(e.lastChild.className="e",e.getElementsByClassName("e").length===2)}),et=K(function(e){e.id=d+0,e.innerHTML="
",y.insertBefore(e,y.firstChild);var t=g.getElementsByName&&g.getElementsByName(d).length===2+g.getElementsByName(d+0).length;return r=!g.getElementById(d),y.removeChild(e),t});try{x.call(y.childNodes,0)[0].nodeType}catch(tt){x=function(e){var t,n=[];for(;t=this[e];e++)n.push(t);return n}}nt.matches=function(e,t){return nt(e,null,null,t)},nt.matchesSelector=function(e,t){return nt(t,null,null,[e]).length>0},s=nt.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(i===1||i===9||i===11){if(typeof e.textContent=="string")return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=s(e)}else if(i===3||i===4)return e.nodeValue}else for(;t=e[r];r++)n+=s(t);return n},o=nt.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?t.nodeName!=="HTML":!1},u=nt.contains=y.contains?function(e,t){var n=e.nodeType===9?e.documentElement:e,r=t&&t.parentNode;return e===r||!!(r&&r.nodeType===1&&n.contains&&n.contains(r))}:y.compareDocumentPosition?function(e,t){return t&&!!(e.compareDocumentPosition(t)&16)}:function(e,t){while(t=t.parentNode)if(t===e)return!0;return!1},nt.attr=function(e,t){var n,r=o(e);return r||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):r||Y?e.getAttribute(t):(n=e.getAttributeNode(t),n?typeof e[t]=="boolean"?e[t]?t:null:n.specified?n.value:null:null)},i=nt.selectors={cacheLength:50,createPseudo:N,match:J,attrHandle:G?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},find:{ID:r?function(e,t,n){if(typeof t.getElementById!==p&&!n){var r=t.getElementById(e);return r&&r.parentNode?[r]:[]}}:function(e,n,r){if(typeof n.getElementById!==p&&!r){var i=n.getElementById(e);return i?i.id===e||typeof i.getAttributeNode!==p&&i.getAttributeNode("id").value===e?[i]:t:[]}},TAG:Q?function(e,t){if(typeof t.getElementsByTagName!==p)return t.getElementsByTagName(e)}:function(e,t){var n=t.getElementsByTagName(e);if(e==="*"){var r,i=[],s=0;for(;r=n[s];s++)r.nodeType===1&&i.push(r);return i}return n},NAME:et&&function(e,t){if(typeof t.getElementsByName!==p)return t.getElementsByName(name)},CLASS:Z&&function(e,t,n){if(typeof t.getElementsByClassName!==p&&!n)return t.getElementsByClassName(e)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace($,""),e[3]=(e[4]||e[5]||"").replace($,""),e[2]==="~="&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),e[1]==="nth"?(e[2]||nt.error(e[0]),e[3]=+(e[3]?e[4]+(e[5]||1):2*(e[2]==="even"||e[2]==="odd")),e[4]=+(e[6]+e[7]||e[2]==="odd")):e[2]&&nt.error(e[0]),e},PSEUDO:function(e){var t,n;if(J.CHILD.test(e[0]))return null;if(e[3])e[2]=e[3];else if(t=e[4])q.test(t)&&(n=ut(t,!0))&&(n=t.indexOf(")",t.length-n)-t.length)&&(t=t.slice(0,n),e[0]=e[0].slice(0,n)),e[2]=t;return e.slice(0,3)}},filter:{ID:r?function(e){return e=e.replace($,""),function(t){return t.getAttribute("id")===e}}:function(e){return e=e.replace($,""),function(t){var n=typeof t.getAttributeNode!==p&&t.getAttributeNode("id");return n&&n.value===e}},TAG:function(e){return e==="*"?function(){return!0}:(e=e.replace($,"").toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[d][e+" "];return t||(t=new RegExp("(^|"+O+")"+e+"("+O+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==p&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r,i){var s=nt.attr(r,e);return s==null?t==="!=":t?(s+="",t==="="?s===n:t==="!="?s!==n:t==="^="?n&&s.indexOf(n)===0:t==="*="?n&&s.indexOf(n)>-1:t==="$="?n&&s.substr(s.length-n.length)===n:t==="~="?(" "+s+" ").indexOf(n)>-1:t==="|="?s===n||s.substr(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r){return e==="nth"?function(e){var t,i,s=e.parentNode;if(n===1&&r===0)return!0;if(s){i=0;for(t=s.firstChild;t;t=t.nextSibling)if(t.nodeType===1){i++;if(e===t)break}}return i-=r,i===n||i%n===0&&i/n>=0}:function(t){var n=t;switch(e){case"only":case"first":while(n=n.previousSibling)if(n.nodeType===1)return!1;if(e==="first")return!0;n=t;case"last":while(n=n.nextSibling)if(n.nodeType===1)return!1;return!0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||nt.error("unsupported pseudo: "+e);return r[d]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?N(function(e,n){var i,s=r(e,t),o=s.length;while(o--)i=T.call(e,s[o]),e[i]=!(n[i]=s[o])}):function(e){return r(e,0,n)}):r}},pseudos:{not:N(function(e){var t=[],n=[],r=a(e.replace(j,"$1"));return r[d]?N(function(e,t,n,i){var s,o=r(e,null,i,[]),u=e.length;while(u--)if(s=o[u])e[u]=!(t[u]=s)}):function(e,i,s){return t[0]=e,r(t,null,s,n),!n.pop()}}),has:N(function(e){return function(t){return nt(e,t).length>0}}),contains:N(function(e){return function(t){return(t.textContent||t.innerText||s(t)).indexOf(e)>-1}}),enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&!!e.checked||t==="option"&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},parent:function(e){return!i.pseudos.empty(e)},empty:function(e){var t;e=e.firstChild;while(e){if(e.nodeName>"@"||(t=e.nodeType)===3||t===4)return!1;e=e.nextSibling}return!0},header:function(e){return X.test(e.nodeName)},text:function(e){var t,n;return e.nodeName.toLowerCase()==="input"&&(t=e.type)==="text"&&((n=e.getAttribute("type"))==null||n.toLowerCase()===t)},radio:rt("radio"),checkbox:rt("checkbox"),file:rt("file"),password:rt("password"),image:rt("image"),submit:it("submit"),reset:it("reset"),button:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&e.type==="button"||t==="button"},input:function(e){return V.test(e.nodeName)},focus:function(e){var t=e.ownerDocument;return e===t.activeElement&&(!t.hasFocus||t.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},active:function(e){return e===e.ownerDocument.activeElement},first:st(function(){return[0]}),last:st(function(e,t){return[t-1]}),eq:st(function(e,t,n){return[n<0?n+t:n]}),even:st(function(e,t){for(var n=0;n=0;)e.push(r);return e}),gt:st(function(e,t,n){for(var r=n<0?n+t:n;++r",e.querySelectorAll("[selected]").length||i.push("\\["+O+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||i.push(":checked")}),K(function(e){e.innerHTML="

",e.querySelectorAll("[test^='']").length&&i.push("[*^$]="+O+"*(?:\"\"|'')"),e.innerHTML="",e.querySelectorAll(":enabled").length||i.push(":enabled",":disabled")}),i=new RegExp(i.join("|")),vt=function(e,r,s,o,u){if(!o&&!u&&!i.test(e)){var a,f,l=!0,c=d,h=r,p=r.nodeType===9&&e;if(r.nodeType===1&&r.nodeName.toLowerCase()!=="object"){a=ut(e),(l=r.getAttribute("id"))?c=l.replace(n,"\\$&"):r.setAttribute("id",c),c="[id='"+c+"'] ",f=a.length;while(f--)a[f]=c+a[f].join("");h=z.test(e)&&r.parentNode||r,p=a.join(",")}if(p)try{return S.apply(s,x.call(h.querySelectorAll(p),0)),s}catch(v){}finally{l||r.removeAttribute("id")}}return t(e,r,s,o,u)},u&&(K(function(t){e=u.call(t,"div");try{u.call(t,"[test!='']:sizzle"),s.push("!=",H)}catch(n){}}),s=new RegExp(s.join("|")),nt.matchesSelector=function(t,n){n=n.replace(r,"='$1']");if(!o(t)&&!s.test(n)&&!i.test(n))try{var a=u.call(t,n);if(a||e||t.document&&t.document.nodeType!==11)return a}catch(f){}return nt(n,null,null,[t]).length>0})}(),i.pseudos.nth=i.pseudos.eq,i.filters=mt.prototype=i.pseudos,i.setFilters=new mt,nt.attr=v.attr,v.find=nt,v.expr=nt.selectors,v.expr[":"]=v.expr.pseudos,v.unique=nt.uniqueSort,v.text=nt.getText,v.isXMLDoc=nt.isXML,v.contains=nt.contains}(e);var nt=/Until$/,rt=/^(?:parents|prev(?:Until|All))/,it=/^.[^:#\[\.,]*$/,st=v.expr.match.needsContext,ot={children:!0,contents:!0,next:!0,prev:!0};v.fn.extend({find:function(e){var t,n,r,i,s,o,u=this;if(typeof e!="string")return v(e).filter(function(){for(t=0,n=u.length;t0)for(i=r;i=0:v.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,s=[],o=st.test(e)||typeof e!="string"?v(e,t||this.context):0;for(;r-1:v.find.matchesSelector(n,e)){s.push(n);break}n=n.parentNode}}return s=s.length>1?v.unique(s):s,this.pushStack(s,"closest",e)},index:function(e){return e?typeof e=="string"?v.inArray(this[0],v(e)):v.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(e,t){var n=typeof e=="string"?v(e,t):v.makeArray(e&&e.nodeType?[e]:e),r=v.merge(this.get(),n);return this.pushStack(ut(n[0])||ut(r[0])?r:v.unique(r))},addBack:function(e){return this.add(e==null?this.prevObject:this.prevObject.filter(e))}}),v.fn.andSelf=v.fn.addBack,v.each({parent:function(e){var t=e.parentNode;return t&&t.nodeType!==11?t:null},parents:function(e){return v.dir(e,"parentNode")},parentsUntil:function(e,t,n){return v.dir(e,"parentNode",n)},next:function(e){return at(e,"nextSibling")},prev:function(e){return at(e,"previousSibling")},nextAll:function(e){return v.dir(e,"nextSibling")},prevAll:function(e){return v.dir(e,"previousSibling")},nextUntil:function(e,t,n){return v.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return v.dir(e,"previousSibling",n)},siblings:function(e){return v.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return v.sibling(e.firstChild)},contents:function(e){return v.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:v.merge([],e.childNodes)}},function(e,t){v.fn[e]=function(n,r){var i=v.map(this,t,n);return nt.test(e)||(r=n),r&&typeof r=="string"&&(i=v.filter(r,i)),i=this.length>1&&!ot[e]?v.unique(i):i,this.length>1&&rt.test(e)&&(i=i.reverse()),this.pushStack(i,e,l.call(arguments).join(","))}}),v.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),t.length===1?v.find.matchesSelector(t[0],e)?[t[0]]:[]:v.find.matches(e,t)},dir:function(e,n,r){var i=[],s=e[n];while(s&&s.nodeType!==9&&(r===t||s.nodeType!==1||!v(s).is(r)))s.nodeType===1&&i.push(s),s=s[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)e.nodeType===1&&e!==t&&n.push(e);return n}});var ct="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ht=/ jQuery\d+="(?:null|\d+)"/g,pt=/^\s+/,dt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,vt=/<([\w:]+)/,mt=/]","i"),Et=/^(?:checkbox|radio)$/,St=/checked\s*(?:[^=]|=\s*.checked.)/i,xt=/\/(java|ecma)script/i,Tt=/^\s*\s*$/g,Nt={option:[1,""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},Ct=lt(i),kt=Ct.appendChild(i.createElement("div"));Nt.optgroup=Nt.option,Nt.tbody=Nt.tfoot=Nt.colgroup=Nt.caption=Nt.thead,Nt.th=Nt.td,v.support.htmlSerialize||(Nt._default=[1,"X
","
"]),v.fn.extend({text:function(e){return v.access(this,function(e){return e===t?v.text(this):this.empty().append((this[0]&&this[0].ownerDocument||i).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(v.isFunction(e))return this.each(function(t){v(this).wrapAll(e.call(this,t))});if(this[0]){var t=v(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&e.firstChild.nodeType===1)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return v.isFunction(e)?this.each(function(t){v(this).wrapInner(e.call(this,t))}):this.each(function(){var t=v(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=v.isFunction(e);return this.each(function(n){v(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){v.nodeName(this,"body")||v(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(e,this.firstChild)})},before:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(e,this),"before",this.selector)}},after:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this.nextSibling)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(this,e),"after",this.selector)}},remove:function(e,t){var n,r=0;for(;(n=this[r])!=null;r++)if(!e||v.filter(e,[n]).length)!t&&n.nodeType===1&&(v.cleanData(n.getElementsByTagName("*")),v.cleanData([n])),n.parentNode&&n.parentNode.removeChild(n);return this},empty:function(){var e,t=0;for(;(e=this[t])!=null;t++){e.nodeType===1&&v.cleanData(e.getElementsByTagName("*"));while(e.firstChild)e.removeChild(e.firstChild)}return this},clone:function(e,t){return e=e==null?!1:e,t=t==null?e:t,this.map(function(){return v.clone(this,e,t)})},html:function(e){return v.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return n.nodeType===1?n.innerHTML.replace(ht,""):t;if(typeof e=="string"&&!yt.test(e)&&(v.support.htmlSerialize||!wt.test(e))&&(v.support.leadingWhitespace||!pt.test(e))&&!Nt[(vt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(dt,"<$1>");try{for(;r1&&typeof f=="string"&&St.test(f))return this.each(function(){v(this).domManip(e,n,r)});if(v.isFunction(f))return this.each(function(i){var s=v(this);e[0]=f.call(this,i,n?s.html():t),s.domManip(e,n,r)});if(this[0]){i=v.buildFragment(e,this,l),o=i.fragment,s=o.firstChild,o.childNodes.length===1&&(o=s);if(s){n=n&&v.nodeName(s,"tr");for(u=i.cacheable||c-1;a0?this.clone(!0):this).get(),v(o[i])[t](r),s=s.concat(r);return this.pushStack(s,e,o.selector)}}),v.extend({clone:function(e,t,n){var r,i,s,o;v.support.html5Clone||v.isXMLDoc(e)||!wt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(kt.innerHTML=e.outerHTML,kt.removeChild(o=kt.firstChild));if((!v.support.noCloneEvent||!v.support.noCloneChecked)&&(e.nodeType===1||e.nodeType===11)&&!v.isXMLDoc(e)){Ot(e,o),r=Mt(e),i=Mt(o);for(s=0;r[s];++s)i[s]&&Ot(r[s],i[s])}if(t){At(e,o);if(n){r=Mt(e),i=Mt(o);for(s=0;r[s];++s)At(r[s],i[s])}}return r=i=null,o},clean:function(e,t,n,r){var s,o,u,a,f,l,c,h,p,d,m,g,y=t===i&&Ct,b=[];if(!t||typeof t.createDocumentFragment=="undefined")t=i;for(s=0;(u=e[s])!=null;s++){typeof u=="number"&&(u+="");if(!u)continue;if(typeof u=="string")if(!gt.test(u))u=t.createTextNode(u);else{y=y||lt(t),c=t.createElement("div"),y.appendChild(c),u=u.replace(dt,"<$1>"),a=(vt.exec(u)||["",""])[1].toLowerCase(),f=Nt[a]||Nt._default,l=f[0],c.innerHTML=f[1]+u+f[2];while(l--)c=c.lastChild;if(!v.support.tbody){h=mt.test(u),p=a==="table"&&!h?c.firstChild&&c.firstChild.childNodes:f[1]===""&&!h?c.childNodes:[];for(o=p.length-1;o>=0;--o)v.nodeName(p[o],"tbody")&&!p[o].childNodes.length&&p[o].parentNode.removeChild(p[o])}!v.support.leadingWhitespace&&pt.test(u)&&c.insertBefore(t.createTextNode(pt.exec(u)[0]),c.firstChild),u=c.childNodes,c.parentNode.removeChild(c)}u.nodeType?b.push(u):v.merge(b,u)}c&&(u=c=y=null);if(!v.support.appendChecked)for(s=0;(u=b[s])!=null;s++)v.nodeName(u,"input")?_t(u):typeof u.getElementsByTagName!="undefined"&&v.grep(u.getElementsByTagName("input"),_t);if(n){m=function(e){if(!e.type||xt.test(e.type))return r?r.push(e.parentNode?e.parentNode.removeChild(e):e):n.appendChild(e)};for(s=0;(u=b[s])!=null;s++)if(!v.nodeName(u,"script")||!m(u))n.appendChild(u),typeof u.getElementsByTagName!="undefined"&&(g=v.grep(v.merge([],u.getElementsByTagName("script")),m),b.splice.apply(b,[s+1,0].concat(g)),s+=g.length)}return b},cleanData:function(e,t){var n,r,i,s,o=0,u=v.expando,a=v.cache,f=v.support.deleteExpando,l=v.event.special;for(;(i=e[o])!=null;o++)if(t||v.acceptData(i)){r=i[u],n=r&&a[r];if(n){if(n.events)for(s in n.events)l[s]?v.event.remove(i,s):v.removeEvent(i,s,n.handle);a[r]&&(delete a[r],f?delete i[u]:i.removeAttribute?i.removeAttribute(u):i[u]=null,v.deletedIds.push(r))}}}}),function(){var e,t;v.uaMatch=function(e){e=e.toLowerCase();var t=/(chrome)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+)/.exec(e)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(e)||/(msie) ([\w.]+)/.exec(e)||e.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(e)||[];return{browser:t[1]||"",version:t[2]||"0"}},e=v.uaMatch(o.userAgent),t={},e.browser&&(t[e.browser]=!0,t.version=e.version),t.chrome?t.webkit=!0:t.webkit&&(t.safari=!0),v.browser=t,v.sub=function(){function e(t,n){return new e.fn.init(t,n)}v.extend(!0,e,this),e.superclass=this,e.fn=e.prototype=this(),e.fn.constructor=e,e.sub=this.sub,e.fn.init=function(r,i){return i&&i instanceof v&&!(i instanceof e)&&(i=e(i)),v.fn.init.call(this,r,i,t)},e.fn.init.prototype=e.fn;var t=e(i);return e}}();var Dt,Pt,Ht,Bt=/alpha\([^)]*\)/i,jt=/opacity=([^)]*)/,Ft=/^(top|right|bottom|left)$/,It=/^(none|table(?!-c[ea]).+)/,qt=/^margin/,Rt=new RegExp("^("+m+")(.*)$","i"),Ut=new RegExp("^("+m+")(?!px)[a-z%]+$","i"),zt=new RegExp("^([-+])=("+m+")","i"),Wt={BODY:"block"},Xt={position:"absolute",visibility:"hidden",display:"block"},Vt={letterSpacing:0,fontWeight:400},$t=["Top","Right","Bottom","Left"],Jt=["Webkit","O","Moz","ms"],Kt=v.fn.toggle;v.fn.extend({css:function(e,n){return v.access(this,function(e,n,r){return r!==t?v.style(e,n,r):v.css(e,n)},e,n,arguments.length>1)},show:function(){return Yt(this,!0)},hide:function(){return Yt(this)},toggle:function(e,t){var n=typeof e=="boolean";return v.isFunction(e)&&v.isFunction(t)?Kt.apply(this,arguments):this.each(function(){(n?e:Gt(this))?v(this).show():v(this).hide()})}}),v.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Dt(e,"opacity");return n===""?"1":n}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":v.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(!e||e.nodeType===3||e.nodeType===8||!e.style)return;var s,o,u,a=v.camelCase(n),f=e.style;n=v.cssProps[a]||(v.cssProps[a]=Qt(f,a)),u=v.cssHooks[n]||v.cssHooks[a];if(r===t)return u&&"get"in u&&(s=u.get(e,!1,i))!==t?s:f[n];o=typeof r,o==="string"&&(s=zt.exec(r))&&(r=(s[1]+1)*s[2]+parseFloat(v.css(e,n)),o="number");if(r==null||o==="number"&&isNaN(r))return;o==="number"&&!v.cssNumber[a]&&(r+="px");if(!u||!("set"in u)||(r=u.set(e,r,i))!==t)try{f[n]=r}catch(l){}},css:function(e,n,r,i){var s,o,u,a=v.camelCase(n);return n=v.cssProps[a]||(v.cssProps[a]=Qt(e.style,a)),u=v.cssHooks[n]||v.cssHooks[a],u&&"get"in u&&(s=u.get(e,!0,i)),s===t&&(s=Dt(e,n)),s==="normal"&&n in Vt&&(s=Vt[n]),r||i!==t?(o=parseFloat(s),r||v.isNumeric(o)?o||0:s):s},swap:function(e,t,n){var r,i,s={};for(i in t)s[i]=e.style[i],e.style[i]=t[i];r=n.call(e);for(i in t)e.style[i]=s[i];return r}}),e.getComputedStyle?Dt=function(t,n){var r,i,s,o,u=e.getComputedStyle(t,null),a=t.style;return u&&(r=u.getPropertyValue(n)||u[n],r===""&&!v.contains(t.ownerDocument,t)&&(r=v.style(t,n)),Ut.test(r)&&qt.test(n)&&(i=a.width,s=a.minWidth,o=a.maxWidth,a.minWidth=a.maxWidth=a.width=r,r=u.width,a.width=i,a.minWidth=s,a.maxWidth=o)),r}:i.documentElement.currentStyle&&(Dt=function(e,t){var n,r,i=e.currentStyle&&e.currentStyle[t],s=e.style;return i==null&&s&&s[t]&&(i=s[t]),Ut.test(i)&&!Ft.test(t)&&(n=s.left,r=e.runtimeStyle&&e.runtimeStyle.left,r&&(e.runtimeStyle.left=e.currentStyle.left),s.left=t==="fontSize"?"1em":i,i=s.pixelLeft+"px",s.left=n,r&&(e.runtimeStyle.left=r)),i===""?"auto":i}),v.each(["height","width"],function(e,t){v.cssHooks[t]={get:function(e,n,r){if(n)return e.offsetWidth===0&&It.test(Dt(e,"display"))?v.swap(e,Xt,function(){return tn(e,t,r)}):tn(e,t,r)},set:function(e,n,r){return Zt(e,n,r?en(e,t,r,v.support.boxSizing&&v.css(e,"boxSizing")==="border-box"):0)}}}),v.support.opacity||(v.cssHooks.opacity={get:function(e,t){return jt.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=v.isNumeric(t)?"alpha(opacity="+t*100+")":"",s=r&&r.filter||n.filter||"";n.zoom=1;if(t>=1&&v.trim(s.replace(Bt,""))===""&&n.removeAttribute){n.removeAttribute("filter");if(r&&!r.filter)return}n.filter=Bt.test(s)?s.replace(Bt,i):s+" "+i}}),v(function(){v.support.reliableMarginRight||(v.cssHooks.marginRight={get:function(e,t){return v.swap(e,{display:"inline-block"},function(){if(t)return Dt(e,"marginRight")})}}),!v.support.pixelPosition&&v.fn.position&&v.each(["top","left"],function(e,t){v.cssHooks[t]={get:function(e,n){if(n){var r=Dt(e,t);return Ut.test(r)?v(e).position()[t]+"px":r}}}})}),v.expr&&v.expr.filters&&(v.expr.filters.hidden=function(e){return e.offsetWidth===0&&e.offsetHeight===0||!v.support.reliableHiddenOffsets&&(e.style&&e.style.display||Dt(e,"display"))==="none"},v.expr.filters.visible=function(e){return!v.expr.filters.hidden(e)}),v.each({margin:"",padding:"",border:"Width"},function(e,t){v.cssHooks[e+t]={expand:function(n){var r,i=typeof n=="string"?n.split(" "):[n],s={};for(r=0;r<4;r++)s[e+$t[r]+t]=i[r]||i[r-2]||i[0];return s}},qt.test(e)||(v.cssHooks[e+t].set=Zt)});var rn=/%20/g,sn=/\[\]$/,on=/\r?\n/g,un=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,an=/^(?:select|textarea)/i;v.fn.extend({serialize:function(){return v.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?v.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||an.test(this.nodeName)||un.test(this.type))}).map(function(e,t){var n=v(this).val();return n==null?null:v.isArray(n)?v.map(n,function(e,n){return{name:t.name,value:e.replace(on,"\r\n")}}):{name:t.name,value:n.replace(on,"\r\n")}}).get()}}),v.param=function(e,n){var r,i=[],s=function(e,t){t=v.isFunction(t)?t():t==null?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};n===t&&(n=v.ajaxSettings&&v.ajaxSettings.traditional);if(v.isArray(e)||e.jquery&&!v.isPlainObject(e))v.each(e,function(){s(this.name,this.value)});else for(r in e)fn(r,e[r],n,s);return i.join("&").replace(rn,"+")};var ln,cn,hn=/#.*$/,pn=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,dn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,vn=/^(?:GET|HEAD)$/,mn=/^\/\//,gn=/\?/,yn=/)<[^<]*)*<\/script>/gi,bn=/([?&])_=[^&]*/,wn=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,En=v.fn.load,Sn={},xn={},Tn=["*/"]+["*"];try{cn=s.href}catch(Nn){cn=i.createElement("a"),cn.href="",cn=cn.href}ln=wn.exec(cn.toLowerCase())||[],v.fn.load=function(e,n,r){if(typeof e!="string"&&En)return En.apply(this,arguments);if(!this.length)return this;var i,s,o,u=this,a=e.indexOf(" ");return a>=0&&(i=e.slice(a,e.length),e=e.slice(0,a)),v.isFunction(n)?(r=n,n=t):n&&typeof n=="object"&&(s="POST"),v.ajax({url:e,type:s,dataType:"html",data:n,complete:function(e,t){r&&u.each(r,o||[e.responseText,t,e])}}).done(function(e){o=arguments,u.html(i?v("
").append(e.replace(yn,"")).find(i):e)}),this},v.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,t){v.fn[t]=function(e){return this.on(t,e)}}),v.each(["get","post"],function(e,n){v[n]=function(e,r,i,s){return v.isFunction(r)&&(s=s||i,i=r,r=t),v.ajax({type:n,url:e,data:r,success:i,dataType:s})}}),v.extend({getScript:function(e,n){return v.get(e,t,n,"script")},getJSON:function(e,t,n){return v.get(e,t,n,"json")},ajaxSetup:function(e,t){return t?Ln(e,v.ajaxSettings):(t=e,e=v.ajaxSettings),Ln(e,t),e},ajaxSettings:{url:cn,isLocal:dn.test(ln[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":Tn},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":v.parseJSON,"text xml":v.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:Cn(Sn),ajaxTransport:Cn(xn),ajax:function(e,n){function T(e,n,s,a){var l,y,b,w,S,T=n;if(E===2)return;E=2,u&&clearTimeout(u),o=t,i=a||"",x.readyState=e>0?4:0,s&&(w=An(c,x,s));if(e>=200&&e<300||e===304)c.ifModified&&(S=x.getResponseHeader("Last-Modified"),S&&(v.lastModified[r]=S),S=x.getResponseHeader("Etag"),S&&(v.etag[r]=S)),e===304?(T="notmodified",l=!0):(l=On(c,w),T=l.state,y=l.data,b=l.error,l=!b);else{b=T;if(!T||e)T="error",e<0&&(e=0)}x.status=e,x.statusText=(n||T)+"",l?d.resolveWith(h,[y,T,x]):d.rejectWith(h,[x,T,b]),x.statusCode(g),g=t,f&&p.trigger("ajax"+(l?"Success":"Error"),[x,c,l?y:b]),m.fireWith(h,[x,T]),f&&(p.trigger("ajaxComplete",[x,c]),--v.active||v.event.trigger("ajaxStop"))}typeof e=="object"&&(n=e,e=t),n=n||{};var r,i,s,o,u,a,f,l,c=v.ajaxSetup({},n),h=c.context||c,p=h!==c&&(h.nodeType||h instanceof v)?v(h):v.event,d=v.Deferred(),m=v.Callbacks("once memory"),g=c.statusCode||{},b={},w={},E=0,S="canceled",x={readyState:0,setRequestHeader:function(e,t){if(!E){var n=e.toLowerCase();e=w[n]=w[n]||e,b[e]=t}return this},getAllResponseHeaders:function(){return E===2?i:null},getResponseHeader:function(e){var n;if(E===2){if(!s){s={};while(n=pn.exec(i))s[n[1].toLowerCase()]=n[2]}n=s[e.toLowerCase()]}return n===t?null:n},overrideMimeType:function(e){return E||(c.mimeType=e),this},abort:function(e){return e=e||S,o&&o.abort(e),T(0,e),this}};d.promise(x),x.success=x.done,x.error=x.fail,x.complete=m.add,x.statusCode=function(e){if(e){var t;if(E<2)for(t in e)g[t]=[g[t],e[t]];else t=e[x.status],x.always(t)}return this},c.url=((e||c.url)+"").replace(hn,"").replace(mn,ln[1]+"//"),c.dataTypes=v.trim(c.dataType||"*").toLowerCase().split(y),c.crossDomain==null&&(a=wn.exec(c.url.toLowerCase()),c.crossDomain=!(!a||a[1]===ln[1]&&a[2]===ln[2]&&(a[3]||(a[1]==="http:"?80:443))==(ln[3]||(ln[1]==="http:"?80:443)))),c.data&&c.processData&&typeof c.data!="string"&&(c.data=v.param(c.data,c.traditional)),kn(Sn,c,n,x);if(E===2)return x;f=c.global,c.type=c.type.toUpperCase(),c.hasContent=!vn.test(c.type),f&&v.active++===0&&v.event.trigger("ajaxStart");if(!c.hasContent){c.data&&(c.url+=(gn.test(c.url)?"&":"?")+c.data,delete c.data),r=c.url;if(c.cache===!1){var N=v.now(),C=c.url.replace(bn,"$1_="+N);c.url=C+(C===c.url?(gn.test(c.url)?"&":"?")+"_="+N:"")}}(c.data&&c.hasContent&&c.contentType!==!1||n.contentType)&&x.setRequestHeader("Content-Type",c.contentType),c.ifModified&&(r=r||c.url,v.lastModified[r]&&x.setRequestHeader("If-Modified-Since",v.lastModified[r]),v.etag[r]&&x.setRequestHeader("If-None-Match",v.etag[r])),x.setRequestHeader("Accept",c.dataTypes[0]&&c.accepts[c.dataTypes[0]]?c.accepts[c.dataTypes[0]]+(c.dataTypes[0]!=="*"?", "+Tn+"; q=0.01":""):c.accepts["*"]);for(l in c.headers)x.setRequestHeader(l,c.headers[l]);if(!c.beforeSend||c.beforeSend.call(h,x,c)!==!1&&E!==2){S="abort";for(l in{success:1,error:1,complete:1})x[l](c[l]);o=kn(xn,c,n,x);if(!o)T(-1,"No Transport");else{x.readyState=1,f&&p.trigger("ajaxSend",[x,c]),c.async&&c.timeout>0&&(u=setTimeout(function(){x.abort("timeout")},c.timeout));try{E=1,o.send(b,T)}catch(k){if(!(E<2))throw k;T(-1,k)}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var Mn=[],_n=/\?/,Dn=/(=)\?(?=&|$)|\?\?/,Pn=v.now();v.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Mn.pop()||v.expando+"_"+Pn++;return this[e]=!0,e}}),v.ajaxPrefilter("json jsonp",function(n,r,i){var s,o,u,a=n.data,f=n.url,l=n.jsonp!==!1,c=l&&Dn.test(f),h=l&&!c&&typeof a=="string"&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Dn.test(a);if(n.dataTypes[0]==="jsonp"||c||h)return s=n.jsonpCallback=v.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,o=e[s],c?n.url=f.replace(Dn,"$1"+s):h?n.data=a.replace(Dn,"$1"+s):l&&(n.url+=(_n.test(f)?"&":"?")+n.jsonp+"="+s),n.converters["script json"]=function(){return u||v.error(s+" was not called"),u[0]},n.dataTypes[0]="json",e[s]=function(){u=arguments},i.always(function(){e[s]=o,n[s]&&(n.jsonpCallback=r.jsonpCallback,Mn.push(s)),u&&v.isFunction(o)&&o(u[0]),u=o=t}),"script"}),v.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(e){return v.globalEval(e),e}}}),v.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),v.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=i.head||i.getElementsByTagName("head")[0]||i.documentElement;return{send:function(s,o){n=i.createElement("script"),n.async="async",e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,i){if(i||!n.readyState||/loaded|complete/.test(n.readyState))n.onload=n.onreadystatechange=null,r&&n.parentNode&&r.removeChild(n),n=t,i||o(200,"success")},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(0,1)}}}});var Hn,Bn=e.ActiveXObject?function(){for(var e in Hn)Hn[e](0,1)}:!1,jn=0;v.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&Fn()||In()}:Fn,function(e){v.extend(v.support,{ajax:!!e,cors:!!e&&"withCredentials"in e})}(v.ajaxSettings.xhr()),v.support.ajax&&v.ajaxTransport(function(n){if(!n.crossDomain||v.support.cors){var r;return{send:function(i,s){var o,u,a=n.xhr();n.username?a.open(n.type,n.url,n.async,n.username,n.password):a.open(n.type,n.url,n.async);if(n.xhrFields)for(u in n.xhrFields)a[u]=n.xhrFields[u];n.mimeType&&a.overrideMimeType&&a.overrideMimeType(n.mimeType),!n.crossDomain&&!i["X-Requested-With"]&&(i["X-Requested-With"]="XMLHttpRequest");try{for(u in i)a.setRequestHeader(u,i[u])}catch(f){}a.send(n.hasContent&&n.data||null),r=function(e,i){var u,f,l,c,h;try{if(r&&(i||a.readyState===4)){r=t,o&&(a.onreadystatechange=v.noop,Bn&&delete Hn[o]);if(i)a.readyState!==4&&a.abort();else{u=a.status,l=a.getAllResponseHeaders(),c={},h=a.responseXML,h&&h.documentElement&&(c.xml=h);try{c.text=a.responseText}catch(p){}try{f=a.statusText}catch(p){f=""}!u&&n.isLocal&&!n.crossDomain?u=c.text?200:404:u===1223&&(u=204)}}}catch(d){i||s(-1,d)}c&&s(u,f,c,l)},n.async?a.readyState===4?setTimeout(r,0):(o=++jn,Bn&&(Hn||(Hn={},v(e).unload(Bn)),Hn[o]=r),a.onreadystatechange=r):r()},abort:function(){r&&r(0,1)}}}});var qn,Rn,Un=/^(?:toggle|show|hide)$/,zn=new RegExp("^(?:([-+])=|)("+m+")([a-z%]*)$","i"),Wn=/queueHooks$/,Xn=[Gn],Vn={"*":[function(e,t){var n,r,i=this.createTween(e,t),s=zn.exec(t),o=i.cur(),u=+o||0,a=1,f=20;if(s){n=+s[2],r=s[3]||(v.cssNumber[e]?"":"px");if(r!=="px"&&u){u=v.css(i.elem,e,!0)||n||1;do a=a||".5",u/=a,v.style(i.elem,e,u+r);while(a!==(a=i.cur()/o)&&a!==1&&--f)}i.unit=r,i.start=u,i.end=s[1]?u+(s[1]+1)*n:n}return i}]};v.Animation=v.extend(Kn,{tweener:function(e,t){v.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;r-1,f={},l={},c,h;a?(l=i.position(),c=l.top,h=l.left):(c=parseFloat(o)||0,h=parseFloat(u)||0),v.isFunction(t)&&(t=t.call(e,n,s)),t.top!=null&&(f.top=t.top-s.top+c),t.left!=null&&(f.left=t.left-s.left+h),"using"in t?t.using.call(e,f):i.css(f)}},v.fn.extend({position:function(){if(!this[0])return;var e=this[0],t=this.offsetParent(),n=this.offset(),r=er.test(t[0].nodeName)?{top:0,left:0}:t.offset();return n.top-=parseFloat(v.css(e,"marginTop"))||0,n.left-=parseFloat(v.css(e,"marginLeft"))||0,r.top+=parseFloat(v.css(t[0],"borderTopWidth"))||0,r.left+=parseFloat(v.css(t[0],"borderLeftWidth"))||0,{top:n.top-r.top,left:n.left-r.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||i.body;while(e&&!er.test(e.nodeName)&&v.css(e,"position")==="static")e=e.offsetParent;return e||i.body})}}),v.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);v.fn[e]=function(i){return v.access(this,function(e,i,s){var o=tr(e);if(s===t)return o?n in o?o[n]:o.document.documentElement[i]:e[i];o?o.scrollTo(r?v(o).scrollLeft():s,r?s:v(o).scrollTop()):e[i]=s},e,i,arguments.length,null)}}),v.each({Height:"height",Width:"width"},function(e,n){v.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){v.fn[i]=function(i,s){var o=arguments.length&&(r||typeof i!="boolean"),u=r||(i===!0||s===!0?"margin":"border");return v.access(this,function(n,r,i){var s;return v.isWindow(n)?n.document.documentElement["client"+e]:n.nodeType===9?(s=n.documentElement,Math.max(n.body["scroll"+e],s["scroll"+e],n.body["offset"+e],s["offset"+e],s["client"+e])):i===t?v.css(n,r,i,u):v.style(n,r,i,u)},n,o?i:t,o,null)}})}),e.jQuery=e.$=v,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return v})})(window); \ No newline at end of file