| |
| |
| (function (window, Object, Array, Error, JSON, undefined ) { |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| var partialComplete = varArgs(function( fn, args ) { |
|
|
| |
| |
| |
|
|
| var numBoundArgs = args.length; |
|
|
| return varArgs(function( callArgs ) { |
| |
| for (var i = 0; i < callArgs.length; i++) { |
| args[numBoundArgs + i] = callArgs[i]; |
| } |
| |
| args.length = numBoundArgs + callArgs.length; |
| |
| return fn.apply(this, args); |
| }); |
| }), |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| compose = varArgs(function(fns) { |
|
|
| var fnsList = arrayAsList(fns); |
| |
| function next(params, curFn) { |
| return [apply(params, curFn)]; |
| } |
| |
| return varArgs(function(startParams){ |
| |
| return foldR(next, startParams, fnsList)[0]; |
| }); |
| }); |
|
|
| |
| |
| |
| |
| |
| function compose2(f1, f2){ |
| return function(){ |
| return f1.call(this,f2.apply(this,arguments)); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function attr(key) { |
| return new Function('o', 'return o["' + key + '"]' ); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| var lazyUnion = varArgs(function(fns) { |
|
|
| return varArgs(function(params){ |
| |
| var maybeValue; |
| |
| for (var i = 0; i < len(fns); i++) { |
| |
| maybeValue = apply(params, fns[i]); |
| |
| if( maybeValue ) { |
| return maybeValue; |
| } |
| } |
| }); |
| }); |
|
|
| |
| |
| |
| |
| |
| |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| function apply(args, fn) { |
| return fn.apply(undefined, args); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function varArgs(fn){ |
|
|
| var numberOfFixedArguments = fn.length -1, |
| slice = Array.prototype.slice; |
| |
| |
| if( numberOfFixedArguments == 0 ) { |
| |
| |
| return function(){ |
| return fn.call(this, slice.call(arguments)); |
| } |
| |
| } else if( numberOfFixedArguments == 1 ) { |
| |
| |
| return function(){ |
| return fn.call(this, arguments[0], slice.call(arguments, 1)); |
| } |
| } |
| |
| |
|
|
| |
| |
| |
| var argsHolder = Array(fn.length); |
| |
| return function(){ |
| |
| for (var i = 0; i < numberOfFixedArguments; i++) { |
| argsHolder[i] = arguments[i]; |
| } |
|
|
| argsHolder[numberOfFixedArguments] = |
| slice.call(arguments, numberOfFixedArguments); |
| |
| return fn.apply( this, argsHolder); |
| } |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| function flip(fn){ |
| return function(a, b){ |
| return fn(b,a); |
| } |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| |
| function lazyIntersection(fn1, fn2) { |
|
|
| return function (param) { |
| |
| return fn1(param) && fn2(param); |
| }; |
| } |
|
|
| |
| |
| |
| function noop(){} |
|
|
| |
| |
| |
| function always(){return true} |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function functor(val){ |
| return function(){ |
| return val; |
| } |
| } |
|
|
| |
| |
| |
| |
|
|
|
|
| |
| |
| |
| function isOfType(T, maybeSomething){ |
| return maybeSomething && maybeSomething.constructor === T; |
| } |
|
|
| var len = attr('length'), |
| isString = partialComplete(isOfType, String); |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function defined( value ) { |
| return value !== undefined; |
| } |
|
|
| |
| |
| |
| |
| |
| function hasAllProperties(fieldList, o) { |
|
|
| return (o instanceof Object) |
| && |
| all(function (field) { |
| return (field in o); |
| }, fieldList); |
| } |
| |
| |
| |
| function cons(x, xs) { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| return [x,xs]; |
| } |
|
|
| |
| |
| |
| var emptyList = null, |
|
|
| |
| |
| |
| |
| |
| head = attr(0), |
|
|
| |
| |
| |
| |
| |
| tail = attr(1); |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function arrayAsList(inputArray){ |
|
|
| return reverseList( |
| inputArray.reduce( |
| flip(cons), |
| emptyList |
| ) |
| ); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| var list = varArgs(arrayAsList); |
|
|
| |
| |
| |
| function listAsArray(list){ |
|
|
| return foldR( function(arraySoFar, listItem){ |
| |
| arraySoFar.unshift(listItem); |
| return arraySoFar; |
| |
| }, [], list ); |
| |
| } |
|
|
| |
| |
| |
| function map(fn, list) { |
|
|
| return list |
| ? cons(fn(head(list)), map(fn,tail(list))) |
| : emptyList |
| ; |
| } |
|
|
| |
| |
| |
| |
| |
| function foldR(fn, startValue, list) { |
| |
| return list |
| ? fn(foldR(fn, startValue, tail(list)), head(list)) |
| : startValue |
| ; |
| } |
|
|
| |
| |
| |
| |
| |
| function foldR1(fn, list) { |
| |
| return tail(list) |
| ? fn(foldR1(fn, tail(list)), head(list)) |
| : head(list) |
| ; |
| } |
|
|
|
|
| |
| |
| |
| |
| function without(list, test, removedFn) { |
| |
| return withoutInner(list, removedFn || noop); |
| |
| function withoutInner(subList, removedFn) { |
| return subList |
| ? ( test(head(subList)) |
| ? (removedFn(head(subList)), tail(subList)) |
| : cons(head(subList), withoutInner(tail(subList), removedFn)) |
| ) |
| : emptyList |
| ; |
| } |
| } |
|
|
| |
| |
| |
| |
| function all(fn, list) { |
| |
| return !list || |
| ( fn(head(list)) && all(fn, tail(list)) ); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| function applyEach(fnList, arguments) { |
|
|
| if( fnList ) { |
| head(fnList).apply(null, arguments); |
| |
| applyEach(tail(fnList), arguments); |
| } |
| } |
|
|
| |
| |
| |
| function reverseList(list){ |
|
|
| |
| |
| function reverseInner( list, reversedAlready ) { |
| if( !list ) { |
| return reversedAlready; |
| } |
| |
| return reverseInner(tail(list), cons(head(list), reversedAlready)) |
| } |
|
|
| return reverseInner(list, emptyList); |
| } |
|
|
| function first(test, list) { |
| return list && |
| (test(head(list)) |
| ? head(list) |
| : first(test,tail(list))); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| var clarinet = (function () { |
|
|
| var clarinet = { |
| parser : function () { return new CParser();}, |
| CParser : CParser, |
| MAX_BUFFER_LENGTH : 64 * 1024, |
| EVENTS : [ |
| "value" |
| , "string" |
| , "key" |
| , "openobject" |
| , "closeobject" |
| , "openarray" |
| , "closearray" |
| , "error" |
| , "end" |
| , "ready" |
| ] |
| }; |
|
|
| var buffers = [ "textNode", "numberNode" ] |
| , _n = 0 |
| ; |
| |
| var BEGIN = _n++; |
| var VALUE = _n++; |
| var OPEN_OBJECT = _n++; |
| var CLOSE_OBJECT = _n++; |
| var OPEN_ARRAY = _n++; |
| var CLOSE_ARRAY = _n++; |
| var STRING = _n++; |
| var OPEN_KEY = _n++; |
| var CLOSE_KEY = _n++; |
| var TRUE = _n++; |
| var TRUE2 = _n++; |
| var TRUE3 = _n++; |
| var FALSE = _n++; |
| var FALSE2 = _n++; |
| var FALSE3 = _n++; |
| var FALSE4 = _n++; |
| var NULL = _n++; |
| var NULL2 = _n++; |
| var NULL3 = _n++; |
| var NUMBER_DECIMAL_POINT = _n++; |
| var NUMBER_DIGIT = _n; |
|
|
| if (!Object.create) { |
| Object.create = function (o) { |
| function f () { this["__proto__"] = o; } |
| f.prototype = o; |
| return new f; |
| }; |
| } |
|
|
| if (!Object.getPrototypeOf) { |
| Object.getPrototypeOf = function (o) { |
| return o["__proto__"]; |
| }; |
| } |
|
|
| if (!Object.keys) { |
| Object.keys = function (o) { |
| var a = []; |
| for (var i in o) if (o.hasOwnProperty(i)) a.push(i); |
| return a; |
| }; |
| } |
|
|
| function checkBufferLength (parser) { |
| var maxAllowed = Math.max(clarinet.MAX_BUFFER_LENGTH, 10) |
| , maxActual = 0 |
| ; |
| for (var i = 0, l = buffers.length; i < l; i ++) { |
| var len = parser[buffers[i]].length; |
| if (len > maxAllowed) { |
| switch (buffers[i]) { |
| case "text": |
| closeText(parser); |
| break; |
|
|
| default: |
| error(parser, "Max buffer length exceeded: "+ buffers[i]); |
| } |
| } |
| maxActual = Math.max(maxActual, len); |
| } |
| parser.bufferCheckPosition = (clarinet.MAX_BUFFER_LENGTH - maxActual) |
| + parser.position; |
| } |
|
|
| function clearBuffers (parser) { |
| for (var i = 0, l = buffers.length; i < l; i ++) { |
| parser[buffers[i]] = ""; |
| } |
| } |
|
|
| var stringTokenPattern = /[\\"\n]/g; |
|
|
| function CParser () { |
| var parser = this; |
| clearBuffers(parser); |
| parser.bufferCheckPosition = clarinet.MAX_BUFFER_LENGTH; |
| parser.q = parser.c = parser.p = ""; |
| parser.closed = parser.closedRoot = parser.sawRoot = false; |
| parser.tag = parser.error = null; |
| parser.state = BEGIN; |
| parser.stack = []; |
| |
| parser.position = parser.column = 0; |
| parser.line = 1; |
| parser.slashed = false; |
| parser.unicodeI = 0; |
| parser.unicodeS = null; |
| parser.depth = 0; |
| emit(parser, "onready"); |
| } |
|
|
| CParser.prototype = |
| { end : function () { end(this); } |
| , write : write |
| , close : function () { return this.write(null); } |
| }; |
|
|
| function emit(parser, event, data) { |
| if (parser[event]) parser[event](data); |
| } |
|
|
| function emitNode(parser, event, data) { |
| closeValue(parser); |
| emit(parser, event, data); |
| } |
|
|
| function closeValue(parser, event) { |
|
|
| if (parser.textNode) { |
| emit(parser, (event ? event : "onvalue"), parser.textNode); |
| } |
| parser.textNode = ""; |
| } |
|
|
| function closeNumber(parser) { |
| if (parser.numberNode) |
| emit(parser, "onvalue", parseFloat(parser.numberNode)); |
| parser.numberNode = ""; |
| } |
|
|
|
|
| function error (parser, er) { |
| closeValue(parser); |
| er += "\nLine: "+parser.line+ |
| "\nColumn: "+parser.column+ |
| "\nChar: "+parser.c; |
| er = new Error(er); |
| parser.error = er; |
| emit(parser, "onerror", er); |
| return parser; |
| } |
|
|
| function end(parser) { |
| if (parser.state !== VALUE || parser.depth !== 0) |
| error(parser, "Unexpected end"); |
|
|
| closeValue(parser); |
| parser.c = ""; |
| parser.closed = true; |
| emit(parser, "onend"); |
| CParser.call(parser); |
| return parser; |
| } |
|
|
| function write (chunk) { |
| var parser = this; |
| |
| |
| |
| |
| if (this.error) |
| return; |
| |
| if (parser.closed) return error(parser, |
| "Cannot write after close. Assign an onready handler."); |
| if (chunk === null) return end(parser); |
| var i = 0, c = chunk[0], p = parser.p; |
|
|
| while (c) { |
| p = c; |
| parser.c = c = chunk.charAt(i++); |
| |
| |
| |
| |
| if(p !== c ) parser.p = p; |
| else p = parser.p; |
|
|
| if(!c) break; |
|
|
| parser.position ++; |
| if (c === "\n") { |
| parser.line ++; |
| parser.column = 0; |
| } else parser.column ++; |
| switch (parser.state) { |
|
|
| case BEGIN: |
| if (c === "{") parser.state = OPEN_OBJECT; |
| else if (c === "[") parser.state = OPEN_ARRAY; |
| else if (c !== '\r' && c !== '\n' && c !== ' ' && c !== '\t') |
| error(parser, "Non-whitespace before {[."); |
| continue; |
|
|
| case OPEN_KEY: |
| case OPEN_OBJECT: |
| if (c === '\r' || c === '\n' || c === ' ' || c === '\t') continue; |
| if(parser.state === OPEN_KEY) parser.stack.push(CLOSE_KEY); |
| else { |
| if(c === '}') { |
| emit(parser, 'onopenobject'); |
| this.depth++; |
| emit(parser, 'oncloseobject'); |
| this.depth--; |
| parser.state = parser.stack.pop() || VALUE; |
| continue; |
| } else parser.stack.push(CLOSE_OBJECT); |
| } |
| if(c === '"') parser.state = STRING; |
| else error(parser, "Malformed object key should start with \""); |
| continue; |
|
|
| case CLOSE_KEY: |
| case CLOSE_OBJECT: |
| if (c === '\r' || c === '\n' || c === ' ' || c === '\t') continue; |
|
|
| if(c===':') { |
| if(parser.state === CLOSE_OBJECT) { |
| parser.stack.push(CLOSE_OBJECT); |
| closeValue(parser, 'onopenobject'); |
| this.depth++; |
| } else closeValue(parser, 'onkey'); |
| parser.state = VALUE; |
| } else if (c==='}') { |
| emitNode(parser, 'oncloseobject'); |
| this.depth--; |
| parser.state = parser.stack.pop() || VALUE; |
| } else if(c===',') { |
| if(parser.state === CLOSE_OBJECT) |
| parser.stack.push(CLOSE_OBJECT); |
| closeValue(parser); |
| parser.state = OPEN_KEY; |
| } else error(parser, 'Bad object'); |
| continue; |
|
|
| case OPEN_ARRAY: |
| case VALUE: |
| if (c === '\r' || c === '\n' || c === ' ' || c === '\t') continue; |
| if(parser.state===OPEN_ARRAY) { |
| emit(parser, 'onopenarray'); |
| this.depth++; |
| parser.state = VALUE; |
| if(c === ']') { |
| emit(parser, 'onclosearray'); |
| this.depth--; |
| parser.state = parser.stack.pop() || VALUE; |
| continue; |
| } else { |
| parser.stack.push(CLOSE_ARRAY); |
| } |
| } |
| if(c === '"') parser.state = STRING; |
| else if(c === '{') parser.state = OPEN_OBJECT; |
| else if(c === '[') parser.state = OPEN_ARRAY; |
| else if(c === 't') parser.state = TRUE; |
| else if(c === 'f') parser.state = FALSE; |
| else if(c === 'n') parser.state = NULL; |
| else if(c === '-') { |
| parser.numberNode += c; |
| } else if(c==='0') { |
| parser.numberNode += c; |
| parser.state = NUMBER_DIGIT; |
| } else if('123456789'.indexOf(c) !== -1) { |
| parser.numberNode += c; |
| parser.state = NUMBER_DIGIT; |
| } else error(parser, "Bad value"); |
| continue; |
|
|
| case CLOSE_ARRAY: |
| if(c===',') { |
| parser.stack.push(CLOSE_ARRAY); |
| closeValue(parser, 'onvalue'); |
| parser.state = VALUE; |
| } else if (c===']') { |
| emitNode(parser, 'onclosearray'); |
| this.depth--; |
| parser.state = parser.stack.pop() || VALUE; |
| } else if (c === '\r' || c === '\n' || c === ' ' || c === '\t') |
| continue; |
| else error(parser, 'Bad array'); |
| continue; |
|
|
| case STRING: |
| |
| var starti = i-1 |
| , slashed = parser.slashed |
| , unicodeI = parser.unicodeI |
| ; |
| STRING_BIGLOOP: while (true) { |
|
|
| |
| while (unicodeI > 0) { |
| parser.unicodeS += c; |
| c = chunk.charAt(i++); |
| if (unicodeI === 4) { |
| |
| parser.textNode += String.fromCharCode(parseInt(parser.unicodeS, 16)); |
| unicodeI = 0; |
| starti = i-1; |
| } else { |
| unicodeI++; |
| } |
| |
| if (!c) break STRING_BIGLOOP; |
| } |
| if (c === '"' && !slashed) { |
| parser.state = parser.stack.pop() || VALUE; |
| parser.textNode += chunk.substring(starti, i-1); |
| if(!parser.textNode) { |
| emit(parser, "onvalue", ""); |
| } |
| break; |
| } |
| if (c === '\\' && !slashed) { |
| slashed = true; |
| parser.textNode += chunk.substring(starti, i-1); |
| c = chunk.charAt(i++); |
| if (!c) break; |
| } |
| if (slashed) { |
| slashed = false; |
| if (c === 'n') { parser.textNode += '\n'; } |
| else if (c === 'r') { parser.textNode += '\r'; } |
| else if (c === 't') { parser.textNode += '\t'; } |
| else if (c === 'f') { parser.textNode += '\f'; } |
| else if (c === 'b') { parser.textNode += '\b'; } |
| else if (c === 'u') { |
| |
| unicodeI = 1; |
| parser.unicodeS = ''; |
| } else { |
| parser.textNode += c; |
| } |
| c = chunk.charAt(i++); |
| starti = i-1; |
| if (!c) break; |
| else continue; |
| } |
|
|
| stringTokenPattern.lastIndex = i; |
| var reResult = stringTokenPattern.exec(chunk); |
| if (reResult === null) { |
| i = chunk.length+1; |
| parser.textNode += chunk.substring(starti, i-1); |
| break; |
| } |
| i = reResult.index+1; |
| c = chunk.charAt(reResult.index); |
| if (!c) { |
| parser.textNode += chunk.substring(starti, i-1); |
| break; |
| } |
| } |
| parser.slashed = slashed; |
| parser.unicodeI = unicodeI; |
| continue; |
|
|
| case TRUE: |
| if (c==='') continue; |
| if (c==='r') parser.state = TRUE2; |
| else error(parser, 'Invalid true started with t'+ c); |
| continue; |
|
|
| case TRUE2: |
| if (c==='') continue; |
| if (c==='u') parser.state = TRUE3; |
| else error(parser, 'Invalid true started with tr'+ c); |
| continue; |
|
|
| case TRUE3: |
| if (c==='') continue; |
| if(c==='e') { |
| emit(parser, "onvalue", true); |
| parser.state = parser.stack.pop() || VALUE; |
| } else error(parser, 'Invalid true started with tru'+ c); |
| continue; |
|
|
| case FALSE: |
| if (c==='') continue; |
| if (c==='a') parser.state = FALSE2; |
| else error(parser, 'Invalid false started with f'+ c); |
| continue; |
|
|
| case FALSE2: |
| if (c==='') continue; |
| if (c==='l') parser.state = FALSE3; |
| else error(parser, 'Invalid false started with fa'+ c); |
| continue; |
|
|
| case FALSE3: |
| if (c==='') continue; |
| if (c==='s') parser.state = FALSE4; |
| else error(parser, 'Invalid false started with fal'+ c); |
| continue; |
|
|
| case FALSE4: |
| if (c==='') continue; |
| if (c==='e') { |
| emit(parser, "onvalue", false); |
| parser.state = parser.stack.pop() || VALUE; |
| } else error(parser, 'Invalid false started with fals'+ c); |
| continue; |
|
|
| case NULL: |
| if (c==='') continue; |
| if (c==='u') parser.state = NULL2; |
| else error(parser, 'Invalid null started with n'+ c); |
| continue; |
|
|
| case NULL2: |
| if (c==='') continue; |
| if (c==='l') parser.state = NULL3; |
| else error(parser, 'Invalid null started with nu'+ c); |
| continue; |
|
|
| case NULL3: |
| if (c==='') continue; |
| if(c==='l') { |
| emit(parser, "onvalue", null); |
| parser.state = parser.stack.pop() || VALUE; |
| } else error(parser, 'Invalid null started with nul'+ c); |
| continue; |
|
|
| case NUMBER_DECIMAL_POINT: |
| if(c==='.') { |
| parser.numberNode += c; |
| parser.state = NUMBER_DIGIT; |
| } else error(parser, 'Leading zero not followed by .'); |
| continue; |
|
|
| case NUMBER_DIGIT: |
| if('0123456789'.indexOf(c) !== -1) parser.numberNode += c; |
| else if (c==='.') { |
| if(parser.numberNode.indexOf('.')!==-1) |
| error(parser, 'Invalid number has two dots'); |
| parser.numberNode += c; |
| } else if (c==='e' || c==='E') { |
| if(parser.numberNode.indexOf('e')!==-1 || |
| parser.numberNode.indexOf('E')!==-1 ) |
| error(parser, 'Invalid number has two exponential'); |
| parser.numberNode += c; |
| } else if (c==="+" || c==="-") { |
| if(!(p==='e' || p==='E')) |
| error(parser, 'Invalid symbol in number'); |
| parser.numberNode += c; |
| } else { |
| closeNumber(parser); |
| i--; |
| parser.state = parser.stack.pop() || VALUE; |
| } |
| continue; |
|
|
| default: |
| error(parser, "Unknown state: " + parser.state); |
| } |
| } |
| if (parser.position >= parser.bufferCheckPosition) |
| checkBufferLength(parser); |
| return parser; |
| } |
|
|
| return clarinet; |
| })(); |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function clarinetListenerAdaptor(clarinetParser, handlers){ |
| |
| var state; |
|
|
| clarinet.EVENTS.forEach(function(eventName){ |
| |
| var handlerFunction = handlers[eventName]; |
| |
| clarinetParser['on'+eventName] = handlerFunction && |
| function(param) { |
| state = handlerFunction( state, param); |
| }; |
| }); |
| } |
|
|
| |
|
|
| |
| |
| |
| |
| |
| |
| function parseResponseHeaders(headerStr) { |
| var headers = {}; |
| |
| headerStr && headerStr.split('\u000d\u000a') |
| .forEach(function(headerPair){ |
| |
| |
| |
| var index = headerPair.indexOf('\u003a\u0020'); |
| |
| headers[headerPair.substring(0, index)] |
| = headerPair.substring(index + 2); |
| }); |
| |
| return headers; |
| } |
| function httpTransport(){ |
| return new XMLHttpRequest(); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function streamingHttp(oboeBus, xhr, method, url, data, headers) { |
| |
| var emitStreamData = oboeBus(STREAM_DATA).emit, |
| emitFail = oboeBus(FAIL_EVENT).emit, |
| numberOfCharsAlreadyGivenToCallback = 0; |
|
|
| |
| |
| oboeBus( ABORTING ).on( function(){ |
| |
| |
| |
| |
| xhr.onreadystatechange = null; |
| |
| xhr.abort(); |
| }); |
|
|
| |
| |
| |
| |
| function handleProgress() { |
| |
| var textSoFar = xhr.responseText, |
| newText = textSoFar.substr(numberOfCharsAlreadyGivenToCallback); |
| |
| |
| |
| |
| |
| |
| |
| |
| if( newText ) { |
| emitStreamData( newText ); |
| } |
|
|
| numberOfCharsAlreadyGivenToCallback = len(textSoFar); |
| } |
| |
| |
| if('onprogress' in xhr){ |
| xhr.onprogress = handleProgress; |
| } |
| |
| xhr.onreadystatechange = function() { |
| |
| switch( xhr.readyState ) { |
| |
| case 2: |
| |
| oboeBus( HTTP_START ).emit( |
| xhr.status, |
| parseResponseHeaders(xhr.getAllResponseHeaders()) ); |
| return; |
| |
| case 4: |
| |
| var successful = String(xhr.status)[0] == 2; |
| |
| if( successful ) { |
| |
| |
| |
| |
| |
| |
| handleProgress(); |
| |
| oboeBus(STREAM_END).emit(); |
| } else { |
|
|
| emitFail( errorReport( |
| xhr.status, |
| xhr.responseText |
| )); |
| } |
| } |
| }; |
|
|
| try{ |
| |
| xhr.open(method, url, true); |
| |
| for( var headerName in headers ){ |
| xhr.setRequestHeader(headerName, headers[headerName]); |
| } |
| xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); |
|
|
| xhr.send(data); |
| |
| } catch( e ) { |
|
|
| |
| |
| |
| |
| |
| |
| window.setTimeout( |
| partialComplete(emitFail, errorReport(undefined, undefined, e)) |
| , 0 |
| ); |
| } |
| } |
|
|
| var jsonPathSyntax = (function() { |
| |
| var |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| regexDescriptor = function regexDescriptor(regex) { |
| return regex.exec.bind(regex); |
| } |
| |
| |
| |
| |
| |
| |
| |
| , jsonPathClause = varArgs(function( componentRegexes ) { |
|
|
| |
| |
| |
| componentRegexes.unshift(/^/); |
| |
| return regexDescriptor( |
| RegExp( |
| componentRegexes.map(attr('source')).join('') |
| ) |
| ); |
| }) |
| |
| , possiblyCapturing = /(\$?)/ |
| , namedNode = /([\w-_]+|\*)/ |
| , namePlaceholder = /()/ |
| , nodeInArrayNotation = /\["([^"]+)"\]/ |
| , numberedNodeInArrayNotation = /\[(\d+|\*)\]/ |
| , fieldList = /{([\w ]*?)}/ |
| , optionalFieldList = /(?:{([\w ]*?)})?/ |
| |
|
|
| |
| , jsonPathNamedNodeInObjectNotation = jsonPathClause( |
| possiblyCapturing, |
| namedNode, |
| optionalFieldList |
| ) |
| |
| |
| , jsonPathNamedNodeInArrayNotation = jsonPathClause( |
| possiblyCapturing, |
| nodeInArrayNotation, |
| optionalFieldList |
| ) |
|
|
| |
| , jsonPathNumberedNodeInArrayNotation = jsonPathClause( |
| possiblyCapturing, |
| numberedNodeInArrayNotation, |
| optionalFieldList |
| ) |
|
|
| |
| , jsonPathPureDuckTyping = jsonPathClause( |
| possiblyCapturing, |
| namePlaceholder, |
| fieldList |
| ) |
| |
| |
| , jsonPathDoubleDot = jsonPathClause(/\.\./) |
| |
| |
| , jsonPathDot = jsonPathClause(/\./) |
| |
| |
| , jsonPathBang = jsonPathClause( |
| possiblyCapturing, |
| /!/ |
| ) |
| |
| |
| , emptyString = jsonPathClause(/$/) |
| |
| ; |
| |
| |
| |
| |
| |
| return function (fn){ |
| return fn( |
| lazyUnion( |
| jsonPathNamedNodeInObjectNotation |
| , jsonPathNamedNodeInArrayNotation |
| , jsonPathNumberedNodeInArrayNotation |
| , jsonPathPureDuckTyping |
| ) |
| , jsonPathDoubleDot |
| , jsonPathDot |
| , jsonPathBang |
| , emptyString |
| ); |
| }; |
|
|
| }()); |
| |
| |
| |
| |
| |
| |
| function namedNode(key, node) { |
| return {key:key, node:node}; |
| } |
|
|
| |
| var keyOf = attr('key'); |
|
|
| |
| var nodeOf = attr('node'); |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| var ROOT_PATH = {}; |
|
|
|
|
| |
| |
| |
| |
| function incrementalContentBuilder( oboeBus ) { |
|
|
| var emitNodeFound = oboeBus(NODE_FOUND).emit, |
| emitRootFound = oboeBus(ROOT_FOUND).emit, |
| emitPathFound = oboeBus(PATH_FOUND).emit; |
|
|
| function arrayIndicesAreKeys( possiblyInconsistentAscent, newDeepestNode) { |
| |
| |
| |
| |
| |
| |
|
|
| var parentNode = nodeOf( head( possiblyInconsistentAscent)); |
| |
| return isOfType( Array, parentNode) |
| ? |
| pathFound( possiblyInconsistentAscent, |
| len(parentNode), |
| newDeepestNode |
| ) |
| : |
| |
| possiblyInconsistentAscent |
| ; |
| } |
| |
| function nodeFound( ascent, newDeepestNode ) { |
| |
| if( !ascent ) { |
| |
| emitRootFound( newDeepestNode); |
| |
| return pathFound( ascent, ROOT_PATH, newDeepestNode); |
| } |
|
|
| |
| |
| var arrayConsistentAscent = arrayIndicesAreKeys( ascent, newDeepestNode), |
| ancestorBranches = tail( arrayConsistentAscent), |
| previouslyUnmappedName = keyOf( head( arrayConsistentAscent)); |
| |
| appendBuiltContent( |
| ancestorBranches, |
| previouslyUnmappedName, |
| newDeepestNode |
| ); |
| |
| return cons( |
| namedNode( previouslyUnmappedName, newDeepestNode ), |
| ancestorBranches |
| ); |
| } |
|
|
|
|
| |
| |
| |
| |
| function appendBuiltContent( ancestorBranches, key, node ){ |
| |
| nodeOf( head( ancestorBranches))[key] = node; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function pathFound(ascent, newDeepestName, maybeNewDeepestNode) { |
|
|
| if( ascent ) { |
| |
| |
| |
| appendBuiltContent( ascent, newDeepestName, maybeNewDeepestNode ); |
| } |
| |
| var ascentWithNewPath = cons( |
| namedNode( newDeepestName, |
| maybeNewDeepestNode), |
| ascent |
| ); |
|
|
| emitPathFound( ascentWithNewPath); |
| |
| return ascentWithNewPath; |
| } |
|
|
|
|
| |
| |
| |
| function nodeFinished( ascent ) { |
|
|
| emitNodeFound( ascent); |
| |
| |
| return tail( ascent); |
| } |
| |
| return { |
|
|
| openobject : function (ascent, firstKey) { |
|
|
| var ascentAfterNodeFound = nodeFound(ascent, {}); |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| return defined(firstKey) |
| ? |
| |
| |
| |
| |
| |
| pathFound(ascentAfterNodeFound, firstKey) |
| : |
| ascentAfterNodeFound |
| ; |
| }, |
| |
| openarray: function (ascent) { |
| return nodeFound(ascent, []); |
| }, |
|
|
| |
| key: pathFound, |
| |
| |
| |
| |
| |
| value: compose2( nodeFinished, nodeFound ), |
| |
| |
| |
| closeobject: nodeFinished, |
| closearray: nodeFinished |
| }; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| var jsonPathCompiler = jsonPathSyntax(function (pathNodeSyntax, |
| doubleDotSyntax, |
| dotSyntax, |
| bangSyntax, |
| emptySyntax ) { |
|
|
| var CAPTURING_INDEX = 1; |
| var NAME_INDEX = 2; |
| var FIELD_LIST_INDEX = 3; |
|
|
| var headKey = compose2(keyOf, head), |
| headNode = compose2(nodeOf, head); |
| |
| |
| |
| |
| |
| |
| |
| |
| function nameClause(previousExpr, detection ) { |
| |
| var name = detection[NAME_INDEX], |
| |
| matchesName = ( !name || name == '*' ) |
| ? always |
| : function(ascent){return headKey(ascent) == name}; |
| |
|
|
| return lazyIntersection(matchesName, previousExpr); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| function duckTypeClause(previousExpr, detection) { |
|
|
| var fieldListStr = detection[FIELD_LIST_INDEX]; |
|
|
| if (!fieldListStr) |
| return previousExpr; |
|
|
| var hasAllrequiredFields = partialComplete( |
| hasAllProperties, |
| arrayAsList(fieldListStr.split(/\W+/)) |
| ), |
| |
| isMatch = compose2( |
| hasAllrequiredFields, |
| headNode |
| ); |
|
|
| return lazyIntersection(isMatch, previousExpr); |
| } |
|
|
| |
| |
| |
| function capture( previousExpr, detection ) { |
|
|
| |
| var capturing = !!detection[CAPTURING_INDEX]; |
|
|
| if (!capturing) |
| return previousExpr; |
| |
| return lazyIntersection(previousExpr, head); |
| |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| function skip1(previousExpr) { |
| |
| |
| if( previousExpr == always ) { |
| |
| |
| |
| |
| |
| return always; |
| } |
|
|
| |
| |
| |
| function notAtRoot(ascent){ |
| return headKey(ascent) != ROOT_PATH; |
| } |
| |
| return lazyIntersection( |
| |
| |
| |
| |
| |
| |
| |
| notAtRoot, |
| |
| |
| |
| |
| compose2(previousExpr, tail) |
| ); |
| |
| } |
| |
| |
| |
| |
| |
| |
| function skipMany(previousExpr) { |
|
|
| if( previousExpr == always ) { |
| |
| |
| |
| |
| |
| return always; |
| } |
| |
| var |
| |
| |
| |
| terminalCaseWhenArrivingAtRoot = rootExpr(), |
| terminalCaseWhenPreviousExpressionIsSatisfied = previousExpr, |
| recursiveCase = skip1(skipManyInner), |
| |
| cases = lazyUnion( |
| terminalCaseWhenArrivingAtRoot |
| , terminalCaseWhenPreviousExpressionIsSatisfied |
| , recursiveCase |
| ); |
| |
| function skipManyInner(ascent) { |
| |
| if( !ascent ) { |
| |
| return false; |
| } |
| |
| return cases(ascent); |
| } |
| |
| return skipManyInner; |
| } |
| |
| |
| |
| |
| |
| function rootExpr() { |
| |
| return function(ascent){ |
| return headKey(ascent) == ROOT_PATH; |
| }; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| function statementExpr(lastClause) { |
| |
| return function(ascent) { |
| |
| |
| var exprMatch = lastClause(ascent); |
| |
| return exprMatch === true ? head(ascent) : exprMatch; |
| }; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function expressionsReader( exprs, parserGeneratedSoFar, detection ) { |
| |
| |
| |
| |
| |
| return foldR( |
| function( parserGeneratedSoFar, expr ){ |
| |
| return expr(parserGeneratedSoFar, detection); |
| }, |
| parserGeneratedSoFar, |
| exprs |
| ); |
|
|
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function generateClauseReaderIfTokenFound ( |
| |
| tokenDetector, clauseEvaluatorGenerators, |
| |
| jsonPath, parserGeneratedSoFar, onSuccess) { |
| |
| var detected = tokenDetector(jsonPath); |
|
|
| if(detected) { |
| var compiledParser = expressionsReader( |
| clauseEvaluatorGenerators, |
| parserGeneratedSoFar, |
| detected |
| ), |
| |
| remainingUnparsedJsonPath = jsonPath.substr(len(detected[0])); |
| |
| return onSuccess(remainingUnparsedJsonPath, compiledParser); |
| } |
| } |
| |
| |
| |
| |
| function clauseMatcher(tokenDetector, exprs) { |
| |
| return partialComplete( |
| generateClauseReaderIfTokenFound, |
| tokenDetector, |
| exprs |
| ); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| var clauseForJsonPath = lazyUnion( |
|
|
| clauseMatcher(pathNodeSyntax , list( capture, |
| duckTypeClause, |
| nameClause, |
| skip1 )) |
| |
| , clauseMatcher(doubleDotSyntax , list( skipMany)) |
| |
| |
| |
| |
| , clauseMatcher(dotSyntax , list() ) |
| |
| , clauseMatcher(bangSyntax , list( capture, |
| rootExpr)) |
| |
| , clauseMatcher(emptySyntax , list( statementExpr)) |
| |
| , function (jsonPath) { |
| throw Error('"' + jsonPath + '" could not be tokenised') |
| } |
| ); |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| function returnFoundParser(_remainingJsonPath, compiledParser){ |
| return compiledParser |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function compileJsonPathToFunction( uncompiledJsonPath, |
| parserGeneratedSoFar ) { |
|
|
| |
| |
| |
| |
| |
| |
| var onFind = uncompiledJsonPath |
| ? compileJsonPathToFunction |
| : returnFoundParser; |
| |
| return clauseForJsonPath( |
| uncompiledJsonPath, |
| parserGeneratedSoFar, |
| onFind |
| ); |
| } |
|
|
| |
| |
| |
| return function(jsonPath){ |
| |
| try { |
| |
| return compileJsonPathToFunction(jsonPath, always); |
| |
| } catch( e ) { |
| throw Error( 'Could not compile "' + jsonPath + |
| '" because ' + e.message |
| ); |
| } |
| } |
|
|
| }); |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function singleEventPubSub(eventType, newListener, removeListener){ |
|
|
| |
| |
| |
| |
| |
| var listenerTupleList, |
| listenerList; |
|
|
| function hasId(id){ |
| return function(tuple) { |
| return tuple.id == id; |
| }; |
| } |
| |
| return { |
|
|
| |
| |
| |
| |
| |
| |
| on:function( listener, listenerId ) { |
| |
| var tuple = { |
| listener: listener |
| , id: listenerId || listener |
| |
| }; |
|
|
| if( newListener ) { |
| newListener.emit(eventType, listener, tuple.id); |
| } |
| |
| listenerTupleList = cons( tuple, listenerTupleList ); |
| listenerList = cons( listener, listenerList ); |
|
|
| return this; |
| }, |
| |
| emit:function () { |
| applyEach( listenerList, arguments ); |
| }, |
| |
| un: function( listenerId ) { |
| |
| var removed; |
| |
| listenerTupleList = without( |
| listenerTupleList, |
| hasId(listenerId), |
| function(tuple){ |
| removed = tuple; |
| } |
| ); |
| |
| if( removed ) { |
| listenerList = without( listenerList, function(listener){ |
| return listener == removed.listener; |
| }); |
| |
| if( removeListener ) { |
| removeListener.emit(eventType, removed.listener, removed.id); |
| } |
| } |
| }, |
| |
| listeners: function(){ |
| |
| return listenerList; |
| }, |
| |
| hasListener: function(listenerId){ |
| var test = listenerId? hasId(listenerId) : always; |
| |
| return defined(first( test, listenerTupleList)); |
| } |
| }; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function pubSub(){ |
|
|
| var singles = {}, |
| newListener = newSingle('newListener'), |
| removeListener = newSingle('removeListener'); |
| |
| function newSingle(eventName) { |
| return singles[eventName] = singleEventPubSub( |
| eventName, |
| newListener, |
| removeListener |
| ); |
| } |
|
|
| |
| function pubSubInstance( eventName ){ |
| |
| return singles[eventName] || newSingle( eventName ); |
| } |
|
|
| |
| ['emit', 'on', 'un'].forEach(function(methodName){ |
| |
| pubSubInstance[methodName] = varArgs(function(eventName, parameters){ |
| apply( parameters, pubSubInstance( eventName )[methodName]); |
| }); |
| }); |
| |
| return pubSubInstance; |
| } |
| |
| |
| |
|
|
| var |
| |
| _S = 1, |
|
|
| |
| NODE_FOUND = _S++, |
| |
| PATH_FOUND = _S++, |
| |
| FAIL_EVENT = 'fail', |
| ROOT_FOUND = _S++, |
| HTTP_START = 'start', |
| STREAM_DATA = 'content', |
| STREAM_END = _S++, |
| ABORTING = _S++; |
| |
| function errorReport(statusCode, body, error) { |
| try{ |
| var jsonBody = JSON.parse(body); |
| }catch(e){} |
|
|
| return { |
| statusCode:statusCode, |
| body:body, |
| jsonBody:jsonBody, |
| thrown:error |
| }; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| function patternAdapter(oboeBus, jsonPathCompiler) { |
|
|
| var predicateEventMap = { |
| node:oboeBus(NODE_FOUND) |
| , path:oboeBus(PATH_FOUND) |
| }; |
| |
| function emitMatchingNode(emitMatch, node, ascent) { |
| |
| |
| |
| |
| |
| |
| |
| var descent = reverseList(ascent); |
| |
| emitMatch( |
| node, |
| |
| |
| |
| listAsArray(tail(map(keyOf,descent))), |
| listAsArray(map(nodeOf, descent)) |
| ); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function addUnderlyingListener( fullEventName, predicateEvent, compiledJsonPath ){ |
| |
| var emitMatch = oboeBus(fullEventName).emit; |
| |
| predicateEvent.on( function (ascent) { |
|
|
| var maybeMatchingMapping = compiledJsonPath(ascent); |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| if (maybeMatchingMapping !== false) { |
|
|
| emitMatchingNode( |
| emitMatch, |
| nodeOf(maybeMatchingMapping), |
| ascent |
| ); |
| } |
| }, fullEventName); |
| |
| oboeBus('removeListener').on( function(removedEventName){ |
|
|
| |
| |
| |
| if( removedEventName == fullEventName ) { |
| |
| if( !oboeBus(removedEventName).listeners( )) { |
| predicateEvent.un( fullEventName ); |
| } |
| } |
| }); |
| } |
|
|
| oboeBus('newListener').on( function(fullEventName){ |
|
|
| var match = /(node|path):(.*)/.exec(fullEventName); |
| |
| if( match ) { |
| var predicateEvent = predicateEventMap[match[1]]; |
| |
| if( !predicateEvent.hasListener( fullEventName) ) { |
| |
| addUnderlyingListener( |
| fullEventName, |
| predicateEvent, |
| jsonPathCompiler( match[2] ) |
| ); |
| } |
| } |
| }) |
|
|
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| function instanceApi(oboeBus){ |
|
|
| var oboeApi, |
| fullyQualifiedNamePattern = /^(node|path):./, |
| rootNodeFinishedEvent = oboeBus('node:!'), |
|
|
| |
| |
| |
| addListener = varArgs(function( eventId, parameters ){ |
| |
| if( oboeApi[eventId] ) { |
| |
| |
| |
| |
| apply(parameters, oboeApi[eventId]); |
| } else { |
| |
| |
| |
| var event = oboeBus(eventId), |
| listener = parameters[0]; |
| |
| if( fullyQualifiedNamePattern.test(eventId) ) { |
| |
| |
| |
| addForgettableCallback(event, listener); |
| } else { |
| |
| |
| |
| event.on( listener); |
| } |
| } |
| |
| return oboeApi; |
| }), |
| |
| |
| |
| |
| removeListener = function( eventId, p2, p3 ){ |
| |
| if( eventId == 'done' ) { |
| |
| rootNodeFinishedEvent.un(p2); |
| |
| } else if( eventId == 'node' || eventId == 'path' ) { |
| |
| |
| oboeBus.un(eventId + ':' + p2, p3); |
| } else { |
| |
| |
| |
| |
| |
| var listener = p2; |
|
|
| oboeBus(eventId).un(listener); |
| } |
| |
| return oboeApi; |
| }; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function addProtectedCallback(eventName, callback) { |
| oboeBus(eventName).on(protectedCallback(callback), callback); |
| return oboeApi; |
| } |
|
|
| |
| |
| |
| |
| function addForgettableCallback(event, callback) { |
| var safeCallback = protectedCallback(callback); |
| |
| event.on( function() { |
| |
| var discard = false; |
| |
| oboeApi.forget = function(){ |
| discard = true; |
| }; |
| |
| apply( arguments, safeCallback ); |
| |
| delete oboeApi.forget; |
| |
| if( discard ) { |
| event.un(callback); |
| } |
| }, callback) |
| |
| return oboeApi; |
| } |
| |
| function protectedCallback( callback ) { |
| return function() { |
| try{ |
| callback.apply(oboeApi, arguments); |
| }catch(e) { |
| |
| |
| oboeBus(FAIL_EVENT).emit( errorReport(undefined, undefined, e)); |
| } |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| function fullyQualifiedPatternMatchEvent(type, pattern) { |
| return oboeBus(type + ':' + pattern); |
| } |
| |
| |
| |
| |
| function addListenersMap(eventId, listenerMap) { |
| |
| for( var pattern in listenerMap ) { |
| addForgettableCallback( |
| fullyQualifiedPatternMatchEvent(eventId, pattern), |
| listenerMap[pattern] |
| ); |
| } |
| } |
| |
| |
| |
| |
| function addNodeOrPathListenerApi( eventId, jsonPathOrListenerMap, callback ){ |
| |
| if( isString(jsonPathOrListenerMap) ) { |
| addForgettableCallback( |
| fullyQualifiedPatternMatchEvent(eventId, jsonPathOrListenerMap), |
| callback |
| ); |
| } else { |
| addListenersMap(eventId, jsonPathOrListenerMap); |
| } |
| |
| return oboeApi; |
| } |
| |
| |
| |
| |
| oboeBus(ROOT_FOUND).on( function(root) { |
| oboeApi.root = functor(root); |
| }); |
|
|
| |
| |
| |
| |
| oboeBus(HTTP_START).on( function(_statusCode, headers) { |
| |
| oboeApi.header = function(name) { |
| return name ? headers[name] |
| : headers |
| ; |
| } |
| }); |
| |
| |
| |
| |
| |
| return oboeApi = { |
| on : addListener, |
| addListener : addListener, |
| removeListener : removeListener, |
| emit : oboeBus.emit, |
| |
| node : partialComplete(addNodeOrPathListenerApi, 'node'), |
| path : partialComplete(addNodeOrPathListenerApi, 'path'), |
| |
| done : partialComplete(addForgettableCallback, rootNodeFinishedEvent), |
| start : partialComplete(addProtectedCallback, HTTP_START ), |
| |
| |
| |
| fail : oboeBus(FAIL_EVENT).on, |
| |
| |
| abort : oboeBus(ABORTING).emit, |
| |
| |
| header : noop, |
| root : noop |
| }; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| function instanceController( oboeBus, |
| clarinetParser, contentBuilderHandlers) { |
| |
| oboeBus(STREAM_DATA).on( clarinetParser.write.bind(clarinetParser)); |
| |
| |
| |
| |
| oboeBus(STREAM_END).on( clarinetParser.close.bind(clarinetParser)); |
| |
|
|
| |
| |
| |
| oboeBus(ABORTING).on( function() { |
| clarinetListenerAdaptor(clarinetParser, {}); |
| }); |
|
|
| clarinetListenerAdaptor(clarinetParser, contentBuilderHandlers); |
| |
| |
| clarinetParser.onerror = function(e) { |
| oboeBus(FAIL_EVENT).emit( |
| errorReport(undefined, undefined, e) |
| ); |
| |
| |
| |
| }; |
| } |
| |
| |
| |
| |
| |
|
|
| function wire (httpMethodName, contentSource, body, headers){ |
|
|
| var oboeBus = pubSub(); |
|
|
| headers = headers ? |
| |
| |
| |
| JSON.parse(JSON.stringify(headers)) |
| : {}; |
| |
| if( body ) { |
| if( !isString(body) ) { |
| |
| |
| |
| body = JSON.stringify(body); |
| |
| |
| headers['Content-Type'] = headers['Content-Type'] || 'application/json'; |
| } |
| } else { |
| body = null; |
| } |
| |
| |
| |
| |
| |
| if( contentSource ) { |
|
|
| streamingHttp( oboeBus, |
| httpTransport(), |
| httpMethodName, |
| contentSource, |
| body, |
| headers |
| ); |
| } |
| |
| instanceController( |
| oboeBus, |
| clarinet.parser(), |
| incrementalContentBuilder(oboeBus) |
| ); |
| |
| patternAdapter(oboeBus, jsonPathCompiler); |
| |
| return new instanceApi(oboeBus); |
| } |
|
|
| |
| function oboe(arg1, arg2) { |
|
|
| if( arg1 ) { |
| if (arg1.url) { |
| |
| |
| |
| |
| return wire( |
| (arg1.method || 'GET'), |
| url(arg1.url, arg1.cached), |
| arg1.body, |
| arg1.headers |
| ); |
| } else { |
| |
| |
| |
| |
| return wire( |
| 'GET', |
| arg1, |
| arg2 |
| ); |
| } |
| } else { |
| |
| |
| return wire(); |
| } |
| |
| |
| function url(baseUrl, cached) { |
| |
| if( cached === false ) { |
| |
| if( baseUrl.indexOf('?') == -1 ) { |
| baseUrl += '?'; |
| } else { |
| baseUrl += '&'; |
| } |
| |
| baseUrl += '_=' + new Date().getTime(); |
| } |
| return baseUrl; |
| } |
| } |
|
|
|
|
| ;if ( typeof define === "function" && define.amd ) {define( "oboe", [], function () { return oboe; } );} else {window.oboe = oboe;}})(window, Object, Array, Error, JSON); |