text: /******/ (function(modules) { // webpackBootstrap
  /******/ 	// The module cache
  /******/ 	var installedModules = {};
  /******/
  /******/ 	// The require function
  /******/ 	function __webpack_require__(moduleId) {
  /******/
  /******/ 		// Check if module is in cache
  /******/ 		if(installedModules[moduleId])
  /******/ 			return installedModules[moduleId].exports;
  /******/
  /******/ 		// Create a new module (and put it into the cache)
  /******/ 		var module = installedModules[moduleId] = {
  /******/ 			exports: {},
  /******/ 			id: moduleId,
  /******/ 			loaded: false
  /******/ 		};
  /******/
  /******/ 		// Execute the module function
  /******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
  /******/
  /******/ 		// Flag the module as loaded
  /******/ 		module.loaded = true;
  /******/
  /******/ 		// Return the exports of the module
  /******/ 		return module.exports;
  /******/ 	}
  /******/
  /******/
  /******/ 	// expose the modules object (__webpack_modules__)
  /******/ 	__webpack_require__.m = modules;
  /******/
  /******/ 	// expose the module cache
  /******/ 	__webpack_require__.c = installedModules;
  /******/
  /******/ 	// __webpack_public_path__
  /******/ 	__webpack_require__.p = "";
  /******/
  /******/ 	// Load entry module and return exports
  /******/ 	return __webpack_require__(0);
  /******/ })
  /************************************************************************/
  /******/ ([
  /* 0 */
  /*!************************************!*\
    !*** ./src/drag-drop/drag-drop.js ***!
    \************************************/
  /***/ function(module, exports, __webpack_require__) {
  
  	/**
  	 * Created by cmdv on 16/06/15.
  	 */
  	'use strict';
  	
  	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  	
  	var _rx = __webpack_require__(/*! rx */ 1);
  	
  	var _rx2 = _interopRequireDefault(_rx);
  	
  	var _jquery = __webpack_require__(/*! jquery */ 4);
  	
  	var _jquery2 = _interopRequireDefault(_jquery);
  	
  	var $dragTarget = (0, _jquery2['default'])('.dragTarget');
  	var $dragArea = (0, _jquery2['default'])('.dragArea');
  	
  	// Get the three major events
  	var mouseup = _rx2['default'].Observable.fromEvent($dragTarget, 'mouseup');
  	var mousemove = _rx2['default'].Observable.fromEvent(document, 'mousemove');
  	var mousedown = _rx2['default'].Observable.fromEvent($dragTarget, 'mousedown');
  	
  	var _mouseUp = mouseup.subscribe(function () {
  	  return $dragTarget.css({ cursor: '-webkit-grab' });
  	});
  	
  	var mousedrag = mousedown.flatMap(function (e) {
  	
  	  $dragTarget.css({ cursor: '-webkit-grabbing' });
  	  // calculate offsets when mouse down
  	  var startX = e.offsetX,
  	      startY = e.offsetY;
  	
  	  // Calculate delta with mousemove until mouseup
  	  return mousemove.map(function (mm) {
  	    mm.preventDefault();
  	
  	    // accommodate for site header and sidebar
  	    var offsets = $dragArea.offset();
  	
  	    return {
  	      left: mm.clientX - startX - offsets.left,
  	      top: mm.clientY - startY - offsets.top
  	    };
  	  }).takeUntil(mouseup);
  	});
  	
  	// Update position
  	var subscription = mousedrag.subscribe(function (pos) {
  	
  	  $dragTarget.css({ top: pos.top, left: pos.left });
  	});
  
  /***/ },
  /* 1 */
  /*!*****************************!*\
    !*** ./~/rx/dist/rx.all.js ***!
    \*****************************/
  /***/ function(module, exports, __webpack_require__) {
  
  	var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global, process) {// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
  	
  	;(function (undefined) {
  	
  	  var objectTypes = {
  	    'boolean': false,
  	    'function': true,
  	    'object': true,
  	    'number': false,
  	    'string': false,
  	    'undefined': false
  	  };
  	
  	  var root = (objectTypes[typeof window] && window) || this,
  	    freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports,
  	    freeModule = objectTypes[typeof module] && module && !module.nodeType && module,
  	    moduleExports = freeModule && freeModule.exports === freeExports && freeExports,
  	    freeGlobal = objectTypes[typeof global] && global;
  	
  	  if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal)) {
  	    root = freeGlobal;
  	  }
  	
  	  var Rx = {
  	      internals: {},
  	      config: {
  	        Promise: root.Promise
  	      },
  	      helpers: { }
  	  };
  	
  	  // Defaults
  	  var noop = Rx.helpers.noop = function () { },
  	    notDefined = Rx.helpers.notDefined = function (x) { return typeof x === 'undefined'; },
  	    identity = Rx.helpers.identity = function (x) { return x; },
  	    pluck = Rx.helpers.pluck = function (property) { return function (x) { return x[property]; }; },
  	    just = Rx.helpers.just = function (value) { return function () { return value; }; },
  	    defaultNow = Rx.helpers.defaultNow = Date.now,
  	    defaultComparer = Rx.helpers.defaultComparer = function (x, y) { return isEqual(x, y); },
  	    defaultSubComparer = Rx.helpers.defaultSubComparer = function (x, y) { return x > y ? 1 : (x < y ? -1 : 0); },
  	    defaultKeySerializer = Rx.helpers.defaultKeySerializer = function (x) { return x.toString(); },
  	    defaultError = Rx.helpers.defaultError = function (err) { throw err; },
  	    isPromise = Rx.helpers.isPromise = function (p) { return !!p && typeof p.subscribe !== 'function' && typeof p.then === 'function'; },
  	    asArray = Rx.helpers.asArray = function () { return Array.prototype.slice.call(arguments); },
  	    not = Rx.helpers.not = function (a) { return !a; },
  	    isFunction = Rx.helpers.isFunction = (function () {
  	
  	      var isFn = function (value) {
  	        return typeof value == 'function' || false;
  	      }
  	
  	      // fallback for older versions of Chrome and Safari
  	      if (isFn(/x/)) {
  	        isFn = function(value) {
  	          return typeof value == 'function' && toString.call(value) == '[object Function]';
  	        };
  	      }
  	
  	      return isFn;
  	    }());
  	
  	  function cloneArray(arr) { for(var a = [], i = 0, len = arr.length; i < len; i++) { a.push(arr[i]); } return a;}
  	
  	  Rx.config.longStackSupport = false;
  	  var hasStacks = false;
  	  try {
  	    throw new Error();
  	  } catch (e) {
  	    hasStacks = !!e.stack;
  	  }
  	
  	  // All code after this point will be filtered from stack traces reported by RxJS
  	  var rStartingLine = captureLine(), rFileName;
  	
  	  var STACK_JUMP_SEPARATOR = "From previous event:";
  	
  	  function makeStackTraceLong(error, observable) {
  	      // If possible, transform the error stack trace by removing Node and RxJS
  	      // cruft, then concatenating with the stack trace of `observable`.
  	      if (hasStacks &&
  	          observable.stack &&
  	          typeof error === "object" &&
  	          error !== null &&
  	          error.stack &&
  	          error.stack.indexOf(STACK_JUMP_SEPARATOR) === -1
  	      ) {
  	        var stacks = [];
  	        for (var o = observable; !!o; o = o.source) {
  	          if (o.stack) {
  	            stacks.unshift(o.stack);
  	          }
  	        }
  	        stacks.unshift(error.stack);
  	
  	        var concatedStacks = stacks.join("\n" + STACK_JUMP_SEPARATOR + "\n");
  	        error.stack = filterStackString(concatedStacks);
  	    }
  	  }
  	
  	  function filterStackString(stackString) {
  	    var lines = stackString.split("\n"),
  	        desiredLines = [];
  	    for (var i = 0, len = lines.length; i < len; i++) {
  	      var line = lines[i];
  	
  	      if (!isInternalFrame(line) && !isNodeFrame(line) && line) {
  	        desiredLines.push(line);
  	      }
  	    }
  	    return desiredLines.join("\n");
  	  }
  	
  	  function isInternalFrame(stackLine) {
  	    var fileNameAndLineNumber = getFileNameAndLineNumber(stackLine);
  	    if (!fileNameAndLineNumber) {
  	      return false;
  	    }
  	    var fileName = fileNameAndLineNumber[0], lineNumber = fileNameAndLineNumber[1];
  	
  	    return fileName === rFileName &&
  	      lineNumber >= rStartingLine &&
  	      lineNumber <= rEndingLine;
  	  }
  	
  	  function isNodeFrame(stackLine) {
  	    return stackLine.indexOf("(module.js:") !== -1 ||
  	      stackLine.indexOf("(node.js:") !== -1;
  	  }
  	
  	  function captureLine() {
  	    if (!hasStacks) { return; }
  	
  	    try {
  	      throw new Error();
  	    } catch (e) {
  	      var lines = e.stack.split("\n");
  	      var firstLine = lines[0].indexOf("@") > 0 ? lines[1] : lines[2];
  	      var fileNameAndLineNumber = getFileNameAndLineNumber(firstLine);
  	      if (!fileNameAndLineNumber) { return; }
  	
  	      rFileName = fileNameAndLineNumber[0];
  	      return fileNameAndLineNumber[1];
  	    }
  	  }
  	
  	  function getFileNameAndLineNumber(stackLine) {
  	    // Named functions: "at functionName (filename:lineNumber:columnNumber)"
  	    var attempt1 = /at .+ \((.+):(\d+):(?:\d+)\)$/.exec(stackLine);
  	    if (attempt1) { return [attempt1[1], Number(attempt1[2])]; }
  	
  	    // Anonymous functions: "at filename:lineNumber:columnNumber"
  	    var attempt2 = /at ([^ ]+):(\d+):(?:\d+)$/.exec(stackLine);
  	    if (attempt2) { return [attempt2[1], Number(attempt2[2])]; }
  	
  	    // Firefox style: "function@filename:lineNumber or @filename:lineNumber"
  	    var attempt3 = /.*@(.+):(\d+)$/.exec(stackLine);
  	    if (attempt3) { return [attempt3[1], Number(attempt3[2])]; }
  	  }
  	
  	  var EmptyError = Rx.EmptyError = function() {
  	    this.message = 'Sequence contains no elements.';
  	    Error.call(this);
  	  };
  	  EmptyError.prototype = Error.prototype;
  	
  	  var ObjectDisposedError = Rx.ObjectDisposedError = function() {
  	    this.message = 'Object has been disposed';
  	    Error.call(this);
  	  };
  	  ObjectDisposedError.prototype = Error.prototype;
  	
  	  var ArgumentOutOfRangeError = Rx.ArgumentOutOfRangeError = function () {
  	    this.message = 'Argument out of range';
  	    Error.call(this);
  	  };
  	  ArgumentOutOfRangeError.prototype = Error.prototype;
  	
  	  var NotSupportedError = Rx.NotSupportedError = function (message) {
  	    this.message = message || 'This operation is not supported';
  	    Error.call(this);
  	  };
  	  NotSupportedError.prototype = Error.prototype;
  	
  	  var NotImplementedError = Rx.NotImplementedError = function (message) {
  	    this.message = message || 'This operation is not implemented';
  	    Error.call(this);
  	  };
  	  NotImplementedError.prototype = Error.prototype;
  	
  	  var notImplemented = Rx.helpers.notImplemented = function () {
  	    throw new NotImplementedError();
  	  };
  	
  	  var notSupported = Rx.helpers.notSupported = function () {
  	    throw new NotSupportedError();
  	  };
  	
  	  // Shim in iterator support
  	  var $iterator$ = (typeof Symbol === 'function' && Symbol.iterator) ||
  	    '_es6shim_iterator_';
  	  // Bug for mozilla version
  	  if (root.Set && typeof new root.Set()['@@iterator'] === 'function') {
  	    $iterator$ = '@@iterator';
  	  }
  	
  	  var doneEnumerator = Rx.doneEnumerator = { done: true, value: undefined };
  	
  	  var isIterable = Rx.helpers.isIterable = function (o) {
  	    return o[$iterator$] !== undefined;
  	  }
  	
  	  var isArrayLike = Rx.helpers.isArrayLike = function (o) {
  	    return o && o.length !== undefined;
  	  }
  	
  	  Rx.helpers.iterator = $iterator$;
  	
  	  var bindCallback = Rx.internals.bindCallback = function (func, thisArg, argCount) {
  	    if (typeof thisArg === 'undefined') { return func; }
  	    switch(argCount) {
  	      case 0:
  	        return function() {
  	          return func.call(thisArg)
  	        };
  	      case 1:
  	        return function(arg) {
  	          return func.call(thisArg, arg);
  	        }
  	      case 2:
  	        return function(value, index) {
  	          return func.call(thisArg, value, index);
  	        };
  	      case 3:
  	        return function(value, index, collection) {
  	          return func.call(thisArg, value, index, collection);
  	        };
  	    }
  	
  	    return function() {
  	      return func.apply(thisArg, arguments);
  	    };
  	  };
  	
  	  /** Used to determine if values are of the language type Object */
  	  var dontEnums = ['toString',
  	    'toLocaleString',
  	    'valueOf',
  	    'hasOwnProperty',
  	    'isPrototypeOf',
  	    'propertyIsEnumerable',
  	    'constructor'],
  	  dontEnumsLength = dontEnums.length;
  	
  	  /** `Object#toString` result shortcuts */
  	  var argsClass = '[object Arguments]',
  	    arrayClass = '[object Array]',
  	    boolClass = '[object Boolean]',
  	    dateClass = '[object Date]',
  	    errorClass = '[object Error]',
  	    funcClass = '[object Function]',
  	    numberClass = '[object Number]',
  	    objectClass = '[object Object]',
  	    regexpClass = '[object RegExp]',
  	    stringClass = '[object String]';
  	
  	  var toString = Object.prototype.toString,
  	    hasOwnProperty = Object.prototype.hasOwnProperty,
  	    supportsArgsClass = toString.call(arguments) == argsClass, // For less <IE9 && FF<4
  	    supportNodeClass,
  	    errorProto = Error.prototype,
  	    objectProto = Object.prototype,
  	    stringProto = String.prototype,
  	    propertyIsEnumerable = objectProto.propertyIsEnumerable;
  	
  	  try {
  	    supportNodeClass = !(toString.call(document) == objectClass && !({ 'toString': 0 } + ''));
  	  } catch (e) {
  	    supportNodeClass = true;
  	  }
  	
  	  var nonEnumProps = {};
  	  nonEnumProps[arrayClass] = nonEnumProps[dateClass] = nonEnumProps[numberClass] = { 'constructor': true, 'toLocaleString': true, 'toString': true, 'valueOf': true };
  	  nonEnumProps[boolClass] = nonEnumProps[stringClass] = { 'constructor': true, 'toString': true, 'valueOf': true };
  	  nonEnumProps[errorClass] = nonEnumProps[funcClass] = nonEnumProps[regexpClass] = { 'constructor': true, 'toString': true };
  	  nonEnumProps[objectClass] = { 'constructor': true };
  	
  	  var support = {};
  	  (function () {
  	    var ctor = function() { this.x = 1; },
  	      props = [];
  	
  	    ctor.prototype = { 'valueOf': 1, 'y': 1 };
  	    for (var key in new ctor) { props.push(key); }
  	    for (key in arguments) { }
  	
  	    // Detect if `name` or `message` properties of `Error.prototype` are enumerable by default.
  	    support.enumErrorProps = propertyIsEnumerable.call(errorProto, 'message') || propertyIsEnumerable.call(errorProto, 'name');
  	
  	    // Detect if `prototype` properties are enumerable by default.
  	    support.enumPrototypes = propertyIsEnumerable.call(ctor, 'prototype');
  	
  	    // Detect if `arguments` object indexes are non-enumerable
  	    support.nonEnumArgs = key != 0;
  	
  	    // Detect if properties shadowing those on `Object.prototype` are non-enumerable.
  	    support.nonEnumShadows = !/valueOf/.test(props);
  	  }(1));
  	
  	  var isObject = Rx.internals.isObject = function(value) {
  	    var type = typeof value;
  	    return value && (type == 'function' || type == 'object') || false;
  	  };
  	
  	  function keysIn(object) {
  	    var result = [];
  	    if (!isObject(object)) {
  	      return result;
  	    }
  	    if (support.nonEnumArgs && object.length && isArguments(object)) {
  	      object = slice.call(object);
  	    }
  	    var skipProto = support.enumPrototypes && typeof object == 'function',
  	        skipErrorProps = support.enumErrorProps && (object === errorProto || object instanceof Error);
  	
  	    for (var key in object) {
  	      if (!(skipProto && key == 'prototype') &&
  	          !(skipErrorProps && (key == 'message' || key == 'name'))) {
  	        result.push(key);
  	      }
  	    }
  	
  	    if (support.nonEnumShadows && object !== objectProto) {
  	      var ctor = object.constructor,
  	          index = -1,
  	          length = dontEnumsLength;
  	
  	      if (object === (ctor && ctor.prototype)) {
  	        var className = object === stringProto ? stringClass : object === errorProto ? errorClass : toString.call(object),
  	            nonEnum = nonEnumProps[className];
  	      }
  	      while (++index < length) {
  	        key = dontEnums[index];
  	        if (!(nonEnum && nonEnum[key]) && hasOwnProperty.call(object, key)) {
  	          result.push(key);
  	        }
  	      }
  	    }
  	    return result;
  	  }
  	
  	  function internalFor(object, callback, keysFunc) {
  	    var index = -1,
  	      props = keysFunc(object),
  	      length = props.length;
  	
  	    while (++index < length) {
  	      var key = props[index];
  	      if (callback(object[key], key, object) === false) {
  	        break;
  	      }
  	    }
  	    return object;
  	  }
  	
  	  function internalForIn(object, callback) {
  	    return internalFor(object, callback, keysIn);
  	  }
  	
  	  function isNode(value) {
  	    // IE < 9 presents DOM nodes as `Object` objects except they have `toString`
  	    // methods that are `typeof` "string" and still can coerce nodes to strings
  	    return typeof value.toString != 'function' && typeof (value + '') == 'string';
  	  }
  	
  	  var isArguments = function(value) {
  	    return (value && typeof value == 'object') ? toString.call(value) == argsClass : false;
  	  }
  	
  	  // fallback for browsers that can't detect `arguments` objects by [[Class]]
  	  if (!supportsArgsClass) {
  	    isArguments = function(value) {
  	      return (value && typeof value == 'object') ? hasOwnProperty.call(value, 'callee') : false;
  	    };
  	  }
  	
  	  var isEqual = Rx.internals.isEqual = function (x, y) {
  	    return deepEquals(x, y, [], []);
  	  };
  	
  	  /** @private
  	   * Used for deep comparison
  	   **/
  	  function deepEquals(a, b, stackA, stackB) {
  	    // exit early for identical values
  	    if (a === b) {
  	      // treat `+0` vs. `-0` as not equal
  	      return a !== 0 || (1 / a == 1 / b);
  	    }
  	
  	    var type = typeof a,
  	        otherType = typeof b;
  	
  	    // exit early for unlike primitive values
  	    if (a === a && (a == null || b == null ||
  	        (type != 'function' && type != 'object' && otherType != 'function' && otherType != 'object'))) {
  	      return false;
  	    }
  	
  	    // compare [[Class]] names
  	    var className = toString.call(a),
  	        otherClass = toString.call(b);
  	
  	    if (className == argsClass) {
  	      className = objectClass;
  	    }
  	    if (otherClass == argsClass) {
  	      otherClass = objectClass;
  	    }
  	    if (className != otherClass) {
  	      return false;
  	    }
  	    switch (className) {
  	      case boolClass:
  	      case dateClass:
  	        // coerce dates and booleans to numbers, dates to milliseconds and booleans
  	        // to `1` or `0` treating invalid dates coerced to `NaN` as not equal
  	        return +a == +b;
  	
  	      case numberClass:
  	        // treat `NaN` vs. `NaN` as equal
  	        return (a != +a) ?
  	          b != +b :
  	          // but treat `-0` vs. `+0` as not equal
  	          (a == 0 ? (1 / a == 1 / b) : a == +b);
  	
  	      case regexpClass:
  	      case stringClass:
  	        // coerce regexes to strings (http://es5.github.io/#x15.10.6.4)
  	        // treat string primitives and their corresponding object instances as equal
  	        return a == String(b);
  	    }
  	    var isArr = className == arrayClass;
  	    if (!isArr) {
  	
  	      // exit for functions and DOM nodes
  	      if (className != objectClass || (!support.nodeClass && (isNode(a) || isNode(b)))) {
  	        return false;
  	      }
  	      // in older versions of Opera, `arguments` objects have `Array` constructors
  	      var ctorA = !support.argsObject && isArguments(a) ? Object : a.constructor,
  	          ctorB = !support.argsObject && isArguments(b) ? Object : b.constructor;
  	
  	      // non `Object` object instances with different constructors are not equal
  	      if (ctorA != ctorB &&
  	            !(hasOwnProperty.call(a, 'constructor') && hasOwnProperty.call(b, 'constructor')) &&
  	            !(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) &&
  	            ('constructor' in a && 'constructor' in b)
  	          ) {
  	        return false;
  	      }
  	    }
  	    // assume cyclic structures are equal
  	    // the algorithm for detecting cyclic structures is adapted from ES 5.1
  	    // section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3)
  	    var initedStack = !stackA;
  	    stackA || (stackA = []);
  	    stackB || (stackB = []);
  	
  	    var length = stackA.length;
  	    while (length--) {
  	      if (stackA[length] == a) {
  	        return stackB[length] == b;
  	      }
  	    }
  	    var size = 0;
  	    var result = true;
  	
  	    // add `a` and `b` to the stack of traversed objects
  	    stackA.push(a);
  	    stackB.push(b);
  	
  	    // recursively compare objects and arrays (susceptible to call stack limits)
  	    if (isArr) {
  	      // compare lengths to determine if a deep comparison is necessary
  	      length = a.length;
  	      size = b.length;
  	      result = size == length;
  	
  	      if (result) {
  	        // deep compare the contents, ignoring non-numeric properties
  	        while (size--) {
  	          var index = length,
  	              value = b[size];
  	
  	          if (!(result = deepEquals(a[size], value, stackA, stackB))) {
  	            break;
  	          }
  	        }
  	      }
  	    }
  	    else {
  	      // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
  	      // which, in this case, is more costly
  	      internalForIn(b, function(value, key, b) {
  	        if (hasOwnProperty.call(b, key)) {
  	          // count the number of properties.
  	          size++;
  	          // deep compare each property value.
  	          return (result = hasOwnProperty.call(a, key) && deepEquals(a[key], value, stackA, stackB));
  	        }
  	      });
  	
  	      if (result) {
  	        // ensure both objects have the same number of properties
  	        internalForIn(a, function(value, key, a) {
  	          if (hasOwnProperty.call(a, key)) {
  	            // `size` will be `-1` if `a` has more properties than `b`
  	            return (result = --size > -1);
  	          }
  	        });
  	      }
  	    }
  	    stackA.pop();
  	    stackB.pop();
  	
  	    return result;
  	  }
  	
  	  var hasProp = {}.hasOwnProperty,
  	      slice = Array.prototype.slice;
  	
  	  var inherits = this.inherits = Rx.internals.inherits = function (child, parent) {
  	    function __() { this.constructor = child; }
  	    __.prototype = parent.prototype;
  	    child.prototype = new __();
  	  };
  	
  	  var addProperties = Rx.internals.addProperties = function (obj) {
  	    for(var sources = [], i = 1, len = arguments.length; i < len; i++) { sources.push(arguments[i]); }
  	    for (var idx = 0, ln = sources.length; idx < ln; idx++) {
  	      var source = sources[idx];
  	      for (var prop in source) {
  	        obj[prop] = source[prop];
  	      }
  	    }
  	  };
  	
  	  // Rx Utils
  	  var addRef = Rx.internals.addRef = function (xs, r) {
  	    return new AnonymousObservable(function (observer) {
  	      return new CompositeDisposable(r.getDisposable(), xs.subscribe(observer));
  	    });
  	  };
  	
  	  function arrayInitialize(count, factory) {
  	    var a = new Array(count);
  	    for (var i = 0; i < count; i++) {
  	      a[i] = factory();
  	    }
  	    return a;
  	  }
  	
  	  var errorObj = {e: {}};
  	  var tryCatchTarget;
  	  function tryCatcher() {
  	    try {
  	      return tryCatchTarget.apply(this, arguments);
  	    } catch (e) {
  	      errorObj.e = e;
  	      return errorObj;
  	    }
  	  }
  	  function tryCatch(fn) {
  	    if (!isFunction(fn)) { throw new TypeError('fn must be a function'); }
  	    tryCatchTarget = fn;
  	    return tryCatcher;
  	  }
  	  function thrower(e) {
  	    throw e;
  	  }
  	
  	  // Collections
  	  function IndexedItem(id, value) {
  	    this.id = id;
  	    this.value = value;
  	  }
  	
  	  IndexedItem.prototype.compareTo = function (other) {
  	    var c = this.value.compareTo(other.value);
  	    c === 0 && (c = this.id - other.id);
  	    return c;
  	  };
  	
  	  // Priority Queue for Scheduling
  	  var PriorityQueue = Rx.internals.PriorityQueue = function (capacity) {
  	    this.items = new Array(capacity);
  	    this.length = 0;
  	  };
  	
  	  var priorityProto = PriorityQueue.prototype;
  	  priorityProto.isHigherPriority = function (left, right) {
  	    return this.items[left].compareTo(this.items[right]) < 0;
  	  };
  	
  	  priorityProto.percolate = function (index) {
  	    if (index >= this.length || index < 0) { return; }
  	    var parent = index - 1 >> 1;
  	    if (parent < 0 || parent === index) { return; }
  	    if (this.isHigherPriority(index, parent)) {
  	      var temp = this.items[index];
  	      this.items[index] = this.items[parent];
  	      this.items[parent] = temp;
  	      this.percolate(parent);
  	    }
  	  };
  	
  	  priorityProto.heapify = function (index) {
  	    +index || (index = 0);
  	    if (index >= this.length || index < 0) { return; }
  	    var left = 2 * index + 1,
  	        right = 2 * index + 2,
  	        first = index;
  	    if (left < this.length && this.isHigherPriority(left, first)) {
  	      first = left;
  	    }
  	    if (right < this.length && this.isHigherPriority(right, first)) {
  	      first = right;
  	    }
  	    if (first !== index) {
  	      var temp = this.items[index];
  	      this.items[index] = this.items[first];
  	      this.items[first] = temp;
  	      this.heapify(first);
  	    }
  	  };
  	
  	  priorityProto.peek = function () { return this.items[0].value; };
  	
  	  priorityProto.removeAt = function (index) {
  	    this.items[index] = this.items[--this.length];
  	    this.items[this.length] = undefined;
  	    this.heapify();
  	  };
  	
  	  priorityProto.dequeue = function () {
  	    var result = this.peek();
  	    this.removeAt(0);
  	    return result;
  	  };
  	
  	  priorityProto.enqueue = function (item) {
  	    var index = this.length++;
  	    this.items[index] = new IndexedItem(PriorityQueue.count++, item);
  	    this.percolate(index);
  	  };
  	
  	  priorityProto.remove = function (item) {
  	    for (var i = 0; i < this.length; i++) {
  	      if (this.items[i].value === item) {
  	        this.removeAt(i);
  	        return true;
  	      }
  	    }
  	    return false;
  	  };
  	  PriorityQueue.count = 0;
  	
  	  /**
  	   * Represents a group of disposable resources that are disposed together.
  	   * @constructor
  	   */
  	  var CompositeDisposable = Rx.CompositeDisposable = function () {
  	    var args = [], i, len;
  	    if (Array.isArray(arguments[0])) {
  	      args = arguments[0];
  	      len = args.length;
  	    } else {
  	      len = arguments.length;
  	      args = new Array(len);
  	      for(i = 0; i < len; i++) { args[i] = arguments[i]; }
  	    }
  	    for(i = 0; i < len; i++) {
  	      if (!isDisposable(args[i])) { throw new TypeError('Not a disposable'); }
  	    }
  	    this.disposables = args;
  	    this.isDisposed = false;
  	    this.length = args.length;
  	  };
  	
  	  var CompositeDisposablePrototype = CompositeDisposable.prototype;
  	
  	  /**
  	   * Adds a disposable to the CompositeDisposable or disposes the disposable if the CompositeDisposable is disposed.
  	   * @param {Mixed} item Disposable to add.
  	   */
  	  CompositeDisposablePrototype.add = function (item) {
  	    if (this.isDisposed) {
  	      item.dispose();
  	    } else {
  	      this.disposables.push(item);
  	      this.length++;
  	    }
  	  };
  	
  	  /**
  	   * Removes and disposes the first occurrence of a disposable from the CompositeDisposable.
  	   * @param {Mixed} item Disposable to remove.
  	   * @returns {Boolean} true if found; false otherwise.
  	   */
  	  CompositeDisposablePrototype.remove = function (item) {
  	    var shouldDispose = false;
  	    if (!this.isDisposed) {
  	      var idx = this.disposables.indexOf(item);
  	      if (idx !== -1) {
  	        shouldDispose = true;
  	        this.disposables.splice(idx, 1);
  	        this.length--;
  	        item.dispose();
  	      }
  	    }
  	    return shouldDispose;
  	  };
  	
  	  /**
  	   *  Disposes all disposables in the group and removes them from the group.
  	   */
  	  CompositeDisposablePrototype.dispose = function () {
  	    if (!this.isDisposed) {
  	      this.isDisposed = true;
  	      var len = this.disposables.length, currentDisposables = new Array(len);
  	      for(var i = 0; i < len; i++) { currentDisposables[i] = this.disposables[i]; }
  	      this.disposables = [];
  	      this.length = 0;
  	
  	      for (i = 0; i < len; i++) {
  	        currentDisposables[i].dispose();
  	      }
  	    }
  	  };
  	
  	  /**
  	   * Provides a set of static methods for creating Disposables.
  	   * @param {Function} dispose Action to run during the first call to dispose. The action is guaranteed to be run at most once.
  	   */
  	  var Disposable = Rx.Disposable = function (action) {
  	    this.isDisposed = false;
  	    this.action = action || noop;
  	  };
  	
  	  /** Performs the task of cleaning up resources. */
  	  Disposable.prototype.dispose = function () {
  	    if (!this.isDisposed) {
  	      this.action();
  	      this.isDisposed = true;
  	    }
  	  };
  	
  	  /**
  	   * Creates a disposable object that invokes the specified action when disposed.
  	   * @param {Function} dispose Action to run during the first call to dispose. The action is guaranteed to be run at most once.
  	   * @return {Disposable} The disposable object that runs the given action upon disposal.
  	   */
  	  var disposableCreate = Disposable.create = function (action) { return new Disposable(action); };
  	
  	  /**
  	   * Gets the disposable that does nothing when disposed.
  	   */
  	  var disposableEmpty = Disposable.empty = { dispose: noop };
  	
  	  /**
  	   * Validates whether the given object is a disposable
  	   * @param {Object} Object to test whether it has a dispose method
  	   * @returns {Boolean} true if a disposable object, else false.
  	   */
  	  var isDisposable = Disposable.isDisposable = function (d) {
  	    return d && isFunction(d.dispose);
  	  };
  	
  	  var checkDisposed = Disposable.checkDisposed = function (disposable) {
  	    if (disposable.isDisposed) { throw new ObjectDisposedError(); }
  	  };
  	
  	  // Single assignment
  	  var SingleAssignmentDisposable = Rx.SingleAssignmentDisposable = function () {
  	    this.isDisposed = false;
  	    this.current = null;
  	  };
  	  SingleAssignmentDisposable.prototype.getDisposable = function () {
  	    return this.current;
  	  };
  	  SingleAssignmentDisposable.prototype.setDisposable = function (value) {
  	    if (this.current) { throw new Error('Disposable has already been assigned'); }
  	    var shouldDispose = this.isDisposed;
  	    !shouldDispose && (this.current = value);
  	    shouldDispose && value && value.dispose();
  	  };
  	  SingleAssignmentDisposable.prototype.dispose = function () {
  	    if (!this.isDisposed) {
  	      this.isDisposed = true;
  	      var old = this.current;
  	      this.current = null;
  	    }
  	    old && old.dispose();
  	  };
  	
  	  // Multiple assignment disposable
  	  var SerialDisposable = Rx.SerialDisposable = function () {
  	    this.isDisposed = false;
  	    this.current = null;
  	  };
  	  SerialDisposable.prototype.getDisposable = function () {
  	    return this.current;
  	  };
  	  SerialDisposable.prototype.setDisposable = function (value) {
  	    var shouldDispose = this.isDisposed;
  	    if (!shouldDispose) {
  	      var old = this.current;
  	      this.current = value;
  	    }
  	    old && old.dispose();
  	    shouldDispose && value && value.dispose();
  	  };
  	  SerialDisposable.prototype.dispose = function () {
  	    if (!this.isDisposed) {
  	      this.isDisposed = true;
  	      var old = this.current;
  	      this.current = null;
  	    }
  	    old && old.dispose();
  	  };
  	
  	  /**
  	   * Represents a disposable resource that only disposes its underlying disposable resource when all dependent disposable objects have been disposed.
  	   */
  	  var RefCountDisposable = Rx.RefCountDisposable = (function () {
  	
  	    function InnerDisposable(disposable) {
  	      this.disposable = disposable;
  	      this.disposable.count++;
  	      this.isInnerDisposed = false;
  	    }
  	
  	    InnerDisposable.prototype.dispose = function () {
  	      if (!this.disposable.isDisposed && !this.isInnerDisposed) {
  	        this.isInnerDisposed = true;
  	        this.disposable.count--;
  	        if (this.disposable.count === 0 && this.disposable.isPrimaryDisposed) {
  	          this.disposable.isDisposed = true;
  	          this.disposable.underlyingDisposable.dispose();
  	        }
  	      }
  	    };
  	
  	    /**
  	     * Initializes a new instance of the RefCountDisposable with the specified disposable.
  	     * @constructor
  	     * @param {Disposable} disposable Underlying disposable.
  	      */
  	    function RefCountDisposable(disposable) {
  	      this.underlyingDisposable = disposable;
  	      this.isDisposed = false;
  	      this.isPrimaryDisposed = false;
  	      this.count = 0;
  	    }
  	
  	    /**
  	     * Disposes the underlying disposable only when all dependent disposables have been disposed
  	     */
  	    RefCountDisposable.prototype.dispose = function () {
  	      if (!this.isDisposed && !this.isPrimaryDisposed) {
  	        this.isPrimaryDisposed = true;
  	        if (this.count === 0) {
  	          this.isDisposed = true;
  	          this.underlyingDisposable.dispose();
  	        }
  	      }
  	    };
  	
  	    /**
  	     * Returns a dependent disposable that when disposed decreases the refcount on the underlying disposable.
  	     * @returns {Disposable} A dependent disposable contributing to the reference count that manages the underlying disposable's lifetime.
  	     */
  	    RefCountDisposable.prototype.getDisposable = function () {
  	      return this.isDisposed ? disposableEmpty : new InnerDisposable(this);
  	    };
  	
  	    return RefCountDisposable;
  	  })();
  	
  	  function ScheduledDisposable(scheduler, disposable) {
  	    this.scheduler = scheduler;
  	    this.disposable = disposable;
  	    this.isDisposed = false;
  	  }
  	
  	  function scheduleItem(s, self) {
  	    if (!self.isDisposed) {
  	      self.isDisposed = true;
  	      self.disposable.dispose();
  	    }
  	  }
  	
  	  ScheduledDisposable.prototype.dispose = function () {
  	    this.scheduler.scheduleWithState(this, scheduleItem);
  	  };
  	
  	  var ScheduledItem = Rx.internals.ScheduledItem = function (scheduler, state, action, dueTime, comparer) {
  	    this.scheduler = scheduler;
  	    this.state = state;
  	    this.action = action;
  	    this.dueTime = dueTime;
  	    this.comparer = comparer || defaultSubComparer;
  	    this.disposable = new SingleAssignmentDisposable();
  	  }
  	
  	  ScheduledItem.prototype.invoke = function () {
  	    this.disposable.setDisposable(this.invokeCore());
  	  };
  	
  	  ScheduledItem.prototype.compareTo = function (other) {
  	    return this.comparer(this.dueTime, other.dueTime);
  	  };
  	
  	  ScheduledItem.prototype.isCancelled = function () {
  	    return this.disposable.isDisposed;
  	  };
  	
  	  ScheduledItem.prototype.invokeCore = function () {
  	    return this.action(this.scheduler, this.state);
  	  };
  	
  	  /** Provides a set of static properties to access commonly used schedulers. */
  	  var Scheduler = Rx.Scheduler = (function () {
  	
  	    function Scheduler(now, schedule, scheduleRelative, scheduleAbsolute) {
  	      this.now = now;
  	      this._schedule = schedule;
  	      this._scheduleRelative = scheduleRelative;
  	      this._scheduleAbsolute = scheduleAbsolute;
  	    }
  	
  	    /** Determines whether the given object is a scheduler */
  	    Scheduler.isScheduler = function (s) {
  	      return s instanceof Scheduler;
  	    }
  	
  	    function invokeAction(scheduler, action) {
  	      action();
  	      return disposableEmpty;
  	    }
  	
  	    var schedulerProto = Scheduler.prototype;
  	
  	    /**
  	     * Schedules an action to be executed.
  	     * @param {Function} action Action to execute.
  	     * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
  	     */
  	    schedulerProto.schedule = function (action) {
  	      return this._schedule(action, invokeAction);
  	    };
  	
  	    /**
  	     * Schedules an action to be executed.
  	     * @param state State passed to the action to be executed.
  	     * @param {Function} action Action to be executed.
  	     * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
  	     */
  	    schedulerProto.scheduleWithState = function (state, action) {
  	      return this._schedule(state, action);
  	    };
  	
  	    /**
  	     * Schedules an action to be executed after the specified relative due time.
  	     * @param {Function} action Action to execute.
  	     * @param {Number} dueTime Relative time after which to execute the action.
  	     * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
  	     */
  	    schedulerProto.scheduleWithRelative = function (dueTime, action) {
  	      return this._scheduleRelative(action, dueTime, invokeAction);
  	    };
  	
  	    /**
  	     * Schedules an action to be executed after dueTime.
  	     * @param state State passed to the action to be executed.
  	     * @param {Function} action Action to be executed.
  	     * @param {Number} dueTime Relative time after which to execute the action.
  	     * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
  	     */
  	    schedulerProto.scheduleWithRelativeAndState = function (state, dueTime, action) {
  	      return this._scheduleRelative(state, dueTime, action);
  	    };
  	
  	    /**
  	     * Schedules an action to be executed at the specified absolute due time.
  	     * @param {Function} action Action to execute.
  	     * @param {Number} dueTime Absolute time at which to execute the action.
  	     * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
  	      */
  	    schedulerProto.scheduleWithAbsolute = function (dueTime, action) {
  	      return this._scheduleAbsolute(action, dueTime, invokeAction);
  	    };
  	
  	    /**
  	     * Schedules an action to be executed at dueTime.
  	     * @param {Mixed} state State passed to the action to be executed.
  	     * @param {Function} action Action to be executed.
  	     * @param {Number}dueTime Absolute time at which to execute the action.
  	     * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
  	     */
  	    schedulerProto.scheduleWithAbsoluteAndState = function (state, dueTime, action) {
  	      return this._scheduleAbsolute(state, dueTime, action);
  	    };
  	
  	    /** Gets the current time according to the local machine's system clock. */
  	    Scheduler.now = defaultNow;
  	
  	    /**
  	     * Normalizes the specified TimeSpan value to a positive value.
  	     * @param {Number} timeSpan The time span value to normalize.
  	     * @returns {Number} The specified TimeSpan value if it is zero or positive; otherwise, 0
  	     */
  	    Scheduler.normalize = function (timeSpan) {
  	      timeSpan < 0 && (timeSpan = 0);
  	      return timeSpan;
  	    };
  	
  	    return Scheduler;
  	  }());
  	
  	  var normalizeTime = Scheduler.normalize, isScheduler = Scheduler.isScheduler;
  	
  	  (function (schedulerProto) {
  	
  	    function invokeRecImmediate(scheduler, pair) {
  	      var state = pair[0], action = pair[1], group = new CompositeDisposable();
  	
  	      function recursiveAction(state1) {
  	        action(state1, function (state2) {
  	          var isAdded = false, isDone = false,
  	          d = scheduler.scheduleWithState(state2, function (scheduler1, state3) {
  	            if (isAdded) {
  	              group.remove(d);
  	            } else {
  	              isDone = true;
  	            }
  	            recursiveAction(state3);
  	            return disposableEmpty;
  	          });
  	          if (!isDone) {
  	            group.add(d);
  	            isAdded = true;
  	          }
  	        });
  	      }
  	      recursiveAction(state);
  	      return group;
  	    }
  	
  	    function invokeRecDate(scheduler, pair, method) {
  	      var state = pair[0], action = pair[1], group = new CompositeDisposable();
  	      function recursiveAction(state1) {
  	        action(state1, function (state2, dueTime1) {
  	          var isAdded = false, isDone = false,
  	          d = scheduler[method](state2, dueTime1, function (scheduler1, state3) {
  	            if (isAdded) {
  	              group.remove(d);
  	            } else {
  	              isDone = true;
  	            }
  	            recursiveAction(state3);
  	            return disposableEmpty;
  	          });
  	          if (!isDone) {
  	            group.add(d);
  	            isAdded = true;
  	          }
  	        });
  	      };
  	      recursiveAction(state);
  	      return group;
  	    }
  	
  	    function scheduleInnerRecursive(action, self) {
  	      action(function(dt) { self(action, dt); });
  	    }
  	
  	    /**
  	     * Schedules an action to be executed recursively.
  	     * @param {Function} action Action to execute recursively. The parameter passed to the action is used to trigger recursive scheduling of the action.
  	     * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
  	     */
  	    schedulerProto.scheduleRecursive = function (action) {
  	      return this.scheduleRecursiveWithState(action, scheduleInnerRecursive);
  	    };
  	
  	    /**
  	     * Schedules an action to be executed recursively.
  	     * @param {Mixed} state State passed to the action to be executed.
  	     * @param {Function} action Action to execute recursively. The last parameter passed to the action is used to trigger recursive scheduling of the action, passing in recursive invocation state.
  	     * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
  	     */
  	    schedulerProto.scheduleRecursiveWithState = function (state, action) {
  	      return this.scheduleWithState([state, action], invokeRecImmediate);
  	    };
  	
  	    /**
  	     * Schedules an action to be executed recursively after a specified relative due time.
  	     * @param {Function} action Action to execute recursively. The parameter passed to the action is used to trigger recursive scheduling of the action at the specified relative time.
  	     * @param {Number}dueTime Relative time after which to execute the action for the first time.
  	     * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
  	     */
  	    schedulerProto.scheduleRecursiveWithRelative = function (dueTime, action) {
  	      return this.scheduleRecursiveWithRelativeAndState(action, dueTime, scheduleInnerRecursive);
  	    };
  	
  	    /**
  	     * Schedules an action to be executed recursively after a specified relative due time.
  	     * @param {Mixed} state State passed to the action to be executed.
  	     * @param {Function} action Action to execute recursively. The last parameter passed to the action is used to trigger recursive scheduling of the action, passing in the recursive due time and invocation state.
  	     * @param {Number}dueTime Relative time after which to execute the action for the first time.
  	     * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
  	     */
  	    schedulerProto.scheduleRecursiveWithRelativeAndState = function (state, dueTime, action) {
  	      return this._scheduleRelative([state, action], dueTime, function (s, p) {
  	        return invokeRecDate(s, p, 'scheduleWithRelativeAndState');
  	      });
  	    };
  	
  	    /**
  	     * Schedules an action to be executed recursively at a specified absolute due time.
  	     * @param {Function} action Action to execute recursively. The parameter passed to the action is used to trigger recursive scheduling of the action at the specified absolute time.
  	     * @param {Number}dueTime Absolute time at which to execute the action for the first time.
  	     * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
  	     */
  	    schedulerProto.scheduleRecursiveWithAbsolute = function (dueTime, action) {
  	      return this.scheduleRecursiveWithAbsoluteAndState(action, dueTime, scheduleInnerRecursive);
  	    };
  	
  	    /**
  	     * Schedules an action to be executed recursively at a specified absolute due time.
  	     * @param {Mixed} state State passed to the action to be executed.
  	     * @param {Function} action Action to execute recursively. The last parameter passed to the action is used to trigger recursive scheduling of the action, passing in the recursive due time and invocation state.
  	     * @param {Number}dueTime Absolute time at which to execute the action for the first time.
  	     * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
  	     */
  	    schedulerProto.scheduleRecursiveWithAbsoluteAndState = function (state, dueTime, action) {
  	      return this._scheduleAbsolute([state, action], dueTime, function (s, p) {
  	        return invokeRecDate(s, p, 'scheduleWithAbsoluteAndState');
  	      });
  	    };
  	  }(Scheduler.prototype));
  	
  	  (function (schedulerProto) {
  	
  	    /**
  	     * Schedules a periodic piece of work by dynamically discovering the scheduler's capabilities. The periodic task will be scheduled using window.setInterval for the base implementation.
  	     * @param {Number} period Period for running the work periodically.
  	     * @param {Function} action Action to be executed.
  	     * @returns {Disposable} The disposable object used to cancel the scheduled recurring action (best effort).
  	     */
  	    Scheduler.prototype.schedulePeriodic = function (period, action) {
  	      return this.schedulePeriodicWithState(null, period, action);
  	    };
  	
  	    /**
  	     * Schedules a periodic piece of work by dynamically discovering the scheduler's capabilities. The periodic task will be scheduled using window.setInterval for the base implementation.
  	     * @param {Mixed} state Initial state passed to the action upon the first iteration.
  	     * @param {Number} period Period for running the work periodically.
  	     * @param {Function} action Action to be executed, potentially updating the state.
  	     * @returns {Disposable} The disposable object used to cancel the scheduled recurring action (best effort).
  	     */
  	    Scheduler.prototype.schedulePeriodicWithState = function(state, period, action) {
  	      if (typeof root.setInterval === 'undefined') { throw new NotSupportedError(); }
  	      period = normalizeTime(period);
  	      var s = state, id = root.setInterval(function () { s = action(s); }, period);
  	      return disposableCreate(function () { root.clearInterval(id); });
  	    };
  	
  	  }(Scheduler.prototype));
  	
  	  (function (schedulerProto) {
  	    /**
  	     * Returns a scheduler that wraps the original scheduler, adding exception handling for scheduled actions.
  	     * @param {Function} handler Handler that's run if an exception is caught. The exception will be rethrown if the handler returns false.
  	     * @returns {Scheduler} Wrapper around the original scheduler, enforcing exception handling.
  	     */
  	    schedulerProto.catchError = schedulerProto['catch'] = function (handler) {
  	      return new CatchScheduler(this, handler);
  	    };
  	  }(Scheduler.prototype));
  	
  	  var SchedulePeriodicRecursive = Rx.internals.SchedulePeriodicRecursive = (function () {
  	    function tick(command, recurse) {
  	      recurse(0, this._period);
  	      try {
  	        this._state = this._action(this._state);
  	      } catch (e) {
  	        this._cancel.dispose();
  	        throw e;
  	      }
  	    }
  	
  	    function SchedulePeriodicRecursive(scheduler, state, period, action) {
  	      this._scheduler = scheduler;
  	      this._state = state;
  	      this._period = period;
  	      this._action = action;
  	    }
  	
  	    SchedulePeriodicRecursive.prototype.start = function () {
  	      var d = new SingleAssignmentDisposable();
  	      this._cancel = d;
  	      d.setDisposable(this._scheduler.scheduleRecursiveWithRelativeAndState(0, this._period, tick.bind(this)));
  	
  	      return d;
  	    };
  	
  	    return SchedulePeriodicRecursive;
  	  }());
  	
  	  /** Gets a scheduler that schedules work immediately on the current thread. */
  	  var immediateScheduler = Scheduler.immediate = (function () {
  	    function scheduleNow(state, action) { return action(this, state); }
  	    return new Scheduler(defaultNow, scheduleNow, notSupported, notSupported);
  	  }());
  	
  	  /**
  	   * Gets a scheduler that schedules work as soon as possible on the current thread.
  	   */
  	  var currentThreadScheduler = Scheduler.currentThread = (function () {
  	    var queue;
  	
  	    function runTrampoline () {
  	      while (queue.length > 0) {
  	        var item = queue.dequeue();
  	        !item.isCancelled() && item.invoke();
  	      }
  	    }
  	
  	    function scheduleNow(state, action) {
  	      var si = new ScheduledItem(this, state, action, this.now());
  	
  	      if (!queue) {
  	        queue = new PriorityQueue(4);
  	        queue.enqueue(si);
  	
  	        var result = tryCatch(runTrampoline)();
  	        queue = null;
  	        if (result === errorObj) { return thrower(result.e); }
  	      } else {
  	        queue.enqueue(si);
  	      }
  	      return si.disposable;
  	    }
  	
  	    var currentScheduler = new Scheduler(defaultNow, scheduleNow, notSupported, notSupported);
  	    currentScheduler.scheduleRequired = function () { return !queue; };
  	
  	    return currentScheduler;
  	  }());
  	
  	  var scheduleMethod, clearMethod;
  	
  	  var localTimer = (function () {
  	    var localSetTimeout, localClearTimeout = noop;
  	    if (!!root.setTimeout) {
  	      localSetTimeout = root.setTimeout;
  	      localClearTimeout = root.clearTimeout;
  	    } else if (!!root.WScript) {
  	      localSetTimeout = function (fn, time) {
  	        root.WScript.Sleep(time);
  	        fn();
  	      };
  	    } else {
  	      throw new NotSupportedError();
  	    }
  	
  	    return {
  	      setTimeout: localSetTimeout,
  	      clearTimeout: localClearTimeout
  	    };
  	  }());
  	  var localSetTimeout = localTimer.setTimeout,
  	    localClearTimeout = localTimer.clearTimeout;
  	
  	  (function () {
  	
  	    var nextHandle = 1, tasksByHandle = {}, currentlyRunning = false;
  	
  	    clearMethod = function (handle) {
  	      delete tasksByHandle[handle];
  	    };
  	
  	    function runTask(handle) {
  	      if (currentlyRunning) {
  	        localSetTimeout(function () { runTask(handle) }, 0);
  	      } else {
  	        var task = tasksByHandle[handle];
  	        if (task) {
  	          currentlyRunning = true;
  	          var result = tryCatch(task)();
  	          clearMethod(handle);
  	          currentlyRunning = false;
  	          if (result === errorObj) { return thrower(result.e); }
  	        }
  	      }
  	    }
  	
  	    var reNative = RegExp('^' +
  	      String(toString)
  	        .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
  	        .replace(/toString| for [^\]]+/g, '.*?') + '$'
  	    );
  	
  	    var setImmediate = typeof (setImmediate = freeGlobal && moduleExports && freeGlobal.setImmediate) == 'function' &&
  	      !reNative.test(setImmediate) && setImmediate;
  	
  	    function postMessageSupported () {
  	      // Ensure not in a worker
  	      if (!root.postMessage || root.importScripts) { return false; }
  	      var isAsync = false, oldHandler = root.onmessage;
  	      // Test for async
  	      root.onmessage = function () { isAsync = true; };
  	      root.postMessage('', '*');
  	      root.onmessage = oldHandler;
  	
  	      return isAsync;
  	    }
  	
  	    // Use in order, setImmediate, nextTick, postMessage, MessageChannel, script readystatechanged, setTimeout
  	    if (isFunction(setImmediate)) {
  	      scheduleMethod = function (action) {
  	        var id = nextHandle++;
  	        tasksByHandle[id] = action;
  	        setImmediate(function () { runTask(id); });
  	
  	        return id;
  	      };
  	    } else if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') {
  	      scheduleMethod = function (action) {
  	        var id = nextHandle++;
  	        tasksByHandle[id] = action;
  	        process.nextTick(function () { runTask(id); });
  	
  	        return id;
  	      };
  	    } else if (postMessageSupported()) {
  	      var MSG_PREFIX = 'ms.rx.schedule' + Math.random();
  	
  	      function onGlobalPostMessage(event) {
  	        // Only if we're a match to avoid any other global events
  	        if (typeof event.data === 'string' && event.data.substring(0, MSG_PREFIX.length) === MSG_PREFIX) {
  	          runTask(event.data.substring(MSG_PREFIX.length));
  	        }
  	      }
  	
  	      if (root.addEventListener) {
  	        root.addEventListener('message', onGlobalPostMessage, false);
  	      } else if (root.attachEvent) {
  	        root.attachEvent('onmessage', onGlobalPostMessage);
  	      } else {
  	        root.onmessage = onGlobalPostMessage;
  	      }
  	
  	      scheduleMethod = function (action) {
  	        var id = nextHandle++;
  	        tasksByHandle[id] = action;
  	        root.postMessage(MSG_PREFIX + currentId, '*');
  	        return id;
  	      };
  	    } else if (!!root.MessageChannel) {
  	      var channel = new root.MessageChannel();
  	
  	      channel.port1.onmessage = function (e) { runTask(e.data); };
  	
  	      scheduleMethod = function (action) {
  	        var id = nextHandle++;
  	        tasksByHandle[id] = action;
  	        channel.port2.postMessage(id);
  	        return id;
  	      };
  	    } else if ('document' in root && 'onreadystatechange' in root.document.createElement('script')) {
  	
  	      scheduleMethod = function (action) {
  	        var scriptElement = root.document.createElement('script');
  	        var id = nextHandle++;
  	        tasksByHandle[id] = action;
  	
  	        scriptElement.onreadystatechange = function () {
  	          runTask(id);
  	          scriptElement.onreadystatechange = null;
  	          scriptElement.parentNode.removeChild(scriptElement);
  	          scriptElement = null;
  	        };
  	        root.document.documentElement.appendChild(scriptElement);
  	        return id;
  	      };
  	
  	    } else {
  	      scheduleMethod = function (action) {
  	        var id = nextHandle++;
  	        tasksByHandle[id] = action;
  	        localSetTimeout(function () {
  	          runTask(id);
  	        }, 0);
  	
  	        return id;
  	      };
  	    }
  	  }());
  	
  	  /**
  	   * Gets a scheduler that schedules work via a timed callback based upon platform.
  	   */
  	  var timeoutScheduler = Scheduler.timeout = Scheduler['default'] = (function () {
  	
  	    function scheduleNow(state, action) {
  	      var scheduler = this, disposable = new SingleAssignmentDisposable();
  	      var id = scheduleMethod(function () {
  	        !disposable.isDisposed && disposable.setDisposable(action(scheduler, state));
  	      });
  	      return new CompositeDisposable(disposable, disposableCreate(function () {
  	        clearMethod(id);
  	      }));
  	    }
  	
  	    function scheduleRelative(state, dueTime, action) {
  	      var scheduler = this, dt = Scheduler.normalize(dueTime), disposable = new SingleAssignmentDisposable();
  	      if (dt === 0) { return scheduler.scheduleWithState(state, action); }
  	      var id = localSetTimeout(function () {
  	        !disposable.isDisposed && disposable.setDisposable(action(scheduler, state));
  	      }, dt);
  	      return new CompositeDisposable(disposable, disposableCreate(function () {
  	        localClearTimeout(id);
  	      }));
  	    }
  	
  	    function scheduleAbsolute(state, dueTime, action) {
  	      return this.scheduleWithRelativeAndState(state, dueTime - this.now(), action);
  	    }
  	
  	    return new Scheduler(defaultNow, scheduleNow, scheduleRelative, scheduleAbsolute);
  	  })();
  	
  	  var CatchScheduler = (function (__super__) {
  	
  	    function scheduleNow(state, action) {
  	      return this._scheduler.scheduleWithState(state, this._wrap(action));
  	    }
  	
  	    function scheduleRelative(state, dueTime, action) {
  	      return this._scheduler.scheduleWithRelativeAndState(state, dueTime, this._wrap(action));
  	    }
  	
  	    function scheduleAbsolute(state, dueTime, action) {
  	      return this._scheduler.scheduleWithAbsoluteAndState(state, dueTime, this._wrap(action));
  	    }
  	
  	    inherits(CatchScheduler, __super__);
  	
  	    function CatchScheduler(scheduler, handler) {
  	      this._scheduler = scheduler;
  	      this._handler = handler;
  	      this._recursiveOriginal = null;
  	      this._recursiveWrapper = null;
  	      __super__.call(this, this._scheduler.now.bind(this._scheduler), scheduleNow, scheduleRelative, scheduleAbsolute);
  	    }
  	
  	    CatchScheduler.prototype._clone = function (scheduler) {
  	        return new CatchScheduler(scheduler, this._handler);
  	    };
  	
  	    CatchScheduler.prototype._wrap = function (action) {
  	      var parent = this;
  	      return function (self, state) {
  	        try {
  	          return action(parent._getRecursiveWrapper(self), state);
  	        } catch (e) {
  	          if (!parent._handler(e)) { throw e; }
  	          return disposableEmpty;
  	        }
  	      };
  	    };
  	
  	    CatchScheduler.prototype._getRecursiveWrapper = function (scheduler) {
  	      if (this._recursiveOriginal !== scheduler) {
  	        this._recursiveOriginal = scheduler;
  	        var wrapper = this._clone(scheduler);
  	        wrapper._recursiveOriginal = scheduler;
  	        wrapper._recursiveWrapper = wrapper;
  	        this._recursiveWrapper = wrapper;
  	      }
  	      return this._recursiveWrapper;
  	    };
  	
  	    CatchScheduler.prototype.schedulePeriodicWithState = function (state, period, action) {
  	      var self = this, failed = false, d = new SingleAssignmentDisposable();
  	
  	      d.setDisposable(this._scheduler.schedulePeriodicWithState(state, period, function (state1) {
  	        if (failed) { return null; }
  	        try {
  	          return action(state1);
  	        } catch (e) {
  	          failed = true;
  	          if (!self._handler(e)) { throw e; }
  	          d.dispose();
  	          return null;
  	        }
  	      }));
  	
  	      return d;
  	    };
  	
  	    return CatchScheduler;
  	  }(Scheduler));
  	
  	  /**
  	   *  Represents a notification to an observer.
  	   */
  	  var Notification = Rx.Notification = (function () {
  	    function Notification(kind, value, exception, accept, acceptObservable, toString) {
  	      this.kind = kind;
  	      this.value = value;
  	      this.exception = exception;
  	      this._accept = accept;
  	      this._acceptObservable = acceptObservable;
  	      this.toString = toString;
  	    }
  	
  	    /**
  	     * Invokes the delegate corresponding to the notification or the observer's method corresponding to the notification and returns the produced result.
  	     *
  	     * @memberOf Notification
  	     * @param {Any} observerOrOnNext Delegate to invoke for an OnNext notification or Observer to invoke the notification on..
  	     * @param {Function} onError Delegate to invoke for an OnError notification.
  	     * @param {Function} onCompleted Delegate to invoke for an OnCompleted notification.
  	     * @returns {Any} Result produced by the observation.
  	     */
  	    Notification.prototype.accept = function (observerOrOnNext, onError, onCompleted) {
  	      return observerOrOnNext && typeof observerOrOnNext === 'object' ?
  	        this._acceptObservable(observerOrOnNext) :
  	        this._accept(observerOrOnNext, onError, onCompleted);
  	    };
  	
  	    /**
  	     * Returns an observable sequence with a single notification.
  	     *
  	     * @memberOf Notifications
  	     * @param {Scheduler} [scheduler] Scheduler to send out the notification calls on.
  	     * @returns {Observable} The observable sequence that surfaces the behavior of the notification upon subscription.
  	     */
  	    Notification.prototype.toObservable = function (scheduler) {
  	      var self = this;
  	      isScheduler(scheduler) || (scheduler = immediateScheduler);
  	      return new AnonymousObservable(function (observer) {
  	        return scheduler.scheduleWithState(self, function (_, notification) {
  	          notification._acceptObservable(observer);
  	          notification.kind === 'N' && observer.onCompleted();
  	        });
  	      });
  	    };
  	
  	    return Notification;
  	  })();
  	
  	  /**
  	   * Creates an object that represents an OnNext notification to an observer.
  	   * @param {Any} value The value contained in the notification.
  	   * @returns {Notification} The OnNext notification containing the value.
  	   */
  	  var notificationCreateOnNext = Notification.createOnNext = (function () {
  	      function _accept(onNext) { return onNext(this.value); }
  	      function _acceptObservable(observer) { return observer.onNext(this.value); }
  	      function toString() { return 'OnNext(' + this.value + ')'; }
  	
  	      return function (value) {
  	        return new Notification('N', value, null, _accept, _acceptObservable, toString);
  	      };
  	  }());
  	
  	  /**
  	   * Creates an object that represents an OnError notification to an observer.
  	   * @param {Any} error The exception contained in the notification.
  	   * @returns {Notification} The OnError notification containing the exception.
  	   */
  	  var notificationCreateOnError = Notification.createOnError = (function () {
  	    function _accept (onNext, onError) { return onError(this.exception); }
  	    function _acceptObservable(observer) { return observer.onError(this.exception); }
  	    function toString () { return 'OnError(' + this.exception + ')'; }
  	
  	    return function (e) {
  	      return new Notification('E', null, e, _accept, _acceptObservable, toString);
  	    };
  	  }());
  	
  	  /**
  	   * Creates an object that represents an OnCompleted notification to an observer.
  	   * @returns {Notification} The OnCompleted notification.
  	   */
  	  var notificationCreateOnCompleted = Notification.createOnCompleted = (function () {
  	    function _accept (onNext, onError, onCompleted) { return onCompleted(); }
  	    function _acceptObservable(observer) { return observer.onCompleted(); }
  	    function toString () { return 'OnCompleted()'; }
  	
  	    return function () {
  	      return new Notification('C', null, null, _accept, _acceptObservable, toString);
  	    };
  	  }());
  	
  	  /**
  	   * Supports push-style iteration over an observable sequence.
  	   */
  	  var Observer = Rx.Observer = function () { };
  	
  	  /**
  	   *  Creates a notification callback from an observer.
  	   * @returns The action that forwards its input notification to the underlying observer.
  	   */
  	  Observer.prototype.toNotifier = function () {
  	    var observer = this;
  	    return function (n) { return n.accept(observer); };
  	  };
  	
  	  /**
  	   *  Hides the identity of an observer.
  	   * @returns An observer that hides the identity of the specified observer.
  	   */
  	  Observer.prototype.asObserver = function () {
  	    return new AnonymousObserver(this.onNext.bind(this), this.onError.bind(this), this.onCompleted.bind(this));
  	  };
  	
  	  /**
  	   *  Checks access to the observer for grammar violations. This includes checking for multiple OnError or OnCompleted calls, as well as reentrancy in any of the observer methods.
  	   *  If a violation is detected, an Error is thrown from the offending observer method call.
  	   * @returns An observer that checks callbacks invocations against the observer grammar and, if the checks pass, forwards those to the specified observer.
  	   */
  	  Observer.prototype.checked = function () { return new CheckedObserver(this); };
  	
  	  /**
  	   *  Creates an observer from the specified OnNext, along with optional OnError, and OnCompleted actions.
  	   * @param {Function} [onNext] Observer's OnNext action implementation.
  	   * @param {Function} [onError] Observer's OnError action implementation.
  	   * @param {Function} [onCompleted] Observer's OnCompleted action implementation.
  	   * @returns {Observer} The observer object implemented using the given actions.
  	   */
  	  var observerCreate = Observer.create = function (onNext, onError, onCompleted) {
  	    onNext || (onNext = noop);
  	    onError || (onError = defaultError);
  	    onCompleted || (onCompleted = noop);
  	    return new AnonymousObserver(onNext, onError, onCompleted);
  	  };
  	
  	  /**
  	   *  Creates an observer from a notification callback.
  	   *
  	   * @static
  	   * @memberOf Observer
  	   * @param {Function} handler Action that handles a notification.
  	   * @returns The observer object that invokes the specified handler using a notification corresponding to each message it receives.
  	   */
  	  Observer.fromNotifier = function (handler, thisArg) {
  	    return new AnonymousObserver(function (x) {
  	      return handler.call(thisArg, notificationCreateOnNext(x));
  	    }, function (e) {
  	      return handler.call(thisArg, notificationCreateOnError(e));
  	    }, function () {
  	      return handler.call(thisArg, notificationCreateOnCompleted());
  	    });
  	  };
  	
  	  /**
  	   * Schedules the invocation of observer methods on the given scheduler.
  	   * @param {Scheduler} scheduler Scheduler to schedule observer messages on.
  	   * @returns {Observer} Observer whose messages are scheduled on the given scheduler.
  	   */
  	  Observer.prototype.notifyOn = function (scheduler) {
  	    return new ObserveOnObserver(scheduler, this);
  	  };
  	
  	  Observer.prototype.makeSafe = function(disposable) {
  	    return new AnonymousSafeObserver(this._onNext, this._onError, this._onCompleted, disposable);
  	  };
  	
  	  /**
  	   * Abstract base class for implementations of the Observer class.
  	   * This base class enforces the grammar of observers where OnError and OnCompleted are terminal messages.
  	   */
  	  var AbstractObserver = Rx.internals.AbstractObserver = (function (__super__) {
  	    inherits(AbstractObserver, __super__);
  	
  	    /**
  	     * Creates a new observer in a non-stopped state.
  	     */
  	    function AbstractObserver() {
  	      this.isStopped = false;
  	      __super__.call(this);
  	    }
  	
  	    // Must be implemented by other observers
  	    AbstractObserver.prototype.next = notImplemented;
  	    AbstractObserver.prototype.error = notImplemented;
  	    AbstractObserver.prototype.completed = notImplemented;
  	
  	    /**
  	     * Notifies the observer of a new element in the sequence.
  	     * @param {Any} value Next element in the sequence.
  	     */
  	    AbstractObserver.prototype.onNext = function (value) {
  	      if (!this.isStopped) { this.next(value); }
  	    };
  	
  	    /**
  	     * Notifies the observer that an exception has occurred.
  	     * @param {Any} error The error that has occurred.
  	     */
  	    AbstractObserver.prototype.onError = function (error) {
  	      if (!this.isStopped) {
  	        this.isStopped = true;
  	        this.error(error);
  	      }
  	    };
  	
  	    /**
  	     * Notifies the observer of the end of the sequence.
  	     */
  	    AbstractObserver.prototype.onCompleted = function () {
  	      if (!this.isStopped) {
  	        this.isStopped = true;
  	        this.completed();
  	      }
  	    };
  	
  	    /**
  	     * Disposes the observer, causing it to transition to the stopped state.
  	     */
  	    AbstractObserver.prototype.dispose = function () {
  	      this.isStopped = true;
  	    };
  	
  	    AbstractObserver.prototype.fail = function (e) {
  	      if (!this.isStopped) {
  	        this.isStopped = true;
  	        this.error(e);
  	        return true;
  	      }
  	
  	      return false;
  	    };
  	
  	    return AbstractObserver;
  	  }(Observer));
  	
  	  /**
  	   * Class to create an Observer instance from delegate-based implementations of the on* methods.
  	   */
  	  var AnonymousObserver = Rx.AnonymousObserver = (function (__super__) {
  	    inherits(AnonymousObserver, __super__);
  	
  	    /**
  	     * Creates an observer from the specified OnNext, OnError, and OnCompleted actions.
  	     * @param {Any} onNext Observer's OnNext action implementation.
  	     * @param {Any} onError Observer's OnError action implementation.
  	     * @param {Any} onCompleted Observer's OnCompleted action implementation.
  	     */
  	    function AnonymousObserver(onNext, onError, onCompleted) {
  	      __super__.call(this);
  	      this._onNext = onNext;
  	      this._onError = onError;
  	      this._onCompleted = onCompleted;
  	    }
  	
  	    /**
  	     * Calls the onNext action.
  	     * @param {Any} value Next element in the sequence.
  	     */
  	    AnonymousObserver.prototype.next = function (value) {
  	      this._onNext(value);
  	    };
  	
  	    /**
  	     * Calls the onError action.
  	     * @param {Any} error The error that has occurred.
  	     */
  	    AnonymousObserver.prototype.error = function (error) {
  	      this._onError(error);
  	    };
  	
  	    /**
  	     *  Calls the onCompleted action.
  	     */
  	    AnonymousObserver.prototype.completed = function () {
  	      this._onCompleted();
  	    };
  	
  	    return AnonymousObserver;
  	  }(AbstractObserver));
  	
  	  var CheckedObserver = (function (__super__) {
  	    inherits(CheckedObserver, __super__);
  	
  	    function CheckedObserver(observer) {
  	      __super__.call(this);
  	      this._observer = observer;
  	      this._state = 0; // 0 - idle, 1 - busy, 2 - done
  	    }
  	
  	    var CheckedObserverPrototype = CheckedObserver.prototype;
  	
  	    CheckedObserverPrototype.onNext = function (value) {
  	      this.checkAccess();
  	      var res = tryCatch(this._observer.onNext).call(this._observer, value);
  	      this._state = 0;
  	      res === errorObj && thrower(res.e);
  	    };
  	
  	    CheckedObserverPrototype.onError = function (err) {
  	      this.checkAccess();
  	      var res = tryCatch(this._observer.onError).call(this._observer, err);
  	      this._state = 2;
  	      res === errorObj && thrower(res.e);
  	    };
  	
  	    CheckedObserverPrototype.onCompleted = function () {
  	      this.checkAccess();
  	      var res = tryCatch(this._observer.onCompleted).call(this._observer);
  	      this._state = 2;
  	      res === errorObj && thrower(res.e);
  	    };
  	
  	    CheckedObserverPrototype.checkAccess = function () {
  	      if (this._state === 1) { throw new Error('Re-entrancy detected'); }
  	      if (this._state === 2) { throw new Error('Observer completed'); }
  	      if (this._state === 0) { this._state = 1; }
  	    };
  	
  	    return CheckedObserver;
  	  }(Observer));
  	
  	  var ScheduledObserver = Rx.internals.ScheduledObserver = (function (__super__) {
  	    inherits(ScheduledObserver, __super__);
  	
  	    function ScheduledObserver(scheduler, observer) {
  	      __super__.call(this);
  	      this.scheduler = scheduler;
  	      this.observer = observer;
  	      this.isAcquired = false;
  	      this.hasFaulted = false;
  	      this.queue = [];
  	      this.disposable = new SerialDisposable();
  	    }
  	
  	    ScheduledObserver.prototype.next = function (value) {
  	      var self = this;
  	      this.queue.push(function () { self.observer.onNext(value); });
  	    };
  	
  	    ScheduledObserver.prototype.error = function (e) {
  	      var self = this;
  	      this.queue.push(function () { self.observer.onError(e); });
  	    };
  	
  	    ScheduledObserver.prototype.completed = function () {
  	      var self = this;
  	      this.queue.push(function () { self.observer.onCompleted(); });
  	    };
  	
  	    ScheduledObserver.prototype.ensureActive = function () {
  	      var isOwner = false, parent = this;
  	      if (!this.hasFaulted && this.queue.length > 0) {
  	        isOwner = !this.isAcquired;
  	        this.isAcquired = true;
  	      }
  	      if (isOwner) {
  	        this.disposable.setDisposable(this.scheduler.scheduleRecursive(function (self) {
  	          var work;
  	          if (parent.queue.length > 0) {
  	            work = parent.queue.shift();
  	          } else {
  	            parent.isAcquired = false;
  	            return;
  	          }
  	          try {
  	            work();
  	          } catch (ex) {
  	            parent.queue = [];
  	            parent.hasFaulted = true;
  	            throw ex;
  	          }
  	          self();
  	        }));
  	      }
  	    };
  	
  	    ScheduledObserver.prototype.dispose = function () {
  	      __super__.prototype.dispose.call(this);
  	      this.disposable.dispose();
  	    };
  	
  	    return ScheduledObserver;
  	  }(AbstractObserver));
  	
  	  var ObserveOnObserver = (function (__super__) {
  	    inherits(ObserveOnObserver, __super__);
  	
  	    function ObserveOnObserver(scheduler, observer, cancel) {
  	      __super__.call(this, scheduler, observer);
  	      this._cancel = cancel;
  	    }
  	
  	    ObserveOnObserver.prototype.next = function (value) {
  	      __super__.prototype.next.call(this, value);
  	      this.ensureActive();
  	    };
  	
  	    ObserveOnObserver.prototype.error = function (e) {
  	      __super__.prototype.error.call(this, e);
  	      this.ensureActive();
  	    };
  	
  	    ObserveOnObserver.prototype.completed = function () {
  	      __super__.prototype.completed.call(this);
  	      this.ensureActive();
  	    };
  	
  	    ObserveOnObserver.prototype.dispose = function () {
  	      __super__.prototype.dispose.call(this);
  	      this._cancel && this._cancel.dispose();
  	      this._cancel = null;
  	    };
  	
  	    return ObserveOnObserver;
  	  })(ScheduledObserver);
  	
  	  var observableProto;
  	
  	  /**
  	   * Represents a push-style collection.
  	   */
  	  var Observable = Rx.Observable = (function () {
  	
  	    function Observable(subscribe) {
  	      if (Rx.config.longStackSupport && hasStacks) {
  	        try {
  	          throw new Error();
  	        } catch (e) {
  	          this.stack = e.stack.substring(e.stack.indexOf("\n") + 1);
  	        }
  	
  	        var self = this;
  	        this._subscribe = function (observer) {
  	          var oldOnError = observer.onError.bind(observer);
  	
  	          observer.onError = function (err) {
  	            makeStackTraceLong(err, self);
  	            oldOnError(err);
  	          };
  	
  	          return subscribe.call(self, observer);
  	        };
  	      } else {
  	        this._subscribe = subscribe;
  	      }
  	    }
  	
  	    observableProto = Observable.prototype;
  	
  	    /**
  	     *  Subscribes an observer to the observable sequence.
  	     *  @param {Mixed} [observerOrOnNext] The object that is to receive notifications or an action to invoke for each element in the observable sequence.
  	     *  @param {Function} [onError] Action to invoke upon exceptional termination of the observable sequence.
  	     *  @param {Function} [onCompleted] Action to invoke upon graceful termination of the observable sequence.
  	     *  @returns {Diposable} A disposable handling the subscriptions and unsubscriptions.
  	     */
  	    observableProto.subscribe = observableProto.forEach = function (observerOrOnNext, onError, onCompleted) {
  	      return this._subscribe(typeof observerOrOnNext === 'object' ?
  	        observerOrOnNext :
  	        observerCreate(observerOrOnNext, onError, onCompleted));
  	    };
  	
  	    /**
  	     * Subscribes to the next value in the sequence with an optional "this" argument.
  	     * @param {Function} onNext The function to invoke on each element in the observable sequence.
  	     * @param {Any} [thisArg] Object to use as this when executing callback.
  	     * @returns {Disposable} A disposable handling the subscriptions and unsubscriptions.
  	     */
  	    observableProto.subscribeOnNext = function (onNext, thisArg) {
  	      return this._subscribe(observerCreate(typeof thisArg !== 'undefined' ? function(x) { onNext.call(thisArg, x); } : onNext));
  	    };
  	
  	    /**
  	     * Subscribes to an exceptional condition in the sequence with an optional "this" argument.
  	     * @param {Function} onError The function to invoke upon exceptional termination of the observable sequence.
  	     * @param {Any} [thisArg] Object to use as this when executing callback.
  	     * @returns {Disposable} A disposable handling the subscriptions and unsubscriptions.
  	     */
  	    observableProto.subscribeOnError = function (onError, thisArg) {
  	      return this._subscribe(observerCreate(null, typeof thisArg !== 'undefined' ? function(e) { onError.call(thisArg, e); } : onError));
  	    };
  	
  	    /**
  	     * Subscribes to the next value in the sequence with an optional "this" argument.
  	     * @param {Function} onCompleted The function to invoke upon graceful termination of the observable sequence.
  	     * @param {Any} [thisArg] Object to use as this when executing callback.
  	     * @returns {Disposable} A disposable handling the subscriptions and unsubscriptions.
  	     */
  	    observableProto.subscribeOnCompleted = function (onCompleted, thisArg) {
  	      return this._subscribe(observerCreate(null, null, typeof thisArg !== 'undefined' ? function() { onCompleted.call(thisArg); } : onCompleted));
  	    };
  	
  	    return Observable;
  	  })();
  	
  	  var ObservableBase = Rx.ObservableBase = (function (__super__) {
  	    inherits(ObservableBase, __super__);
  	
  	    function fixSubscriber(subscriber) {
  	      return subscriber && isFunction(subscriber.dispose) ? subscriber :
  	        isFunction(subscriber) ? disposableCreate(subscriber) : disposableEmpty;
  	    }
  	
  	    function setDisposable(s, state) {
  	      var ado = state[0], self = state[1];
  	      var sub = tryCatch(self.subscribeCore).call(self, ado);
  	
  	      if (sub === errorObj) {
  	        if(!ado.fail(errorObj.e)) { return thrower(errorObj.e); }
  	      }
  	      ado.setDisposable(fixSubscriber(sub));
  	    }
  	
  	    function subscribe(observer) {
  	      var ado = new AutoDetachObserver(observer), state = [ado, this];
  	
  	      if (currentThreadScheduler.scheduleRequired()) {
  	        currentThreadScheduler.scheduleWithState(state, setDisposable);
  	      } else {
  	        setDisposable(null, state);
  	      }
  	      return ado;
  	    }
  	
  	    function ObservableBase() {
  	      __super__.call(this, subscribe);
  	    }
  	
  	    ObservableBase.prototype.subscribeCore = notImplemented;
  	
  	    return ObservableBase;
  	  }(Observable));
  	
  	  var Enumerable = Rx.internals.Enumerable = function () { };
  	
  	  var ConcatEnumerableObservable = (function(__super__) {
  	    inherits(ConcatEnumerableObservable, __super__);
  	    function ConcatEnumerableObservable(sources) {
  	      this.sources = sources;
  	      __super__.call(this);
  	    }
  	    
  	    ConcatEnumerableObservable.prototype.subscribeCore = function (o) {
  	      var isDisposed, subscription = new SerialDisposable();
  	      var cancelable = immediateScheduler.scheduleRecursiveWithState(this.sources[$iterator$](), function (e, self) {
  	        if (isDisposed) { return; }
  	        var currentItem = tryCatch(e.next).call(e);
  	        if (currentItem === errorObj) { return o.onError(currentItem.e); }
  	
  	        if (currentItem.done) {
  	          return o.onCompleted();
  	        }
  	
  	        // Check if promise
  	        var currentValue = currentItem.value;
  	        isPromise(currentValue) && (currentValue = observableFromPromise(currentValue));
  	
  	        var d = new SingleAssignmentDisposable();
  	        subscription.setDisposable(d);
  	        d.setDisposable(currentValue.subscribe(new InnerObserver(o, self, e)));
  	      });
  	
  	      return new CompositeDisposable(subscription, cancelable, disposableCreate(function () {
  	        isDisposed = true;
  	      }));
  	    };
  	    
  	    function InnerObserver(o, s, e) {
  	      this.o = o;
  	      this.s = s;
  	      this.e = e;
  	      this.isStopped = false;
  	    }
  	    InnerObserver.prototype.onNext = function (x) { if(!this.isStopped) { this.o.onNext(x); } };
  	    InnerObserver.prototype.onError = function (err) {
  	      if (!this.isStopped) {
  	        this.isStopped = true;
  	        this.o.onError(err);
  	      }
  	    };
  	    InnerObserver.prototype.onCompleted = function () {
  	      if (!this.isStopped) {
  	        this.isStopped = true;
  	        this.s(this.e);
  	      }
  	    };
  	    InnerObserver.prototype.dispose = function () { this.isStopped = true; };
  	    InnerObserver.prototype.fail = function (err) {
  	      if (!this.isStopped) {
  	        this.isStopped = true;
  	        this.o.onError(err);
  	        return true;
  	      }
  	      return false;
  	    };
  	    
  	    return ConcatEnumerableObservable;
  	  }(ObservableBase));
  	
  	  Enumerable.prototype.concat = function () {
  	    return new ConcatEnumerableObservable(this);
  	  };
  	  
  	  var CatchErrorObservable = (function(__super__) {
  	    inherits(CatchErrorObservable, __super__);
  	    function CatchErrorObservable(sources) {
  	      this.sources = sources;
  	      __super__.call(this);
  	    }
  	    
  	    CatchErrorObservable.prototype.subscribeCore = function (o) {
  	      var e = this.sources[$iterator$]();
  	
  	      var isDisposed, subscription = new SerialDisposable();
  	      var cancelable = immediateScheduler.scheduleRecursiveWithState(null, function (lastException, self) {
  	        if (isDisposed) { return; }
  	        var currentItem = tryCatch(e.next).call(e);
  	        if (currentItem === errorObj) { return o.onError(currentItem.e); }
  	
  	        if (currentItem.done) {
  	          return lastException !== null ? o.onError(lastException) : o.onCompleted();
  	        }
  	
  	        // Check if promise
  	        var currentValue = currentItem.value;
  	        isPromise(currentValue) && (currentValue = observableFromPromise(currentValue));
  	
  	        var d = new SingleAssignmentDisposable();
  	        subscription.setDisposable(d);
  	        d.setDisposable(currentValue.subscribe(
  	          function(x) { o.onNext(x); },
  	          self,
  	          function() { o.onCompleted(); }));
  	      });
  	      return new CompositeDisposable(subscription, cancelable, disposableCreate(function () {
  	        isDisposed = true;
  	      }));
  	    };
  	    
  	    return CatchErrorObservable;
  	  }(ObservableBase));
  	
  	  Enumerable.prototype.catchError = function () {
  	    return new CatchErrorObservable(this);
  	  };
  	
  	  Enumerable.prototype.catchErrorWhen = function (notificationHandler) {
  	    var sources = this;
  	    return new AnonymousObservable(function (o) {
  	      var exceptions = new Subject(),
  	        notifier = new Subject(),
  	        handled = notificationHandler(exceptions),
  	        notificationDisposable = handled.subscribe(notifier);
  	
  	      var e = sources[$iterator$]();
  	
  	      var isDisposed,
  	        lastException,
  	        subscription = new SerialDisposable();
  	      var cancelable = immediateScheduler.scheduleRecursive(function (self) {
  	        if (isDisposed) { return; }
  	        var currentItem = tryCatch(e.next).call(e);
  	        if (currentItem === errorObj) { return o.onError(currentItem.e); }
  	
  	        if (currentItem.done) {
  	          if (lastException) {
  	            o.onError(lastException);
  	          } else {
  	            o.onCompleted();
  	          }
  	          return;
  	        }
  	
  	        // Check if promise
  	        var currentValue = currentItem.value;
  	        isPromise(currentValue) && (currentValue = observableFromPromise(currentValue));
  	
  	        var outer = new SingleAssignmentDisposable();
  	        var inner = new SingleAssignmentDisposable();
  	        subscription.setDisposable(new CompositeDisposable(inner, outer));
  	        outer.setDisposable(currentValue.subscribe(
  	          function(x) { o.onNext(x); },
  	          function (exn) {
  	            inner.setDisposable(notifier.subscribe(self, function(ex) {
  	              o.onError(ex);
  	            }, function() {
  	              o.onCompleted();
  	            }));
  	
  	            exceptions.onNext(exn);
  	          },
  	          function() { o.onCompleted(); }));
  	      });
  	
  	      return new CompositeDisposable(notificationDisposable, subscription, cancelable, disposableCreate(function () {
  	        isDisposed = true;
  	      }));
  	    });
  	  };
  	  
  	  var RepeatEnumerable = (function (__super__) {
  	    inherits(RepeatEnumerable, __super__);
  	    
  	    function RepeatEnumerable(v, c) {
  	      this.v = v;
  	      this.c = c == null ? -1 : c;
  	    }
  	    RepeatEnumerable.prototype[$iterator$] = function () {
  	      return new RepeatEnumerator(this); 
  	    };
  	    
  	    function RepeatEnumerator(p) {
  	      this.v = p.v;
  	      this.l = p.c;
  	    }
  	    RepeatEnumerator.prototype.next = function () {
  	      if (this.l === 0) { return doneEnumerator; }
  	      if (this.l > 0) { this.l--; }
  	      return { done: false, value: this.v }; 
  	    };
  	    
  	    return RepeatEnumerable;
  	  }(Enumerable));
  	
  	  var enumerableRepeat = Enumerable.repeat = function (value, repeatCount) {
  	    return new RepeatEnumerable(value, repeatCount);
  	  };
  	  
  	  var OfEnumerable = (function(__super__) {
  	    inherits(OfEnumerable, __super__);
  	    function OfEnumerable(s, fn, thisArg) {
  	      this.s = s;
  	      this.fn = fn ? bindCallback(fn, thisArg, 3) : null;
  	    }
  	    OfEnumerable.prototype[$iterator$] = function () {
  	      return new OfEnumerator(this);
  	    };
  	    
  	    function OfEnumerator(p) {
  	      this.i = -1;
  	      this.s = p.s;
  	      this.l = this.s.length;
  	      this.fn = p.fn;
  	    }
  	    OfEnumerator.prototype.next = function () {
  	     return ++this.i < this.l ?
  	       { done: false, value: !this.fn ? this.s[this.i] : this.fn(this.s[this.i], this.i, this.s) } :
  	       doneEnumerator; 
  	    };
  	    
  	    return OfEnumerable;
  	  }(Enumerable));
  	
  	  var enumerableOf = Enumerable.of = function (source, selector, thisArg) {
  	    return new OfEnumerable(source, selector, thisArg);
  	  };
  	
  	   /**
  	   *  Wraps the source sequence in order to run its observer callbacks on the specified scheduler.
  	   *
  	   *  This only invokes observer callbacks on a scheduler. In case the subscription and/or unsubscription actions have side-effects
  	   *  that require to be run on a scheduler, use subscribeOn.
  	   *
  	   *  @param {Scheduler} scheduler Scheduler to notify observers on.
  	   *  @returns {Observable} The source sequence whose observations happen on the specified scheduler.
  	   */
  	  observableProto.observeOn = function (scheduler) {
  	    var source = this;
  	    return new AnonymousObservable(function (observer) {
  	      return source.subscribe(new ObserveOnObserver(scheduler, observer));
  	    }, source);
  	  };
  	
  	   /**
  	   *  Wraps the source sequence in order to run its subscription and unsubscription logic on the specified scheduler. This operation is not commonly used;
  	   *  see the remarks section for more information on the distinction between subscribeOn and observeOn.
  	
  	   *  This only performs the side-effects of subscription and unsubscription on the specified scheduler. In order to invoke observer
  	   *  callbacks on a scheduler, use observeOn.
  	
  	   *  @param {Scheduler} scheduler Scheduler to perform subscription and unsubscription actions on.
  	   *  @returns {Observable} The source sequence whose subscriptions and unsubscriptions happen on the specified scheduler.
  	   */
  	  observableProto.subscribeOn = function (scheduler) {
  	    var source = this;
  	    return new AnonymousObservable(function (observer) {
  	      var m = new SingleAssignmentDisposable(), d = new SerialDisposable();
  	      d.setDisposable(m);
  	      m.setDisposable(scheduler.schedule(function () {
  	        d.setDisposable(new ScheduledDisposable(scheduler, source.subscribe(observer)));
  	      }));
  	      return d;
  	    }, source);
  	  };
  	
  		var FromPromiseObservable = (function(__super__) {
  			inherits(FromPromiseObservable, __super__);
  			function FromPromiseObservable(p) {
  				this.p = p;
  				__super__.call(this);
  			}
  			
  			FromPromiseObservable.prototype.subscribeCore = function(o) {
  				this.p.then(function (data) {
  					o.onNext(data);
  					o.onCompleted();
  				}, function (err) { o.onError(err); });
  				return disposableEmpty;	
  			};
  			
  			return FromPromiseObservable;
  		}(ObservableBase));	 
  		 
  		 /**
  		 * Converts a Promise to an Observable sequence
  		 * @param {Promise} An ES6 Compliant promise.
  		 * @returns {Observable} An Observable sequence which wraps the existing promise success and failure.
  		 */
  		var observableFromPromise = Observable.fromPromise = function (promise) {
  			return new FromPromiseObservable(promise);
  		};
  	  /*
  	   * Converts an existing observable sequence to an ES6 Compatible Promise
  	   * @example
  	   * var promise = Rx.Observable.return(42).toPromise(RSVP.Promise);
  	   *
  	   * // With config
  	   * Rx.config.Promise = RSVP.Promise;
  	   * var promise = Rx.Observable.return(42).toPromise();
  	   * @param {Function} [promiseCtor] The constructor of the promise. If not provided, it looks for it in Rx.config.Promise.
  	   * @returns {Promise} An ES6 compatible promise with the last value from the observable sequence.
  	   */
  	  observableProto.toPromise = function (promiseCtor) {
  	    promiseCtor || (promiseCtor = Rx.config.Promise);
  	    if (!promiseCtor) { throw new NotSupportedError('Promise type not provided nor in Rx.config.Promise'); }
  	    var source = this;
  	    return new promiseCtor(function (resolve, reject) {
  	      // No cancellation can be done
  	      var value, hasValue = false;
  	      source.subscribe(function (v) {
  	        value = v;
  	        hasValue = true;
  	      }, reject, function () {
  	        hasValue && resolve(value);
  	      });
  	    });
  	  };
  	
  	  var ToArrayObservable = (function(__super__) {
  	    inherits(ToArrayObservable, __super__);
  	    function ToArrayObservable(source) {
  	      this.source = source;
  	      __super__.call(this);
  	    }
  	
  	    ToArrayObservable.prototype.subscribeCore = function(o) {
  	      return this.source.subscribe(new InnerObserver(o));
  	    };
  	
  	    function InnerObserver(o) {
  	      this.o = o;
  	      this.a = [];
  	      this.isStopped = false;
  	    }
  	    InnerObserver.prototype.onNext = function (x) { if(!this.isStopped) { this.a.push(x); } };
  	    InnerObserver.prototype.onError = function (e) {
  	      if (!this.isStopped) {
  	        this.isStopped = true;
  	        this.o.onError(e);
  	      }
  	    };
  	    InnerObserver.prototype.onCompleted = function () {
  	      if (!this.isStopped) {
  	        this.isStopped = true;
  	        this.o.onNext(this.a);
  	        this.o.onCompleted();
  	      }
  	    };
  	    InnerObserver.prototype.dispose = function () { this.isStopped = true; }
  	    InnerObserver.prototype.fail = function (e) {
  	      if (!this.isStopped) {
  	        this.isStopped = true;
  	        this.o.onError(e);
  	        return true;
  	      }
  	 
  	      return false;
  	    };
  	
  	    return ToArrayObservable;
  	  }(ObservableBase));
  	
  	  /**
  	  * Creates an array from an observable sequence.
  	  * @returns {Observable} An observable sequence containing a single element with a list containing all the elements of the source sequence.
  	  */
  	  observableProto.toArray = function () {
  	    return new ToArrayObservable(this);
  	  };
  	
  	  /**
  	   *  Creates an observable sequence from a specified subscribe method implementation.
  	   * @example
  	   *  var res = Rx.Observable.create(function (observer) { return function () { } );
  	   *  var res = Rx.Observable.create(function (observer) { return Rx.Disposable.empty; } );
  	   *  var res = Rx.Observable.create(function (observer) { } );
  	   * @param {Function} subscribe Implementation of the resulting observable sequence's subscribe method, returning a function that will be wrapped in a Disposable.
  	   * @returns {Observable} The observable sequence with the specified implementation for the Subscribe method.
  	   */
  	  Observable.create = Observable.createWithDisposable = function (subscribe, parent) {
  	    return new AnonymousObservable(subscribe, parent);
  	  };
  	
  	  /**
  	   *  Returns an observable sequence that invokes the specified factory function whenever a new observer subscribes.
  	   *
  	   * @example
  	   *  var res = Rx.Observable.defer(function () { return Rx.Observable.fromArray([1,2,3]); });
  	   * @param {Function} observableFactory Observable factory function to invoke for each observer that subscribes to the resulting sequence or Promise.
  	   * @returns {Observable} An observable sequence whose observers trigger an invocation of the given observable factory function.
  	   */
  	  var observableDefer = Observable.defer = function (observableFactory) {
  	    return new AnonymousObservable(function (observer) {
  	      var result;
  	      try {
  	        result = observableFactory();
  	      } catch (e) {
  	        return observableThrow(e).subscribe(observer);
  	      }
  	      isPromise(result) && (result = observableFromPromise(result));
  	      return result.subscribe(observer);
  	    });
  	  };
  	
  	  var EmptyObservable = (function(__super__) {
  	    inherits(EmptyObservable, __super__);
  	    function EmptyObservable(scheduler) {
  	      this.scheduler = scheduler;
  	      __super__.call(this);
  	    }
  	
  	    EmptyObservable.prototype.subscribeCore = function (observer) {
  	      var sink = new EmptySink(observer, this);
  	      return sink.run();
  	    };
  	
  	    function EmptySink(observer, parent) {
  	      this.observer = observer;
  	      this.parent = parent;
  	    }
  	
  	    function scheduleItem(s, state) {
  	      state.onCompleted();
  	    }
  	
  	    EmptySink.prototype.run = function () {
  	      return this.parent.scheduler.scheduleWithState(this.observer, scheduleItem);
  	    };
  	
  	    return EmptyObservable;
  	  }(ObservableBase));
  	
  	  /**
  	   *  Returns an empty observable sequence, using the specified scheduler to send out the single OnCompleted message.
  	   *
  	   * @example
  	   *  var res = Rx.Observable.empty();
  	   *  var res = Rx.Observable.empty(Rx.Scheduler.timeout);
  	   * @param {Scheduler} [scheduler] Scheduler to send the termination call on.
  	   * @returns {Observable} An observable sequence with no elements.
  	   */
  	  var observableEmpty = Observable.empty = function (scheduler) {
  	    isScheduler(scheduler) || (scheduler = immediateScheduler);
  	    return new EmptyObservable(scheduler);
  	  };
  	
  	  var FromObservable = (function(__super__) {
  	    inherits(FromObservable, __super__);
  	    function FromObservable(iterable, mapper, scheduler) {
  	      this.iterable = iterable;
  	      this.mapper = mapper;
  	      this.scheduler = scheduler;
  	      __super__.call(this);
  	    }
  	
  	    FromObservable.prototype.subscribeCore = function (observer) {
  	      var sink = new FromSink(observer, this);
  	      return sink.run();
  	    };
  	
  	    return FromObservable;
  	  }(ObservableBase));
  	
  	  var FromSink = (function () {
  	    function FromSink(observer, parent) {
  	      this.observer = observer;
  	      this.parent = parent;
  	    }
  	
  	    FromSink.prototype.run = function () {
  	      var list = Object(this.parent.iterable),
  	          it = getIterable(list),
  	          observer = this.observer,
  	          mapper = this.parent.mapper;
  	
  	      function loopRecursive(i, recurse) {
  	        try {
  	          var next = it.next();
  	        } catch (e) {
  	          return observer.onError(e);
  	        }
  	        if (next.done) {
  	          return observer.onCompleted();
  	        }
  	
  	        var result = next.value;
  	
  	        if (mapper) {
  	          try {
  	            result = mapper(result, i);
  	          } catch (e) {
  	            return observer.onError(e);
  	          }
  	        }
  	
  	        observer.onNext(result);
  	        recurse(i + 1);
  	      }
  	
  	      return this.parent.scheduler.scheduleRecursiveWithState(0, loopRecursive);
  	    };
  	
  	    return FromSink;
  	  }());
  	
  	  var maxSafeInteger = Math.pow(2, 53) - 1;
  	
  	  function StringIterable(str) {
  	    this._s = s;
  	  }
  	
  	  StringIterable.prototype[$iterator$] = function () {
  	    return new StringIterator(this._s);
  	  };
  	
  	  function StringIterator(str) {
  	    this._s = s;
  	    this._l = s.length;
  	    this._i = 0;
  	  }
  	
  	  StringIterator.prototype[$iterator$] = function () {
  	    return this;
  	  };
  	
  	  StringIterator.prototype.next = function () {
  	    return this._i < this._l ? { done: false, value: this._s.charAt(this._i++) } : doneEnumerator;
  	  };
  	
  	  function ArrayIterable(a) {
  	    this._a = a;
  	  }
  	
  	  ArrayIterable.prototype[$iterator$] = function () {
  	    return new ArrayIterator(this._a);
  	  };
  	
  	  function ArrayIterator(a) {
  	    this._a = a;
  	    this._l = toLength(a);
  	    this._i = 0;
  	  }
  	
  	  ArrayIterator.prototype[$iterator$] = function () {
  	    return this;
  	  };
  	
  	  ArrayIterator.prototype.next = function () {
  	    return this._i < this._l ? { done: false, value: this._a[this._i++] } : doneEnumerator;
  	  };
  	
  	  function numberIsFinite(value) {
  	    return typeof value === 'number' && root.isFinite(value);
  	  }
  	
  	  function isNan(n) {
  	    return n !== n;
  	  }
  	
  	  function getIterable(o) {
  	    var i = o[$iterator$], it;
  	    if (!i && typeof o === 'string') {
  	      it = new StringIterable(o);
  	      return it[$iterator$]();
  	    }
  	    if (!i && o.length !== undefined) {
  	      it = new ArrayIterable(o);
  	      return it[$iterator$]();
  	    }
  	    if (!i) { throw new TypeError('Object is not iterable'); }
  	    return o[$iterator$]();
  	  }
  	
  	  function sign(value) {
  	    var number = +value;
  	    if (number === 0) { return number; }
  	    if (isNaN(number)) { return number; }
  	    return number < 0 ? -1 : 1;
  	  }
  	
  	  function toLength(o) {
  	    var len = +o.length;
  	    if (isNaN(len)) { return 0; }
  	    if (len === 0 || !numberIsFinite(len)) { return len; }
  	    len = sign(len) * Math.floor(Math.abs(len));
  	    if (len <= 0) { return 0; }
  	    if (len > maxSafeInteger) { return maxSafeInteger; }
  	    return len;
  	  }
  	
  	  /**
  	  * This method creates a new Observable sequence from an array-like or iterable object.
  	  * @param {Any} arrayLike An array-like or iterable object to convert to an Observable sequence.
  	  * @param {Function} [mapFn] Map function to call on every element of the array.
  	  * @param {Any} [thisArg] The context to use calling the mapFn if provided.
  	  * @param {Scheduler} [scheduler] Optional scheduler to use for scheduling.  If not provided, defaults to Scheduler.currentThread.
  	  */
  	  var observableFrom = Observable.from = function (iterable, mapFn, thisArg, scheduler) {
  	    if (iterable == null) {
  	      throw new Error('iterable cannot be null.')
  	    }
  	    if (mapFn && !isFunction(mapFn)) {
  	      throw new Error('mapFn when provided must be a function');
  	    }
  	    if (mapFn) {
  	      var mapper = bindCallback(mapFn, thisArg, 2);
  	    }
  	    isScheduler(scheduler) || (scheduler = currentThreadScheduler);
  	    return new FromObservable(iterable, mapper, scheduler);
  	  }
  	
  	  var FromArrayObservable = (function(__super__) {
  	    inherits(FromArrayObservable, __super__);
  	    function FromArrayObservable(args, scheduler) {
  	      this.args = args;
  	      this.scheduler = scheduler;
  	      __super__.call(this);
  	    }
  	
  	    FromArrayObservable.prototype.subscribeCore = function (observer) {
  	      var sink = new FromArraySink(observer, this);
  	      return sink.run();
  	    };
  	
  	    return FromArrayObservable;
  	  }(ObservableBase));
  	
  	  function FromArraySink(observer, parent) {
  	    this.observer = observer;
  	    this.parent = parent;
  	  }
  	
  	  FromArraySink.prototype.run = function () {
  	    var observer = this.observer, args = this.parent.args, len = args.length;
  	    function loopRecursive(i, recurse) {
  	      if (i < len) {
  	        observer.onNext(args[i]);
  	        recurse(i + 1);
  	      } else {
  	        observer.onCompleted();
  	      }
  	    }
  	
  	    return this.parent.scheduler.scheduleRecursiveWithState(0, loopRecursive);
  	  };
  	
  	  /**
  	  *  Converts an array to an observable sequence, using an optional scheduler to enumerate the array.
  	  * @deprecated use Observable.from or Observable.of
  	  * @param {Scheduler} [scheduler] Scheduler to run the enumeration of the input sequence on.
  	  * @returns {Observable} The observable sequence whose elements are pulled from the given enumerable sequence.
  	  */
  	  var observableFromArray = Observable.fromArray = function (array, scheduler) {
  	    isScheduler(scheduler) || (scheduler = currentThreadScheduler);
  	    return new FromArrayObservable(array, scheduler)
  	  };
  	
  	  /**
  	   *  Generates an observable sequence by running a state-driven loop producing the sequence's elements, using the specified scheduler to send out observer messages.
  	   *
  	   * @example
  	   *  var res = Rx.Observable.generate(0, function (x) { return x < 10; }, function (x) { return x + 1; }, function (x) { return x; });
  	   *  var res = Rx.Observable.generate(0, function (x) { return x < 10; }, function (x) { return x + 1; }, function (x) { return x; }, Rx.Scheduler.timeout);
  	   * @param {Mixed} initialState Initial state.
  	   * @param {Function} condition Condition to terminate generation (upon returning false).
  	   * @param {Function} iterate Iteration step function.
  	   * @param {Function} resultSelector Selector function for results produced in the sequence.
  	   * @param {Scheduler} [scheduler] Scheduler on which to run the generator loop. If not provided, defaults to Scheduler.currentThread.
  	   * @returns {Observable} The generated sequence.
  	   */
  	  Observable.generate = function (initialState, condition, iterate, resultSelector, scheduler) {
  	    isScheduler(scheduler) || (scheduler = currentThreadScheduler);
  	    return new AnonymousObservable(function (o) {
  	      var first = true;
  	      return scheduler.scheduleRecursiveWithState(initialState, function (state, self) {
  	        var hasResult, result;
  	        try {
  	          if (first) {
  	            first = false;
  	          } else {
  	            state = iterate(state);
  	          }
  	          hasResult = condition(state);
  	          hasResult && (result = resultSelector(state));
  	        } catch (e) {
  	          return o.onError(e);
  	        }
  	        if (hasResult) {
  	          o.onNext(result);
  	          self(state);
  	        } else {
  	          o.onCompleted();
  	        }
  	      });
  	    });
  	  };
  	
  	  function observableOf (scheduler, array) {
  	    isScheduler(scheduler) || (scheduler = currentThreadScheduler);
  	    return new FromArrayObservable(array, scheduler);
  	  }
  	
  	  /**
  	  *  This method creates a new Observable instance with a variable number of arguments, regardless of number or type of the arguments.
  	  * @returns {Observable} The observable sequence whose elements are pulled from the given arguments.
  	  */
  	  Observable.of = function () {
  	    var len = arguments.length, args = new Array(len);
  	    for(var i = 0; i < len; i++) { args[i] = arguments[i]; }
  	    return new FromArrayObservable(args, currentThreadScheduler);
  	  };
  	
  	  /**
  	  *  This method creates a new Observable instance with a variable number of arguments, regardless of number or type of the arguments.
  	  * @param {Scheduler} scheduler A scheduler to use for scheduling the arguments.
  	  * @returns {Observable} The observable sequence whose elements are pulled from the given arguments.
  	  */
  	  Observable.ofWithScheduler = function (scheduler) {
  	    var len = arguments.length, args = new Array(len - 1);
  	    for(var i = 1; i < len; i++) { args[i - 1] = arguments[i]; }
  	    return new FromArrayObservable(args, scheduler);
  	  };
  	
  	  /**
  	   * Creates an Observable sequence from changes to an array using Array.observe.
  	   * @param {Array} array An array to observe changes.
  	   * @returns {Observable} An observable sequence containing changes to an array from Array.observe.
  	   */
  	  Observable.ofArrayChanges = function(array) {
  	    if (!Array.isArray(array)) { throw new TypeError('Array.observe only accepts arrays.'); }
  	    if (typeof Array.observe !== 'function' && typeof Array.unobserve !== 'function') { throw new TypeError('Array.observe is not supported on your platform') }
  	    return new AnonymousObservable(function(observer) {
  	      function observerFn(changes) {
  	        for(var i = 0, len = changes.length; i < len; i++) {
  	          observer.onNext(changes[i]);
  	        }
  	      }
  	      
  	      Array.observe(array, observerFn);
  	
  	      return function () {
  	        Array.unobserve(array, observerFn);
  	      };
  	    });
  	  };
  	
  	  /**
  	   * Creates an Observable sequence from changes to an object using Object.observe.
  	   * @param {Object} obj An object to observe changes.
  	   * @returns {Observable} An observable sequence containing changes to an object from Object.observe.
  	   */
  	  Observable.ofObjectChanges = function(obj) {
  	    if (obj == null) { throw new TypeError('object must not be null or undefined.'); }
  	    if (typeof Object.observe !== 'function' && typeof Object.unobserve !== 'function') { throw new TypeError('Object.observe is not supported on your platform') }
  	    return new AnonymousObservable(function(observer) {
  	      function observerFn(changes) {
  	        for(var i = 0, len = changes.length; i < len; i++) {
  	          observer.onNext(changes[i]);
  	        }
  	      }
  	
  	      Object.observe(obj, observerFn);
  	
  	      return function () {
  	        Object.unobserve(obj, observerFn);
  	      };
  	    });
  	  };
  	
  	  var NeverObservable = (function(__super__) {
  	    inherits(NeverObservable, __super__);
  	    function NeverObservable() {
  	      __super__.call(this);
  	    }
  	
  	    NeverObservable.prototype.subscribeCore = function (observer) {
  	      return disposableEmpty;
  	    };
  	
  	    return NeverObservable;
  	  }(ObservableBase));
  	
  	  /**
  	   * Returns a non-terminating observable sequence, which can be used to denote an infinite duration (e.g. when using reactive joins).
  	   * @returns {Observable} An observable sequence whose observers will never get called.
  	   */
  	  var observableNever = Observable.never = function () {
  	    return new NeverObservable();
  	  };
  	
  	  var PairsObservable = (function(__super__) {
  	    inherits(PairsObservable, __super__);
  	    function PairsObservable(obj, scheduler) {
  	      this.obj = obj;
  	      this.keys = Object.keys(obj);
  	      this.scheduler = scheduler;
  	      __super__.call(this);
  	    }
  	
  	    PairsObservable.prototype.subscribeCore = function (observer) {
  	      var sink = new PairsSink(observer, this);
  	      return sink.run();
  	    };
  	
  	    return PairsObservable;
  	  }(ObservableBase));
  	
  	  function PairsSink(observer, parent) {
  	    this.observer = observer;
  	    this.parent = parent;
  	  }
  	
  	  PairsSink.prototype.run = function () {
  	    var observer = this.observer, obj = this.parent.obj, keys = this.parent.keys, len = keys.length;
  	    function loopRecursive(i, recurse) {
  	      if (i < len) {
  	        var key = keys[i];
  	        observer.onNext([key, obj[key]]);
  	        recurse(i + 1);
  	      } else {
  	        observer.onCompleted();
  	      }
  	    }
  	
  	    return this.parent.scheduler.scheduleRecursiveWithState(0, loopRecursive);
  	  };
  	
  	  /**
  	   * Convert an object into an observable sequence of [key, value] pairs.
  	   * @param {Object} obj The object to inspect.
  	   * @param {Scheduler} [scheduler] Scheduler to run the enumeration of the input sequence on.
  	   * @returns {Observable} An observable sequence of [key, value] pairs from the object.
  	   */
  	  Observable.pairs = function (obj, scheduler) {
  	    scheduler || (scheduler = currentThreadScheduler);
  	    return new PairsObservable(obj, scheduler);
  	  };
  	
  	    var RangeObservable = (function(__super__) {
  	    inherits(RangeObservable, __super__);
  	    function RangeObservable(start, count, scheduler) {
  	      this.start = start;
  	      this.rangeCount = count;
  	      this.scheduler = scheduler;
  	      __super__.call(this);
  	    }
  	
  	    RangeObservable.prototype.subscribeCore = function (observer) {
  	      var sink = new RangeSink(observer, this);
  	      return sink.run();
  	    };
  	
  	    return RangeObservable;
  	  }(ObservableBase));
  	
  	  var RangeSink = (function () {
  	    function RangeSink(observer, parent) {
  	      this.observer = observer;
  	      this.parent = parent;
  	    }
  	
  	    RangeSink.prototype.run = function () {
  	      var start = this.parent.start, count = this.parent.rangeCount, observer = this.observer;
  	      function loopRecursive(i, recurse) {
  	        if (i < count) {
  	          observer.onNext(start + i);
  	          recurse(i + 1);
  	        } else {
  	          observer.onCompleted();
  	        }
  	      }
  	
  	      return this.parent.scheduler.scheduleRecursiveWithState(0, loopRecursive);
  	    };
  	
  	    return RangeSink;
  	  }());
  	
  	  /**
  	  *  Generates an observable sequence of integral numbers within a specified range, using the specified scheduler to send out observer messages.
  	  * @param {Number} start The value of the first integer in the sequence.
  	  * @param {Number} count The number of sequential integers to generate.
  	  * @param {Scheduler} [scheduler] Scheduler to run the generator loop on. If not specified, defaults to Scheduler.currentThread.
  	  * @returns {Observable} An observable sequence that contains a range of sequential integral numbers.
  	  */
  	  Observable.range = function (start, count, scheduler) {
  	    isScheduler(scheduler) || (scheduler = currentThreadScheduler);
  	    return new RangeObservable(start, count, scheduler);
  	  };
  	
  	  var RepeatObservable = (function(__super__) {
  	    inherits(RepeatObservable, __super__);
  	    function RepeatObservable(value, repeatCount, scheduler) {
  	      this.value = value;
  	      this.repeatCount = repeatCount == null ? -1 : repeatCount;
  	      this.scheduler = scheduler;
  	      __super__.call(this);
  	    }
  	
  	    RepeatObservable.prototype.subscribeCore = function (observer) {
  	      var sink = new RepeatSink(observer, this);
  	      return sink.run();
  	    };
  	
  	    return RepeatObservable;
  	  }(ObservableBase));
  	
  	  function RepeatSink(observer, parent) {
  	    this.observer = observer;
  	    this.parent = parent;
  	  }
  	
  	  RepeatSink.prototype.run = function () {
  	    var observer = this.observer, value = this.parent.value;
  	    function loopRecursive(i, recurse) {
  	      if (i === -1 || i > 0) {
  	        observer.onNext(value);
  	        i > 0 && i--;
  	      }
  	      if (i === 0) { return observer.onCompleted(); }
  	      recurse(i);
  	    }
  	
  	    return this.parent.scheduler.scheduleRecursiveWithState(this.parent.repeatCount, loopRecursive);
  	  };
  	
  	  /**
  	   *  Generates an observable sequence that repeats the given element the specified number of times, using the specified scheduler to send out observer messages.
  	   * @param {Mixed} value Element to repeat.
  	   * @param {Number} repeatCount [Optiona] Number of times to repeat the element. If not specified, repeats indefinitely.
  	   * @param {Scheduler} scheduler Scheduler to run the producer loop on. If not specified, defaults to Scheduler.immediate.
  	   * @returns {Observable} An observable sequence that repeats the given element the specified number of times.
  	   */
  	  Observable.repeat = function (value, repeatCount, scheduler) {
  	    isScheduler(scheduler) || (scheduler = currentThreadScheduler);
  	    return new RepeatObservable(value, repeatCount, scheduler);
  	  };
  	
  	  var JustObservable = (function(__super__) {
  	    inherits(JustObservable, __super__);
  	    function JustObservable(value, scheduler) {
  	      this.value = value;
  	      this.scheduler = scheduler;
  	      __super__.call(this);
  	    }
  	
  	    JustObservable.prototype.subscribeCore = function (observer) {
  	      var sink = new JustSink(observer, this);
  	      return sink.run();
  	    };
  	
  	    function JustSink(observer, parent) {
  	      this.observer = observer;
  	      this.parent = parent;
  	    }
  	
  	    function scheduleItem(s, state) {
  	      var value = state[0], observer = state[1];
  	      observer.onNext(value);
  	      observer.onCompleted();
  	    }
  	
  	    JustSink.prototype.run = function () {
  	      return this.parent.scheduler.scheduleWithState([this.parent.value, this.observer], scheduleItem);
  	    };
  	
  	    return JustObservable;
  	  }(ObservableBase));
  	
  	  /**
  	   *  Returns an observable sequence that contains a single element, using the specified scheduler to send out observer messages.
  	   *  There is an alias called 'just' or browsers <IE9.
  	   * @param {Mixed} value Single element in the resulting observable sequence.
  	   * @param {Scheduler} scheduler Scheduler to send the single element on. If not specified, defaults to Scheduler.immediate.
  	   * @returns {Observable} An observable sequence containing the single specified element.
  	   */
  	  var observableReturn = Observable['return'] = Observable.just = Observable.returnValue = function (value, scheduler) {
  	    isScheduler(scheduler) || (scheduler = immediateScheduler);
  	    return new JustObservable(value, scheduler);
  	  };
  	
  	  var ThrowObservable = (function(__super__) {
  	    inherits(ThrowObservable, __super__);
  	    function ThrowObservable(error, scheduler) {
  	      this.error = error;
  	      this.scheduler = scheduler;
  	      __super__.call(this);
  	    }
  	
  	    ThrowObservable.prototype.subscribeCore = function (o) {
  	      var sink = new ThrowSink(o, this);
  	      return sink.run();
  	    };
  	
  	    function ThrowSink(o, p) {
  	      this.o = o;
  	      this.p = p;
  	    }
  	
  	    function scheduleItem(s, state) {
  	      var e = state[0], o = state[1];
  	      o.onError(e);
  	    }
  	
  	    ThrowSink.prototype.run = function () {
  	      return this.p.scheduler.scheduleWithState([this.p.error, this.o], scheduleItem);
  	    };
  	
  	    return ThrowObservable;
  	  }(ObservableBase));
  	
  	  /**
  	   *  Returns an observable sequence that terminates with an exception, using the specified scheduler to send out the single onError message.
  	   *  There is an alias to this method called 'throwError' for browsers <IE9.
  	   * @param {Mixed} error An object used for the sequence's termination.
  	   * @param {Scheduler} scheduler Scheduler to send the exceptional termination call on. If not specified, defaults to Scheduler.immediate.
  	   * @returns {Observable} The observable sequence that terminates exceptionally with the specified exception object.
  	   */
  	  var observableThrow = Observable['throw'] = Observable.throwError = Observable.throwException = function (error, scheduler) {
  	    isScheduler(scheduler) || (scheduler = immediateScheduler);
  	    return new ThrowObservable(error, scheduler);
  	  };
  	
  	  /**
  	   * Constructs an observable sequence that depends on a resource object, whose lifetime is tied to the resulting observable sequence's lifetime.
  	   * @param {Function} resourceFactory Factory function to obtain a resource object.
  	   * @param {Function} observableFactory Factory function to obtain an observable sequence that depends on the obtained resource.
  	   * @returns {Observable} An observable sequence whose lifetime controls the lifetime of the dependent resource object.
  	   */
  	  Observable.using = function (resourceFactory, observableFactory) {
  	    return new AnonymousObservable(function (observer) {
  	      var disposable = disposableEmpty, resource, source;
  	      try {
  	        resource = resourceFactory();
  	        resource && (disposable = resource);
  	        source = observableFactory(resource);
  	      } catch (exception) {
  	        return new CompositeDisposable(observableThrow(exception).subscribe(observer), disposable);
  	      }
  	      return new CompositeDisposable(source.subscribe(observer), disposable);
  	    });
  	  };
  	
  	  /**
  	   * Propagates the observable sequence or Promise that reacts first.
  	   * @param {Observable} rightSource Second observable sequence or Promise.
  	   * @returns {Observable} {Observable} An observable sequence that surfaces either of the given sequences, whichever reacted first.
  	   */
  	  observableProto.amb = function (rightSource) {
  	    var leftSource = this;
  	    return new AnonymousObservable(function (observer) {
  	      var choice,
  	        leftChoice = 'L', rightChoice = 'R',
  	        leftSubscription = new SingleAssignmentDisposable(),
  	        rightSubscription = new SingleAssignmentDisposable();
  	
  	      isPromise(rightSource) && (rightSource = observableFromPromise(rightSource));
  	
  	      function choiceL() {
  	        if (!choice) {
  	          choice = leftChoice;
  	          rightSubscription.dispose();
  	        }
  	      }
  	
  	      function choiceR() {
  	        if (!choice) {
  	          choice = rightChoice;
  	          leftSubscription.dispose();
  	        }
  	      }
  	
  	      leftSubscription.setDisposable(leftSource.subscribe(function (left) {
  	        choiceL();
  	        choice === leftChoice && observer.onNext(left);
  	      }, function (err) {
  	        choiceL();
  	        choice === leftChoice && observer.onError(err);
  	      }, function () {
  	        choiceL();
  	        choice === leftChoice && observer.onCompleted();
  	      }));
  	
  	      rightSubscription.setDisposable(rightSource.subscribe(function (right) {
  	        choiceR();
  	        choice === rightChoice && observer.onNext(right);
  	      }, function (err) {
  	        choiceR();
  	        choice === rightChoice && observer.onError(err);
  	      }, function () {
  	        choiceR();
  	        choice === rightChoice && observer.onCompleted();
  	      }));
  	
  	      return new CompositeDisposable(leftSubscription, rightSubscription);
  	    });
  	  };
  	
  	  /**
  	   * Propagates the observable sequence or Promise that reacts first.
  	   *
  	   * @example
  	   * var = Rx.Observable.amb(xs, ys, zs);
  	   * @returns {Observable} An observable sequence that surfaces any of the given sequences, whichever reacted first.
  	   */
  	  Observable.amb = function () {
  	    var acc = observableNever(), items = [];
  	    if (Array.isArray(arguments[0])) {
  	      items = arguments[0];
  	    } else {
  	      for(var i = 0, len = arguments.length; i < len; i++) { items.push(arguments[i]); }
  	    }
  	
  	    function func(previous, current) {
  	      return previous.amb(current);
  	    }
  	    for (var i = 0, len = items.length; i < len; i++) {
  	      acc = func(acc, items[i]);
  	    }
  	    return acc;
  	  };
  	
  	  function observableCatchHandler(source, handler) {
  	    return new AnonymousObservable(function (o) {
  	      var d1 = new SingleAssignmentDisposable(), subscription = new SerialDisposable();
  	      subscription.setDisposable(d1);
  	      d1.setDisposable(source.subscribe(function (x) { o.onNext(x); }, function (e) {
  	        try {
  	          var result = handler(e);
  	        } catch (ex) {
  	          return o.onError(ex);
  	        }
  	        isPromise(result) && (result = observableFromPromise(result));
  	
  	        var d = new SingleAssignmentDisposable();
  	        subscription.setDisposable(d);
  	        d.setDisposable(result.subscribe(o));
  	      }, function (x) { o.onCompleted(x); }));
  	
  	      return subscription;
  	    }, source);
  	  }
  	
  	  /**
  	   * Continues an observable sequence that is terminated by an exception with the next observable sequence.
  	   * @example
  	   * 1 - xs.catchException(ys)
  	   * 2 - xs.catchException(function (ex) { return ys(ex); })
  	   * @param {Mixed} handlerOrSecond Exception handler function that returns an observable sequence given the error that occurred in the first sequence, or a second observable sequence used to produce results when an error occurred in the first sequence.
  	   * @returns {Observable} An observable sequence containing the first sequence's elements, followed by the elements of the handler sequence in case an exception occurred.
  	   */
  	  observableProto['catch'] = observableProto.catchError = observableProto.catchException = function (handlerOrSecond) {
  	    return typeof handlerOrSecond === 'function' ?
  	      observableCatchHandler(this, handlerOrSecond) :
  	      observableCatch([this, handlerOrSecond]);
  	  };
  	
  	  /**
  	   * Continues an observable sequence that is terminated by an exception with the next observable sequence.
  	   * @param {Array | Arguments} args Arguments or an array to use as the next sequence if an error occurs.
  	   * @returns {Observable} An observable sequence containing elements from consecutive source sequences until a source sequence terminates successfully.
  	   */
  	  var observableCatch = Observable.catchError = Observable['catch'] = Observable.catchException = function () {
  	    var items = [];
  	    if (Array.isArray(arguments[0])) {
  	      items = arguments[0];
  	    } else {
  	      for(var i = 0, len = arguments.length; i < len; i++) { items.push(arguments[i]); }
  	    }
  	    return enumerableOf(items).catchError();
  	  };
  	
  	  /**
  	   * Merges the specified observable sequences into one observable sequence by using the selector function whenever any of the observable sequences or Promises produces an element.
  	   * This can be in the form of an argument list of observables or an array.
  	   *
  	   * @example
  	   * 1 - obs = observable.combineLatest(obs1, obs2, obs3, function (o1, o2, o3) { return o1 + o2 + o3; });
  	   * 2 - obs = observable.combineLatest([obs1, obs2, obs3], function (o1, o2, o3) { return o1 + o2 + o3; });
  	   * @returns {Observable} An observable sequence containing the result of combining elements of the sources using the specified result selector function.
  	   */
  	  observableProto.combineLatest = function () {
  	    var len = arguments.length, args = new Array(len);
  	    for(var i = 0; i < len; i++) { args[i] = arguments[i]; }
  	    if (Array.isArray(args[0])) {
  	      args[0].unshift(this);
  	    } else {
  	      args.unshift(this);
  	    }
  	    return combineLatest.apply(this, args);
  	  };
  	
  	  /**
  	   * Merges the specified observable sequences into one observable sequence by using the selector function whenever any of the observable sequences or Promises produces an element.
  	   *
  	   * @example
  	   * 1 - obs = Rx.Observable.combineLatest(obs1, obs2, obs3, function (o1, o2, o3) { return o1 + o2 + o3; });
  	   * 2 - obs = Rx.Observable.combineLatest([obs1, obs2, obs3], function (o1, o2, o3) { return o1 + o2 + o3; });
  	   * @returns {Observable} An observable sequence containing the result of combining elements of the sources using the specified result selector function.
  	   */
  	  var combineLatest = Observable.combineLatest = function () {
  	    var len = arguments.length, args = new Array(len);
  	    for(var i = 0; i < len; i++) { args[i] = arguments[i]; }
  	    var resultSelector = args.pop();
  	    Array.isArray(args[0]) && (args = args[0]);
  	
  	    return new AnonymousObservable(function (o) {
  	      var n = args.length,
  	        falseFactory = function () { return false; },
  	        hasValue = arrayInitialize(n, falseFactory),
  	        hasValueAll = false,
  	        isDone = arrayInitialize(n, falseFactory),
  	        values = new Array(n);
  	
  	      function next(i) {
  	        hasValue[i] = true;
  	        if (hasValueAll || (hasValueAll = hasValue.every(identity))) {
  	          try {
  	            var res = resultSelector.apply(null, values);
  	          } catch (e) {
  	            return o.onError(e);
  	          }
  	          o.onNext(res);
  	        } else if (isDone.filter(function (x, j) { return j !== i; }).every(identity)) {
  	          o.onCompleted();
  	        }
  	      }
  	
  	      function done (i) {
  	        isDone[i] = true;
  	        isDone.every(identity) && o.onCompleted();
  	      }
  	
  	      var subscriptions = new Array(n);
  	      for (var idx = 0; idx < n; idx++) {
  	        (function (i) {
  	          var source = args[i], sad = new SingleAssignmentDisposable();
  	          isPromise(source) && (source = observableFromPromise(source));
  	          sad.setDisposable(source.subscribe(function (x) {
  	              values[i] = x;
  	              next(i);
  	            },
  	            function(e) { o.onError(e); },
  	            function () { done(i); }
  	          ));
  	          subscriptions[i] = sad;
  	        }(idx));
  	      }
  	
  	      return new CompositeDisposable(subscriptions);
  	    }, this);
  	  };
  	
  	  /**
  	   * Concatenates all the observable sequences.  This takes in either an array or variable arguments to concatenate.
  	   * @returns {Observable} An observable sequence that contains the elements of each given sequence, in sequential order.
  	   */
  	  observableProto.concat = function () {
  	    for(var args = [], i = 0, len = arguments.length; i < len; i++) { args.push(arguments[i]); }
  	    args.unshift(this);
  	    return observableConcat.apply(null, args);
  	  };
  	
  		var ConcatObservable = (function(__super__) {
  			inherits(ConcatObservable, __super__);
  			function ConcatObservable(sources) {
  				this.sources = sources;
  				__super__.call(this);
  			}
  			
  			ConcatObservable.prototype.subscribeCore = function(o) {
  	      var sink = new ConcatSink(this.sources, o);
  	      return sink.run();
  			};
  	    
  	    function ConcatSink(sources, o) {
  	      this.sources = sources;
  	      this.o = o;
  	    }
  	    ConcatSink.prototype.run = function () {
  	      var isDisposed, subscription = new SerialDisposable(), sources = this.sources, length = sources.length, o = this.o;
  	      var cancelable = immediateScheduler.scheduleRecursiveWithState(0, function (i, self) {
  	        if (isDisposed) { return; }
  	        if (i === length) {
  						return o.onCompleted();
  					}
  		
  	        // Check if promise
  	        var currentValue = sources[i];
  	        isPromise(currentValue) && (currentValue = observableFromPromise(currentValue));
  	
  	        var d = new SingleAssignmentDisposable();
  	        subscription.setDisposable(d);
  	        d.setDisposable(currentValue.subscribe(
  	          function (x) { o.onNext(x); },
  	          function (e) { o.onError(e); },
  	          function () { self(i + 1); }
  	        ));
  	      });
  	
  	      return new CompositeDisposable(subscription, cancelable, disposableCreate(function () {
  	        isDisposed = true;
  	      }));
  	    };
  	    
  			
  			return ConcatObservable;
  		}(ObservableBase));
  	  
  	  /**
  	   * Concatenates all the observable sequences.
  	   * @param {Array | Arguments} args Arguments or an array to concat to the observable sequence.
  	   * @returns {Observable} An observable sequence that contains the elements of each given sequence, in sequential order.
  	   */
  	  var observableConcat = Observable.concat = function () {
  	    var args;
  	    if (Array.isArray(arguments[0])) {
  	      args = arguments[0];
  	    } else {
  	      args = new Array(arguments.length);
  	      for(var i = 0, len = arguments.length; i < len; i++) { args[i] = arguments[i]; }
  	    }
  	    return new ConcatObservable(args);
  	  };
  	
  	  /**
  	   * Concatenates an observable sequence of observable sequences.
  	   * @returns {Observable} An observable sequence that contains the elements of each observed inner sequence, in sequential order.
  	   */
  	  observableProto.concatAll = observableProto.concatObservable = function () {
  	    return this.merge(1);
  	  };
  	
  	  var MergeObservable = (function (__super__) {
  	    inherits(MergeObservable, __super__);
  	
  	    function MergeObservable(source, maxConcurrent) {
  	      this.source = source;
  	      this.maxConcurrent = maxConcurrent;
  	      __super__.call(this);
  	    }
  	
  	    MergeObservable.prototype.subscribeCore = function(observer) {
  	      var g = new CompositeDisposable();
  	      g.add(this.source.subscribe(new MergeObserver(observer, this.maxConcurrent, g)));
  	      return g;
  	    };
  	
  	    return MergeObservable;
  	
  	  }(ObservableBase));
  	
  	  var MergeObserver = (function () {
  	    function MergeObserver(o, max, g) {
  	      this.o = o;
  	      this.max = max;
  	      this.g = g;
  	      this.done = false;
  	      this.q = [];
  	      this.activeCount = 0;
  	      this.isStopped = false;
  	    }
  	    MergeObserver.prototype.handleSubscribe = function (xs) {
  	      var sad = new SingleAssignmentDisposable();
  	      this.g.add(sad);
  	      isPromise(xs) && (xs = observableFromPromise(xs));
  	      sad.setDisposable(xs.subscribe(new InnerObserver(this, sad)));
  	    };
  	    MergeObserver.prototype.onNext = function (innerSource) {
  	      if (this.isStopped) { return; }
  	        if(this.activeCount < this.max) {
  	          this.activeCount++;
  	          this.handleSubscribe(innerSource);
  	        } else {
  	          this.q.push(innerSource);
  	        }
  	      };
  	      MergeObserver.prototype.onError = function (e) {
  	        if (!this.isStopped) {
  	          this.isStopped = true;
  	          this.o.onError(e);
  	        }
  	      };
  	      MergeObserver.prototype.onCompleted = function () {
  	        if (!this.isStopped) {
  	          this.isStopped = true;
  	          this.done = true;
  	          this.activeCount === 0 && this.o.onCompleted();
  	        }
  	      };
  	      MergeObserver.prototype.dispose = function() { this.isStopped = true; };
  	      MergeObserver.prototype.fail = function (e) {
  	        if (!this.isStopped) {
  	          this.isStopped = true;
  	          this.o.onError(e);
  	          return true;
  	        }
  	
  	        return false;
  	      };
  	
  	      function InnerObserver(parent, sad) {
  	        this.parent = parent;
  	        this.sad = sad;
  	        this.isStopped = false;
  	      }
  	      InnerObserver.prototype.onNext = function (x) { if(!this.isStopped) { this.parent.o.onNext(x); } };
  	      InnerObserver.prototype.onError = function (e) {
  	        if (!this.isStopped) {
  	          this.isStopped = true;
  	          this.parent.o.onError(e);
  	        }
  	      };
  	      InnerObserver.prototype.onCompleted = function () {
  	        if(!this.isStopped) {
  	          this.isStopped = true;
  	          var parent = this.parent;
  	          parent.g.remove(this.sad);
  	          if (parent.q.length > 0) {
  	            parent.handleSubscribe(parent.q.shift());
  	          } else {
  	            parent.activeCount--;
  	            parent.done && parent.activeCount === 0 && parent.o.onCompleted();
  	          }
  	        }
  	      };
  	      InnerObserver.prototype.dispose = function() { this.isStopped = true; };
  	      InnerObserver.prototype.fail = function (e) {
  	        if (!this.isStopped) {
  	          this.isStopped = true;
  	          this.parent.o.onError(e);
  	          return true;
  	        }
  	
  	        return false;
  	      };
  	
  	      return MergeObserver;
  	  }());
  	
  	
  	
  	
  	
  	  /**
  	  * Merges an observable sequence of observable sequences into an observable sequence, limiting the number of concurrent subscriptions to inner sequences.
  	  * Or merges two observable sequences into a single observable sequence.
  	  *
  	  * @example
  	  * 1 - merged = sources.merge(1);
  	  * 2 - merged = source.merge(otherSource);
  	  * @param {Mixed} [maxConcurrentOrOther] Maximum number of inner observable sequences being subscribed to concurrently or the second observable sequence.
  	  * @returns {Observable} The observable sequence that merges the elements of the inner sequences.
  	  */
  	  observableProto.merge = function (maxConcurrentOrOther) {
  	    return typeof maxConcurrentOrOther !== 'number' ?
  	      observableMerge(this, maxConcurrentOrOther) :
  	      new MergeObservable(this, maxConcurrentOrOther);
  	  };
  	
  	  /**
  	   * Merges all the observable sequences into a single observable sequence.
  	   * The scheduler is optional and if not specified, the immediate scheduler is used.
  	   * @returns {Observable} The observable sequence that merges the elements of the observable sequences.
  	   */
  	  var observableMerge = Observable.merge = function () {
  	    var scheduler, sources = [], i, len = arguments.length;
  	    if (!arguments[0]) {
  	      scheduler = immediateScheduler;
  	      for(i = 1; i < len; i++) { sources.push(arguments[i]); }
  	    } else if (isScheduler(arguments[0])) {
  	      scheduler = arguments[0];
  	      for(i = 1; i < len; i++) { sources.push(arguments[i]); }
  	    } else {
  	      scheduler = immediateScheduler;
  	      for(i = 0; i < len; i++) { sources.push(arguments[i]); }
  	    }
  	    if (Array.isArray(sources[0])) {
  	      sources = sources[0];
  	    }
  	    return observableOf(scheduler, sources).mergeAll();
  	  };
  	
  	  var MergeAllObservable = (function (__super__) {
  	    inherits(MergeAllObservable, __super__);
  	
  	    function MergeAllObservable(source) {
  	      this.source = source;
  	      __super__.call(this);
  	    }
  	
  	    MergeAllObservable.prototype.subscribeCore = function (observer) {
  	      var g = new CompositeDisposable(), m = new SingleAssignmentDisposable();
  	      g.add(m);
  	      m.setDisposable(this.source.subscribe(new MergeAllObserver(observer, g)));
  	      return g;
  	    };
  	    
  	    function MergeAllObserver(o, g) {
  	      this.o = o;
  	      this.g = g;
  	      this.isStopped = false;
  	      this.done = false;
  	    }
  	    MergeAllObserver.prototype.onNext = function(innerSource) {
  	      if(this.isStopped) { return; }
  	      var sad = new SingleAssignmentDisposable();
  	      this.g.add(sad);
  	
  	      isPromise(innerSource) && (innerSource = observableFromPromise(innerSource));
  	
  	      sad.setDisposable(innerSource.subscribe(new InnerObserver(this, this.g, sad)));
  	    };
  	    MergeAllObserver.prototype.onError = function (e) {
  	      if(!this.isStopped) {
  	        this.isStopped = true;
  	        this.o.onError(e);
  	      }
  	    };
  	    MergeAllObserver.prototype.onCompleted = function () {
  	      if(!this.isStopped) {
  	        this.isStopped = true;
  	        this.done = true;
  	        this.g.length === 1 && this.o.onCompleted();
  	      }
  	    };
  	    MergeAllObserver.prototype.dispose = function() { this.isStopped = true; };
  	    MergeAllObserver.prototype.fail = function (e) {
  	      if (!this.isStopped) {
  	        this.isStopped = true;
  	        this.o.onError(e);
  	        return true;
  	      }
  	
  	      return false;
  	    };
  	
  	    function InnerObserver(parent, g, sad) {
  	      this.parent = parent;
  	      this.g = g;
  	      this.sad = sad;
  	      this.isStopped = false;
  	    }
  	    InnerObserver.prototype.onNext = function (x) { if (!this.isStopped) { this.parent.o.onNext(x); } };
  	    InnerObserver.prototype.onError = function (e) {
  	      if(!this.isStopped) {
  	        this.isStopped = true;
  	        this.parent.o.onError(e);
  	      }
  	    };
  	    InnerObserver.prototype.onCompleted = function () {
  	      if(!this.isStopped) {
  	        var parent = this.parent;
  	        this.isStopped = true;
  	        parent.g.remove(this.sad);
  	        parent.done && parent.g.length === 1 && parent.o.onCompleted();
  	      }
  	    };
  	    InnerObserver.prototype.dispose = function() { this.isStopped = true; };
  	    InnerObserver.prototype.fail = function (e) {
  	      if (!this.isStopped) {
  	        this.isStopped = true;
  	        this.parent.o.onError(e);
  	        return true;
  	      }
  	
  	      return false;
  	    };
  	
  	    return MergeAllObservable;
  	  }(ObservableBase));
  	
  	  /**
  	  * Merges an observable sequence of observable sequences into an observable sequence.
  	  * @returns {Observable} The observable sequence that merges the elements of the inner sequences.
  	  */
  	  observableProto.mergeAll = observableProto.mergeObservable = function () {
  	    return new MergeAllObservable(this);
  	  };
  	
  	  var CompositeError = Rx.CompositeError = function(errors) {
  	    this.name = "NotImplementedError";
  	    this.innerErrors = errors;
  	    this.message = 'This contains multiple errors. Check the innerErrors';
  	    Error.call(this);
  	  }
  	  CompositeError.prototype = Error.prototype;
  	
  	  /**
  	  * Flattens an Observable that emits Observables into one Observable, in a way that allows an Observer to
  	  * receive all successfully emitted items from all of the source Observables without being interrupted by
  	  * an error notification from one of them.
  	  *
  	  * This behaves like Observable.prototype.mergeAll except that if any of the merged Observables notify of an
  	  * error via the Observer's onError, mergeDelayError will refrain from propagating that
  	  * error notification until all of the merged Observables have finished emitting items.
  	  * @param {Array | Arguments} args Arguments or an array to merge.
  	  * @returns {Observable} an Observable that emits all of the items emitted by the Observables emitted by the Observable
  	  */
  	  Observable.mergeDelayError = function() {
  	    var args;
  	    if (Array.isArray(arguments[0])) {
  	      args = arguments[0];
  	    } else {
  	      var len = arguments.length;
  	      args = new Array(len);
  	      for(var i = 0; i < len; i++) { args[i] = arguments[i]; }
  	    }
  	    var source = observableOf(null, args);
  	
  	    return new AnonymousObservable(function (o) {
  	      var group = new CompositeDisposable(),
  	        m = new SingleAssignmentDisposable(),
  	        isStopped = false,
  	        errors = [];
  	
  	      function setCompletion() {
  	        if (errors.length === 0) {
  	          o.onCompleted();
  	        } else if (errors.length === 1) {
  	          o.onError(errors[0]);
  	        } else {
  	          o.onError(new CompositeError(errors));
  	        }
  	      }
  	
  	      group.add(m);
  	
  	      m.setDisposable(source.subscribe(
  	        function (innerSource) {
  	          var innerSubscription = new SingleAssignmentDisposable();
  	          group.add(innerSubscription);
  	
  	          // Check for promises support
  	          isPromise(innerSource) && (innerSource = observableFromPromise(innerSource));
  	
  	          innerSubscription.setDisposable(innerSource.subscribe(
  	            function (x) { o.onNext(x); },
  	            function (e) {
  	              errors.push(e);
  	              group.remove(innerSubscription);
  	              isStopped && group.length === 1 && setCompletion();
  	            },
  	            function () {
  	              group.remove(innerSubscription);
  	              isStopped && group.length === 1 && setCompletion();
  	          }));
  	        },
  	        function (e) {
  	          errors.push(e);
  	          isStopped = true;
  	          group.length === 1 && setCompletion();
  	        },
  	        function () {
  	          isStopped = true;
  	          group.length === 1 && setCompletion();
  	        }));
  	      return group;
  	    });
  	  };
  	
  	  /**
  	   * Continues an observable sequence that is terminated normally or by an exception with the next observable sequence.
  	   * @param {Observable} second Second observable sequence used to produce results after the first sequence terminates.
  	   * @returns {Observable} An observable sequence that concatenates the first and second sequence, even if the first sequence terminates exceptionally.
  	   */
  	  observableProto.onErrorResumeNext = function (second) {
  	    if (!second) { throw new Error('Second observable is required'); }
  	    return onErrorResumeNext([this, second]);
  	  };
  	
  	  /**
  	   * Continues an observable sequence that is terminated normally or by an exception with the next observable sequence.
  	   *
  	   * @example
  	   * 1 - res = Rx.Observable.onErrorResumeNext(xs, ys, zs);
  	   * 1 - res = Rx.Observable.onErrorResumeNext([xs, ys, zs]);
  	   * @returns {Observable} An observable sequence that concatenates the source sequences, even if a sequence terminates exceptionally.
  	   */
  	  var onErrorResumeNext = Observable.onErrorResumeNext = function () {
  	    var sources = [];
  	    if (Array.isArray(arguments[0])) {
  	      sources = arguments[0];
  	    } else {
  	      for(var i = 0, len = arguments.length; i < len; i++) { sources.push(arguments[i]); }
  	    }
  	    return new AnonymousObservable(function (observer) {
  	      var pos = 0, subscription = new SerialDisposable(),
  	      cancelable = immediateScheduler.scheduleRecursive(function (self) {
  	        var current, d;
  	        if (pos < sources.length) {
  	          current = sources[pos++];
  	          isPromise(current) && (current = observableFromPromise(current));
  	          d = new SingleAssignmentDisposable();
  	          subscription.setDisposable(d);
  	          d.setDisposable(current.subscribe(observer.onNext.bind(observer), self, self));
  	        } else {
  	          observer.onCompleted();
  	        }
  	      });
  	      return new CompositeDisposable(subscription, cancelable);
  	    });
  	  };
  	
  	  /**
  	   * Returns the values from the source observable sequence only after the other observable sequence produces a value.
  	   * @param {Observable | Promise} other The observable sequence or Promise that triggers propagation of elements of the source sequence.
  	   * @returns {Observable} An observable sequence containing the elements of the source sequence starting from the point the other sequence triggered propagation.
  	   */
  	  observableProto.skipUntil = function (other) {
  	    var source = this;
  	    return new AnonymousObservable(function (o) {
  	      var isOpen = false;
  	      var disposables = new CompositeDisposable(source.subscribe(function (left) {
  	        isOpen && o.onNext(left);
  	      }, function (e) { o.onError(e); }, function () {
  	        isOpen && o.onCompleted();
  	      }));
  	
  	      isPromise(other) && (other = observableFromPromise(other));
  	
  	      var rightSubscription = new SingleAssignmentDisposable();
  	      disposables.add(rightSubscription);
  	      rightSubscription.setDisposable(other.subscribe(function () {
  	        isOpen = true;
  	        rightSubscription.dispose();
  	      }, function (e) { o.onError(e); }, function () {
  	        rightSubscription.dispose();
  	      }));
  	
  	      return disposables;
  	    }, source);
  	  };
  	
  	  var SwitchObservable = (function(__super__) {
  	    inherits(SwitchObservable, __super__);
  	    function SwitchObservable(source) {
  	      this.source = source;
  	      __super__.call(this);
  	    }
  	
  	    SwitchObservable.prototype.subscribeCore = function (o) {
  	      var inner = new SerialDisposable(), s = this.source.subscribe(new SwitchObserver(o, inner));
  	      return new CompositeDisposable(s, inner);
  	    };
  	
  	    function SwitchObserver(o, inner) {
  	      this.o = o;
  	      this.inner = inner;
  	      this.stopped = false;
  	      this.latest = 0;
  	      this.hasLatest = false;
  	      this.isStopped = false;
  	    }
  	    SwitchObserver.prototype.onNext = function (innerSource) {
  	      if (this.isStopped) { return; }
  	      var d = new SingleAssignmentDisposable(), id = ++this.latest;
  	      this.hasLatest = true;
  	      this.inner.setDisposable(d);
  	      isPromise(innerSource) && (innerSource = observableFromPromise(innerSource));
  	      d.setDisposable(innerSource.subscribe(new InnerObserver(this, id)));
  	    };
  	    SwitchObserver.prototype.onError = function (e) {
  	      if (!this.isStopped) {
  	        this.isStopped = true;
  	        this.o.onError(e);
  	      }
  	    };
  	    SwitchObserver.prototype.onCompleted = function () {
  	      if (!this.isStopped) {
  	        this.isStopped = true;
  	        this.stopped = true;
  	        !this.hasLatest && this.o.onCompleted();
  	      }
  	    };
  	    SwitchObserver.prototype.dispose = function () { this.isStopped = true; };
  	    SwitchObserver.prototype.fail = function (e) {
  	      if(!this.isStopped) {
  	        this.isStopped = true;
  	        this.o.onError(e);
  	        return true;
  	      }
  	      return false;
  	    };
  	
  	    function InnerObserver(parent, id) {
  	      this.parent = parent;
  	      this.id = id;
  	      this.isStopped = false;
  	    }
  	    InnerObserver.prototype.onNext = function (x) {
  	      if (this.isStopped) { return; }
  	      this.parent.latest === this.id && this.parent.o.onNext(x);
  	    };
  	    InnerObserver.prototype.onError = function (e) {
  	      if (!this.isStopped) {
  	        this.isStopped = true;
  	        this.parent.latest === this.id && this.parent.o.onError(e);
  	      }
  	    };
  	    InnerObserver.prototype.onCompleted = function () {
  	      if (!this.isStopped) {
  	        this.isStopped = true;
  	        if (this.parent.latest === this.id) {
  	          this.parent.hasLatest = false;
  	          this.parent.isStopped && this.parent.o.onCompleted();
  	        }
  	      }
  	    };
  	    InnerObserver.prototype.dispose = function () { this.isStopped = true; }
  	    InnerObserver.prototype.fail = function (e) {
  	      if(!this.isStopped) {
  	        this.isStopped = true;
  	        this.parent.o.onError(e);
  	        return true;
  	      }
  	      return false;
  	    };
  	
  	    return SwitchObservable;
  	  }(ObservableBase));
  	
  	  /**
  	  * Transforms an observable sequence of observable sequences into an observable sequence producing values only from the most recent observable sequence.
  	  * @returns {Observable} The observable sequence that at any point in time produces the elements of the most recent inner observable sequence that has been received.
  	  */
  	  observableProto['switch'] = observableProto.switchLatest = function () {
  	    return new SwitchObservable(this);
  	  };
  	
  	  var TakeUntilObservable = (function(__super__) {
  	    inherits(TakeUntilObservable, __super__);
  	
  	    function TakeUntilObservable(source, other) {
  	      this.source = source;
  	      this.other = isPromise(other) ? observableFromPromise(other) : other;
  	      __super__.call(this);
  	    }
  	
  	    TakeUntilObservable.prototype.subscribeCore = function(o) {
  	      return new CompositeDisposable(
  	        this.source.subscribe(o),
  	        this.other.subscribe(new InnerObserver(o))
  	      );
  	    };
  	
  	    function InnerObserver(o) {
  	      this.o = o;
  	      this.isStopped = false;
  	    }
  	    InnerObserver.prototype.onNext = function (x) {
  	      if (this.isStopped) { return; }
  	      this.o.onCompleted();
  	    };
  	    InnerObserver.prototype.onError = function (err) {
  	      if (!this.isStopped) {
  	        this.isStopped = true;
  	        this.o.onError(err);
  	      }
  	    };
  	    InnerObserver.prototype.onCompleted = function () {
  	      !this.isStopped && (this.isStopped = true);
  	    };
  	    InnerObserver.prototype.dispose = function() { this.isStopped = true; };
  	    InnerObserver.prototype.fail = function (e) {
  	      if (!this.isStopped) {
  	        this.isStopped = true;
  	        this.o.onError(e);
  	        return true;
  	      }
  	      return false;
  	    };
  	
  	    return TakeUntilObservable;
  	  }(ObservableBase));
  	
  	  /**
  	   * Returns the values from the source observable sequence until the other observable sequence produces a value.
  	   * @param {Observable | Promise} other Observable sequence or Promise that terminates propagation of elements of the source sequence.
  	   * @returns {Observable} An observable sequence containing the elements of the source sequence up to the point the other sequence interrupted further propagation.
  	   */
  	  observableProto.takeUntil = function (other) {
  	    return new TakeUntilObservable(this, other);
  	  };
  	
  	  function falseFactory() { return false; }
  	
  	  /**
  	   * Merges the specified observable sequences into one observable sequence by using the selector function only when the (first) source observable sequence produces an element.
  	   * @returns {Observable} An observable sequence containing the result of combining elements of the sources using the specified result selector function.
  	   */
  	  observableProto.withLatestFrom = function () {
  	    var len = arguments.length, args = new Array(len)
  	    for(var i = 0; i < len; i++) { args[i] = arguments[i]; }
  	    var resultSelector = args.pop(), source = this;
  	    Array.isArray(args[0]) && (args = args[0]);
  	
  	    return new AnonymousObservable(function (observer) {
  	      var n = args.length,
  	        hasValue = arrayInitialize(n, falseFactory),
  	        hasValueAll = false,
  	        values = new Array(n);
  	
  	      var subscriptions = new Array(n + 1);
  	      for (var idx = 0; idx < n; idx++) {
  	        (function (i) {
  	          var other = args[i], sad = new SingleAssignmentDisposable();
  	          isPromise(other) && (other = observableFromPromise(other));
  	          sad.setDisposable(other.subscribe(function (x) {
  	            values[i] = x;
  	            hasValue[i] = true;
  	            hasValueAll = hasValue.every(identity);
  	          }, function (e) { observer.onError(e); }, noop));
  	          subscriptions[i] = sad;
  	        }(idx));
  	      }
  	
  	      var sad = new SingleAssignmentDisposable();
  	      sad.setDisposable(source.subscribe(function (x) {
  	        var allValues = [x].concat(values);
  	        if (!hasValueAll) { return; }
  	        var res = tryCatch(resultSelector).apply(null, allValues);
  	        if (res === errorObj) { return observer.onError(res.e); }
  	        observer.onNext(res);
  	      }, function (e) { observer.onError(e); }, function () {
  	        observer.onCompleted();
  	      }));
  	      subscriptions[n] = sad;
  	
  	      return new CompositeDisposable(subscriptions);
  	    }, this);
  	  };
  	
  	  function zipArray(second, resultSelector) {
  	    var first = this;
  	    return new AnonymousObservable(function (o) {
  	      var index = 0, len = second.length;
  	      return first.subscribe(function (left) {
  	        if (index < len) {
  	          var right = second[index++], res = tryCatch(resultSelector)(left, right);
  	          if (res === errorObj) { return o.onError(res.e); }
  	          o.onNext(res);
  	        } else {
  	          o.onCompleted();
  	        }
  	      }, function (e) { o.onError(e); }, function () { o.onCompleted(); });
  	    }, first);
  	  }
  	
  	  function falseFactory() { return false; }
  	  function emptyArrayFactory() { return []; }
  	
  	  /**
  	   * Merges the specified observable sequences into one observable sequence by using the selector function whenever all of the observable sequences or an array have produced an element at a corresponding index.
  	   * The last element in the arguments must be a function to invoke for each series of elements at corresponding indexes in the args.
  	   * @returns {Observable} An observable sequence containing the result of combining elements of the args using the specified result selector function.
  	   */
  	  observableProto.zip = function () {
  	    if (Array.isArray(arguments[0])) { return zipArray.apply(this, arguments); }
  	    var len = arguments.length, args = new Array(len);
  	    for(var i = 0; i < len; i++) { args[i] = arguments[i]; }
  	
  	    var parent = this, resultSelector = args.pop();
  	    args.unshift(parent);
  	    return new AnonymousObservable(function (o) {
  	      var n = args.length,
  	        queues = arrayInitialize(n, emptyArrayFactory),
  	        isDone = arrayInitialize(n, falseFactory);
  	
  	      var subscriptions = new Array(n);
  	      for (var idx = 0; idx < n; idx++) {
  	        (function (i) {
  	          var source = args[i], sad = new SingleAssignmentDisposable();
  	          isPromise(source) && (source = observableFromPromise(source));
  	          sad.setDisposable(source.subscribe(function (x) {
  	            queues[i].push(x);
  	            if (queues.every(function (x) { return x.length > 0; })) {
  	              var queuedValues = queues.map(function (x) { return x.shift(); }),
  	                  res = tryCatch(resultSelector).apply(parent, queuedValues);
  	              if (res === errorObj) { return o.onError(res.e); }
  	              o.onNext(res);
  	            } else if (isDone.filter(function (x, j) { return j !== i; }).every(identity)) {
  	              o.onCompleted();
  	            }
  	          }, function (e) { o.onError(e); }, function () {
  	            isDone[i] = true;
  	            isDone.every(identity) && o.onCompleted();
  	          }));
  	          subscriptions[i] = sad;
  	        })(idx);
  	      }
  	
  	      return new CompositeDisposable(subscriptions);
  	    }, parent);
  	  };
  	
  	  /**
  	   * Merges the specified observable sequences into one observable sequence by using the selector function whenever all of the observable sequences have produced an element at a corresponding index.
  	   * @param arguments Observable sources.
  	   * @param {Function} resultSelector Function to invoke for each series of elements at corresponding indexes in the sources.
  	   * @returns {Observable} An observable sequence containing the result of combining elements of the sources using the specified result selector function.
  	   */
  	  Observable.zip = function () {
  	    var len = arguments.length, args = new Array(len);
  	    for(var i = 0; i < len; i++) { args[i] = arguments[i]; }
  	    var first = args.shift();
  	    return first.zip.apply(first, args);
  	  };
  	
  	  function falseFactory() { return false; }
  	  function arrayFactory() { return []; }
  	
  	  /**
  	   * Merges the specified observable sequences into one observable sequence by emitting a list with the elements of the observable sequences at corresponding indexes.
  	   * @param arguments Observable sources.
  	   * @returns {Observable} An observable sequence containing lists of elements at corresponding indexes.
  	   */
  	  Observable.zipArray = function () {
  	    var sources;
  	    if (Array.isArray(arguments[0])) {
  	      sources = arguments[0];
  	    } else {
  	      var len = arguments.length;
  	      sources = new Array(len);
  	      for(var i = 0; i < len; i++) { sources[i] = arguments[i]; }
  	    }
  	    return new AnonymousObservable(function (o) {
  	      var n = sources.length,
  	        queues = arrayInitialize(n, arrayFactory),
  	        isDone = arrayInitialize(n, falseFactory);
  	
  	      var subscriptions = new Array(n);
  	      for (var idx = 0; idx < n; idx++) {
  	        (function (i) {
  	          subscriptions[i] = new SingleAssignmentDisposable();
  	          subscriptions[i].setDisposable(sources[i].subscribe(function (x) {
  	            queues[i].push(x);
  	            if (queues.every(function (x) { return x.length > 0; })) {
  	              var res = queues.map(function (x) { return x.shift(); });
  	              o.onNext(res);
  	            } else if (isDone.filter(function (x, j) { return j !== i; }).every(identity)) {
  	              return o.onCompleted();
  	            }
  	          }, function (e) { o.onError(e); }, function () {
  	            isDone[i] = true;
  	            isDone.every(identity) && o.onCompleted();
  	          }));
  	        })(idx);
  	      }
  	
  	      return new CompositeDisposable(subscriptions);
  	    });
  	  };
  	
  	  /**
  	   *  Hides the identity of an observable sequence.
  	   * @returns {Observable} An observable sequence that hides the identity of the source sequence.
  	   */
  	  observableProto.asObservable = function () {
  	    var source = this;
  	    return new AnonymousObservable(function (o) { return source.subscribe(o); }, source);
  	  };
  	
  	  /**
  	   *  Projects each element of an observable sequence into zero or more buffers which are produced based on element count information.
  	   *
  	   * @example
  	   *  var res = xs.bufferWithCount(10);
  	   *  var res = xs.bufferWithCount(10, 1);
  	   * @param {Number} count Length of each buffer.
  	   * @param {Number} [skip] Number of elements to skip between creation of consecutive buffers. If not provided, defaults to the count.
  	   * @returns {Observable} An observable sequence of buffers.
  	   */
  	  observableProto.bufferWithCount = function (count, skip) {
  	    if (typeof skip !== 'number') {
  	      skip = count;
  	    }
  	    return this.windowWithCount(count, skip).selectMany(function (x) {
  	      return x.toArray();
  	    }).where(function (x) {
  	      return x.length > 0;
  	    });
  	  };
  	
  	  /**
  	   * Dematerializes the explicit notification values of an observable sequence as implicit notifications.
  	   * @returns {Observable} An observable sequence exhibiting the behavior corresponding to the source sequence's notification values.
  	   */
  	  observableProto.dematerialize = function () {
  	    var source = this;
  	    return new AnonymousObservable(function (o) {
  	      return source.subscribe(function (x) { return x.accept(o); }, function(e) { o.onError(e); }, function () { o.onCompleted(); });
  	    }, this);
  	  };
  	
  	  /**
  	   *  Returns an observable sequence that contains only distinct contiguous elements according to the keySelector and the comparer.
  	   *
  	   *  var obs = observable.distinctUntilChanged();
  	   *  var obs = observable.distinctUntilChanged(function (x) { return x.id; });
  	   *  var obs = observable.distinctUntilChanged(function (x) { return x.id; }, function (x, y) { return x === y; });
  	   *
  	   * @param {Function} [keySelector] A function to compute the comparison key for each element. If not provided, it projects the value.
  	   * @param {Function} [comparer] Equality comparer for computed key values. If not provided, defaults to an equality comparer function.
  	   * @returns {Observable} An observable sequence only containing the distinct contiguous elements, based on a computed key value, from the source sequence.
  	   */
  	  observableProto.distinctUntilChanged = function (keySelector, comparer) {
  	    var source = this;
  	    comparer || (comparer = defaultComparer);
  	    return new AnonymousObservable(function (o) {
  	      var hasCurrentKey = false, currentKey;
  	      return source.subscribe(function (value) {
  	        var key = value;
  	        if (keySelector) {
  	          key = tryCatch(keySelector)(value);
  	          if (key === errorObj) { return o.onError(key.e); }
  	        }
  	        if (hasCurrentKey) {
  	          var comparerEquals = tryCatch(comparer)(currentKey, key);
  	          if (comparerEquals === errorObj) { return o.onError(comparerEquals.e); }
  	        }
  	        if (!hasCurrentKey || !comparerEquals) {
  	          hasCurrentKey = true;
  	          currentKey = key;
  	          o.onNext(value);
  	        }
  	      }, function (e) { o.onError(e); }, function () { o.onCompleted(); });
  	    }, this);
  	  };
  	
  	  var TapObservable = (function(__super__) {
  	    inherits(TapObservable,__super__);
  	    function TapObservable(source, observerOrOnNext, onError, onCompleted) {
  	      this.source = source;
  	      this.t = !observerOrOnNext || isFunction(observerOrOnNext) ?
  	        observerCreate(observerOrOnNext || noop, onError || noop, onCompleted || noop) :
  	        observerOrOnNext;
  	      __super__.call(this);
  	    }
  	
  	    TapObservable.prototype.subscribeCore = function(o) {
  	      return this.source.subscribe(new InnerObserver(o, this.t));
  	    };
  	
  	    function InnerObserver(o, t) {
  	      this.o = o;
  	      this.t = t;
  	      this.isStopped = false;
  	    }
  	    InnerObserver.prototype.onNext = function(x) {
  	      if (this.isStopped) { return; }
  	      var res = tryCatch(this.t.onNext).call(this.t, x);
  	      if (res === errorObj) { this.o.onError(res.e); }
  	      this.o.onNext(x);
  	    };
  	    InnerObserver.prototype.onError = function(err) {
  	      if (!this.isStopped) {
  	        this.isStopped = true;
  	        var res = tryCatch(this.t.onError).call(this.t, err);
  	        if (res === errorObj) { return this.o.onError(res.e); }
  	        this.o.onError(err);
  	      }
  	    };
  	    InnerObserver.prototype.onCompleted = function() {
  	      if (!this.isStopped) {
  	        this.isStopped = true;
  	        var res = tryCatch(this.t.onCompleted).call(this.t);
  	        if (res === errorObj) { return this.o.onError(res.e); }
  	        this.o.onCompleted();
  	      }
  	    };
  	    InnerObserver.prototype.dispose = function() { this.isStopped = true; };
  	    InnerObserver.prototype.fail = function (e) {
  	      if (!this.isStopped) {
  	        this.isStopped = true;
  	        this.o.onError(e);
  	        return true;
  	      }
  	      return false;
  	    };
  	
  	    return TapObservable;
  	  }(ObservableBase));
  	
  	  /**
  	  *  Invokes an action for each element in the observable sequence and invokes an action upon graceful or exceptional termination of the observable sequence.
  	  *  This method can be used for debugging, logging, etc. of query behavior by intercepting the message stream to run arbitrary actions for messages on the pipeline.
  	  * @param {Function | Observer} observerOrOnNext Action to invoke for each element in the observable sequence or an o.
  	  * @param {Function} [onError]  Action to invoke upon exceptional termination of the observable sequence. Used if only the observerOrOnNext parameter is also a function.
  	  * @param {Function} [onCompleted]  Action to invoke upon graceful termination of the observable sequence. Used if only the observerOrOnNext parameter is also a function.
  	  * @returns {Observable} The source sequence with the side-effecting behavior applied.
  	  */
  	  observableProto['do'] = observableProto.tap = observableProto.doAction = function (observerOrOnNext, onError, onCompleted) {
  	    return new TapObservable(this, observerOrOnNext, onError, onCompleted);
  	  };
  	
  	  /**
  	  *  Invokes an action for each element in the observable sequence.
  	  *  This method can be used for debugging, logging, etc. of query behavior by intercepting the message stream to run arbitrary actions for messages on the pipeline.
  	  * @param {Function} onNext Action to invoke for each element in the observable sequence.
  	  * @param {Any} [thisArg] Object to use as this when executing callback.
  	  * @returns {Observable} The source sequence with the side-effecting behavior applied.
  	  */
  	  observableProto.doOnNext = observableProto.tapOnNext = function (onNext, thisArg) {
  	    return this.tap(typeof thisArg !== 'undefined' ? function (x) { onNext.call(thisArg, x); } : onNext);
  	  };
  	
  	  /**
  	  *  Invokes an action upon exceptional termination of the observable sequence.
  	  *  This method can be used for debugging, logging, etc. of query behavior by intercepting the message stream to run arbitrary actions for messages on the pipeline.
  	  * @param {Function} onError Action to invoke upon exceptional termination of the observable sequence.
  	  * @param {Any} [thisArg] Object to use as this when executing callback.
  	  * @returns {Observable} The source sequence with the side-effecting behavior applied.
  	  */
  	  observableProto.doOnError = observableProto.tapOnError = function (onError, thisArg) {
  	    return this.tap(noop, typeof thisArg !== 'undefined' ? function (e) { onError.call(thisArg, e); } : onError);
  	  };
  	
  	  /**
  	  *  Invokes an action upon graceful termination of the observable sequence.
  	  *  This method can be used for debugging, logging, etc. of query behavior by intercepting the message stream to run arbitrary actions for messages on the pipeline.
  	  * @param {Function} onCompleted Action to invoke upon graceful termination of the observable sequence.
  	  * @param {Any} [thisArg] Object to use as this when executing callback.
  	  * @returns {Observable} The source sequence with the side-effecting behavior applied.
  	  */
  	  observableProto.doOnCompleted = observableProto.tapOnCompleted = function (onCompleted, thisArg) {
  	    return this.tap(noop, null, typeof thisArg !== 'undefined' ? function () { onCompleted.call(thisArg); } : onCompleted);
  	  };
  	
  	  /**
  	   *  Invokes a specified action after the source observable sequence terminates gracefully or exceptionally.
  	   * @param {Function} finallyAction Action to invoke after the source observable sequence terminates.
  	   * @returns {Observable} Source sequence with the action-invoking termination behavior applied.
  	   */
  	  observableProto['finally'] = observableProto.ensure = function (action) {
  	    var source = this;
  	    return new AnonymousObservable(function (observer) {
  	      var subscription;
  	      try {
  	        subscription = source.subscribe(observer);
  	      } catch (e) {
  	        action();
  	        throw e;
  	      }
  	      return disposableCreate(function () {
  	        try {
  	          subscription.dispose();
  	        } catch (e) {
  	          throw e;
  	        } finally {
  	          action();
  	        }
  	      });
  	    }, this);
  	  };
  	
  	  /**
  	   * @deprecated use #finally or #ensure instead.
  	   */
  	  observableProto.finallyAction = function (action) {
  	    //deprecate('finallyAction', 'finally or ensure');
  	    return this.ensure(action);
  	  };
  	
  	  var IgnoreElementsObservable = (function(__super__) {
  	    inherits(IgnoreElementsObservable, __super__);
  	
  	    function IgnoreElementsObservable(source) {
  	      this.source = source;
  	      __super__.call(this);
  	    }
  	
  	    IgnoreElementsObservable.prototype.subscribeCore = function (o) {
  	      return this.source.subscribe(new InnerObserver(o));
  	    };
  	
  	    function InnerObserver(o) {
  	      this.o = o;
  	      this.isStopped = false;
  	    }
  	    InnerObserver.prototype.onNext = noop;
  	    InnerObserver.prototype.onError = function (err) {
  	      if(!this.isStopped) {
  	        this.isStopped = true;
  	        this.o.onError(err);
  	      }
  	    };
  	    InnerObserver.prototype.onCompleted = function () {
  	      if(!this.isStopped) {
  	        this.isStopped = true;
  	        this.o.onCompleted();
  	      }
  	    };
  	    InnerObserver.prototype.dispose = function() { this.isStopped = true; };
  	    InnerObserver.prototype.fail = function (e) {
  	      if (!this.isStopped) {
  	        this.isStopped = true;
  	        this.observer.onError(e);
  	        return true;
  	      }
  	
  	      return false;
  	    };
  	
  	    return IgnoreElementsObservable;
  	  }(ObservableBase));
  	
  	  /**
  	   *  Ignores all elements in an observable sequence leaving only the termination messages.
  	   * @returns {Observable} An empty observable sequence that signals termination, successful or exceptional, of the source sequence.
  	   */
  	  observableProto.ignoreElements = function () {
  	    return new IgnoreElementsObservable(this);
  	  };
  	
  	  /**
  	   *  Materializes the implicit notifications of an observable sequence as explicit notification values.
  	   * @returns {Observable} An observable sequence containing the materialized notification values from the source sequence.
  	   */
  	  observableProto.materialize = function () {
  	    var source = this;
  	    return new AnonymousObservable(function (observer) {
  	      return source.subscribe(function (value) {
  	        observer.onNext(notificationCreateOnNext(value));
  	      }, function (e) {
  	        observer.onNext(notificationCreateOnError(e));
  	        observer.onCompleted();
  	      }, function () {
  	        observer.onNext(notificationCreateOnCompleted());
  	        observer.onCompleted();
  	      });
  	    }, source);
  	  };
  	
  	  /**
  	   *  Repeats the observable sequence a specified number of times. If the repeat count is not specified, the sequence repeats indefinitely.
  	   * @param {Number} [repeatCount]  Number of times to repeat the sequence. If not provided, repeats the sequence indefinitely.
  	   * @returns {Observable} The observable sequence producing the elements of the given sequence repeatedly.
  	   */
  	  observableProto.repeat = function (repeatCount) {
  	    return enumerableRepeat(this, repeatCount).concat();
  	  };
  	
  	  /**
  	   *  Repeats the source observable sequence the specified number of times or until it successfully terminates. If the retry count is not specified, it retries indefinitely.
  	   *  Note if you encounter an error and want it to retry once, then you must use .retry(2);
  	   *
  	   * @example
  	   *  var res = retried = retry.repeat();
  	   *  var res = retried = retry.repeat(2);
  	   * @param {Number} [retryCount]  Number of times to retry the sequence. If not provided, retry the sequence indefinitely.
  	   * @returns {Observable} An observable sequence producing the elements of the given sequence repeatedly until it terminates successfully.
  	   */
  	  observableProto.retry = function (retryCount) {
  	    return enumerableRepeat(this, retryCount).catchError();
  	  };
  	
  	  /**
  	   *  Repeats the source observable sequence upon error each time the notifier emits or until it successfully terminates. 
  	   *  if the notifier completes, the observable sequence completes.
  	   *
  	   * @example
  	   *  var timer = Observable.timer(500);
  	   *  var source = observable.retryWhen(timer);
  	   * @param {Observable} [notifier] An observable that triggers the retries or completes the observable with onNext or onCompleted respectively.
  	   * @returns {Observable} An observable sequence producing the elements of the given sequence repeatedly until it terminates successfully.
  	   */
  	  observableProto.retryWhen = function (notifier) {
  	    return enumerableRepeat(this).catchErrorWhen(notifier);
  	  };
  	  var ScanObservable = (function(__super__) {
  	    inherits(ScanObservable, __super__);
  	    function ScanObservable(source, accumulator, hasSeed, seed) {
  	      this.source = source;
  	      this.accumulator = accumulator;
  	      this.hasSeed = hasSeed;
  	      this.seed = seed;
  	      __super__.call(this);
  	    }
  	
  	    ScanObservable.prototype.subscribeCore = function(observer) {
  	      return this.source.subscribe(new ScanObserver(observer,this));
  	    };
  	
  	    return ScanObservable;
  	  }(ObservableBase));
  	
  	  function ScanObserver(observer, parent) {
  	    this.observer = observer;
  	    this.accumulator = parent.accumulator;
  	    this.hasSeed = parent.hasSeed;
  	    this.seed = parent.seed;
  	    this.hasAccumulation = false;
  	    this.accumulation = null;
  	    this.hasValue = false;
  	    this.isStopped = false;
  	  }
  	  ScanObserver.prototype.onNext = function (x) {
  	    if (this.isStopped) { return; }
  	    !this.hasValue && (this.hasValue = true);
  	    try {
  	      if (this.hasAccumulation) {
  	        this.accumulation = this.accumulator(this.accumulation, x);
  	      } else {
  	        this.accumulation = this.hasSeed ? this.accumulator(this.seed, x) : x;
  	        this.hasAccumulation = true;
  	      }
  	    } catch (e) {
  	      return this.observer.onError(e);
  	    }
  	    this.observer.onNext(this.accumulation);
  	  };
  	  ScanObserver.prototype.onError = function (e) { 
  	    if (!this.isStopped) {
  	      this.isStopped = true;
  	      this.observer.onError(e);
  	    }
  	  };
  	  ScanObserver.prototype.onCompleted = function () {
  	    if (!this.isStopped) {
  	      this.isStopped = true;
  	      !this.hasValue && this.hasSeed && this.observer.onNext(this.seed);
  	      this.observer.onCompleted();
  	    }
  	  };
  	  ScanObserver.prototype.dispose = function() { this.isStopped = true; };
  	  ScanObserver.prototype.fail = function (e) {
  	    if (!this.isStopped) {
  	      this.isStopped = true;
  	      this.observer.onError(e);
  	      return true;
  	    }
  	    return false;
  	  };
  	
  	  /**
  	  *  Applies an accumulator function over an observable sequence and returns each intermediate result. The optional seed value is used as the initial accumulator value.
  	  *  For aggregation behavior with no intermediate results, see Observable.aggregate.
  	  * @param {Mixed} [seed] The initial accumulator value.
  	  * @param {Function} accumulator An accumulator function to be invoked on each element.
  	  * @returns {Observable} An observable sequence containing the accumulated values.
  	  */
  	  observableProto.scan = function () {
  	    var hasSeed = false, seed, accumulator, source = this;
  	    if (arguments.length === 2) {
  	      hasSeed = true;
  	      seed = arguments[0];
  	      accumulator = arguments[1];
  	    } else {
  	      accumulator = arguments[0];
  	    }
  	    return new ScanObservable(this, accumulator, hasSeed, seed);
  	  };
  	
  	  /**
  	   *  Bypasses a specified number of elements at the end of an observable sequence.
  	   * @description
  	   *  This operator accumulates a queue with a length enough to store the first `count` elements. As more elements are
  	   *  received, elements are taken from the front of the queue and produced on the result sequence. This causes elements to be delayed.
  	   * @param count Number of elements to bypass at the end of the source sequence.
  	   * @returns {Observable} An observable sequence containing the source sequence elements except for the bypassed ones at the end.
  	   */
  	  observableProto.skipLast = function (count) {
  	    if (count < 0) { throw new ArgumentOutOfRangeError(); }
  	    var source = this;
  	    return new AnonymousObservable(function (o) {
  	      var q = [];
  	      return source.subscribe(function (x) {
  	        q.push(x);
  	        q.length > count && o.onNext(q.shift());
  	      }, function (e) { o.onError(e); }, function () { o.onCompleted(); });
  	    }, source);
  	  };
  	
  	  /**
  	   *  Prepends a sequence of values to an observable sequence with an optional scheduler and an argument list of values to prepend.
  	   *  @example
  	   *  var res = source.startWith(1, 2, 3);
  	   *  var res = source.startWith(Rx.Scheduler.timeout, 1, 2, 3);
  	   * @param {Arguments} args The specified values to prepend to the observable sequence
  	   * @returns {Observable} The source sequence prepended with the specified values.
  	   */
  	  observableProto.startWith = function () {
  	    var values, scheduler, start = 0;
  	    if (!!arguments.length && isScheduler(arguments[0])) {
  	      scheduler = arguments[0];
  	      start = 1;
  	    } else {
  	      scheduler = immediateScheduler;
  	    }
  	    for(var args = [], i = start, len = arguments.length; i < len; i++) { args.push(arguments[i]); }
  	    return enumerableOf([observableFromArray(args, scheduler), this]).concat();
  	  };
  	
  	  /**
  	   *  Returns a specified number of contiguous elements from the end of an observable sequence.
  	   * @description
  	   *  This operator accumulates a buffer with a length enough to store elements count elements. Upon completion of
  	   *  the source sequence, this buffer is drained on the result sequence. This causes the elements to be delayed.
  	   * @param {Number} count Number of elements to take from the end of the source sequence.
  	   * @returns {Observable} An observable sequence containing the specified number of elements from the end of the source sequence.
  	   */
  	  observableProto.takeLast = function (count) {
  	    if (count < 0) { throw new ArgumentOutOfRangeError(); }
  	    var source = this;
  	    return new AnonymousObservable(function (o) {
  	      var q = [];
  	      return source.subscribe(function (x) {
  	        q.push(x);
  	        q.length > count && q.shift();
  	      }, function (e) { o.onError(e); }, function () {
  	        while (q.length > 0) { o.onNext(q.shift()); }
  	        o.onCompleted();
  	      });
  	    }, source);
  	  };
  	
  	  /**
  	   *  Returns an array with the specified number of contiguous elements from the end of an observable sequence.
  	   *
  	   * @description
  	   *  This operator accumulates a buffer with a length enough to store count elements. Upon completion of the
  	   *  source sequence, this buffer is produced on the result sequence.
  	   * @param {Number} count Number of elements to take from the end of the source sequence.
  	   * @returns {Observable} An observable sequence containing a single array with the specified number of elements from the end of the source sequence.
  	   */
  	  observableProto.takeLastBuffer = function (count) {
  	    var source = this;
  	    return new AnonymousObservable(function (o) {
  	      var q = [];
  	      return source.subscribe(function (x) {
  	        q.push(x);
  	        q.length > count && q.shift();
  	      }, function (e) { o.onError(e); }, function () {
  	        o.onNext(q);
  	        o.onCompleted();
  	      });
  	    }, source);
  	  };
  	
  	  /**
  	   *  Projects each element of an observable sequence into zero or more windows which are produced based on element count information.
  	   *
  	   *  var res = xs.windowWithCount(10);
  	   *  var res = xs.windowWithCount(10, 1);
  	   * @param {Number} count Length of each window.
  	   * @param {Number} [skip] Number of elements to skip between creation of consecutive windows. If not specified, defaults to the count.
  	   * @returns {Observable} An observable sequence of windows.
  	   */
  	  observableProto.windowWithCount = function (count, skip) {
  	    var source = this;
  	    +count || (count = 0);
  	    Math.abs(count) === Infinity && (count = 0);
  	    if (count <= 0) { throw new ArgumentOutOfRangeError(); }
  	    skip == null && (skip = count);
  	    +skip || (skip = 0);
  	    Math.abs(skip) === Infinity && (skip = 0);
  	
  	    if (skip <= 0) { throw new ArgumentOutOfRangeError(); }
  	    return new AnonymousObservable(function (observer) {
  	      var m = new SingleAssignmentDisposable(),
  	        refCountDisposable = new RefCountDisposable(m),
  	        n = 0,
  	        q = [];
  	
  	      function createWindow () {
  	        var s = new Subject();
  	        q.push(s);
  	        observer.onNext(addRef(s, refCountDisposable));
  	      }
  	
  	      createWindow();
  	
  	      m.setDisposable(source.subscribe(
  	        function (x) {
  	          for (var i = 0, len = q.length; i < len; i++) { q[i].onNext(x); }
  	          var c = n - count + 1;
  	          c >= 0 && c % skip === 0 && q.shift().onCompleted();
  	          ++n % skip === 0 && createWindow();
  	        },
  	        function (e) {
  	          while (q.length > 0) { q.shift().onError(e); }
  	          observer.onError(e);
  	        },
  	        function () {
  	          while (q.length > 0) { q.shift().onCompleted(); }
  	          observer.onCompleted();
  	        }
  	      ));
  	      return refCountDisposable;
  	    }, source);
  	  };
  	
  	  function concatMap(source, selector, thisArg) {
  	    var selectorFunc = bindCallback(selector, thisArg, 3);
  	    return source.map(function (x, i) {
  	      var result = selectorFunc(x, i, source);
  	      isPromise(result) && (result = observableFromPromise(result));
  	      (isArrayLike(result) || isIterable(result)) && (result = observableFrom(result));
  	      return result;
  	    }).concatAll();
  	  }
  	
  	  /**
  	   *  One of the Following:
  	   *  Projects each element of an observable sequence to an observable sequence and merges the resulting observable sequences into one observable sequence.
  	   *
  	   * @example
  	   *  var res = source.concatMap(function (x) { return Rx.Observable.range(0, x); });
  	   *  Or:
  	   *  Projects each element of an observable sequence to an observable sequence, invokes the result selector for the source element and each of the corresponding inner sequence's elements, and merges the results into one observable sequence.
  	   *
  	   *  var res = source.concatMap(function (x) { return Rx.Observable.range(0, x); }, function (x, y) { return x + y; });
  	   *  Or:
  	   *  Projects each element of the source observable sequence to the other observable sequence and merges the resulting observable sequences into one observable sequence.
  	   *
  	   *  var res = source.concatMap(Rx.Observable.fromArray([1,2,3]));
  	   * @param {Function} selector A transform function to apply to each element or an observable sequence to project each element from the
  	   * source sequence onto which could be either an observable or Promise.
  	   * @param {Function} [resultSelector]  A transform function to apply to each element of the intermediate sequence.
  	   * @returns {Observable} An observable sequence whose elements are the result of invoking the one-to-many transform function collectionSelector on each element of the input sequence and then mapping each of those sequence elements and their corresponding source element to a result element.
  	   */
  	  observableProto.selectConcat = observableProto.concatMap = function (selector, resultSelector, thisArg) {
  	    if (isFunction(selector) && isFunction(resultSelector)) {
  	      return this.concatMap(function (x, i) {
  	        var selectorResult = selector(x, i);
  	        isPromise(selectorResult) && (selectorResult = observableFromPromise(selectorResult));
  	        (isArrayLike(selectorResult) || isIterable(selectorResult)) && (selectorResult = observableFrom(selectorResult));
  	
  	        return selectorResult.map(function (y, i2) {
  	          return resultSelector(x, y, i, i2);
  	        });
  	      });
  	    }
  	    return isFunction(selector) ?
  	      concatMap(this, selector, thisArg) :
  	      concatMap(this, function () { return selector; });
  	  };
  	
  	  /**
  	   * Projects each notification of an observable sequence to an observable sequence and concats the resulting observable sequences into one observable sequence.
  	   * @param {Function} onNext A transform function to apply to each element; the second parameter of the function represents the index of the source element.
  	   * @param {Function} onError A transform function to apply when an error occurs in the source sequence.
  	   * @param {Function} onCompleted A transform function to apply when the end of the source sequence is reached.
  	   * @param {Any} [thisArg] An optional "this" to use to invoke each transform.
  	   * @returns {Observable} An observable sequence whose elements are the result of invoking the one-to-many transform function corresponding to each notification in the input sequence.
  	   */
  	  observableProto.concatMapObserver = observableProto.selectConcatObserver = function(onNext, onError, onCompleted, thisArg) {
  	    var source = this,
  	        onNextFunc = bindCallback(onNext, thisArg, 2),
  	        onErrorFunc = bindCallback(onError, thisArg, 1),
  	        onCompletedFunc = bindCallback(onCompleted, thisArg, 0);
  	    return new AnonymousObservable(function (observer) {
  	      var index = 0;
  	      return source.subscribe(
  	        function (x) {
  	          var result;
  	          try {
  	            result = onNextFunc(x, index++);
  	          } catch (e) {
  	            observer.onError(e);
  	            return;
  	          }
  	          isPromise(result) && (result = observableFromPromise(result));
  	          observer.onNext(result);
  	        },
  	        function (err) {
  	          var result;
  	          try {
  	            result = onErrorFunc(err);
  	          } catch (e) {
  	            observer.onError(e);
  	            return;
  	          }
  	          isPromise(result) && (result = observableFromPromise(result));
  	          observer.onNext(result);
  	          observer.onCompleted();
  	        },
  	        function () {
  	          var result;
  	          try {
  	            result = onCompletedFunc();
  	          } catch (e) {
  	            observer.onError(e);
  	            return;
  	          }
  	          isPromise(result) && (result = observableFromPromise(result));
  	          observer.onNext(result);
  	          observer.onCompleted();
  	        });
  	    }, this).concatAll();
  	  };
  	
  	    /**
  	     *  Returns the elements of the specified sequence or the specified value in a singleton sequence if the sequence is empty.
  	     *
  	     *  var res = obs = xs.defaultIfEmpty();
  	     *  2 - obs = xs.defaultIfEmpty(false);
  	     *
  	     * @memberOf Observable#
  	     * @param defaultValue The value to return if the sequence is empty. If not provided, this defaults to null.
  	     * @returns {Observable} An observable sequence that contains the specified default value if the source is empty; otherwise, the elements of the source itself.
  	     */
  	    observableProto.defaultIfEmpty = function (defaultValue) {
  	      var source = this;
  	      defaultValue === undefined && (defaultValue = null);
  	      return new AnonymousObservable(function (observer) {
  	        var found = false;
  	        return source.subscribe(function (x) {
  	          found = true;
  	          observer.onNext(x);
  	        },
  	        function (e) { observer.onError(e); }, 
  	        function () {
  	          !found && observer.onNext(defaultValue);
  	          observer.onCompleted();
  	        });
  	      }, source);
  	    };
  	
  	  // Swap out for Array.findIndex
  	  function arrayIndexOfComparer(array, item, comparer) {
  	    for (var i = 0, len = array.length; i < len; i++) {
  	      if (comparer(array[i], item)) { return i; }
  	    }
  	    return -1;
  	  }
  	
  	  function HashSet(comparer) {
  	    this.comparer = comparer;
  	    this.set = [];
  	  }
  	  HashSet.prototype.push = function(value) {
  	    var retValue = arrayIndexOfComparer(this.set, value, this.comparer) === -1;
  	    retValue && this.set.push(value);
  	    return retValue;
  	  };
  	
  	  /**
  	   *  Returns an observable sequence that contains only distinct elements according to the keySelector and the comparer.
  	   *  Usage of this operator should be considered carefully due to the maintenance of an internal lookup structure which can grow large.
  	   *
  	   * @example
  	   *  var res = obs = xs.distinct();
  	   *  2 - obs = xs.distinct(function (x) { return x.id; });
  	   *  2 - obs = xs.distinct(function (x) { return x.id; }, function (a,b) { return a === b; });
  	   * @param {Function} [keySelector]  A function to compute the comparison key for each element.
  	   * @param {Function} [comparer]  Used to compare items in the collection.
  	   * @returns {Observable} An observable sequence only containing the distinct elements, based on a computed key value, from the source sequence.
  	   */
  	  observableProto.distinct = function (keySelector, comparer) {
  	    var source = this;
  	    comparer || (comparer = defaultComparer);
  	    return new AnonymousObservable(function (o) {
  	      var hashSet = new HashSet(comparer);
  	      return source.subscribe(function (x) {
  	        var key = x;
  	
  	        if (keySelector) {
  	          try {
  	            key = keySelector(x);
  	          } catch (e) {
  	            o.onError(e);
  	            return;
  	          }
  	        }
  	        hashSet.push(key) && o.onNext(x);
  	      },
  	      function (e) { o.onError(e); }, function () { o.onCompleted(); });
  	    }, this);
  	  };
  	
  	  /**
  	   *  Groups the elements of an observable sequence according to a specified key selector function and comparer and selects the resulting elements by using a specified function.
  	   *
  	   * @example
  	   *  var res = observable.groupBy(function (x) { return x.id; });
  	   *  2 - observable.groupBy(function (x) { return x.id; }), function (x) { return x.name; });
  	   *  3 - observable.groupBy(function (x) { return x.id; }), function (x) { return x.name; }, function (x) { return x.toString(); });
  	   * @param {Function} keySelector A function to extract the key for each element.
  	   * @param {Function} [elementSelector]  A function to map each source element to an element in an observable group.
  	   * @param {Function} [comparer] Used to determine whether the objects are equal.
  	   * @returns {Observable} A sequence of observable groups, each of which corresponds to a unique key value, containing all elements that share that same key value.
  	   */
  	  observableProto.groupBy = function (keySelector, elementSelector, comparer) {
  	    return this.groupByUntil(keySelector, elementSelector, observableNever, comparer);
  	  };
  	
  	    /**
  	     *  Groups the elements of an observable sequence according to a specified key selector function.
  	     *  A duration selector function is used to control the lifetime of groups. When a group expires, it receives an OnCompleted notification. When a new element with the same
  	     *  key value as a reclaimed group occurs, the group will be reborn with a new lifetime request.
  	     *
  	     * @example
  	     *  var res = observable.groupByUntil(function (x) { return x.id; }, null,  function () { return Rx.Observable.never(); });
  	     *  2 - observable.groupBy(function (x) { return x.id; }), function (x) { return x.name; },  function () { return Rx.Observable.never(); });
  	     *  3 - observable.groupBy(function (x) { return x.id; }), function (x) { return x.name; },  function () { return Rx.Observable.never(); }, function (x) { return x.toString(); });
  	     * @param {Function} keySelector A function to extract the key for each element.
  	     * @param {Function} durationSelector A function to signal the expiration of a group.
  	     * @param {Function} [comparer] Used to compare objects. When not specified, the default comparer is used.
  	     * @returns {Observable}
  	     *  A sequence of observable groups, each of which corresponds to a unique key value, containing all elements that share that same key value.
  	     *  If a group's lifetime expires, a new group with the same key value can be created once an element with such a key value is encoutered.
  	     *
  	     */
  	    observableProto.groupByUntil = function (keySelector, elementSelector, durationSelector, comparer) {
  	      var source = this;
  	      elementSelector || (elementSelector = identity);
  	      comparer || (comparer = defaultComparer);
  	      return new AnonymousObservable(function (observer) {
  	        function handleError(e) { return function (item) { item.onError(e); }; }
  	        var map = new Dictionary(0, comparer),
  	          groupDisposable = new CompositeDisposable(),
  	          refCountDisposable = new RefCountDisposable(groupDisposable);
  	
  	        groupDisposable.add(source.subscribe(function (x) {
  	          var key;
  	          try {
  	            key = keySelector(x);
  	          } catch (e) {
  	            map.getValues().forEach(handleError(e));
  	            observer.onError(e);
  	            return;
  	          }
  	
  	          var fireNewMapEntry = false,
  	            writer = map.tryGetValue(key);
  	          if (!writer) {
  	            writer = new Subject();
  	            map.set(key, writer);
  	            fireNewMapEntry = true;
  	          }
  	
  	          if (fireNewMapEntry) {
  	            var group = new GroupedObservable(key, writer, refCountDisposable),
  	              durationGroup = new GroupedObservable(key, writer);
  	            try {
  	              duration = durationSelector(durationGroup);
  	            } catch (e) {
  	              map.getValues().forEach(handleError(e));
  	              observer.onError(e);
  	              return;
  	            }
  	
  	            observer.onNext(group);
  	
  	            var md = new SingleAssignmentDisposable();
  	            groupDisposable.add(md);
  	
  	            var expire = function () {
  	              map.remove(key) && writer.onCompleted();
  	              groupDisposable.remove(md);
  	            };
  	
  	            md.setDisposable(duration.take(1).subscribe(
  	              noop,
  	              function (exn) {
  	                map.getValues().forEach(handleError(exn));
  	                observer.onError(exn);
  	              },
  	              expire)
  	            );
  	          }
  	
  	          var element;
  	          try {
  	            element = elementSelector(x);
  	          } catch (e) {
  	            map.getValues().forEach(handleError(e));
  	            observer.onError(e);
  	            return;
  	          }
  	
  	          writer.onNext(element);
  	      }, function (ex) {
  	        map.getValues().forEach(handleError(ex));
  	        observer.onError(ex);
  	      }, function () {
  	        map.getValues().forEach(function (item) { item.onCompleted(); });
  	        observer.onCompleted();
  	      }));
  	
  	      return refCountDisposable;
  	    }, source);
  	  };
  	
  	  var MapObservable = (function (__super__) {
  	    inherits(MapObservable, __super__);
  	
  	    function MapObservable(source, selector, thisArg) {
  	      this.source = source;
  	      this.selector = bindCallback(selector, thisArg, 3);
  	      __super__.call(this);
  	    }
  	    
  	    function innerMap(selector, self) {
  	      return function (x, i, o) { return selector.call(this, self.selector(x, i, o), i, o); }
  	    }
  	
  	    MapObservable.prototype.internalMap = function (selector, thisArg) {
  	      return new MapObservable(this.source, innerMap(selector, this), thisArg);
  	    };
  	
  	    MapObservable.prototype.subscribeCore = function (o) {
  	      return this.source.subscribe(new InnerObserver(o, this.selector, this));
  	    };
  	    
  	    function InnerObserver(o, selector, source) {
  	      this.o = o;
  	      this.selector = selector;
  	      this.source = source;
  	      this.i = 0;
  	      this.isStopped = false;
  	    }
  	  
  	    InnerObserver.prototype.onNext = function(x) {
  	      if (this.isStopped) { return; }
  	      var result = tryCatch(this.selector)(x, this.i++, this.source);
  	      if (result === errorObj) {
  	        return this.o.onError(result.e);
  	      }
  	      this.o.onNext(result);
  	    };
  	    InnerObserver.prototype.onError = function (e) {
  	      if(!this.isStopped) { this.isStopped = true; this.o.onError(e); }
  	    };
  	    InnerObserver.prototype.onCompleted = function () {
  	      if(!this.isStopped) { this.isStopped = true; this.o.onCompleted(); }
  	    };
  	    InnerObserver.prototype.dispose = function() { this.isStopped = true; };
  	    InnerObserver.prototype.fail = function (e) {
  	      if (!this.isStopped) {
  	        this.isStopped = true;
  	        this.o.onError(e);
  	        return true;
  	      }
  	  
  	      return false;
  	    };
  	
  	    return MapObservable;
  	
  	  }(ObservableBase));
  	
  	  /**
  	  * Projects each element of an observable sequence into a new form by incorporating the element's index.
  	  * @param {Function} selector A transform function to apply to each source element; the second parameter of the function represents the index of the source element.
  	  * @param {Any} [thisArg] Object to use as this when executing callback.
  	  * @returns {Observable} An observable sequence whose elements are the result of invoking the transform function on each element of source.
  	  */
  	  observableProto.map = observableProto.select = function (selector, thisArg) {
  	    var selectorFn = typeof selector === 'function' ? selector : function () { return selector; };
  	    return this instanceof MapObservable ?
  	      this.internalMap(selectorFn, thisArg) :
  	      new MapObservable(this, selectorFn, thisArg);
  	  };
  	
  	  /**
  	   * Retrieves the value of a specified nested property from all elements in
  	   * the Observable sequence.
  	   * @param {Arguments} arguments The nested properties to pluck.
  	   * @returns {Observable} Returns a new Observable sequence of property values.
  	   */
  	  observableProto.pluck = function () {
  	    var args = arguments, len = arguments.length;
  	    if (len === 0) { throw new Error('List of properties cannot be empty.'); }
  	    return this.map(function (x) {
  	      var currentProp = x;
  	      for (var i = 0; i < len; i++) {
  	        var p = currentProp[args[i]];
  	        if (typeof p !== 'undefined') {
  	          currentProp = p;
  	        } else {
  	          return undefined;
  	        }
  	      }
  	      return currentProp;
  	    });
  	  };
  	
  	  function flatMap(source, selector, thisArg) {
  	    var selectorFunc = bindCallback(selector, thisArg, 3);
  	    return source.map(function (x, i) {
  	      var result = selectorFunc(x, i, source);
  	      isPromise(result) && (result = observableFromPromise(result));
  	      (isArrayLike(result) || isIterable(result)) && (result = observableFrom(result));
  	      return result;
  	    }).mergeAll();
  	  }
  	
  	  /**
  	   *  One of the Following:
  	   *  Projects each element of an observable sequence to an observable sequence and merges the resulting observable sequences into one observable sequence.
  	   *
  	   * @example
  	   *  var res = source.selectMany(function (x) { return Rx.Observable.range(0, x); });
  	   *  Or:
  	   *  Projects each element of an observable sequence to an observable sequence, invokes the result selector for the source element and each of the corresponding inner sequence's elements, and merges the results into one observable sequence.
  	   *
  	   *  var res = source.selectMany(function (x) { return Rx.Observable.range(0, x); }, function (x, y) { return x + y; });
  	   *  Or:
  	   *  Projects each element of the source observable sequence to the other observable sequence and merges the resulting observable sequences into one observable sequence.
  	   *
  	   *  var res = source.selectMany(Rx.Observable.fromArray([1,2,3]));
  	   * @param {Function} selector A transform function to apply to each element or an observable sequence to project each element from the source sequence onto which could be either an observable or Promise.
  	   * @param {Function} [resultSelector]  A transform function to apply to each element of the intermediate sequence.
  	   * @param {Any} [thisArg] Object to use as this when executing callback.
  	   * @returns {Observable} An observable sequence whose elements are the result of invoking the one-to-many transform function collectionSelector on each element of the input sequence and then mapping each of those sequence elements and their corresponding source element to a result element.
  	   */
  	  observableProto.selectMany = observableProto.flatMap = function (selector, resultSelector, thisArg) {
  	    if (isFunction(selector) && isFunction(resultSelector)) {
  	      return this.flatMap(function (x, i) {
  	        var selectorResult = selector(x, i);
  	        isPromise(selectorResult) && (selectorResult = observableFromPromise(selectorResult));
  	        (isArrayLike(selectorResult) || isIterable(selectorResult)) && (selectorResult = observableFrom(selectorResult));
  	
  	        return selectorResult.map(function (y, i2) {
  	          return resultSelector(x, y, i, i2);
  	        });
  	      }, thisArg);
  	    }
  	    return isFunction(selector) ?
  	      flatMap(this, selector, thisArg) :
  	      flatMap(this, function () { return selector; });
  	  };
  	
  	  /**
  	   * Projects each notification of an observable sequence to an observable sequence and merges the resulting observable sequences into one observable sequence.
  	   * @param {Function} onNext A transform function to apply to each element; the second parameter of the function represents the index of the source element.
  	   * @param {Function} onError A transform function to apply when an error occurs in the source sequence.
  	   * @param {Function} onCompleted A transform function to apply when the end of the source sequence is reached.
  	   * @param {Any} [thisArg] An optional "this" to use to invoke each transform.
  	   * @returns {Observable} An observable sequence whose elements are the result of invoking the one-to-many transform function corresponding to each notification in the input sequence.
  	   */
  	  observableProto.flatMapObserver = observableProto.selectManyObserver = function (onNext, onError, onCompleted, thisArg) {
  	    var source = this;
  	    return new AnonymousObservable(function (observer) {
  	      var index = 0;
  	
  	      return source.subscribe(
  	        function (x) {
  	          var result;
  	          try {
  	            result = onNext.call(thisArg, x, index++);
  	          } catch (e) {
  	            observer.onError(e);
  	            return;
  	          }
  	          isPromise(result) && (result = observableFromPromise(result));
  	          observer.onNext(result);
  	        },
  	        function (err) {
  	          var result;
  	          try {
  	            result = onError.call(thisArg, err);
  	          } catch (e) {
  	            observer.onError(e);
  	            return;
  	          }
  	          isPromise(result) && (result = observableFromPromise(result));
  	          observer.onNext(result);
  	          observer.onCompleted();
  	        },
  	        function () {
  	          var result;
  	          try {
  	            result = onCompleted.call(thisArg);
  	          } catch (e) {
  	            observer.onError(e);
  	            return;
  	          }
  	          isPromise(result) && (result = observableFromPromise(result));
  	          observer.onNext(result);
  	          observer.onCompleted();
  	        });
  	    }, source).mergeAll();
  	  };
  	
  	  /**
  	   *  Projects each element of an observable sequence into a new sequence of observable sequences by incorporating the element's index and then
  	   *  transforms an observable sequence of observable sequences into an observable sequence producing values only from the most recent observable sequence.
  	   * @param {Function} selector A transform function to apply to each source element; the second parameter of the function represents the index of the source element.
  	   * @param {Any} [thisArg] Object to use as this when executing callback.
  	   * @returns {Observable} An observable sequence whose elements are the result of invoking the transform function on each element of source producing an Observable of Observable sequences
  	   *  and that at any point in time produces the elements of the most recent inner observable sequence that has been received.
  	   */
  	  observableProto.selectSwitch = observableProto.flatMapLatest = observableProto.switchMap = function (selector, thisArg) {
  	    return this.select(selector, thisArg).switchLatest();
  	  };
  	
  	  var SkipObservable = (function(__super__) {
  	    inherits(SkipObservable, __super__);
  	    function SkipObservable(source, count) {
  	      this.source = source;
  	      this.skipCount = count;
  	      __super__.call(this);
  	    }
  	    
  	    SkipObservable.prototype.subscribeCore = function (o) {
  	      return this.source.subscribe(new InnerObserver(o, this.skipCount));
  	    };
  	    
  	    function InnerObserver(o, c) {
  	      this.c = c;
  	      this.r = c;
  	      this.o = o;
  	      this.isStopped = false;
  	    }
  	    InnerObserver.prototype.onNext = function (x) {
  	      if (this.isStopped) { return; }
  	      if (this.r <= 0) { 
  	        this.o.onNext(x);
  	      } else {
  	        this.r--;
  	      }
  	    };
  	    InnerObserver.prototype.onError = function(e) {
  	      if (!this.isStopped) { this.isStopped = true; this.o.onError(e); }
  	    };
  	    InnerObserver.prototype.onCompleted = function() {
  	      if (!this.isStopped) { this.isStopped = true; this.o.onCompleted(); }
  	    };
  	    InnerObserver.prototype.dispose = function() { this.isStopped = true; };
  	    InnerObserver.prototype.fail = function(e) {
  	      if (!this.isStopped) {
  	        this.isStopped = true;
  	        this.o.onError(e);
  	        return true;
  	      }
  	      return false;
  	    };
  	    
  	    return SkipObservable;
  	  }(ObservableBase));  
  	  
  	  /**
  	   * Bypasses a specified number of elements in an observable sequence and then returns the remaining elements.
  	   * @param {Number} count The number of elements to skip before returning the remaining elements.
  	   * @returns {Observable} An observable sequence that contains the elements that occur after the specified index in the input sequence.
  	   */
  	  observableProto.skip = function (count) {
  	    if (count < 0) { throw new ArgumentOutOfRangeError(); }
  	    return new SkipObservable(this, count);
  	  };
  	  /**
  	   *  Bypasses elements in an observable sequence as long as a specified condition is true and then returns the remaining elements.
  	   *  The element's index is used in the logic of the predicate function.
  	   *
  	   *  var res = source.skipWhile(function (value) { return value < 10; });
  	   *  var res = source.skipWhile(function (value, index) { return value < 10 || index < 10; });
  	   * @param {Function} predicate A function to test each element for a condition; the second parameter of the function represents the index of the source element.
  	   * @param {Any} [thisArg] Object to use as this when executing callback.
  	   * @returns {Observable} An observable sequence that contains the elements from the input sequence starting at the first element in the linear series that does not pass the test specified by predicate.
  	   */
  	  observableProto.skipWhile = function (predicate, thisArg) {
  	    var source = this,
  	        callback = bindCallback(predicate, thisArg, 3);
  	    return new AnonymousObservable(function (o) {
  	      var i = 0, running = false;
  	      return source.subscribe(function (x) {
  	        if (!running) {
  	          try {
  	            running = !callback(x, i++, source);
  	          } catch (e) {
  	            o.onError(e);
  	            return;
  	          }
  	        }
  	        running && o.onNext(x);
  	      }, function (e) { o.onError(e); }, function () { o.onCompleted(); });
  	    }, source);
  	  };
  	
  	  /**
  	   *  Returns a specified number of contiguous elements from the start of an observable sequence, using the specified scheduler for the edge case of take(0).
  	   *
  	   *  var res = source.take(5);
  	   *  var res = source.take(0, Rx.Scheduler.timeout);
  	   * @param {Number} count The number of elements to return.
  	   * @param {Scheduler} [scheduler] Scheduler used to produce an OnCompleted message in case <paramref name="count count</paramref> is set to 0.
  	   * @returns {Observable} An observable sequence that contains the specified number of elements from the start of the input sequence.
  	   */
  	  observableProto.take = function (count, scheduler) {
  	    if (count < 0) { throw new ArgumentOutOfRangeError(); }
  	    if (count === 0) { return observableEmpty(scheduler); }
  	    var source = this;
  	    return new AnonymousObservable(function (o) {
  	      var remaining = count;
  	      return source.subscribe(function (x) {
  	        if (remaining-- > 0) {
  	          o.onNext(x);
  	          remaining <= 0 && o.onCompleted();
  	        }
  	      }, function (e) { o.onError(e); }, function () { o.onCompleted(); });
  	    }, source);
  	  };
  	
  	  /**
  	   *  Returns elements from an observable sequence as long as a specified condition is true.
  	   *  The element's index is used in the logic of the predicate function.
  	   * @param {Function} predicate A function to test each element for a condition; the second parameter of the function represents the index of the source element.
  	   * @param {Any} [thisArg] Object to use as this when executing callback.
  	   * @returns {Observable} An observable sequence that contains the elements from the input sequence that occur before the element at which the test no longer passes.
  	   */
  	  observableProto.takeWhile = function (predicate, thisArg) {
  	    var source = this,
  	        callback = bindCallback(predicate, thisArg, 3);
  	    return new AnonymousObservable(function (o) {
  	      var i = 0, running = true;
  	      return source.subscribe(function (x) {
  	        if (running) {
  	          try {
  	            running = callback(x, i++, source);
  	          } catch (e) {
  	            o.onError(e);
  	            return;
  	          }
  	          if (running) {
  	            o.onNext(x);
  	          } else {
  	            o.onCompleted();
  	          }
  	        }
  	      }, function (e) { o.onError(e); }, function () { o.onCompleted(); });
  	    }, source);
  	  };
  	
  	  var FilterObservable = (function (__super__) {
  	    inherits(FilterObservable, __super__);
  	
  	    function FilterObservable(source, predicate, thisArg) {
  	      this.source = source;
  	      this.predicate = bindCallback(predicate, thisArg, 3);
  	      __super__.call(this);
  	    }
  	
  	    FilterObservable.prototype.subscribeCore = function (o) {
  	      return this.source.subscribe(new InnerObserver(o, this.predicate, this));
  	    };
  	    
  	    function innerPredicate(predicate, self) {
  	      return function(x, i, o) { return self.predicate(x, i, o) && predicate.call(this, x, i, o); }
  	    }
  	
  	    FilterObservable.prototype.internalFilter = function(predicate, thisArg) {
  	      return new FilterObservable(this.source, innerPredicate(predicate, this), thisArg);
  	    };
  	    
  	    function InnerObserver(o, predicate, source) {
  	      this.o = o;
  	      this.predicate = predicate;
  	      this.source = source;
  	      this.i = 0;
  	      this.isStopped = false;
  	    }
  	  
  	    InnerObserver.prototype.onNext = function(x) {
  	      if (this.isStopped) { return; }
  	      var shouldYield = tryCatch(this.predicate)(x, this.i++, this.source);
  	      if (shouldYield === errorObj) {
  	        return this.o.onError(shouldYield.e);
  	      }
  	      shouldYield && this.o.onNext(x);
  	    };
  	    InnerObserver.prototype.onError = function (e) {
  	      if(!this.isStopped) { this.isStopped = true; this.o.onError(e); }
  	    };
  	    InnerObserver.prototype.onCompleted = function () {
  	      if(!this.isStopped) { this.isStopped = true; this.o.onCompleted(); }
  	    };
  	    InnerObserver.prototype.dispose = function() { this.isStopped = true; };
  	    InnerObserver.prototype.fail = function (e) {
  	      if (!this.isStopped) {
  	        this.isStopped = true;
  	        this.o.onError(e);
  	        return true;
  	      }
  	      return false;
  	    };
  	
  	    return FilterObservable;
  	
  	  }(ObservableBase));
  	
  	  /**
  	  *  Filters the elements of an observable sequence based on a predicate by incorporating the element's index.
  	  * @param {Function} predicate A function to test each source element for a condition; the second parameter of the function represents the index of the source element.
  	  * @param {Any} [thisArg] Object to use as this when executing callback.
  	  * @returns {Observable} An observable sequence that contains elements from the input sequence that satisfy the condition.
  	  */
  	  observableProto.filter = observableProto.where = function (predicate, thisArg) {
  	    return this instanceof FilterObservable ? this.internalFilter(predicate, thisArg) :
  	      new FilterObservable(this, predicate, thisArg);
  	  };
  	
  	  function extremaBy(source, keySelector, comparer) {
  	    return new AnonymousObservable(function (o) {
  	      var hasValue = false, lastKey = null, list = [];
  	      return source.subscribe(function (x) {
  	        var comparison, key;
  	        try {
  	          key = keySelector(x);
  	        } catch (ex) {
  	          o.onError(ex);
  	          return;
  	        }
  	        comparison = 0;
  	        if (!hasValue) {
  	          hasValue = true;
  	          lastKey = key;
  	        } else {
  	          try {
  	            comparison = comparer(key, lastKey);
  	          } catch (ex1) {
  	            o.onError(ex1);
  	            return;
  	          }
  	        }
  	        if (comparison > 0) {
  	          lastKey = key;
  	          list = [];
  	        }
  	        if (comparison >= 0) { list.push(x); }
  	      }, function (e) { o.onError(e); }, function () {
  	        o.onNext(list);
  	        o.onCompleted();
  	      });
  	    }, source);
  	  }
  	
  	  function firstOnly(x) {
  	    if (x.length === 0) { throw new EmptyError(); }
  	    return x[0];
  	  }
  	
  	  /**
  	   * Applies an accumulator function over an observable sequence, returning the result of the aggregation as a single element in the result sequence. The specified seed value is used as the initial accumulator value.
  	   * For aggregation behavior with incremental intermediate results, see Observable.scan.
  	   * @deprecated Use #reduce instead
  	   * @param {Mixed} [seed] The initial accumulator value.
  	   * @param {Function} accumulator An accumulator function to be invoked on each element.
  	   * @returns {Observable} An observable sequence containing a single element with the final accumulator value.
  	   */
  	  observableProto.aggregate = function () {
  	    var hasSeed = false, accumulator, seed, source = this;
  	    if (arguments.length === 2) {
  	      hasSeed = true;
  	      seed = arguments[0];
  	      accumulator = arguments[1];
  	    } else {
  	      accumulator = arguments[0];
  	    }
  	    return new AnonymousObservable(function (o) {
  	      var hasAccumulation, accumulation, hasValue;
  	      return source.subscribe (
  	        function (x) {
  	          !hasValue && (hasValue = true);
  	          try {
  	            if (hasAccumulation) {
  	              accumulation = accumulator(accumulation, x);
  	            } else {
  	              accumulation = hasSeed ? accumulator(seed, x) : x;
  	              hasAccumulation = true;
  	            }
  	          } catch (e) {
  	            return o.onError(e);
  	          }
  	        },
  	        function (e) { o.onError(e); },
  	        function () {
  	          hasValue && o.onNext(accumulation);
  	          !hasValue && hasSeed && o.onNext(seed);
  	          !hasValue && !hasSeed && o.onError(new EmptyError());
  	          o.onCompleted();
  	        }
  	      );
  	    }, source);
  	  };
  	
  	  var ReduceObservable = (function(__super__) {
  	    inherits(ReduceObservable, __super__);
  	    function ReduceObservable(source, acc, hasSeed, seed) {
  	      this.source = source;
  	      this.acc = acc;
  	      this.hasSeed = hasSeed;
  	      this.seed = seed;
  	      __super__.call(this);
  	    }
  	
  	    ReduceObservable.prototype.subscribeCore = function(observer) {
  	      return this.source.subscribe(new InnerObserver(observer,this));
  	    };
  	
  	    function InnerObserver(o, parent) {
  	      this.o = o;
  	      this.acc = parent.acc;
  	      this.hasSeed = parent.hasSeed;
  	      this.seed = parent.seed;
  	      this.hasAccumulation = false;
  	      this.result = null;
  	      this.hasValue = false;
  	      this.isStopped = false;
  	    }
  	    InnerObserver.prototype.onNext = function (x) {
  	      if (this.isStopped) { return; }
  	      !this.hasValue && (this.hasValue = true);
  	      if (this.hasAccumulation) {
  	        this.result = tryCatch(this.acc)(this.result, x);
  	      } else {
  	        this.result = this.hasSeed ? tryCatch(this.acc)(this.seed, x) : x;
  	        this.hasAccumulation = true;
  	      }
  	      if (this.result === errorObj) { this.o.onError(this.result.e); }
  	    };
  	    InnerObserver.prototype.onError = function (e) { 
  	      if (!this.isStopped) { this.isStopped = true; this.o.onError(e); } 
  	    };
  	    InnerObserver.prototype.onCompleted = function () {
  	      if (!this.isStopped) {
  	        this.isStopped = true;
  	        this.hasValue && this.o.onNext(this.result);
  	        !this.hasValue && this.hasSeed && this.o.onNext(this.seed);
  	        !this.hasValue && !this.hasSeed && this.o.onError(new EmptyError());
  	        this.o.onCompleted();
  	      }
  	    };
  	    InnerObserver.prototype.dispose = function () { this.isStopped = true; };
  	    InnerObserver.prototype.fail = function(e) {
  	      if (!this.isStopped) {
  	        this.isStopped = true;
  	        this.o.onError(e);
  	        return true;
  	      }
  	      return false;
  	    };
  	
  	    return ReduceObservable;
  	  }(ObservableBase));
  	
  	  /**
  	  * Applies an accumulator function over an observable sequence, returning the result of the aggregation as a single element in the result sequence. The specified seed value is used as the initial accumulator value.
  	  * For aggregation behavior with incremental intermediate results, see Observable.scan.
  	  * @param {Function} accumulator An accumulator function to be invoked on each element.
  	  * @param {Any} [seed] The initial accumulator value.
  	  * @returns {Observable} An observable sequence containing a single element with the final accumulator value.
  	  */
  	  observableProto.reduce = function (accumulator) {
  	    var hasSeed = false;
  	    if (arguments.length === 2) {
  	      hasSeed = true;
  	      var seed = arguments[1];
  	    }
  	    return new ReduceObservable(this, accumulator, hasSeed, seed);
  	  };
  	
  	  /**
  	   * Determines whether any element of an observable sequence satisfies a condition if present, else if any items are in the sequence.
  	   * @param {Function} [predicate] A function to test each element for a condition.
  	   * @returns {Observable} An observable sequence containing a single element determining whether any elements in the source sequence pass the test in the specified predicate if given, else if any items are in the sequence.
  	   */
  	  observableProto.some = function (predicate, thisArg) {
  	    var source = this;
  	    return predicate ?
  	      source.filter(predicate, thisArg).some() :
  	      new AnonymousObservable(function (observer) {
  	        return source.subscribe(function () {
  	          observer.onNext(true);
  	          observer.onCompleted();
  	        }, function (e) { observer.onError(e); }, function () {
  	          observer.onNext(false);
  	          observer.onCompleted();
  	        });
  	      }, source);
  	  };
  	
  	  /** @deprecated use #some instead */
  	  observableProto.any = function () {
  	    //deprecate('any', 'some');
  	    return this.some.apply(this, arguments);
  	  };
  	
  	  /**
  	   * Determines whether an observable sequence is empty.
  	   * @returns {Observable} An observable sequence containing a single element determining whether the source sequence is empty.
  	   */
  	  observableProto.isEmpty = function () {
  	    return this.any().map(not);
  	  };
  	
  	  /**
  	   * Determines whether all elements of an observable sequence satisfy a condition.
  	   * @param {Function} [predicate] A function to test each element for a condition.
  	   * @param {Any} [thisArg] Object to use as this when executing callback.
  	   * @returns {Observable} An observable sequence containing a single element determining whether all elements in the source sequence pass the test in the specified predicate.
  	   */
  	  observableProto.every = function (predicate, thisArg) {
  	    return this.filter(function (v) { return !predicate(v); }, thisArg).some().map(not);
  	  };
  	
  	  /** @deprecated use #every instead */
  	  observableProto.all = function () {
  	    //deprecate('all', 'every');
  	    return this.every.apply(this, arguments);
  	  };
  	
  	  /**
  	   * Determines whether an observable sequence includes a specified element with an optional equality comparer.
  	   * @param searchElement The value to locate in the source sequence.
  	   * @param {Number} [fromIndex] An equality comparer to compare elements.
  	   * @returns {Observable} An observable sequence containing a single element determining whether the source sequence includes an element that has the specified value from the given index.
  	   */
  	  observableProto.includes = function (searchElement, fromIndex) {
  	    var source = this;
  	    function comparer(a, b) {
  	      return (a === 0 && b === 0) || (a === b || (isNaN(a) && isNaN(b)));
  	    }
  	    return new AnonymousObservable(function (o) {
  	      var i = 0, n = +fromIndex || 0;
  	      Math.abs(n) === Infinity && (n = 0);
  	      if (n < 0) {
  	        o.onNext(false);
  	        o.onCompleted();
  	        return disposableEmpty;
  	      }
  	      return source.subscribe(
  	        function (x) {
  	          if (i++ >= n && comparer(x, searchElement)) {
  	            o.onNext(true);
  	            o.onCompleted();
  	          }
  	        },
  	        function (e) { o.onError(e); },
  	        function () {
  	          o.onNext(false);
  	          o.onCompleted();
  	        });
  	    }, this);
  	  };
  	
  	  /**
  	   * @deprecated use #includes instead.
  	   */
  	  observableProto.contains = function (searchElement, fromIndex) {
  	    //deprecate('contains', 'includes');
  	    observableProto.includes(searchElement, fromIndex);
  	  };
  	
  	  /**
  	   * Returns an observable sequence containing a value that represents how many elements in the specified observable sequence satisfy a condition if provided, else the count of items.
  	   * @example
  	   * res = source.count();
  	   * res = source.count(function (x) { return x > 3; });
  	   * @param {Function} [predicate]A function to test each element for a condition.
  	   * @param {Any} [thisArg] Object to use as this when executing callback.
  	   * @returns {Observable} An observable sequence containing a single element with a number that represents how many elements in the input sequence satisfy the condition in the predicate function if provided, else the count of items in the sequence.
  	   */
  	  observableProto.count = function (predicate, thisArg) {
  	    return predicate ?
  	      this.filter(predicate, thisArg).count() :
  	      this.reduce(function (count) { return count + 1; }, 0);
  	  };
  	
  	  /**
  	   * Returns the first index at which a given element can be found in the observable sequence, or -1 if it is not present.
  	   * @param {Any} searchElement Element to locate in the array.
  	   * @param {Number} [fromIndex] The index to start the search.  If not specified, defaults to 0.
  	   * @returns {Observable} And observable sequence containing the first index at which a given element can be found in the observable sequence, or -1 if it is not present.
  	   */
  	  observableProto.indexOf = function(searchElement, fromIndex) {
  	    var source = this;
  	    return new AnonymousObservable(function (o) {
  	      var i = 0, n = +fromIndex || 0;
  	      Math.abs(n) === Infinity && (n = 0);
  	      if (n < 0) {
  	        o.onNext(-1);
  	        o.onCompleted();
  	        return disposableEmpty;
  	      }
  	      return source.subscribe(
  	        function (x) {
  	          if (i >= n && x === searchElement) {
  	            o.onNext(i);
  	            o.onCompleted();
  	          }
  	          i++;
  	        },
  	        function (e) { o.onError(e); },
  	        function () {
  	          o.onNext(-1);
  	          o.onCompleted();
  	        });
  	    }, source);
  	  };
  	
  	  /**
  	   * Computes the sum of a sequence of values that are obtained by invoking an optional transform function on each element of the input sequence, else if not specified computes the sum on each item in the sequence.
  	   * @param {Function} [selector] A transform function to apply to each element.
  	   * @param {Any} [thisArg] Object to use as this when executing callback.
  	   * @returns {Observable} An observable sequence containing a single element with the sum of the values in the source sequence.
  	   */
  	  observableProto.sum = function (keySelector, thisArg) {
  	    return keySelector && isFunction(keySelector) ?
  	      this.map(keySelector, thisArg).sum() :
  	      this.reduce(function (prev, curr) { return prev + curr; }, 0);
  	  };
  	
  	  /**
  	   * Returns the elements in an observable sequence with the minimum key value according to the specified comparer.
  	   * @example
  	   * var res = source.minBy(function (x) { return x.value; });
  	   * var res = source.minBy(function (x) { return x.value; }, function (x, y) { return x - y; });
  	   * @param {Function} keySelector Key selector function.
  	   * @param {Function} [comparer] Comparer used to compare key values.
  	   * @returns {Observable} An observable sequence containing a list of zero or more elements that have a minimum key value.
  	   */
  	  observableProto.minBy = function (keySelector, comparer) {
  	    comparer || (comparer = defaultSubComparer);
  	    return extremaBy(this, keySelector, function (x, y) { return comparer(x, y) * -1; });
  	  };
  	
  	  /**
  	   * Returns the minimum element in an observable sequence according to the optional comparer else a default greater than less than check.
  	   * @example
  	   * var res = source.min();
  	   * var res = source.min(function (x, y) { return x.value - y.value; });
  	   * @param {Function} [comparer] Comparer used to compare elements.
  	   * @returns {Observable} An observable sequence containing a single element with the minimum element in the source sequence.
  	   */
  	  observableProto.min = function (comparer) {
  	    return this.minBy(identity, comparer).map(function (x) { return firstOnly(x); });
  	  };
  	
  	  /**
  	   * Returns the elements in an observable sequence with the maximum  key value according to the specified comparer.
  	   * @example
  	   * var res = source.maxBy(function (x) { return x.value; });
  	   * var res = source.maxBy(function (x) { return x.value; }, function (x, y) { return x - y;; });
  	   * @param {Function} keySelector Key selector function.
  	   * @param {Function} [comparer]  Comparer used to compare key values.
  	   * @returns {Observable} An observable sequence containing a list of zero or more elements that have a maximum key value.
  	   */
  	  observableProto.maxBy = function (keySelector, comparer) {
  	    comparer || (comparer = defaultSubComparer);
  	    return extremaBy(this, keySelector, comparer);
  	  };
  	
  	  /**
  	   * Returns the maximum value in an observable sequence according to the specified comparer.
  	   * @example
  	   * var res = source.max();
  	   * var res = source.max(function (x, y) { return x.value - y.value; });
  	   * @param {Function} [comparer] Comparer used to compare elements.
  	   * @returns {Observable} An observable sequence containing a single element with the maximum element in the source sequence.
  	   */
  	  observableProto.max = function (comparer) {
  	    return this.maxBy(identity, comparer).map(function (x) { return firstOnly(x); });
  	  };
  	
  	  /**
  	   * Computes the average of an observable sequence of values that are in the sequence or obtained by invoking a transform function on each element of the input sequence if present.
  	   * @param {Function} [selector] A transform function to apply to each element.
  	   * @param {Any} [thisArg] Object to use as this when executing callback.
  	   * @returns {Observable} An observable sequence containing a single element with the average of the sequence of values.
  	   */
  	  observableProto.average = function (keySelector, thisArg) {
  	    return keySelector && isFunction(keySelector) ?
  	      this.map(keySelector, thisArg).average() :
  	      this.reduce(function (prev, cur) {
  	        return {
  	          sum: prev.sum + cur,
  	          count: prev.count + 1
  	        };
  	      }, {sum: 0, count: 0 }).map(function (s) {
  	        if (s.count === 0) { throw new EmptyError(); }
  	        return s.sum / s.count;
  	      });
  	  };
  	
  	  /**
  	   *  Determines whether two sequences are equal by comparing the elements pairwise using a specified equality comparer.
  	   *
  	   * @example
  	   * var res = res = source.sequenceEqual([1,2,3]);
  	   * var res = res = source.sequenceEqual([{ value: 42 }], function (x, y) { return x.value === y.value; });
  	   * 3 - res = source.sequenceEqual(Rx.Observable.returnValue(42));
  	   * 4 - res = source.sequenceEqual(Rx.Observable.returnValue({ value: 42 }), function (x, y) { return x.value === y.value; });
  	   * @param {Observable} second Second observable sequence or array to compare.
  	   * @param {Function} [comparer] Comparer used to compare elements of both sequences.
  	   * @returns {Observable} An observable sequence that contains a single element which indicates whether both sequences are of equal length and their corresponding elements are equal according to the specified equality comparer.
  	   */
  	  observableProto.sequenceEqual = function (second, comparer) {
  	    var first = this;
  	    comparer || (comparer = defaultComparer);
  	    return new AnonymousObservable(function (o) {
  	      var donel = false, doner = false, ql = [], qr = [];
  	      var subscription1 = first.subscribe(function (x) {
  	        var equal, v;
  	        if (qr.length > 0) {
  	          v = qr.shift();
  	          try {
  	            equal = comparer(v, x);
  	          } catch (e) {
  	            o.onError(e);
  	            return;
  	          }
  	          if (!equal) {
  	            o.onNext(false);
  	            o.onCompleted();
  	          }
  	        } else if (doner) {
  	          o.onNext(false);
  	          o.onCompleted();
  	        } else {
  	          ql.push(x);
  	        }
  	      }, function(e) { o.onError(e); }, function () {
  	        donel = true;
  	        if (ql.length === 0) {
  	          if (qr.length > 0) {
  	            o.onNext(false);
  	            o.onCompleted();
  	          } else if (doner) {
  	            o.onNext(true);
  	            o.onCompleted();
  	          }
  	        }
  	      });
  	
  	      (isArrayLike(second) || isIterable(second)) && (second = observableFrom(second));
  	      isPromise(second) && (second = observableFromPromise(second));
  	      var subscription2 = second.subscribe(function (x) {
  	        var equal;
  	        if (ql.length > 0) {
  	          var v = ql.shift();
  	          try {
  	            equal = comparer(v, x);
  	          } catch (exception) {
  	            o.onError(exception);
  	            return;
  	          }
  	          if (!equal) {
  	            o.onNext(false);
  	            o.onCompleted();
  	          }
  	        } else if (donel) {
  	          o.onNext(false);
  	          o.onCompleted();
  	        } else {
  	          qr.push(x);
  	        }
  	      }, function(e) { o.onError(e); }, function () {
  	        doner = true;
  	        if (qr.length === 0) {
  	          if (ql.length > 0) {
  	            o.onNext(false);
  	            o.onCompleted();
  	          } else if (donel) {
  	            o.onNext(true);
  	            o.onCompleted();
  	          }
  	        }
  	      });
  	      return new CompositeDisposable(subscription1, subscription2);
  	    }, first);
  	  };
  	
  	  function elementAtOrDefault(source, index, hasDefault, defaultValue) {
  	    if (index < 0) { throw new ArgumentOutOfRangeError(); }
  	    return new AnonymousObservable(function (o) {
  	      var i = index;
  	      return source.subscribe(function (x) {
  	        if (i-- === 0) {
  	          o.onNext(x);
  	          o.onCompleted();
  	        }
  	      }, function (e) { o.onError(e); }, function () {
  	        if (!hasDefault) {
  	          o.onError(new ArgumentOutOfRangeError());
  	        } else {
  	          o.onNext(defaultValue);
  	          o.onCompleted();
  	        }
  	      });
  	    }, source);
  	  }
  	
  	  /**
  	   * Returns the element at a specified index in a sequence.
  	   * @example
  	   * var res = source.elementAt(5);
  	   * @param {Number} index The zero-based index of the element to retrieve.
  	   * @returns {Observable} An observable sequence that produces the element at the specified position in the source sequence.
  	   */
  	  observableProto.elementAt =  function (index) {
  	    return elementAtOrDefault(this, index, false);
  	  };
  	
  	  /**
  	   * Returns the element at a specified index in a sequence or a default value if the index is out of range.
  	   * @example
  	   * var res = source.elementAtOrDefault(5);
  	   * var res = source.elementAtOrDefault(5, 0);
  	   * @param {Number} index The zero-based index of the element to retrieve.
  	   * @param [defaultValue] The default value if the index is outside the bounds of the source sequence.
  	   * @returns {Observable} An observable sequence that produces the element at the specified position in the source sequence, or a default value if the index is outside the bounds of the source sequence.
  	   */
  	  observableProto.elementAtOrDefault = function (index, defaultValue) {
  	    return elementAtOrDefault(this, index, true, defaultValue);
  	  };
  	
  	  function singleOrDefaultAsync(source, hasDefault, defaultValue) {
  	    return new AnonymousObservable(function (o) {
  	      var value = defaultValue, seenValue = false;
  	      return source.subscribe(function (x) {
  	        if (seenValue) {
  	          o.onError(new Error('Sequence contains more than one element'));
  	        } else {
  	          value = x;
  	          seenValue = true;
  	        }
  	      }, function (e) { o.onError(e); }, function () {
  	        if (!seenValue && !hasDefault) {
  	          o.onError(new EmptyError());
  	        } else {
  	          o.onNext(value);
  	          o.onCompleted();
  	        }
  	      });
  	    }, source);
  	  }
  	
  	  /**
  	   * Returns the only element of an observable sequence that satisfies the condition in the optional predicate, and reports an exception if there is not exactly one element in the observable sequence.
  	   * @param {Function} [predicate] A predicate function to evaluate for elements in the source sequence.
  	   * @param {Any} [thisArg] Object to use as `this` when executing the predicate.
  	   * @returns {Observable} Sequence containing the single element in the observable sequence that satisfies the condition in the predicate.
  	   */
  	  observableProto.single = function (predicate, thisArg) {
  	    return predicate && isFunction(predicate) ?
  	      this.where(predicate, thisArg).single() :
  	      singleOrDefaultAsync(this, false);
  	  };
  	
  	  /**
  	   * Returns the only element of an observable sequence that matches the predicate, or a default value if no such element exists; this method reports an exception if there is more than one element in the observable sequence.
  	   * @example
  	   * var res = res = source.singleOrDefault();
  	   * var res = res = source.singleOrDefault(function (x) { return x === 42; });
  	   * res = source.singleOrDefault(function (x) { return x === 42; }, 0);
  	   * res = source.singleOrDefault(null, 0);
  	   * @memberOf Observable#
  	   * @param {Function} predicate A predicate function to evaluate for elements in the source sequence.
  	   * @param [defaultValue] The default value if the index is outside the bounds of the source sequence.
  	   * @param {Any} [thisArg] Object to use as `this` when executing the predicate.
  	   * @returns {Observable} Sequence containing the single element in the observable sequence that satisfies the condition in the predicate, or a default value if no such element exists.
  	   */
  	  observableProto.singleOrDefault = function (predicate, defaultValue, thisArg) {
  	    return predicate && isFunction(predicate) ?
  	      this.filter(predicate, thisArg).singleOrDefault(null, defaultValue) :
  	      singleOrDefaultAsync(this, true, defaultValue);
  	  };
  	
  	  function firstOrDefaultAsync(source, hasDefault, defaultValue) {
  	    return new AnonymousObservable(function (o) {
  	      return source.subscribe(function (x) {
  	        o.onNext(x);
  	        o.onCompleted();
  	      }, function (e) { o.onError(e); }, function () {
  	        if (!hasDefault) {
  	          o.onError(new EmptyError());
  	        } else {
  	          o.onNext(defaultValue);
  	          o.onCompleted();
  	        }
  	      });
  	    }, source);
  	  }
  	
  	  /**
  	   * Returns the first element of an observable sequence that satisfies the condition in the predicate if present else the first item in the sequence.
  	   * @example
  	   * var res = res = source.first();
  	   * var res = res = source.first(function (x) { return x > 3; });
  	   * @param {Function} [predicate] A predicate function to evaluate for elements in the source sequence.
  	   * @param {Any} [thisArg] Object to use as `this` when executing the predicate.
  	   * @returns {Observable} Sequence containing the first element in the observable sequence that satisfies the condition in the predicate if provided, else the first item in the sequence.
  	   */
  	  observableProto.first = function (predicate, thisArg) {
  	    return predicate ?
  	      this.where(predicate, thisArg).first() :
  	      firstOrDefaultAsync(this, false);
  	  };
  	
  	  /**
  	   * Returns the first element of an observable sequence that satisfies the condition in the predicate, or a default value if no such element exists.
  	   * @param {Function} [predicate] A predicate function to evaluate for elements in the source sequence.
  	   * @param {Any} [defaultValue] The default value if no such element exists.  If not specified, defaults to null.
  	   * @param {Any} [thisArg] Object to use as `this` when executing the predicate.
  	   * @returns {Observable} Sequence containing the first element in the observable sequence that satisfies the condition in the predicate, or a default value if no such element exists.
  	   */
  	  observableProto.firstOrDefault = function (predicate, defaultValue, thisArg) {
  	    return predicate ?
  	      this.where(predicate).firstOrDefault(null, defaultValue) :
  	      firstOrDefaultAsync(this, true, defaultValue);
  	  };
  	
  	  function lastOrDefaultAsync(source, hasDefault, defaultValue) {
  	    return new AnonymousObservable(function (o) {
  	      var value = defaultValue, seenValue = false;
  	      return source.subscribe(function (x) {
  	        value = x;
  	        seenValue = true;
  	      }, function (e) { o.onError(e); }, function () {
  	        if (!seenValue && !hasDefault) {
  	          o.onError(new EmptyError());
  	        } else {
  	          o.onNext(value);
  	          o.onCompleted();
  	        }
  	      });
  	    }, source);
  	  }
  	
  	  /**
  	   * Returns the last element of an observable sequence that satisfies the condition in the predicate if specified, else the last element.
  	   * @param {Function} [predicate] A predicate function to evaluate for elements in the source sequence.
  	   * @param {Any} [thisArg] Object to use as `this` when executing the predicate.
  	   * @returns {Observable} Sequence containing the last element in the observable sequence that satisfies the condition in the predicate.
  	   */
  	  observableProto.last = function (predicate, thisArg) {
  	    return predicate ?
  	      this.where(predicate, thisArg).last() :
  	      lastOrDefaultAsync(this, false);
  	  };
  	
  	  /**
  	   * Returns the last element of an observable sequence that satisfies the condition in the predicate, or a default value if no such element exists.
  	   * @param {Function} [predicate] A predicate function to evaluate for elements in the source sequence.
  	   * @param [defaultValue] The default value if no such element exists.  If not specified, defaults to null.
  	   * @param {Any} [thisArg] Object to use as `this` when executing the predicate.
  	   * @returns {Observable} Sequence containing the last element in the observable sequence that satisfies the condition in the predicate, or a default value if no such element exists.
  	   */
  	  observableProto.lastOrDefault = function (predicate, defaultValue, thisArg) {
  	    return predicate ?
  	      this.where(predicate, thisArg).lastOrDefault(null, defaultValue) :
  	      lastOrDefaultAsync(this, true, defaultValue);
  	  };
  	
  	  function findValue (source, predicate, thisArg, yieldIndex) {
  	    var callback = bindCallback(predicate, thisArg, 3);
  	    return new AnonymousObservable(function (o) {
  	      var i = 0;
  	      return source.subscribe(function (x) {
  	        var shouldRun;
  	        try {
  	          shouldRun = callback(x, i, source);
  	        } catch (e) {
  	          o.onError(e);
  	          return;
  	        }
  	        if (shouldRun) {
  	          o.onNext(yieldIndex ? i : x);
  	          o.onCompleted();
  	        } else {
  	          i++;
  	        }
  	      }, function (e) { o.onError(e); }, function () {
  	        o.onNext(yieldIndex ? -1 : undefined);
  	        o.onCompleted();
  	      });
  	    }, source);
  	  }
  	
  	  /**
  	   * Searches for an element that matches the conditions defined by the specified predicate, and returns the first occurrence within the entire Observable sequence.
  	   * @param {Function} predicate The predicate that defines the conditions of the element to search for.
  	   * @param {Any} [thisArg] Object to use as `this` when executing the predicate.
  	   * @returns {Observable} An Observable sequence with the first element that matches the conditions defined by the specified predicate, if found; otherwise, undefined.
  	   */
  	  observableProto.find = function (predicate, thisArg) {
  	    return findValue(this, predicate, thisArg, false);
  	  };
  	
  	  /**
  	   * Searches for an element that matches the conditions defined by the specified predicate, and returns
  	   * an Observable sequence with the zero-based index of the first occurrence within the entire Observable sequence.
  	   * @param {Function} predicate The predicate that defines the conditions of the element to search for.
  	   * @param {Any} [thisArg] Object to use as `this` when executing the predicate.
  	   * @returns {Observable} An Observable sequence with the zero-based index of the first occurrence of an element that matches the conditions defined by match, if found; otherwise, –1.
  	  */
  	  observableProto.findIndex = function (predicate, thisArg) {
  	    return findValue(this, predicate, thisArg, true);
  	  };
  	
  	  /**
  	   * Converts the observable sequence to a Set if it exists.
  	   * @returns {Observable} An observable sequence with a single value of a Set containing the values from the observable sequence.
  	   */
  	  observableProto.toSet = function () {
  	    if (typeof root.Set === 'undefined') { throw new TypeError(); }
  	    var source = this;
  	    return new AnonymousObservable(function (o) {
  	      var s = new root.Set();
  	      return source.subscribe(
  	        function (x) { s.add(x); },
  	        function (e) { o.onError(e); },
  	        function () {
  	          o.onNext(s);
  	          o.onCompleted();
  	        });
  	    }, source);
  	  };
  	
  	  /**
  	  * Converts the observable sequence to a Map if it exists.
  	  * @param {Function} keySelector A function which produces the key for the Map.
  	  * @param {Function} [elementSelector] An optional function which produces the element for the Map. If not present, defaults to the value from the observable sequence.
  	  * @returns {Observable} An observable sequence with a single value of a Map containing the values from the observable sequence.
  	  */
  	  observableProto.toMap = function (keySelector, elementSelector) {
  	    if (typeof root.Map === 'undefined') { throw new TypeError(); }
  	    var source = this;
  	    return new AnonymousObservable(function (o) {
  	      var m = new root.Map();
  	      return source.subscribe(
  	        function (x) {
  	          var key;
  	          try {
  	            key = keySelector(x);
  	          } catch (e) {
  	            o.onError(e);
  	            return;
  	          }
  	
  	          var element = x;
  	          if (elementSelector) {
  	            try {
  	              element = elementSelector(x);
  	            } catch (e) {
  	              o.onError(e);
  	              return;
  	            }
  	          }
  	
  	          m.set(key, element);
  	        },
  	        function (e) { o.onError(e); },
  	        function () {
  	          o.onNext(m);
  	          o.onCompleted();
  	        });
  	    }, source);
  	  };
  	
  	  var fnString = 'function',
  	      throwString = 'throw',
  	      isObject = Rx.internals.isObject;
  	
  	  function toThunk(obj, ctx) {
  	    if (Array.isArray(obj)) {  return objectToThunk.call(ctx, obj); }
  	    if (isGeneratorFunction(obj)) { return observableSpawn(obj.call(ctx)); }
  	    if (isGenerator(obj)) {  return observableSpawn(obj); }
  	    if (isObservable(obj)) { return observableToThunk(obj); }
  	    if (isPromise(obj)) { return promiseToThunk(obj); }
  	    if (typeof obj === fnString) { return obj; }
  	    if (isObject(obj) || Array.isArray(obj)) { return objectToThunk.call(ctx, obj); }
  	
  	    return obj;
  	  }
  	
  	  function objectToThunk(obj) {
  	    var ctx = this;
  	
  	    return function (done) {
  	      var keys = Object.keys(obj),
  	          pending = keys.length,
  	          results = new obj.constructor(),
  	          finished;
  	
  	      if (!pending) {
  	        timeoutScheduler.schedule(function () { done(null, results); });
  	        return;
  	      }
  	
  	      for (var i = 0, len = keys.length; i < len; i++) {
  	        run(obj[keys[i]], keys[i]);
  	      }
  	
  	      function run(fn, key) {
  	        if (finished) { return; }
  	        try {
  	          fn = toThunk(fn, ctx);
  	
  	          if (typeof fn !== fnString) {
  	            results[key] = fn;
  	            return --pending || done(null, results);
  	          }
  	
  	          fn.call(ctx, function(err, res) {
  	            if (finished) { return; }
  	
  	            if (err) {
  	              finished = true;
  	              return done(err);
  	            }
  	
  	            results[key] = res;
  	            --pending || done(null, results);
  	          });
  	        } catch (e) {
  	          finished = true;
  	          done(e);
  	        }
  	      }
  	    }
  	  }
  	
  	  function observableToThunk(observable) {
  	    return function (fn) {
  	      var value, hasValue = false;
  	      observable.subscribe(
  	        function (v) {
  	          value = v;
  	          hasValue = true;
  	        },
  	        fn,
  	        function () {
  	          hasValue && fn(null, value);
  	        });
  	    }
  	  }
  	
  	  function promiseToThunk(promise) {
  	    return function(fn) {
  	      promise.then(function(res) {
  	        fn(null, res);
  	      }, fn);
  	    }
  	  }
  	
  	  function isObservable(obj) {
  	    return obj && typeof obj.subscribe === fnString;
  	  }
  	
  	  function isGeneratorFunction(obj) {
  	    return obj && obj.constructor && obj.constructor.name === 'GeneratorFunction';
  	  }
  	
  	  function isGenerator(obj) {
  	    return obj && typeof obj.next === fnString && typeof obj[throwString] === fnString;
  	  }
  	
  	  /*
  	   * Spawns a generator function which allows for Promises, Observable sequences, Arrays, Objects, Generators and functions.
  	   * @param {Function} The spawning function.
  	   * @returns {Function} a function which has a done continuation.
  	   */
  	  var observableSpawn = Rx.spawn = function (fn) {
  	    var isGenFun = isGeneratorFunction(fn);
  	
  	    return function (done) {
  	      var ctx = this,
  	        gen = fn;
  	
  	      if (isGenFun) {
  	        for(var args = [], i = 0, len = arguments.length; i < len; i++) { args.push(arguments[i]); }
  	        var len = args.length,
  	          hasCallback = len && typeof args[len - 1] === fnString;
  	
  	        done = hasCallback ? args.pop() : handleError;
  	        gen = fn.apply(this, args);
  	      } else {
  	        done = done || handleError;
  	      }
  	
  	      next();
  	
  	      function exit(err, res) {
  	        timeoutScheduler.schedule(done.bind(ctx, err, res));
  	      }
  	
  	      function next(err, res) {
  	        var ret;
  	
  	        // multiple args
  	        if (arguments.length > 2) {
  	          for(var res = [], i = 1, len = arguments.length; i < len; i++) { res.push(arguments[i]); }
  	        }
  	
  	        if (err) {
  	          try {
  	            ret = gen[throwString](err);
  	          } catch (e) {
  	            return exit(e);
  	          }
  	        }
  	
  	        if (!err) {
  	          try {
  	            ret = gen.next(res);
  	          } catch (e) {
  	            return exit(e);
  	          }
  	        }
  	
  	        if (ret.done)  {
  	          return exit(null, ret.value);
  	        }
  	
  	        ret.value = toThunk(ret.value, ctx);
  	
  	        if (typeof ret.value === fnString) {
  	          var called = false;
  	          try {
  	            ret.value.call(ctx, function() {
  	              if (called) {
  	                return;
  	              }
  	
  	              called = true;
  	              next.apply(ctx, arguments);
  	            });
  	          } catch (e) {
  	            timeoutScheduler.schedule(function () {
  	              if (called) {
  	                return;
  	              }
  	
  	              called = true;
  	              next.call(ctx, e);
  	            });
  	          }
  	          return;
  	        }
  	
  	        // Not supported
  	        next(new TypeError('Rx.spawn only supports a function, Promise, Observable, Object or Array.'));
  	      }
  	    }
  	  };
  	
  	  function handleError(err) {
  	    if (!err) { return; }
  	    timeoutScheduler.schedule(function() {
  	      throw err;
  	    });
  	  }
  	
  	  /**
  	   * Invokes the specified function asynchronously on the specified scheduler, surfacing the result through an observable sequence.
  	   *
  	   * @example
  	   * var res = Rx.Observable.start(function () { console.log('hello'); });
  	   * var res = Rx.Observable.start(function () { console.log('hello'); }, Rx.Scheduler.timeout);
  	   * var res = Rx.Observable.start(function () { this.log('hello'); }, Rx.Scheduler.timeout, console);
  	   *
  	   * @param {Function} func Function to run asynchronously.
  	   * @param {Scheduler} [scheduler]  Scheduler to run the function on. If not specified, defaults to Scheduler.timeout.
  	   * @param [context]  The context for the func parameter to be executed.  If not specified, defaults to undefined.
  	   * @returns {Observable} An observable sequence exposing the function's result value, or an exception.
  	   *
  	   * Remarks
  	   * * The function is called immediately, not during the subscription of the resulting sequence.
  	   * * Multiple subscriptions to the resulting sequence can observe the function's result.
  	   */
  	  Observable.start = function (func, context, scheduler) {
  	    return observableToAsync(func, context, scheduler)();
  	  };
  	
  	  /**
  	   * Converts the function into an asynchronous function. Each invocation of the resulting asynchronous function causes an invocation of the original synchronous function on the specified scheduler.
  	   * @param {Function} function Function to convert to an asynchronous function.
  	   * @param {Scheduler} [scheduler] Scheduler to run the function on. If not specified, defaults to Scheduler.timeout.
  	   * @param {Mixed} [context] The context for the func parameter to be executed.  If not specified, defaults to undefined.
  	   * @returns {Function} Asynchronous function.
  	   */
  	  var observableToAsync = Observable.toAsync = function (func, context, scheduler) {
  	    isScheduler(scheduler) || (scheduler = timeoutScheduler);
  	    return function () {
  	      var args = arguments,
  	        subject = new AsyncSubject();
  	
  	      scheduler.schedule(function () {
  	        var result;
  	        try {
  	          result = func.apply(context, args);
  	        } catch (e) {
  	          subject.onError(e);
  	          return;
  	        }
  	        subject.onNext(result);
  	        subject.onCompleted();
  	      });
  	      return subject.asObservable();
  	    };
  	  };
  	
  	  /**
  	   * Converts a callback function to an observable sequence.
  	   *
  	   * @param {Function} function Function with a callback as the last parameter to convert to an Observable sequence.
  	   * @param {Mixed} [context] The context for the func parameter to be executed.  If not specified, defaults to undefined.
  	   * @param {Function} [selector] A selector which takes the arguments from the callback to produce a single item to yield on next.
  	   * @returns {Function} A function, when executed with the required parameters minus the callback, produces an Observable sequence with a single value of the arguments to the callback as an array.
  	   */
  	  Observable.fromCallback = function (func, context, selector) {
  	    return function () {
  	      var len = arguments.length, args = new Array(len)
  	      for(var i = 0; i < len; i++) { args[i] = arguments[i]; }
  	
  	      return new AnonymousObservable(function (observer) {
  	        function handler() {
  	          var len = arguments.length, results = new Array(len);
  	          for(var i = 0; i < len; i++) { results[i] = arguments[i]; }
  	
  	          if (selector) {
  	            try {
  	              results = selector.apply(context, results);
  	            } catch (e) {
  	              return observer.onError(e);
  	            }
  	
  	            observer.onNext(results);
  	          } else {
  	            if (results.length <= 1) {
  	              observer.onNext.apply(observer, results);
  	            } else {
  	              observer.onNext(results);
  	            }
  	          }
  	
  	          observer.onCompleted();
  	        }
  	
  	        args.push(handler);
  	        func.apply(context, args);
  	      }).publishLast().refCount();
  	    };
  	  };
  	
  	  /**
  	   * Converts a Node.js callback style function to an observable sequence.  This must be in function (err, ...) format.
  	   * @param {Function} func The function to call
  	   * @param {Mixed} [context] The context for the func parameter to be executed.  If not specified, defaults to undefined.
  	   * @param {Function} [selector] A selector which takes the arguments from the callback minus the error to produce a single item to yield on next.
  	   * @returns {Function} An async function which when applied, returns an observable sequence with the callback arguments as an array.
  	   */
  	  Observable.fromNodeCallback = function (func, context, selector) {
  	    return function () {
  	      var len = arguments.length, args = new Array(len);
  	      for(var i = 0; i < len; i++) { args[i] = arguments[i]; }
  	
  	      return new AnonymousObservable(function (observer) {
  	        function handler(err) {
  	          if (err) {
  	            observer.onError(err);
  	            return;
  	          }
  	
  	          var len = arguments.length, results = [];
  	          for(var i = 1; i < len; i++) { results[i - 1] = arguments[i]; }
  	
  	          if (selector) {
  	            try {
  	              results = selector.apply(context, results);
  	            } catch (e) {
  	              return observer.onError(e);
  	            }
  	            observer.onNext(results);
  	          } else {
  	            if (results.length <= 1) {
  	              observer.onNext.apply(observer, results);
  	            } else {
  	              observer.onNext(results);
  	            }
  	          }
  	
  	          observer.onCompleted();
  	        }
  	
  	        args.push(handler);
  	        func.apply(context, args);
  	      }).publishLast().refCount();
  	    };
  	  };
  	
  	  function createListener (element, name, handler) {
  	    if (element.addEventListener) {
  	      element.addEventListener(name, handler, false);
  	      return disposableCreate(function () {
  	        element.removeEventListener(name, handler, false);
  	      });
  	    }
  	    throw new Error('No listener found');
  	  }
  	
  	  function createEventListener (el, eventName, handler) {
  	    var disposables = new CompositeDisposable();
  	
  	    // Asume NodeList or HTMLCollection
  	    var toStr = Object.prototype.toString;
  	    if (toStr.call(el) === '[object NodeList]' || toStr.call(el) === '[object HTMLCollection]') {
  	      for (var i = 0, len = el.length; i < len; i++) {
  	        disposables.add(createEventListener(el.item(i), eventName, handler));
  	      }
  	    } else if (el) {
  	      disposables.add(createListener(el, eventName, handler));
  	    }
  	
  	    return disposables;
  	  }
  	
  	  /**
  	   * Configuration option to determine whether to use native events only
  	   */
  	  Rx.config.useNativeEvents = false;
  	
  	  /**
  	   * Creates an observable sequence by adding an event listener to the matching DOMElement or each item in the NodeList.
  	   *
  	   * @example
  	   *   var source = Rx.Observable.fromEvent(element, 'mouseup');
  	   *
  	   * @param {Object} element The DOMElement or NodeList to attach a listener.
  	   * @param {String} eventName The event name to attach the observable sequence.
  	   * @param {Function} [selector] A selector which takes the arguments from the event handler to produce a single item to yield on next.
  	   * @returns {Observable} An observable sequence of events from the specified element and the specified event.
  	   */
  	  Observable.fromEvent = function (element, eventName, selector) {
  	    // Node.js specific
  	    if (element.addListener) {
  	      return fromEventPattern(
  	        function (h) { element.addListener(eventName, h); },
  	        function (h) { element.removeListener(eventName, h); },
  	        selector);
  	    }
  	
  	    // Use only if non-native events are allowed
  	    if (!Rx.config.useNativeEvents) {
  	      // Handles jq, Angular.js, Zepto, Marionette, Ember.js
  	      if (typeof element.on === 'function' && typeof element.off === 'function') {
  	        return fromEventPattern(
  	          function (h) { element.on(eventName, h); },
  	          function (h) { element.off(eventName, h); },
  	          selector);
  	      }
  	    }
  	    return new AnonymousObservable(function (observer) {
  	      return createEventListener(
  	        element,
  	        eventName,
  	        function handler (e) {
  	          var results = e;
  	
  	          if (selector) {
  	            try {
  	              results = selector(arguments);
  	            } catch (err) {
  	              return observer.onError(err);
  	            }
  	          }
  	
  	          observer.onNext(results);
  	        });
  	    }).publish().refCount();
  	  };
  	
  	  /**
  	   * Creates an observable sequence from an event emitter via an addHandler/removeHandler pair.
  	   * @param {Function} addHandler The function to add a handler to the emitter.
  	   * @param {Function} [removeHandler] The optional function to remove a handler from an emitter.
  	   * @param {Function} [selector] A selector which takes the arguments from the event handler to produce a single item to yield on next.
  	   * @returns {Observable} An observable sequence which wraps an event from an event emitter
  	   */
  	  var fromEventPattern = Observable.fromEventPattern = function (addHandler, removeHandler, selector) {
  	    return new AnonymousObservable(function (observer) {
  	      function innerHandler (e) {
  	        var result = e;
  	        if (selector) {
  	          try {
  	            result = selector(arguments);
  	          } catch (err) {
  	            return observer.onError(err);
  	          }
  	        }
  	        observer.onNext(result);
  	      }
  	
  	      var returnValue = addHandler(innerHandler);
  	      return disposableCreate(function () {
  	        if (removeHandler) {
  	          removeHandler(innerHandler, returnValue);
  	        }
  	      });
  	    }).publish().refCount();
  	  };
  	
  	  /**
  	   * Invokes the asynchronous function, surfacing the result through an observable sequence.
  	   * @param {Function} functionAsync Asynchronous function which returns a Promise to run.
  	   * @returns {Observable} An observable sequence exposing the function's result value, or an exception.
  	   */
  	  Observable.startAsync = function (functionAsync) {
  	    var promise;
  	    try {
  	      promise = functionAsync();
  	    } catch (e) {
  	      return observableThrow(e);
  	    }
  	    return observableFromPromise(promise);
  	  }
  	
  	  var PausableObservable = (function (__super__) {
  	
  	    inherits(PausableObservable, __super__);
  	
  	    function subscribe(observer) {
  	      var conn = this.source.publish(),
  	        subscription = conn.subscribe(observer),
  	        connection = disposableEmpty;
  	
  	      var pausable = this.pauser.distinctUntilChanged().subscribe(function (b) {
  	        if (b) {
  	          connection = conn.connect();
  	        } else {
  	          connection.dispose();
  	          connection = disposableEmpty;
  	        }
  	      });
  	
  	      return new CompositeDisposable(subscription, connection, pausable);
  	    }
  	
  	    function PausableObservable(source, pauser) {
  	      this.source = source;
  	      this.controller = new Subject();
  	
  	      if (pauser && pauser.subscribe) {
  	        this.pauser = this.controller.merge(pauser);
  	      } else {
  	        this.pauser = this.controller;
  	      }
  	
  	      __super__.call(this, subscribe, source);
  	    }
  	
  	    PausableObservable.prototype.pause = function () {
  	      this.controller.onNext(false);
  	    };
  	
  	    PausableObservable.prototype.resume = function () {
  	      this.controller.onNext(true);
  	    };
  	
  	    return PausableObservable;
  	
  	  }(Observable));
  	
  	  /**
  	   * Pauses the underlying observable sequence based upon the observable sequence which yields true/false.
  	   * @example
  	   * var pauser = new Rx.Subject();
  	   * var source = Rx.Observable.interval(100).pausable(pauser);
  	   * @param {Observable} pauser The observable sequence used to pause the underlying sequence.
  	   * @returns {Observable} The observable sequence which is paused based upon the pauser.
  	   */
  	  observableProto.pausable = function (pauser) {
  	    return new PausableObservable(this, pauser);
  	  };
  	
  	  function combineLatestSource(source, subject, resultSelector) {
  	    return new AnonymousObservable(function (o) {
  	      var hasValue = [false, false],
  	        hasValueAll = false,
  	        isDone = false,
  	        values = new Array(2),
  	        err;
  	
  	      function next(x, i) {
  	        values[i] = x
  	        hasValue[i] = true;
  	        if (hasValueAll || (hasValueAll = hasValue.every(identity))) {
  	          if (err) { return o.onError(err); }
  	          var res = tryCatch(resultSelector).apply(null, values);
  	          if (res === errorObj) { return o.onError(res.e); }
  	          o.onNext(res);
  	        }
  	        isDone && values[1] && o.onCompleted();
  	      }
  	
  	      return new CompositeDisposable(
  	        source.subscribe(
  	          function (x) {
  	            next(x, 0);
  	          },
  	          function (e) {
  	            if (values[1]) {
  	              o.onError(e);
  	            } else {
  	              err = e;
  	            }
  	          },
  	          function () {
  	            isDone = true;
  	            values[1] && o.onCompleted();
  	          }),
  	        subject.subscribe(
  	          function (x) {
  	            next(x, 1);
  	          },
  	          function (e) { o.onError(e); },
  	          function () {
  	            isDone = true;
  	            next(true, 1);
  	          })
  	        );
  	    }, source);
  	  }
  	
  	  var PausableBufferedObservable = (function (__super__) {
  	
  	    inherits(PausableBufferedObservable, __super__);
  	
  	    function subscribe(o) {
  	      var q = [], previousShouldFire;
  	
  	      function drainQueue() { while (q.length > 0) { o.onNext(q.shift()); } }
  	
  	      var subscription =
  	        combineLatestSource(
  	          this.source,
  	          this.pauser.distinctUntilChanged().startWith(false),
  	          function (data, shouldFire) {
  	            return { data: data, shouldFire: shouldFire };
  	          })
  	          .subscribe(
  	            function (results) {
  	              if (previousShouldFire !== undefined && results.shouldFire != previousShouldFire) {
  	                previousShouldFire = results.shouldFire;
  	                // change in shouldFire
  	                if (results.shouldFire) { drainQueue(); }
  	              } else {
  	                previousShouldFire = results.shouldFire;
  	                // new data
  	                if (results.shouldFire) {
  	                  o.onNext(results.data);
  	                } else {
  	                  q.push(results.data);
  	                }
  	              }
  	            },
  	            function (err) {
  	              drainQueue();
  	              o.onError(err);
  	            },
  	            function () {
  	              drainQueue();
  	              o.onCompleted();
  	            }
  	          );
  	      return subscription;
  	    }
  	
  	    function PausableBufferedObservable(source, pauser) {
  	      this.source = source;
  	      this.controller = new Subject();
  	
  	      if (pauser && pauser.subscribe) {
  	        this.pauser = this.controller.merge(pauser);
  	      } else {
  	        this.pauser = this.controller;
  	      }
  	
  	      __super__.call(this, subscribe, source);
  	    }
  	
  	    PausableBufferedObservable.prototype.pause = function () {
  	      this.controller.onNext(false);
  	    };
  	
  	    PausableBufferedObservable.prototype.resume = function () {
  	      this.controller.onNext(true);
  	    };
  	
  	    return PausableBufferedObservable;
  	
  	  }(Observable));
  	
  	  /**
  	   * Pauses the underlying observable sequence based upon the observable sequence which yields true/false,
  	   * and yields the values that were buffered while paused.
  	   * @example
  	   * var pauser = new Rx.Subject();
  	   * var source = Rx.Observable.interval(100).pausableBuffered(pauser);
  	   * @param {Observable} pauser The observable sequence used to pause the underlying sequence.
  	   * @returns {Observable} The observable sequence which is paused based upon the pauser.
  	   */
  	  observableProto.pausableBuffered = function (subject) {
  	    return new PausableBufferedObservable(this, subject);
  	  };
  	
  	  var ControlledObservable = (function (__super__) {
  	
  	    inherits(ControlledObservable, __super__);
  	
  	    function subscribe (observer) {
  	      return this.source.subscribe(observer);
  	    }
  	
  	    function ControlledObservable (source, enableQueue, scheduler) {
  	      __super__.call(this, subscribe, source);
  	      this.subject = new ControlledSubject(enableQueue, scheduler);
  	      this.source = source.multicast(this.subject).refCount();
  	    }
  	
  	    ControlledObservable.prototype.request = function (numberOfItems) {
  	      return this.subject.request(numberOfItems == null ? -1 : numberOfItems);
  	    };
  	
  	    return ControlledObservable;
  	
  	  }(Observable));
  	
  	  var ControlledSubject = (function (__super__) {
  	
  	    function subscribe (observer) {
  	      return this.subject.subscribe(observer);
  	    }
  	
  	    inherits(ControlledSubject, __super__);
  	
  	    function ControlledSubject(enableQueue, scheduler) {
  	      enableQueue == null && (enableQueue = true);
  	
  	      __super__.call(this, subscribe);
  	      this.subject = new Subject();
  	      this.enableQueue = enableQueue;
  	      this.queue = enableQueue ? [] : null;
  	      this.requestedCount = 0;
  	      this.requestedDisposable = disposableEmpty;
  	      this.error = null;
  	      this.hasFailed = false;
  	      this.hasCompleted = false;
  	      this.scheduler = scheduler || currentThreadScheduler;
  	    }
  	
  	    addProperties(ControlledSubject.prototype, Observer, {
  	      onCompleted: function () {
  	        this.hasCompleted = true;
  	        if (!this.enableQueue || this.queue.length === 0) {
  	          this.subject.onCompleted();
  	        } else {
  	          this.queue.push(Notification.createOnCompleted());
  	        }
  	      },
  	      onError: function (error) {
  	        this.hasFailed = true;
  	        this.error = error;
  	        if (!this.enableQueue || this.queue.length === 0) {
  	          this.subject.onError(error);
  	        } else {
  	          this.queue.push(Notification.createOnError(error));
  	        }
  	      },
  	      onNext: function (value) {
  	        var hasRequested = false;
  	
  	        if (this.requestedCount === 0) {
  	          this.enableQueue && this.queue.push(Notification.createOnNext(value));
  	        } else {
  	          (this.requestedCount !== -1 && this.requestedCount-- === 0) && this.disposeCurrentRequest();
  	          hasRequested = true;
  	        }
  	        hasRequested && this.subject.onNext(value);
  	      },
  	      _processRequest: function (numberOfItems) {
  	        if (this.enableQueue) {
  	          while ((this.queue.length >= numberOfItems && numberOfItems > 0) ||
  	          (this.queue.length > 0 && this.queue[0].kind !== 'N')) {
  	            var first = this.queue.shift();
  	            first.accept(this.subject);
  	            if (first.kind === 'N') {
  	              numberOfItems--;
  	            } else {
  	              this.disposeCurrentRequest();
  	              this.queue = [];
  	            }
  	          }
  	
  	          return { numberOfItems : numberOfItems, returnValue: this.queue.length !== 0};
  	        }
  	
  	        return { numberOfItems: numberOfItems, returnValue: false };
  	      },
  	      request: function (number) {
  	        this.disposeCurrentRequest();
  	        var self = this;
  	
  	        this.requestedDisposable = this.scheduler.scheduleWithState(number,
  	        function(s, i) {
  	          var r = self._processRequest(i), remaining = r.numberOfItems;
  	          if (!r.returnValue) {
  	            self.requestedCount = remaining;
  	            self.requestedDisposable = disposableCreate(function () {
  	              self.requestedCount = 0;
  	            });
  	          }
  	        });
  	
  	        return this.requestedDisposable;
  	      },
  	      disposeCurrentRequest: function () {
  	        this.requestedDisposable.dispose();
  	        this.requestedDisposable = disposableEmpty;
  	      }
  	    });
  	
  	    return ControlledSubject;
  	  }(Observable));
  	
  	  /**
  	   * Attaches a controller to the observable sequence with the ability to queue.
  	   * @example
  	   * var source = Rx.Observable.interval(100).controlled();
  	   * source.request(3); // Reads 3 values
  	   * @param {bool} enableQueue truthy value to determine if values should be queued pending the next request
  	   * @param {Scheduler} scheduler determines how the requests will be scheduled
  	   * @returns {Observable} The observable sequence which only propagates values on request.
  	   */
  	  observableProto.controlled = function (enableQueue, scheduler) {
  	
  	    if (enableQueue && isScheduler(enableQueue)) {
  	        scheduler = enableQueue;
  	        enableQueue = true;
  	    }
  	
  	    if (enableQueue == null) {  enableQueue = true; }
  	    return new ControlledObservable(this, enableQueue, scheduler);
  	  };
  	
  	  var StopAndWaitObservable = (function (__super__) {
  	
  	    function subscribe (observer) {
  	      this.subscription = this.source.subscribe(new StopAndWaitObserver(observer, this, this.subscription));
  	
  	      var self = this;
  	      timeoutScheduler.schedule(function () { self.source.request(1); });
  	
  	      return this.subscription;
  	    }
  	
  	    inherits(StopAndWaitObservable, __super__);
  	
  	    function StopAndWaitObservable (source) {
  	      __super__.call(this, subscribe, source);
  	      this.source = source;
  	    }
  	
  	    var StopAndWaitObserver = (function (__sub__) {
  	
  	      inherits(StopAndWaitObserver, __sub__);
  	
  	      function StopAndWaitObserver (observer, observable, cancel) {
  	        __sub__.call(this);
  	        this.observer = observer;
  	        this.observable = observable;
  	        this.cancel = cancel;
  	      }
  	
  	      var stopAndWaitObserverProto = StopAndWaitObserver.prototype;
  	
  	      stopAndWaitObserverProto.completed = function () {
  	        this.observer.onCompleted();
  	        this.dispose();
  	      };
  	
  	      stopAndWaitObserverProto.error = function (error) {
  	        this.observer.onError(error);
  	        this.dispose();
  	      }
  	
  	      stopAndWaitObserverProto.next = function (value) {
  	        this.observer.onNext(value);
  	
  	        var self = this;
  	        timeoutScheduler.schedule(function () {
  	          self.observable.source.request(1);
  	        });
  	      };
  	
  	      stopAndWaitObserverProto.dispose = function () {
  	        this.observer = null;
  	        if (this.cancel) {
  	          this.cancel.dispose();
  	          this.cancel = null;
  	        }
  	        __sub__.prototype.dispose.call(this);
  	      };
  	
  	      return StopAndWaitObserver;
  	    }(AbstractObserver));
  	
  	    return StopAndWaitObservable;
  	  }(Observable));
  	
  	
  	  /**
  	   * Attaches a stop and wait observable to the current observable.
  	   * @returns {Observable} A stop and wait observable.
  	   */
  	  ControlledObservable.prototype.stopAndWait = function () {
  	    return new StopAndWaitObservable(this);
  	  };
  	
  	  var WindowedObservable = (function (__super__) {
  	
  	    function subscribe (observer) {
  	      this.subscription = this.source.subscribe(new WindowedObserver(observer, this, this.subscription));
  	
  	      var self = this;
  	      timeoutScheduler.schedule(function () {
  	        self.source.request(self.windowSize);
  	      });
  	
  	      return this.subscription;
  	    }
  	
  	    inherits(WindowedObservable, __super__);
  	
  	    function WindowedObservable(source, windowSize) {
  	      __super__.call(this, subscribe, source);
  	      this.source = source;
  	      this.windowSize = windowSize;
  	    }
  	
  	    var WindowedObserver = (function (__sub__) {
  	
  	      inherits(WindowedObserver, __sub__);
  	
  	      function WindowedObserver(observer, observable, cancel) {
  	        this.observer = observer;
  	        this.observable = observable;
  	        this.cancel = cancel;
  	        this.received = 0;
  	      }
  	
  	      var windowedObserverPrototype = WindowedObserver.prototype;
  	
  	      windowedObserverPrototype.completed = function () {
  	        this.observer.onCompleted();
  	        this.dispose();
  	      };
  	
  	      windowedObserverPrototype.error = function (error) {
  	        this.observer.onError(error);
  	        this.dispose();
  	      };
  	
  	      windowedObserverPrototype.next = function (value) {
  	        this.observer.onNext(value);
  	
  	        this.received = ++this.received % this.observable.windowSize;
  	        if (this.received === 0) {
  	          var self = this;
  	          timeoutScheduler.schedule(function () {
  	            self.observable.source.request(self.observable.windowSize);
  	          });
  	        }
  	      };
  	
  	      windowedObserverPrototype.dispose = function () {
  	        this.observer = null;
  	        if (this.cancel) {
  	          this.cancel.dispose();
  	          this.cancel = null;
  	        }
  	        __sub__.prototype.dispose.call(this);
  	      };
  	
  	      return WindowedObserver;
  	    }(AbstractObserver));
  	
  	    return WindowedObservable;
  	  }(Observable));
  	
  	  /**
  	   * Creates a sliding windowed observable based upon the window size.
  	   * @param {Number} windowSize The number of items in the window
  	   * @returns {Observable} A windowed observable based upon the window size.
  	   */
  	  ControlledObservable.prototype.windowed = function (windowSize) {
  	    return new WindowedObservable(this, windowSize);
  	  };
  	
  	  /**
  	   * Pipes the existing Observable sequence into a Node.js Stream.
  	   * @param {Stream} dest The destination Node.js stream.
  	   * @returns {Stream} The destination stream.
  	   */
  	  observableProto.pipe = function (dest) {
  	    var source = this.pausableBuffered();
  	
  	    function onDrain() {
  	      source.resume();
  	    }
  	
  	    dest.addListener('drain', onDrain);
  	
  	    source.subscribe(
  	      function (x) {
  	        !dest.write(String(x)) && source.pause();
  	      },
  	      function (err) {
  	        dest.emit('error', err);
  	      },
  	      function () {
  	        // Hack check because STDIO is not closable
  	        !dest._isStdio && dest.end();
  	        dest.removeListener('drain', onDrain);
  	      });
  	
  	    source.resume();
  	
  	    return dest;
  	  };
  	
  	  /**
  	   * Multicasts the source sequence notifications through an instantiated subject into all uses of the sequence within a selector function. Each
  	   * subscription to the resulting sequence causes a separate multicast invocation, exposing the sequence resulting from the selector function's
  	   * invocation. For specializations with fixed subject types, see Publish, PublishLast, and Replay.
  	   *
  	   * @example
  	   * 1 - res = source.multicast(observable);
  	   * 2 - res = source.multicast(function () { return new Subject(); }, function (x) { return x; });
  	   *
  	   * @param {Function|Subject} subjectOrSubjectSelector
  	   * Factory function to create an intermediate subject through which the source sequence's elements will be multicast to the selector function.
  	   * Or:
  	   * Subject to push source elements into.
  	   *
  	   * @param {Function} [selector] Optional selector function which can use the multicasted source sequence subject to the policies enforced by the created subject. Specified only if <paramref name="subjectOrSubjectSelector" is a factory function.
  	   * @returns {Observable} An observable sequence that contains the elements of a sequence produced by multicasting the source sequence within a selector function.
  	   */
  	  observableProto.multicast = function (subjectOrSubjectSelector, selector) {
  	    var source = this;
  	    return typeof subjectOrSubjectSelector === 'function' ?
  	      new AnonymousObservable(function (observer) {
  	        var connectable = source.multicast(subjectOrSubjectSelector());
  	        return new CompositeDisposable(selector(connectable).subscribe(observer), connectable.connect());
  	      }, source) :
  	      new ConnectableObservable(source, subjectOrSubjectSelector);
  	  };
  	
  	  /**
  	   * Returns an observable sequence that is the result of invoking the selector on a connectable observable sequence that shares a single subscription to the underlying sequence.
  	   * This operator is a specialization of Multicast using a regular Subject.
  	   *
  	   * @example
  	   * var resres = source.publish();
  	   * var res = source.publish(function (x) { return x; });
  	   *
  	   * @param {Function} [selector] Selector function which can use the multicasted source sequence as many times as needed, without causing multiple subscriptions to the source sequence. Subscribers to the given source will receive all notifications of the source from the time of the subscription on.
  	   * @returns {Observable} An observable sequence that contains the elements of a sequence produced by multicasting the source sequence within a selector function.
  	   */
  	  observableProto.publish = function (selector) {
  	    return selector && isFunction(selector) ?
  	      this.multicast(function () { return new Subject(); }, selector) :
  	      this.multicast(new Subject());
  	  };
  	
  	  /**
  	   * Returns an observable sequence that shares a single subscription to the underlying sequence.
  	   * This operator is a specialization of publish which creates a subscription when the number of observers goes from zero to one, then shares that subscription with all subsequent observers until the number of observers returns to zero, at which point the subscription is disposed.
  	   * @returns {Observable} An observable sequence that contains the elements of a sequence produced by multicasting the source sequence.
  	   */
  	  observableProto.share = function () {
  	    return this.publish().refCount();
  	  };
  	
  	  /**
  	   * Returns an observable sequence that is the result of invoking the selector on a connectable observable sequence that shares a single subscription to the underlying sequence containing only the last notification.
  	   * This operator is a specialization of Multicast using a AsyncSubject.
  	   *
  	   * @example
  	   * var res = source.publishLast();
  	   * var res = source.publishLast(function (x) { return x; });
  	   *
  	   * @param selector [Optional] Selector function which can use the multicasted source sequence as many times as needed, without causing multiple subscriptions to the source sequence. Subscribers to the given source will only receive the last notification of the source.
  	   * @returns {Observable} An observable sequence that contains the elements of a sequence produced by multicasting the source sequence within a selector function.
  	   */
  	  observableProto.publishLast = function (selector) {
  	    return selector && isFunction(selector) ?
  	      this.multicast(function () { return new AsyncSubject(); }, selector) :
  	      this.multicast(new AsyncSubject());
  	  };
  	
  	  /**
  	   * Returns an observable sequence that is the result of invoking the selector on a connectable observable sequence that shares a single subscription to the underlying sequence and starts with initialValue.
  	   * This operator is a specialization of Multicast using a BehaviorSubject.
  	   *
  	   * @example
  	   * var res = source.publishValue(42);
  	   * var res = source.publishValue(function (x) { return x.select(function (y) { return y * y; }) }, 42);
  	   *
  	   * @param {Function} [selector] Optional selector function which can use the multicasted source sequence as many times as needed, without causing multiple subscriptions to the source sequence. Subscribers to the given source will receive immediately receive the initial value, followed by all notifications of the source from the time of the subscription on.
  	   * @param {Mixed} initialValue Initial value received by observers upon subscription.
  	   * @returns {Observable} An observable sequence that contains the elements of a sequence produced by multicasting the source sequence within a selector function.
  	   */
  	  observableProto.publishValue = function (initialValueOrSelector, initialValue) {
  	    return arguments.length === 2 ?
  	      this.multicast(function () {
  	        return new BehaviorSubject(initialValue);
  	      }, initialValueOrSelector) :
  	      this.multicast(new BehaviorSubject(initialValueOrSelector));
  	  };
  	
  	  /**
  	   * Returns an observable sequence that shares a single subscription to the underlying sequence and starts with an initialValue.
  	   * This operator is a specialization of publishValue which creates a subscription when the number of observers goes from zero to one, then shares that subscription with all subsequent observers until the number of observers returns to zero, at which point the subscription is disposed.
  	   * @param {Mixed} initialValue Initial value received by observers upon subscription.
  	   * @returns {Observable} An observable sequence that contains the elements of a sequence produced by multicasting the source sequence.
  	   */
  	  observableProto.shareValue = function (initialValue) {
  	    return this.publishValue(initialValue).refCount();
  	  };
  	
  	  /**
  	   * Returns an observable sequence that is the result of invoking the selector on a connectable observable sequence that shares a single subscription to the underlying sequence replaying notifications subject to a maximum time length for the replay buffer.
  	   * This operator is a specialization of Multicast using a ReplaySubject.
  	   *
  	   * @example
  	   * var res = source.replay(null, 3);
  	   * var res = source.replay(null, 3, 500);
  	   * var res = source.replay(null, 3, 500, scheduler);
  	   * var res = source.replay(function (x) { return x.take(6).repeat(); }, 3, 500, scheduler);
  	   *
  	   * @param selector [Optional] Selector function which can use the multicasted source sequence as many times as needed, without causing multiple subscriptions to the source sequence. Subscribers to the given source will receive all the notifications of the source subject to the specified replay buffer trimming policy.
  	   * @param bufferSize [Optional] Maximum element count of the replay buffer.
  	   * @param windowSize [Optional] Maximum time length of the replay buffer.
  	   * @param scheduler [Optional] Scheduler where connected observers within the selector function will be invoked on.
  	   * @returns {Observable} An observable sequence that contains the elements of a sequence produced by multicasting the source sequence within a selector function.
  	   */
  	  observableProto.replay = function (selector, bufferSize, windowSize, scheduler) {
  	    return selector && isFunction(selector) ?
  	      this.multicast(function () { return new ReplaySubject(bufferSize, windowSize, scheduler); }, selector) :
  	      this.multicast(new ReplaySubject(bufferSize, windowSize, scheduler));
  	  };
  	
  	  /**
  	   * Returns an observable sequence that shares a single subscription to the underlying sequence replaying notifications subject to a maximum time length for the replay buffer.
  	   * This operator is a specialization of replay which creates a subscription when the number of observers goes from zero to one, then shares that subscription with all subsequent observers until the number of observers returns to zero, at which point the subscription is disposed.
  	   *
  	   * @example
  	   * var res = source.shareReplay(3);
  	   * var res = source.shareReplay(3, 500);
  	   * var res = source.shareReplay(3, 500, scheduler);
  	   *
  	
  	   * @param bufferSize [Optional] Maximum element count of the replay buffer.
  	   * @param window [Optional] Maximum time length of the replay buffer.
  	   * @param scheduler [Optional] Scheduler where connected observers within the selector function will be invoked on.
  	   * @returns {Observable} An observable sequence that contains the elements of a sequence produced by multicasting the source sequence.
  	   */
  	  observableProto.shareReplay = function (bufferSize, windowSize, scheduler) {
  	    return this.replay(null, bufferSize, windowSize, scheduler).refCount();
  	  };
  	
  	  var InnerSubscription = function (subject, observer) {
  	    this.subject = subject;
  	    this.observer = observer;
  	  };
  	
  	  InnerSubscription.prototype.dispose = function () {
  	    if (!this.subject.isDisposed && this.observer !== null) {
  	      var idx = this.subject.observers.indexOf(this.observer);
  	      this.subject.observers.splice(idx, 1);
  	      this.observer = null;
  	    }
  	  };
  	
  	  /**
  	   *  Represents a value that changes over time.
  	   *  Observers can subscribe to the subject to receive the last (or initial) value and all subsequent notifications.
  	   */
  	  var BehaviorSubject = Rx.BehaviorSubject = (function (__super__) {
  	    function subscribe(observer) {
  	      checkDisposed(this);
  	      if (!this.isStopped) {
  	        this.observers.push(observer);
  	        observer.onNext(this.value);
  	        return new InnerSubscription(this, observer);
  	      }
  	      if (this.hasError) {
  	        observer.onError(this.error);
  	      } else {
  	        observer.onCompleted();
  	      }
  	      return disposableEmpty;
  	    }
  	
  	    inherits(BehaviorSubject, __super__);
  	
  	    /**
  	     *  Initializes a new instance of the BehaviorSubject class which creates a subject that caches its last value and starts with the specified value.
  	     *  @param {Mixed} value Initial value sent to observers when no other value has been received by the subject yet.
  	     */
  	    function BehaviorSubject(value) {
  	      __super__.call(this, subscribe);
  	      this.value = value,
  	      this.observers = [],
  	      this.isDisposed = false,
  	      this.isStopped = false,
  	      this.hasError = false;
  	    }
  	
  	    addProperties(BehaviorSubject.prototype, Observer, {
  	      /**
  	       * Gets the current value or throws an exception.
  	       * Value is frozen after onCompleted is called.
  	       * After onError is called always throws the specified exception.
  	       * An exception is always thrown after dispose is called.
  	       * @returns {Mixed} The initial value passed to the constructor until onNext is called; after which, the last value passed to onNext.
  	       */
  	      getValue: function () {
  	          checkDisposed(this);
  	          if (this.hasError) {
  	              throw this.error;
  	          }
  	          return this.value;
  	      },
  	      /**
  	       * Indicates whether the subject has observers subscribed to it.
  	       * @returns {Boolean} Indicates whether the subject has observers subscribed to it.
  	       */
  	      hasObservers: function () { return this.observers.length > 0; },
  	      /**
  	       * Notifies all subscribed observers about the end of the sequence.
  	       */
  	      onCompleted: function () {
  	        checkDisposed(this);
  	        if (this.isStopped) { return; }
  	        this.isStopped = true;
  	        for (var i = 0, os = cloneArray(this.observers), len = os.length; i < len; i++) {
  	          os[i].onCompleted();
  	        }
  	
  	        this.observers.length = 0;
  	      },
  	      /**
  	       * Notifies all subscribed observers about the exception.
  	       * @param {Mixed} error The exception to send to all observers.
  	       */
  	      onError: function (error) {
  	        checkDisposed(this);
  	        if (this.isStopped) { return; }
  	        this.isStopped = true;
  	        this.hasError = true;
  	        this.error = error;
  	
  	        for (var i = 0, os = cloneArray(this.observers), len = os.length; i < len; i++) {
  	          os[i].onError(error);
  	        }
  	
  	        this.observers.length = 0;
  	      },
  	      /**
  	       * Notifies all subscribed observers about the arrival of the specified element in the sequence.
  	       * @param {Mixed} value The value to send to all observers.
  	       */
  	      onNext: function (value) {
  	        checkDisposed(this);
  	        if (this.isStopped) { return; }
  	        this.value = value;
  	        for (var i = 0, os = cloneArray(this.observers), len = os.length; i < len; i++) {
  	          os[i].onNext(value);
  	        }
  	      },
  	      /**
  	       * Unsubscribe all observers and release resources.
  	       */
  	      dispose: function () {
  	        this.isDisposed = true;
  	        this.observers = null;
  	        this.value = null;
  	        this.exception = null;
  	      }
  	    });
  	
  	    return BehaviorSubject;
  	  }(Observable));
  	
  	  /**
  	   * Represents an object that is both an observable sequence as well as an observer.
  	   * Each notification is broadcasted to all subscribed and future observers, subject to buffer trimming policies.
  	   */
  	  var ReplaySubject = Rx.ReplaySubject = (function (__super__) {
  	
  	    var maxSafeInteger = Math.pow(2, 53) - 1;
  	
  	    function createRemovableDisposable(subject, observer) {
  	      return disposableCreate(function () {
  	        observer.dispose();
  	        !subject.isDisposed && subject.observers.splice(subject.observers.indexOf(observer), 1);
  	      });
  	    }
  	
  	    function subscribe(observer) {
  	      var so = new ScheduledObserver(this.scheduler, observer),
  	        subscription = createRemovableDisposable(this, so);
  	      checkDisposed(this);
  	      this._trim(this.scheduler.now());
  	      this.observers.push(so);
  	
  	      for (var i = 0, len = this.q.length; i < len; i++) {
  	        so.onNext(this.q[i].value);
  	      }
  	
  	      if (this.hasError) {
  	        so.onError(this.error);
  	      } else if (this.isStopped) {
  	        so.onCompleted();
  	      }
  	
  	      so.ensureActive();
  	      return subscription;
  	    }
  	
  	    inherits(ReplaySubject, __super__);
  	
  	    /**
  	     *  Initializes a new instance of the ReplaySubject class with the specified buffer size, window size and scheduler.
  	     *  @param {Number} [bufferSize] Maximum element count of the replay buffer.
  	     *  @param {Number} [windowSize] Maximum time length of the replay buffer.
  	     *  @param {Scheduler} [scheduler] Scheduler the observers are invoked on.
  	     */
  	    function ReplaySubject(bufferSize, windowSize, scheduler) {
  	      this.bufferSize = bufferSize == null ? maxSafeInteger : bufferSize;
  	      this.windowSize = windowSize == null ? maxSafeInteger : windowSize;
  	      this.scheduler = scheduler || currentThreadScheduler;
  	      this.q = [];
  	      this.observers = [];
  	      this.isStopped = false;
  	      this.isDisposed = false;
  	      this.hasError = false;
  	      this.error = null;
  	      __super__.call(this, subscribe);
  	    }
  	
  	    addProperties(ReplaySubject.prototype, Observer.prototype, {
  	      /**
  	       * Indicates whether the subject has observers subscribed to it.
  	       * @returns {Boolean} Indicates whether the subject has observers subscribed to it.
  	       */
  	      hasObservers: function () {
  	        return this.observers.length > 0;
  	      },
  	      _trim: function (now) {
  	        while (this.q.length > this.bufferSize) {
  	          this.q.shift();
  	        }
  	        while (this.q.length > 0 && (now - this.q[0].interval) > this.windowSize) {
  	          this.q.shift();
  	        }
  	      },
  	      /**
  	       * Notifies all subscribed observers about the arrival of the specified element in the sequence.
  	       * @param {Mixed} value The value to send to all observers.
  	       */
  	      onNext: function (value) {
  	        checkDisposed(this);
  	        if (this.isStopped) { return; }
  	        var now = this.scheduler.now();
  	        this.q.push({ interval: now, value: value });
  	        this._trim(now);
  	
  	        for (var i = 0, os = cloneArray(this.observers), len = os.length; i < len; i++) {
  	          var observer = os[i];
  	          observer.onNext(value);
  	          observer.ensureActive();
  	        }
  	      },
  	      /**
  	       * Notifies all subscribed observers about the exception.
  	       * @param {Mixed} error The exception to send to all observers.
  	       */
  	      onError: function (error) {
  	        checkDisposed(this);
  	        if (this.isStopped) { return; }
  	        this.isStopped = true;
  	        this.error = error;
  	        this.hasError = true;
  	        var now = this.scheduler.now();
  	        this._trim(now);
  	        for (var i = 0, os = cloneArray(this.observers), len = os.length; i < len; i++) {
  	          var observer = os[i];
  	          observer.onError(error);
  	          observer.ensureActive();
  	        }
  	        this.observers.length = 0;
  	      },
  	      /**
  	       * Notifies all subscribed observers about the end of the sequence.
  	       */
  	      onCompleted: function () {
  	        checkDisposed(this);
  	        if (this.isStopped) { return; }
  	        this.isStopped = true;
  	        var now = this.scheduler.now();
  	        this._trim(now);
  	        for (var i = 0, os = cloneArray(this.observers), len = os.length; i < len; i++) {
  	          var observer = os[i];
  	          observer.onCompleted();
  	          observer.ensureActive();
  	        }
  	        this.observers.length = 0;
  	      },
  	      /**
  	       * Unsubscribe all observers and release resources.
  	       */
  	      dispose: function () {
  	        this.isDisposed = true;
  	        this.observers = null;
  	      }
  	    });
  	
  	    return ReplaySubject;
  	  }(Observable));
  	
  	  var ConnectableObservable = Rx.ConnectableObservable = (function (__super__) {
  	    inherits(ConnectableObservable, __super__);
  	
  	    function ConnectableObservable(source, subject) {
  	      var hasSubscription = false,
  	        subscription,
  	        sourceObservable = source.asObservable();
  	
  	      this.connect = function () {
  	        if (!hasSubscription) {
  	          hasSubscription = true;
  	          subscription = new CompositeDisposable(sourceObservable.subscribe(subject), disposableCreate(function () {
  	            hasSubscription = false;
  	          }));
  	        }
  	        return subscription;
  	      };
  	
  	      __super__.call(this, function (o) { return subject.subscribe(o); });
  	    }
  	
  	    ConnectableObservable.prototype.refCount = function () {
  	      var connectableSubscription, count = 0, source = this;
  	      return new AnonymousObservable(function (observer) {
  	          var shouldConnect = ++count === 1,
  	            subscription = source.subscribe(observer);
  	          shouldConnect && (connectableSubscription = source.connect());
  	          return function () {
  	            subscription.dispose();
  	            --count === 0 && connectableSubscription.dispose();
  	          };
  	      });
  	    };
  	
  	    return ConnectableObservable;
  	  }(Observable));
  	
  	  /**
  	   * Returns an observable sequence that shares a single subscription to the underlying sequence. This observable sequence
  	   * can be resubscribed to, even if all prior subscriptions have ended. (unlike `.publish().refCount()`)
  	   * @returns {Observable} An observable sequence that contains the elements of a sequence produced by multicasting the source.
  	   */
  	  observableProto.singleInstance = function() {
  	    var source = this, hasObservable = false, observable;
  	
  	    function getObservable() {
  	      if (!hasObservable) {
  	        hasObservable = true;
  	        observable = source.finally(function() { hasObservable = false; }).publish().refCount();
  	      }
  	      return observable;
  	    };
  	
  	    return new AnonymousObservable(function(o) {
  	      return getObservable().subscribe(o);
  	    });
  	  };
  	
  	  var Dictionary = (function () {
  	
  	    var primes = [1, 3, 7, 13, 31, 61, 127, 251, 509, 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071, 262139, 524287, 1048573, 2097143, 4194301, 8388593, 16777213, 33554393, 67108859, 134217689, 268435399, 536870909, 1073741789, 2147483647],
  	      noSuchkey = "no such key",
  	      duplicatekey = "duplicate key";
  	
  	    function isPrime(candidate) {
  	      if ((candidate & 1) === 0) { return candidate === 2; }
  	      var num1 = Math.sqrt(candidate),
  	        num2 = 3;
  	      while (num2 <= num1) {
  	        if (candidate % num2 === 0) { return false; }
  	        num2 += 2;
  	      }
  	      return true;
  	    }
  	
  	    function getPrime(min) {
  	      var index, num, candidate;
  	      for (index = 0; index < primes.length; ++index) {
  	        num = primes[index];
  	        if (num >= min) { return num; }
  	      }
  	      candidate = min | 1;
  	      while (candidate < primes[primes.length - 1]) {
  	        if (isPrime(candidate)) { return candidate; }
  	        candidate += 2;
  	      }
  	      return min;
  	    }
  	
  	    function stringHashFn(str) {
  	      var hash = 757602046;
  	      if (!str.length) { return hash; }
  	      for (var i = 0, len = str.length; i < len; i++) {
  	        var character = str.charCodeAt(i);
  	        hash = ((hash << 5) - hash) + character;
  	        hash = hash & hash;
  	      }
  	      return hash;
  	    }
  	
  	    function numberHashFn(key) {
  	      var c2 = 0x27d4eb2d;
  	      key = (key ^ 61) ^ (key >>> 16);
  	      key = key + (key << 3);
  	      key = key ^ (key >>> 4);
  	      key = key * c2;
  	      key = key ^ (key >>> 15);
  	      return key;
  	    }
  	
  	    var getHashCode = (function () {
  	      var uniqueIdCounter = 0;
  	
  	      return function (obj) {
  	        if (obj == null) { throw new Error(noSuchkey); }
  	
  	        // Check for built-ins before tacking on our own for any object
  	        if (typeof obj === 'string') { return stringHashFn(obj); }
  	        if (typeof obj === 'number') { return numberHashFn(obj); }
  	        if (typeof obj === 'boolean') { return obj === true ? 1 : 0; }
  	        if (obj instanceof Date) { return numberHashFn(obj.valueOf()); }
  	        if (obj instanceof RegExp) { return stringHashFn(obj.toString()); }
  	        if (typeof obj.valueOf === 'function') {
  	          // Hack check for valueOf
  	          var valueOf = obj.valueOf();
  	          if (typeof valueOf === 'number') { return numberHashFn(valueOf); }
  	          if (typeof valueOf === 'string') { return stringHashFn(valueOf); }
  	        }
  	        if (obj.hashCode) { return obj.hashCode(); }
  	
  	        var id = 17 * uniqueIdCounter++;
  	        obj.hashCode = function () { return id; };
  	        return id;
  	      };
  	    }());
  	
  	    function newEntry() {
  	      return { key: null, value: null, next: 0, hashCode: 0 };
  	    }
  	
  	    function Dictionary(capacity, comparer) {
  	      if (capacity < 0) { throw new ArgumentOutOfRangeError(); }
  	      if (capacity > 0) { this._initialize(capacity); }
  	
  	      this.comparer = comparer || defaultComparer;
  	      this.freeCount = 0;
  	      this.size = 0;
  	      this.freeList = -1;
  	    }
  	
  	    var dictionaryProto = Dictionary.prototype;
  	
  	    dictionaryProto._initialize = function (capacity) {
  	      var prime = getPrime(capacity), i;
  	      this.buckets = new Array(prime);
  	      this.entries = new Array(prime);
  	      for (i = 0; i < prime; i++) {
  	        this.buckets[i] = -1;
  	        this.entries[i] = newEntry();
  	      }
  	      this.freeList = -1;
  	    };
  	
  	    dictionaryProto.add = function (key, value) {
  	      this._insert(key, value, true);
  	    };
  	
  	    dictionaryProto._insert = function (key, value, add) {
  	      if (!this.buckets) { this._initialize(0); }
  	      var index3,
  	        num = getHashCode(key) & 2147483647,
  	        index1 = num % this.buckets.length;
  	      for (var index2 = this.buckets[index1]; index2 >= 0; index2 = this.entries[index2].next) {
  	        if (this.entries[index2].hashCode === num && this.comparer(this.entries[index2].key, key)) {
  	          if (add) { throw new Error(duplicatekey); }
  	          this.entries[index2].value = value;
  	          return;
  	        }
  	      }
  	      if (this.freeCount > 0) {
  	        index3 = this.freeList;
  	        this.freeList = this.entries[index3].next;
  	        --this.freeCount;
  	      } else {
  	        if (this.size === this.entries.length) {
  	          this._resize();
  	          index1 = num % this.buckets.length;
  	        }
  	        index3 = this.size;
  	        ++this.size;
  	      }
  	      this.entries[index3].hashCode = num;
  	      this.entries[index3].next = this.buckets[index1];
  	      this.entries[index3].key = key;
  	      this.entries[index3].value = value;
  	      this.buckets[index1] = index3;
  	    };
  	
  	    dictionaryProto._resize = function () {
  	      var prime = getPrime(this.size * 2),
  	        numArray = new Array(prime);
  	      for (index = 0; index < numArray.length; ++index) {  numArray[index] = -1; }
  	      var entryArray = new Array(prime);
  	      for (index = 0; index < this.size; ++index) { entryArray[index] = this.entries[index]; }
  	      for (var index = this.size; index < prime; ++index) { entryArray[index] = newEntry(); }
  	      for (var index1 = 0; index1 < this.size; ++index1) {
  	        var index2 = entryArray[index1].hashCode % prime;
  	        entryArray[index1].next = numArray[index2];
  	        numArray[index2] = index1;
  	      }
  	      this.buckets = numArray;
  	      this.entries = entryArray;
  	    };
  	
  	    dictionaryProto.remove = function (key) {
  	      if (this.buckets) {
  	        var num = getHashCode(key) & 2147483647,
  	          index1 = num % this.buckets.length,
  	          index2 = -1;
  	        for (var index3 = this.buckets[index1]; index3 >= 0; index3 = this.entries[index3].next) {
  	          if (this.entries[index3].hashCode === num && this.comparer(this.entries[index3].key, key)) {
  	            if (index2 < 0) {
  	              this.buckets[index1] = this.entries[index3].next;
  	            } else {
  	              this.entries[index2].next = this.entries[index3].next;
  	            }
  	            this.entries[index3].hashCode = -1;
  	            this.entries[index3].next = this.freeList;
  	            this.entries[index3].key = null;
  	            this.entries[index3].value = null;
  	            this.freeList = index3;
  	            ++this.freeCount;
  	            return true;
  	          } else {
  	            index2 = index3;
  	          }
  	        }
  	      }
  	      return false;
  	    };
  	
  	    dictionaryProto.clear = function () {
  	      var index, len;
  	      if (this.size <= 0) { return; }
  	      for (index = 0, len = this.buckets.length; index < len; ++index) {
  	        this.buckets[index] = -1;
  	      }
  	      for (index = 0; index < this.size; ++index) {
  	        this.entries[index] = newEntry();
  	      }
  	      this.freeList = -1;
  	      this.size = 0;
  	    };
  	
  	    dictionaryProto._findEntry = function (key) {
  	      if (this.buckets) {
  	        var num = getHashCode(key) & 2147483647;
  	        for (var index = this.buckets[num % this.buckets.length]; index >= 0; index = this.entries[index].next) {
  	          if (this.entries[index].hashCode === num && this.comparer(this.entries[index].key, key)) {
  	            return index;
  	          }
  	        }
  	      }
  	      return -1;
  	    };
  	
  	    dictionaryProto.count = function () {
  	      return this.size - this.freeCount;
  	    };
  	
  	    dictionaryProto.tryGetValue = function (key) {
  	      var entry = this._findEntry(key);
  	      return entry >= 0 ?
  	        this.entries[entry].value :
  	        undefined;
  	    };
  	
  	    dictionaryProto.getValues = function () {
  	      var index = 0, results = [];
  	      if (this.entries) {
  	        for (var index1 = 0; index1 < this.size; index1++) {
  	          if (this.entries[index1].hashCode >= 0) {
  	            results[index++] = this.entries[index1].value;
  	          }
  	        }
  	      }
  	      return results;
  	    };
  	
  	    dictionaryProto.get = function (key) {
  	      var entry = this._findEntry(key);
  	      if (entry >= 0) { return this.entries[entry].value; }
  	      throw new Error(noSuchkey);
  	    };
  	
  	    dictionaryProto.set = function (key, value) {
  	      this._insert(key, value, false);
  	    };
  	
  	    dictionaryProto.containskey = function (key) {
  	      return this._findEntry(key) >= 0;
  	    };
  	
  	    return Dictionary;
  	  }());
  	
  	  /**
  	   *  Correlates the elements of two sequences based on overlapping durations.
  	   *
  	   *  @param {Observable} right The right observable sequence to join elements for.
  	   *  @param {Function} leftDurationSelector A function to select the duration (expressed as an observable sequence) of each element of the left observable sequence, used to determine overlap.
  	   *  @param {Function} rightDurationSelector A function to select the duration (expressed as an observable sequence) of each element of the right observable sequence, used to determine overlap.
  	   *  @param {Function} resultSelector A function invoked to compute a result element for any two overlapping elements of the left and right observable sequences. The parameters passed to the function correspond with the elements from the left and right source sequences for which overlap occurs.
  	   *  @returns {Observable} An observable sequence that contains result elements computed from source elements that have an overlapping duration.
  	   */
  	  observableProto.join = function (right, leftDurationSelector, rightDurationSelector, resultSelector) {
  	    var left = this;
  	    return new AnonymousObservable(function (observer) {
  	      var group = new CompositeDisposable();
  	      var leftDone = false, rightDone = false;
  	      var leftId = 0, rightId = 0;
  	      var leftMap = new Dictionary(), rightMap = new Dictionary();
  	
  	      group.add(left.subscribe(
  	        function (value) {
  	          var id = leftId++;
  	          var md = new SingleAssignmentDisposable();
  	
  	          leftMap.add(id, value);
  	          group.add(md);
  	
  	          var expire = function () {
  	            leftMap.remove(id) && leftMap.count() === 0 && leftDone && observer.onCompleted();
  	            group.remove(md);
  	          };
  	
  	          var duration;
  	          try {
  	            duration = leftDurationSelector(value);
  	          } catch (e) {
  	            observer.onError(e);
  	            return;
  	          }
  	
  	          md.setDisposable(duration.take(1).subscribe(noop, observer.onError.bind(observer), expire));
  	
  	          rightMap.getValues().forEach(function (v) {
  	            var result;
  	            try {
  	              result = resultSelector(value, v);
  	            } catch (exn) {
  	              observer.onError(exn);
  	              return;
  	            }
  	
  	            observer.onNext(result);
  	          });
  	        },
  	        observer.onError.bind(observer),
  	        function () {
  	          leftDone = true;
  	          (rightDone || leftMap.count() === 0) && observer.onCompleted();
  	        })
  	      );
  	
  	      group.add(right.subscribe(
  	        function (value) {
  	          var id = rightId++;
  	          var md = new SingleAssignmentDisposable();
  	
  	          rightMap.add(id, value);
  	          group.add(md);
  	
  	          var expire = function () {
  	            rightMap.remove(id) && rightMap.count() === 0 && rightDone && observer.onCompleted();
  	            group.remove(md);
  	          };
  	
  	          var duration;
  	          try {
  	            duration = rightDurationSelector(value);
  	          } catch (e) {
  	            observer.onError(e);
  	            return;
  	          }
  	
  	          md.setDisposable(duration.take(1).subscribe(noop, observer.onError.bind(observer), expire));
  	
  	          leftMap.getValues().forEach(function (v) {
  	            var result;
  	            try {
  	              result = resultSelector(v, value);
  	            } catch (exn) {
  	              observer.onError(exn);
  	              return;
  	            }
  	
  	            observer.onNext(result);
  	          });
  	        },
  	        observer.onError.bind(observer),
  	        function () {
  	          rightDone = true;
  	          (leftDone || rightMap.count() === 0) && observer.onCompleted();
  	        })
  	      );
  	      return group;
  	    }, left);
  	  };
  	
  	  /**
  	   *  Correlates the elements of two sequences based on overlapping durations, and groups the results.
  	   *
  	   *  @param {Observable} right The right observable sequence to join elements for.
  	   *  @param {Function} leftDurationSelector A function to select the duration (expressed as an observable sequence) of each element of the left observable sequence, used to determine overlap.
  	   *  @param {Function} rightDurationSelector A function to select the duration (expressed as an observable sequence) of each element of the right observable sequence, used to determine overlap.
  	   *  @param {Function} resultSelector A function invoked to compute a result element for any element of the left sequence with overlapping elements from the right observable sequence. The first parameter passed to the function is an element of the left sequence. The second parameter passed to the function is an observable sequence with elements from the right sequence that overlap with the left sequence's element.
  	   *  @returns {Observable} An observable sequence that contains result elements computed from source elements that have an overlapping duration.
  	   */
  	  observableProto.groupJoin = function (right, leftDurationSelector, rightDurationSelector, resultSelector) {
  	    var left = this;
  	    return new AnonymousObservable(function (observer) {
  	      var group = new CompositeDisposable();
  	      var r = new RefCountDisposable(group);
  	      var leftMap = new Dictionary(), rightMap = new Dictionary();
  	      var leftId = 0, rightId = 0;
  	
  	      function handleError(e) { return function (v) { v.onError(e); }; };
  	
  	      group.add(left.subscribe(
  	        function (value) {
  	          var s = new Subject();
  	          var id = leftId++;
  	          leftMap.add(id, s);
  	
  	          var result;
  	          try {
  	            result = resultSelector(value, addRef(s, r));
  	          } catch (e) {
  	            leftMap.getValues().forEach(handleError(e));
  	            observer.onError(e);
  	            return;
  	          }
  	          observer.onNext(result);
  	
  	          rightMap.getValues().forEach(function (v) { s.onNext(v); });
  	
  	          var md = new SingleAssignmentDisposable();
  	          group.add(md);
  	
  	          var expire = function () {
  	            leftMap.remove(id) && s.onCompleted();
  	            group.remove(md);
  	          };
  	
  	          var duration;
  	          try {
  	            duration = leftDurationSelector(value);
  	          } catch (e) {
  	            leftMap.getValues().forEach(handleError(e));
  	            observer.onError(e);
  	            return;
  	          }
  	
  	          md.setDisposable(duration.take(1).subscribe(
  	            noop,
  	            function (e) {
  	              leftMap.getValues().forEach(handleError(e));
  	              observer.onError(e);
  	            },
  	            expire)
  	          );
  	        },
  	        function (e) {
  	          leftMap.getValues().forEach(handleError(e));
  	          observer.onError(e);
  	        },
  	        observer.onCompleted.bind(observer))
  	      );
  	
  	      group.add(right.subscribe(
  	        function (value) {
  	          var id = rightId++;
  	          rightMap.add(id, value);
  	
  	          var md = new SingleAssignmentDisposable();
  	          group.add(md);
  	
  	          var expire = function () {
  	            rightMap.remove(id);
  	            group.remove(md);
  	          };
  	
  	          var duration;
  	          try {
  	            duration = rightDurationSelector(value);
  	          } catch (e) {
  	            leftMap.getValues().forEach(handleError(e));
  	            observer.onError(e);
  	            return;
  	          }
  	          md.setDisposable(duration.take(1).subscribe(
  	            noop,
  	            function (e) {
  	              leftMap.getValues().forEach(handleError(e));
  	              observer.onError(e);
  	            },
  	            expire)
  	          );
  	
  	          leftMap.getValues().forEach(function (v) { v.onNext(value); });
  	        },
  	        function (e) {
  	          leftMap.getValues().forEach(handleError(e));
  	          observer.onError(e);
  	        })
  	      );
  	
  	      return r;
  	    }, left);
  	  };
  	
  	    /**
  	     *  Projects each element of an observable sequence into zero or more buffers.
  	     *
  	     *  @param {Mixed} bufferOpeningsOrClosingSelector Observable sequence whose elements denote the creation of new windows, or, a function invoked to define the boundaries of the produced windows (a new window is started when the previous one is closed, resulting in non-overlapping windows).
  	     *  @param {Function} [bufferClosingSelector] A function invoked to define the closing of each produced window. If a closing selector function is specified for the first parameter, this parameter is ignored.
  	     *  @returns {Observable} An observable sequence of windows.
  	     */
  	    observableProto.buffer = function (bufferOpeningsOrClosingSelector, bufferClosingSelector) {
  	        return this.window.apply(this, arguments).selectMany(function (x) { return x.toArray(); });
  	    };
  	
  	  /**
  	   *  Projects each element of an observable sequence into zero or more windows.
  	   *
  	   *  @param {Mixed} windowOpeningsOrClosingSelector Observable sequence whose elements denote the creation of new windows, or, a function invoked to define the boundaries of the produced windows (a new window is started when the previous one is closed, resulting in non-overlapping windows).
  	   *  @param {Function} [windowClosingSelector] A function invoked to define the closing of each produced window. If a closing selector function is specified for the first parameter, this parameter is ignored.
  	   *  @returns {Observable} An observable sequence of windows.
  	   */
  	  observableProto.window = function (windowOpeningsOrClosingSelector, windowClosingSelector) {
  	    if (arguments.length === 1 && typeof arguments[0] !== 'function') {
  	      return observableWindowWithBoundaries.call(this, windowOpeningsOrClosingSelector);
  	    }
  	    return typeof windowOpeningsOrClosingSelector === 'function' ?
  	      observableWindowWithClosingSelector.call(this, windowOpeningsOrClosingSelector) :
  	      observableWindowWithOpenings.call(this, windowOpeningsOrClosingSelector, windowClosingSelector);
  	  };
  	
  	  function observableWindowWithOpenings(windowOpenings, windowClosingSelector) {
  	    return windowOpenings.groupJoin(this, windowClosingSelector, observableEmpty, function (_, win) {
  	      return win;
  	    });
  	  }
  	
  	  function observableWindowWithBoundaries(windowBoundaries) {
  	    var source = this;
  	    return new AnonymousObservable(function (observer) {
  	      var win = new Subject(),
  	        d = new CompositeDisposable(),
  	        r = new RefCountDisposable(d);
  	
  	      observer.onNext(addRef(win, r));
  	
  	      d.add(source.subscribe(function (x) {
  	        win.onNext(x);
  	      }, function (err) {
  	        win.onError(err);
  	        observer.onError(err);
  	      }, function () {
  	        win.onCompleted();
  	        observer.onCompleted();
  	      }));
  	
  	      isPromise(windowBoundaries) && (windowBoundaries = observableFromPromise(windowBoundaries));
  	
  	      d.add(windowBoundaries.subscribe(function (w) {
  	        win.onCompleted();
  	        win = new Subject();
  	        observer.onNext(addRef(win, r));
  	      }, function (err) {
  	        win.onError(err);
  	        observer.onError(err);
  	      }, function () {
  	        win.onCompleted();
  	        observer.onCompleted();
  	      }));
  	
  	      return r;
  	    }, source);
  	  }
  	
  	  function observableWindowWithClosingSelector(windowClosingSelector) {
  	    var source = this;
  	    return new AnonymousObservable(function (observer) {
  	      var m = new SerialDisposable(),
  	        d = new CompositeDisposable(m),
  	        r = new RefCountDisposable(d),
  	        win = new Subject();
  	      observer.onNext(addRef(win, r));
  	      d.add(source.subscribe(function (x) {
  	          win.onNext(x);
  	      }, function (err) {
  	          win.onError(err);
  	          observer.onError(err);
  	      }, function () {
  	          win.onCompleted();
  	          observer.onCompleted();
  	      }));
  	
  	      function createWindowClose () {
  	        var windowClose;
  	        try {
  	          windowClose = windowClosingSelector();
  	        } catch (e) {
  	          observer.onError(e);
  	          return;
  	        }
  	
  	        isPromise(windowClose) && (windowClose = observableFromPromise(windowClose));
  	
  	        var m1 = new SingleAssignmentDisposable();
  	        m.setDisposable(m1);
  	        m1.setDisposable(windowClose.take(1).subscribe(noop, function (err) {
  	          win.onError(err);
  	          observer.onError(err);
  	        }, function () {
  	          win.onCompleted();
  	          win = new Subject();
  	          observer.onNext(addRef(win, r));
  	          createWindowClose();
  	        }));
  	      }
  	
  	      createWindowClose();
  	      return r;
  	    }, source);
  	  }
  	
  	  /**
  	   * Returns a new observable that triggers on the second and subsequent triggerings of the input observable.
  	   * The Nth triggering of the input observable passes the arguments from the N-1th and Nth triggering as a pair.
  	   * The argument passed to the N-1th triggering is held in hidden internal state until the Nth triggering occurs.
  	   * @returns {Observable} An observable that triggers on successive pairs of observations from the input observable as an array.
  	   */
  	  observableProto.pairwise = function () {
  	    var source = this;
  	    return new AnonymousObservable(function (observer) {
  	      var previous, hasPrevious = false;
  	      return source.subscribe(
  	        function (x) {
  	          if (hasPrevious) {
  	            observer.onNext([previous, x]);
  	          } else {
  	            hasPrevious = true;
  	          }
  	          previous = x;
  	        },
  	        observer.onError.bind(observer),
  	        observer.onCompleted.bind(observer));
  	    }, source);
  	  };
  	
  	  /**
  	   * Returns two observables which partition the observations of the source by the given function.
  	   * The first will trigger observations for those values for which the predicate returns true.
  	   * The second will trigger observations for those values where the predicate returns false.
  	   * The predicate is executed once for each subscribed observer.
  	   * Both also propagate all error observations arising from the source and each completes
  	   * when the source completes.
  	   * @param {Function} predicate
  	   *    The function to determine which output Observable will trigger a particular observation.
  	   * @returns {Array}
  	   *    An array of observables. The first triggers when the predicate returns true,
  	   *    and the second triggers when the predicate returns false.
  	  */
  	  observableProto.partition = function(predicate, thisArg) {
  	    return [
  	      this.filter(predicate, thisArg),
  	      this.filter(function (x, i, o) { return !predicate.call(thisArg, x, i, o); })
  	    ];
  	  };
  	
  	  var WhileEnumerable = (function(__super__) {
  	    inherits(WhileEnumerable, __super__);
  	    function WhileEnumerable(c, s) {
  	      this.c = c;
  	      this.s = s;
  	    }
  	    WhileEnumerable.prototype[$iterator$] = function () {
  	      var self = this;
  	      return {
  	        next: function () {
  	          return self.c() ?
  	           { done: false, value: self.s } :
  	           { done: true, value: void 0 };
  	        }
  	      };
  	    };
  	    return WhileEnumerable;
  	  }(Enumerable));
  	  
  	  function enumerableWhile(condition, source) {
  	    return new WhileEnumerable(condition, source);
  	  }  
  	
  	   /**
  	   *  Returns an observable sequence that is the result of invoking the selector on the source sequence, without sharing subscriptions.
  	   *  This operator allows for a fluent style of writing queries that use the same sequence multiple times.
  	   *
  	   * @param {Function} selector Selector function which can use the source sequence as many times as needed, without sharing subscriptions to the source sequence.
  	   * @returns {Observable} An observable sequence that contains the elements of a sequence produced by multicasting the source sequence within a selector function.
  	   */
  	  observableProto.letBind = observableProto['let'] = function (func) {
  	    return func(this);
  	  };
  	
  	   /**
  	   *  Determines whether an observable collection contains values. There is an alias for this method called 'ifThen' for browsers <IE9
  	   *
  	   * @example
  	   *  1 - res = Rx.Observable.if(condition, obs1);
  	   *  2 - res = Rx.Observable.if(condition, obs1, obs2);
  	   *  3 - res = Rx.Observable.if(condition, obs1, scheduler);
  	   * @param {Function} condition The condition which determines if the thenSource or elseSource will be run.
  	   * @param {Observable} thenSource The observable sequence or Promise that will be run if the condition function returns true.
  	   * @param {Observable} [elseSource] The observable sequence or Promise that will be run if the condition function returns false. If this is not provided, it defaults to Rx.Observabe.Empty with the specified scheduler.
  	   * @returns {Observable} An observable sequence which is either the thenSource or elseSource.
  	   */
  	  Observable['if'] = Observable.ifThen = function (condition, thenSource, elseSourceOrScheduler) {
  	    return observableDefer(function () {
  	      elseSourceOrScheduler || (elseSourceOrScheduler = observableEmpty());
  	
  	      isPromise(thenSource) && (thenSource = observableFromPromise(thenSource));
  	      isPromise(elseSourceOrScheduler) && (elseSourceOrScheduler = observableFromPromise(elseSourceOrScheduler));
  	
  	      // Assume a scheduler for empty only
  	      typeof elseSourceOrScheduler.now === 'function' && (elseSourceOrScheduler = observableEmpty(elseSourceOrScheduler));
  	      return condition() ? thenSource : elseSourceOrScheduler;
  	    });
  	  };
  	
  	   /**
  	   *  Concatenates the observable sequences obtained by running the specified result selector for each element in source.
  	   * There is an alias for this method called 'forIn' for browsers <IE9
  	   * @param {Array} sources An array of values to turn into an observable sequence.
  	   * @param {Function} resultSelector A function to apply to each item in the sources array to turn it into an observable sequence.
  	   * @returns {Observable} An observable sequence from the concatenated observable sequences.
  	   */
  	  Observable['for'] = Observable.forIn = function (sources, resultSelector, thisArg) {
  	    return enumerableOf(sources, resultSelector, thisArg).concat();
  	  };
  	
  	   /**
  	   *  Repeats source as long as condition holds emulating a while loop.
  	   * There is an alias for this method called 'whileDo' for browsers <IE9
  	   *
  	   * @param {Function} condition The condition which determines if the source will be repeated.
  	   * @param {Observable} source The observable sequence that will be run if the condition function returns true.
  	   * @returns {Observable} An observable sequence which is repeated as long as the condition holds.
  	   */
  	  var observableWhileDo = Observable['while'] = Observable.whileDo = function (condition, source) {
  	    isPromise(source) && (source = observableFromPromise(source));
  	    return enumerableWhile(condition, source).concat();
  	  };
  	
  	   /**
  	   *  Repeats source as long as condition holds emulating a do while loop.
  	   *
  	   * @param {Function} condition The condition which determines if the source will be repeated.
  	   * @param {Observable} source The observable sequence that will be run if the condition function returns true.
  	   * @returns {Observable} An observable sequence which is repeated as long as the condition holds.
  	   */
  	  observableProto.doWhile = function (condition) {
  	    return observableConcat([this, observableWhileDo(condition, this)]);
  	  };
  	
  	   /**
  	   *  Uses selector to determine which source in sources to use.
  	   *  There is an alias 'switchCase' for browsers <IE9.
  	   *
  	   * @example
  	   *  1 - res = Rx.Observable.case(selector, { '1': obs1, '2': obs2 });
  	   *  1 - res = Rx.Observable.case(selector, { '1': obs1, '2': obs2 }, obs0);
  	   *  1 - res = Rx.Observable.case(selector, { '1': obs1, '2': obs2 }, scheduler);
  	   *
  	   * @param {Function} selector The function which extracts the value for to test in a case statement.
  	   * @param {Array} sources A object which has keys which correspond to the case statement labels.
  	   * @param {Observable} [elseSource] The observable sequence or Promise that will be run if the sources are not matched. If this is not provided, it defaults to Rx.Observabe.empty with the specified scheduler.
  	   *
  	   * @returns {Observable} An observable sequence which is determined by a case statement.
  	   */
  	  Observable['case'] = Observable.switchCase = function (selector, sources, defaultSourceOrScheduler) {
  	    return observableDefer(function () {
  	      isPromise(defaultSourceOrScheduler) && (defaultSourceOrScheduler = observableFromPromise(defaultSourceOrScheduler));
  	      defaultSourceOrScheduler || (defaultSourceOrScheduler = observableEmpty());
  	
  	      typeof defaultSourceOrScheduler.now === 'function' && (defaultSourceOrScheduler = observableEmpty(defaultSourceOrScheduler));
  	
  	      var result = sources[selector()];
  	      isPromise(result) && (result = observableFromPromise(result));
  	
  	      return result || defaultSourceOrScheduler;
  	    });
  	  };
  	
  	   /**
  	   *  Expands an observable sequence by recursively invoking selector.
  	   *
  	   * @param {Function} selector Selector function to invoke for each produced element, resulting in another sequence to which the selector will be invoked recursively again.
  	   * @param {Scheduler} [scheduler] Scheduler on which to perform the expansion. If not provided, this defaults to the current thread scheduler.
  	   * @returns {Observable} An observable sequence containing all the elements produced by the recursive expansion.
  	   */
  	  observableProto.expand = function (selector, scheduler) {
  	    isScheduler(scheduler) || (scheduler = immediateScheduler);
  	    var source = this;
  	    return new AnonymousObservable(function (observer) {
  	      var q = [],
  	        m = new SerialDisposable(),
  	        d = new CompositeDisposable(m),
  	        activeCount = 0,
  	        isAcquired = false;
  	
  	      var ensureActive = function () {
  	        var isOwner = false;
  	        if (q.length > 0) {
  	          isOwner = !isAcquired;
  	          isAcquired = true;
  	        }
  	        if (isOwner) {
  	          m.setDisposable(scheduler.scheduleRecursive(function (self) {
  	            var work;
  	            if (q.length > 0) {
  	              work = q.shift();
  	            } else {
  	              isAcquired = false;
  	              return;
  	            }
  	            var m1 = new SingleAssignmentDisposable();
  	            d.add(m1);
  	            m1.setDisposable(work.subscribe(function (x) {
  	              observer.onNext(x);
  	              var result = null;
  	              try {
  	                result = selector(x);
  	              } catch (e) {
  	                observer.onError(e);
  	              }
  	              q.push(result);
  	              activeCount++;
  	              ensureActive();
  	            }, observer.onError.bind(observer), function () {
  	              d.remove(m1);
  	              activeCount--;
  	              if (activeCount === 0) {
  	                observer.onCompleted();
  	              }
  	            }));
  	            self();
  	          }));
  	        }
  	      };
  	
  	      q.push(source);
  	      activeCount++;
  	      ensureActive();
  	      return d;
  	    }, this);
  	  };
  	
  	   /**
  	   *  Runs all observable sequences in parallel and collect their last elements.
  	   *
  	   * @example
  	   *  1 - res = Rx.Observable.forkJoin([obs1, obs2]);
  	   *  1 - res = Rx.Observable.forkJoin(obs1, obs2, ...);
  	   * @returns {Observable} An observable sequence with an array collecting the last elements of all the input sequences.
  	   */
  	  Observable.forkJoin = function () {
  	    var allSources = [];
  	    if (Array.isArray(arguments[0])) {
  	      allSources = arguments[0];
  	    } else {
  	      for(var i = 0, len = arguments.length; i < len; i++) { allSources.push(arguments[i]); }
  	    }
  	    return new AnonymousObservable(function (subscriber) {
  	      var count = allSources.length;
  	      if (count === 0) {
  	        subscriber.onCompleted();
  	        return disposableEmpty;
  	      }
  	      var group = new CompositeDisposable(),
  	        finished = false,
  	        hasResults = new Array(count),
  	        hasCompleted = new Array(count),
  	        results = new Array(count);
  	
  	      for (var idx = 0; idx < count; idx++) {
  	        (function (i) {
  	          var source = allSources[i];
  	          isPromise(source) && (source = observableFromPromise(source));
  	          group.add(
  	            source.subscribe(
  	              function (value) {
  	              if (!finished) {
  	                hasResults[i] = true;
  	                results[i] = value;
  	              }
  	            },
  	            function (e) {
  	              finished = true;
  	              subscriber.onError(e);
  	              group.dispose();
  	            },
  	            function () {
  	              if (!finished) {
  	                if (!hasResults[i]) {
  	                    subscriber.onCompleted();
  	                    return;
  	                }
  	                hasCompleted[i] = true;
  	                for (var ix = 0; ix < count; ix++) {
  	                  if (!hasCompleted[ix]) { return; }
  	                }
  	                finished = true;
  	                subscriber.onNext(results);
  	                subscriber.onCompleted();
  	              }
  	            }));
  	        })(idx);
  	      }
  	
  	      return group;
  	    });
  	  };
  	
  	   /**
  	   *  Runs two observable sequences in parallel and combines their last elemenets.
  	   *
  	   * @param {Observable} second Second observable sequence.
  	   * @param {Function} resultSelector Result selector function to invoke with the last elements of both sequences.
  	   * @returns {Observable} An observable sequence with the result of calling the selector function with the last elements of both input sequences.
  	   */
  	  observableProto.forkJoin = function (second, resultSelector) {
  	    var first = this;
  	    return new AnonymousObservable(function (observer) {
  	      var leftStopped = false, rightStopped = false,
  	        hasLeft = false, hasRight = false,
  	        lastLeft, lastRight,
  	        leftSubscription = new SingleAssignmentDisposable(), rightSubscription = new SingleAssignmentDisposable();
  	
  	      isPromise(second) && (second = observableFromPromise(second));
  	
  	      leftSubscription.setDisposable(
  	          first.subscribe(function (left) {
  	            hasLeft = true;
  	            lastLeft = left;
  	          }, function (err) {
  	            rightSubscription.dispose();
  	            observer.onError(err);
  	          }, function () {
  	            leftStopped = true;
  	            if (rightStopped) {
  	              if (!hasLeft) {
  	                  observer.onCompleted();
  	              } else if (!hasRight) {
  	                  observer.onCompleted();
  	              } else {
  	                var result;
  	                try {
  	                  result = resultSelector(lastLeft, lastRight);
  	                } catch (e) {
  	                  observer.onError(e);
  	                  return;
  	                }
  	                observer.onNext(result);
  	                observer.onCompleted();
  	              }
  	            }
  	          })
  	      );
  	
  	      rightSubscription.setDisposable(
  	        second.subscribe(function (right) {
  	          hasRight = true;
  	          lastRight = right;
  	        }, function (err) {
  	          leftSubscription.dispose();
  	          observer.onError(err);
  	        }, function () {
  	          rightStopped = true;
  	          if (leftStopped) {
  	            if (!hasLeft) {
  	              observer.onCompleted();
  	            } else if (!hasRight) {
  	              observer.onCompleted();
  	            } else {
  	              var result;
  	              try {
  	                result = resultSelector(lastLeft, lastRight);
  	              } catch (e) {
  	                observer.onError(e);
  	                return;
  	              }
  	              observer.onNext(result);
  	              observer.onCompleted();
  	            }
  	          }
  	        })
  	      );
  	
  	      return new CompositeDisposable(leftSubscription, rightSubscription);
  	    }, first);
  	  };
  	
  	  /**
  	   * Comonadic bind operator.
  	   * @param {Function} selector A transform function to apply to each element.
  	   * @param {Object} scheduler Scheduler used to execute the operation. If not specified, defaults to the ImmediateScheduler.
  	   * @returns {Observable} An observable sequence which results from the comonadic bind operation.
  	   */
  	  observableProto.manySelect = observableProto.extend = function (selector, scheduler) {
  	    isScheduler(scheduler) || (scheduler = immediateScheduler);
  	    var source = this;
  	    return observableDefer(function () {
  	      var chain;
  	
  	      return source
  	        .map(function (x) {
  	          var curr = new ChainObservable(x);
  	
  	          chain && chain.onNext(x);
  	          chain = curr;
  	
  	          return curr;
  	        })
  	        .tap(
  	          noop,
  	          function (e) { chain && chain.onError(e); },
  	          function () { chain && chain.onCompleted(); }
  	        )
  	        .observeOn(scheduler)
  	        .map(selector);
  	    }, source);
  	  };
  	
  	  var ChainObservable = (function (__super__) {
  	
  	    function subscribe (observer) {
  	      var self = this, g = new CompositeDisposable();
  	      g.add(currentThreadScheduler.schedule(function () {
  	        observer.onNext(self.head);
  	        g.add(self.tail.mergeAll().subscribe(observer));
  	      }));
  	
  	      return g;
  	    }
  	
  	    inherits(ChainObservable, __super__);
  	
  	    function ChainObservable(head) {
  	      __super__.call(this, subscribe);
  	      this.head = head;
  	      this.tail = new AsyncSubject();
  	    }
  	
  	    addProperties(ChainObservable.prototype, Observer, {
  	      onCompleted: function () {
  	        this.onNext(Observable.empty());
  	      },
  	      onError: function (e) {
  	        this.onNext(Observable.throwError(e));
  	      },
  	      onNext: function (v) {
  	        this.tail.onNext(v);
  	        this.tail.onCompleted();
  	      }
  	    });
  	
  	    return ChainObservable;
  	
  	  }(Observable));
  	
  	  /** @private */
  	  var Map = root.Map || (function () {
  	
  	    function Map() {
  	      this._keys = [];
  	      this._values = [];
  	    }
  	
  	    Map.prototype.get = function (key) {
  	      var i = this._keys.indexOf(key);
  	      return i !== -1 ? this._values[i] : undefined;
  	    };
  	
  	    Map.prototype.set = function (key, value) {
  	      var i = this._keys.indexOf(key);
  	      i !== -1 && (this._values[i] = value);
  	      this._values[this._keys.push(key) - 1] = value;
  	    };
  	
  	    Map.prototype.forEach = function (callback, thisArg) {
  	      for (var i = 0, len = this._keys.length; i < len; i++) {
  	        callback.call(thisArg, this._values[i], this._keys[i]);
  	      }
  	    };
  	
  	    return Map;
  	  }());
  	
  	  /**
  	   * @constructor
  	   * Represents a join pattern over observable sequences.
  	   */
  	  function Pattern(patterns) {
  	    this.patterns = patterns;
  	  }
  	
  	  /**
  	   *  Creates a pattern that matches the current plan matches and when the specified observable sequences has an available value.
  	   *  @param other Observable sequence to match in addition to the current pattern.
  	   *  @return {Pattern} Pattern object that matches when all observable sequences in the pattern have an available value.
  	   */
  	  Pattern.prototype.and = function (other) {
  	    return new Pattern(this.patterns.concat(other));
  	  };
  	
  	  /**
  	   *  Matches when all observable sequences in the pattern (specified using a chain of and operators) have an available value and projects the values.
  	   *  @param {Function} selector Selector that will be invoked with available values from the source sequences, in the same order of the sequences in the pattern.
  	   *  @return {Plan} Plan that produces the projected values, to be fed (with other plans) to the when operator.
  	   */
  	  Pattern.prototype.thenDo = function (selector) {
  	    return new Plan(this, selector);
  	  };
  	
  	  function Plan(expression, selector) {
  	      this.expression = expression;
  	      this.selector = selector;
  	  }
  	
  	  Plan.prototype.activate = function (externalSubscriptions, observer, deactivate) {
  	    var self = this;
  	    var joinObservers = [];
  	    for (var i = 0, len = this.expression.patterns.length; i < len; i++) {
  	      joinObservers.push(planCreateObserver(externalSubscriptions, this.expression.patterns[i], observer.onError.bind(observer)));
  	    }
  	    var activePlan = new ActivePlan(joinObservers, function () {
  	      var result;
  	      try {
  	        result = self.selector.apply(self, arguments);
  	      } catch (e) {
  	        observer.onError(e);
  	        return;
  	      }
  	      observer.onNext(result);
  	    }, function () {
  	      for (var j = 0, jlen = joinObservers.length; j < jlen; j++) {
  	        joinObservers[j].removeActivePlan(activePlan);
  	      }
  	      deactivate(activePlan);
  	    });
  	    for (i = 0, len = joinObservers.length; i < len; i++) {
  	      joinObservers[i].addActivePlan(activePlan);
  	    }
  	    return activePlan;
  	  };
  	
  	  function planCreateObserver(externalSubscriptions, observable, onError) {
  	    var entry = externalSubscriptions.get(observable);
  	    if (!entry) {
  	      var observer = new JoinObserver(observable, onError);
  	      externalSubscriptions.set(observable, observer);
  	      return observer;
  	    }
  	    return entry;
  	  }
  	
  	  function ActivePlan(joinObserverArray, onNext, onCompleted) {
  	    this.joinObserverArray = joinObserverArray;
  	    this.onNext = onNext;
  	    this.onCompleted = onCompleted;
  	    this.joinObservers = new Map();
  	    for (var i = 0, len = this.joinObserverArray.length; i < len; i++) {
  	      var joinObserver = this.joinObserverArray[i];
  	      this.joinObservers.set(joinObserver, joinObserver);
  	    }
  	  }
  	
  	  ActivePlan.prototype.dequeue = function () {
  	    this.joinObservers.forEach(function (v) { v.queue.shift(); });
  	  };
  	
  	  ActivePlan.prototype.match = function () {
  	    var i, len, hasValues = true;
  	    for (i = 0, len = this.joinObserverArray.length; i < len; i++) {
  	      if (this.joinObserverArray[i].queue.length === 0) {
  	        hasValues = false;
  	        break;
  	      }
  	    }
  	    if (hasValues) {
  	      var firstValues = [],
  	          isCompleted = false;
  	      for (i = 0, len = this.joinObserverArray.length; i < len; i++) {
  	        firstValues.push(this.joinObserverArray[i].queue[0]);
  	        this.joinObserverArray[i].queue[0].kind === 'C' && (isCompleted = true);
  	      }
  	      if (isCompleted) {
  	        this.onCompleted();
  	      } else {
  	        this.dequeue();
  	        var values = [];
  	        for (i = 0, len = firstValues.length; i < firstValues.length; i++) {
  	          values.push(firstValues[i].value);
  	        }
  	        this.onNext.apply(this, values);
  	      }
  	    }
  	  };
  	
  	  var JoinObserver = (function (__super__) {
  	    inherits(JoinObserver, __super__);
  	
  	    function JoinObserver(source, onError) {
  	      __super__.call(this);
  	      this.source = source;
  	      this.onError = onError;
  	      this.queue = [];
  	      this.activePlans = [];
  	      this.subscription = new SingleAssignmentDisposable();
  	      this.isDisposed = false;
  	    }
  	
  	    var JoinObserverPrototype = JoinObserver.prototype;
  	
  	    JoinObserverPrototype.next = function (notification) {
  	      if (!this.isDisposed) {
  	        if (notification.kind === 'E') {
  	          return this.onError(notification.exception);
  	        }
  	        this.queue.push(notification);
  	        var activePlans = this.activePlans.slice(0);
  	        for (var i = 0, len = activePlans.length; i < len; i++) {
  	          activePlans[i].match();
  	        }
  	      }
  	    };
  	
  	    JoinObserverPrototype.error = noop;
  	    JoinObserverPrototype.completed = noop;
  	
  	    JoinObserverPrototype.addActivePlan = function (activePlan) {
  	      this.activePlans.push(activePlan);
  	    };
  	
  	    JoinObserverPrototype.subscribe = function () {
  	      this.subscription.setDisposable(this.source.materialize().subscribe(this));
  	    };
  	
  	    JoinObserverPrototype.removeActivePlan = function (activePlan) {
  	      this.activePlans.splice(this.activePlans.indexOf(activePlan), 1);
  	      this.activePlans.length === 0 && this.dispose();
  	    };
  	
  	    JoinObserverPrototype.dispose = function () {
  	      __super__.prototype.dispose.call(this);
  	      if (!this.isDisposed) {
  	        this.isDisposed = true;
  	        this.subscription.dispose();
  	      }
  	    };
  	
  	    return JoinObserver;
  	  } (AbstractObserver));
  	
  	  /**
  	   *  Creates a pattern that matches when both observable sequences have an available value.
  	   *
  	   *  @param right Observable sequence to match with the current sequence.
  	   *  @return {Pattern} Pattern object that matches when both observable sequences have an available value.
  	   */
  	  observableProto.and = function (right) {
  	    return new Pattern([this, right]);
  	  };
  	
  	  /**
  	   *  Matches when the observable sequence has an available value and projects the value.
  	   *
  	   *  @param {Function} selector Selector that will be invoked for values in the source sequence.
  	   *  @returns {Plan} Plan that produces the projected values, to be fed (with other plans) to the when operator.
  	   */
  	  observableProto.thenDo = function (selector) {
  	    return new Pattern([this]).thenDo(selector);
  	  };
  	
  	  /**
  	   *  Joins together the results from several patterns.
  	   *
  	   *  @param plans A series of plans (specified as an Array of as a series of arguments) created by use of the Then operator on patterns.
  	   *  @returns {Observable} Observable sequence with the results form matching several patterns.
  	   */
  	  Observable.when = function () {
  	    var len = arguments.length, plans;
  	    if (Array.isArray(arguments[0])) {
  	      plans = arguments[0];
  	    } else {
  	      plans = new Array(len);
  	      for(var i = 0; i < len; i++) { plans[i] = arguments[i]; }
  	    }
  	    return new AnonymousObservable(function (o) {
  	      var activePlans = [],
  	          externalSubscriptions = new Map();
  	      var outObserver = observerCreate(
  	        function (x) { o.onNext(x); },
  	        function (err) {
  	          externalSubscriptions.forEach(function (v) { v.onError(err); });
  	          o.onError(err);
  	        },
  	        function (x) { o.onCompleted(); }
  	      );
  	      try {
  	        for (var i = 0, len = plans.length; i < len; i++) {
  	          activePlans.push(plans[i].activate(externalSubscriptions, outObserver, function (activePlan) {
  	            var idx = activePlans.indexOf(activePlan);
  	            activePlans.splice(idx, 1);
  	            activePlans.length === 0 && o.onCompleted();
  	          }));
  	        }
  	      } catch (e) {
  	        observableThrow(e).subscribe(o);
  	      }
  	      var group = new CompositeDisposable();
  	      externalSubscriptions.forEach(function (joinObserver) {
  	        joinObserver.subscribe();
  	        group.add(joinObserver);
  	      });
  	
  	      return group;
  	    });
  	  };
  	
  	  function observableTimerDate(dueTime, scheduler) {
  	    return new AnonymousObservable(function (observer) {
  	      return scheduler.scheduleWithAbsolute(dueTime, function () {
  	        observer.onNext(0);
  	        observer.onCompleted();
  	      });
  	    });
  	  }
  	
  	  function observableTimerDateAndPeriod(dueTime, period, scheduler) {
  	    return new AnonymousObservable(function (observer) {
  	      var d = dueTime, p = normalizeTime(period);
  	      return scheduler.scheduleRecursiveWithAbsoluteAndState(0, d, function (count, self) {
  	        if (p > 0) {
  	          var now = scheduler.now();
  	          d = d + p;
  	          d <= now && (d = now + p);
  	        }
  	        observer.onNext(count);
  	        self(count + 1, d);
  	      });
  	    });
  	  }
  	
  	  function observableTimerTimeSpan(dueTime, scheduler) {
  	    return new AnonymousObservable(function (observer) {
  	      return scheduler.scheduleWithRelative(normalizeTime(dueTime), function () {
  	        observer.onNext(0);
  	        observer.onCompleted();
  	      });
  	    });
  	  }
  	
  	  function observableTimerTimeSpanAndPeriod(dueTime, period, scheduler) {
  	    return dueTime === period ?
  	      new AnonymousObservable(function (observer) {
  	        return scheduler.schedulePeriodicWithState(0, period, function (count) {
  	          observer.onNext(count);
  	          return count + 1;
  	        });
  	      }) :
  	      observableDefer(function () {
  	        return observableTimerDateAndPeriod(scheduler.now() + dueTime, period, scheduler);
  	      });
  	  }
  	
  	  /**
  	   *  Returns an observable sequence that produces a value after each period.
  	   *
  	   * @example
  	   *  1 - res = Rx.Observable.interval(1000);
  	   *  2 - res = Rx.Observable.interval(1000, Rx.Scheduler.timeout);
  	   *
  	   * @param {Number} period Period for producing the values in the resulting sequence (specified as an integer denoting milliseconds).
  	   * @param {Scheduler} [scheduler] Scheduler to run the timer on. If not specified, Rx.Scheduler.timeout is used.
  	   * @returns {Observable} An observable sequence that produces a value after each period.
  	   */
  	  var observableinterval = Observable.interval = function (period, scheduler) {
  	    return observableTimerTimeSpanAndPeriod(period, period, isScheduler(scheduler) ? scheduler : timeoutScheduler);
  	  };
  	
  	  /**
  	   *  Returns an observable sequence that produces a value after dueTime has elapsed and then after each period.
  	   * @param {Number} dueTime Absolute (specified as a Date object) or relative time (specified as an integer denoting milliseconds) at which to produce the first value.
  	   * @param {Mixed} [periodOrScheduler]  Period to produce subsequent values (specified as an integer denoting milliseconds), or the scheduler to run the timer on. If not specified, the resulting timer is not recurring.
  	   * @param {Scheduler} [scheduler]  Scheduler to run the timer on. If not specified, the timeout scheduler is used.
  	   * @returns {Observable} An observable sequence that produces a value after due time has elapsed and then each period.
  	   */
  	  var observableTimer = Observable.timer = function (dueTime, periodOrScheduler, scheduler) {
  	    var period;
  	    isScheduler(scheduler) || (scheduler = timeoutScheduler);
  	    if (periodOrScheduler !== undefined && typeof periodOrScheduler === 'number') {
  	      period = periodOrScheduler;
  	    } else if (isScheduler(periodOrScheduler)) {
  	      scheduler = periodOrScheduler;
  	    }
  	    if (dueTime instanceof Date && period === undefined) {
  	      return observableTimerDate(dueTime.getTime(), scheduler);
  	    }
  	    if (dueTime instanceof Date && period !== undefined) {
  	      period = periodOrScheduler;
  	      return observableTimerDateAndPeriod(dueTime.getTime(), period, scheduler);
  	    }
  	    return period === undefined ?
  	      observableTimerTimeSpan(dueTime, scheduler) :
  	      observableTimerTimeSpanAndPeriod(dueTime, period, scheduler);
  	  };
  	
  	  function observableDelayTimeSpan(source, dueTime, scheduler) {
  	    return new AnonymousObservable(function (observer) {
  	      var active = false,
  	        cancelable = new SerialDisposable(),
  	        exception = null,
  	        q = [],
  	        running = false,
  	        subscription;
  	      subscription = source.materialize().timestamp(scheduler).subscribe(function (notification) {
  	        var d, shouldRun;
  	        if (notification.value.kind === 'E') {
  	          q = [];
  	          q.push(notification);
  	          exception = notification.value.exception;
  	          shouldRun = !running;
  	        } else {
  	          q.push({ value: notification.value, timestamp: notification.timestamp + dueTime });
  	          shouldRun = !active;
  	          active = true;
  	        }
  	        if (shouldRun) {
  	          if (exception !== null) {
  	            observer.onError(exception);
  	          } else {
  	            d = new SingleAssignmentDisposable();
  	            cancelable.setDisposable(d);
  	            d.setDisposable(scheduler.scheduleRecursiveWithRelative(dueTime, function (self) {
  	              var e, recurseDueTime, result, shouldRecurse;
  	              if (exception !== null) {
  	                return;
  	              }
  	              running = true;
  	              do {
  	                result = null;
  	                if (q.length > 0 && q[0].timestamp - scheduler.now() <= 0) {
  	                  result = q.shift().value;
  	                }
  	                if (result !== null) {
  	                  result.accept(observer);
  	                }
  	              } while (result !== null);
  	              shouldRecurse = false;
  	              recurseDueTime = 0;
  	              if (q.length > 0) {
  	                shouldRecurse = true;
  	                recurseDueTime = Math.max(0, q[0].timestamp - scheduler.now());
  	              } else {
  	                active = false;
  	              }
  	              e = exception;
  	              running = false;
  	              if (e !== null) {
  	                observer.onError(e);
  	              } else if (shouldRecurse) {
  	                self(recurseDueTime);
  	              }
  	            }));
  	          }
  	        }
  	      });
  	      return new CompositeDisposable(subscription, cancelable);
  	    }, source);
  	  }
  	
  	  function observableDelayDate(source, dueTime, scheduler) {
  	    return observableDefer(function () {
  	      return observableDelayTimeSpan(source, dueTime - scheduler.now(), scheduler);
  	    });
  	  }
  	
  	  /**
  	   *  Time shifts the observable sequence by dueTime. The relative time intervals between the values are preserved.
  	   *
  	   * @example
  	   *  1 - res = Rx.Observable.delay(new Date());
  	   *  2 - res = Rx.Observable.delay(new Date(), Rx.Scheduler.timeout);
  	   *
  	   *  3 - res = Rx.Observable.delay(5000);
  	   *  4 - res = Rx.Observable.delay(5000, 1000, Rx.Scheduler.timeout);
  	   * @memberOf Observable#
  	   * @param {Number} dueTime Absolute (specified as a Date object) or relative time (specified as an integer denoting milliseconds) by which to shift the observable sequence.
  	   * @param {Scheduler} [scheduler] Scheduler to run the delay timers on. If not specified, the timeout scheduler is used.
  	   * @returns {Observable} Time-shifted sequence.
  	   */
  	  observableProto.delay = function (dueTime, scheduler) {
  	    isScheduler(scheduler) || (scheduler = timeoutScheduler);
  	    return dueTime instanceof Date ?
  	      observableDelayDate(this, dueTime.getTime(), scheduler) :
  	      observableDelayTimeSpan(this, dueTime, scheduler);
  	  };
  	
  	  /**
  	   *  Ignores values from an observable sequence which are followed by another value before dueTime.
  	   * @param {Number} dueTime Duration of the debounce period for each value (specified as an integer denoting milliseconds).
  	   * @param {Scheduler} [scheduler]  Scheduler to run the debounce timers on. If not specified, the timeout scheduler is used.
  	   * @returns {Observable} The debounced sequence.
  	   */
  	  observableProto.debounce = observableProto.throttleWithTimeout = function (dueTime, scheduler) {
  	    isScheduler(scheduler) || (scheduler = timeoutScheduler);
  	    var source = this;
  	    return new AnonymousObservable(function (observer) {
  	      var cancelable = new SerialDisposable(), hasvalue = false, value, id = 0;
  	      var subscription = source.subscribe(
  	        function (x) {
  	          hasvalue = true;
  	          value = x;
  	          id++;
  	          var currentId = id,
  	            d = new SingleAssignmentDisposable();
  	          cancelable.setDisposable(d);
  	          d.setDisposable(scheduler.scheduleWithRelative(dueTime, function () {
  	            hasvalue && id === currentId && observer.onNext(value);
  	            hasvalue = false;
  	          }));
  	        },
  	        function (e) {
  	          cancelable.dispose();
  	          observer.onError(e);
  	          hasvalue = false;
  	          id++;
  	        },
  	        function () {
  	          cancelable.dispose();
  	          hasvalue && observer.onNext(value);
  	          observer.onCompleted();
  	          hasvalue = false;
  	          id++;
  	        });
  	      return new CompositeDisposable(subscription, cancelable);
  	    }, this);
  	  };
  	
  	  /**
  	   * @deprecated use #debounce or #throttleWithTimeout instead.
  	   */
  	  observableProto.throttle = function(dueTime, scheduler) {
  	    //deprecate('throttle', 'debounce or throttleWithTimeout');
  	    return this.debounce(dueTime, scheduler);
  	  };
  	
  	  /**
  	   *  Projects each element of an observable sequence into zero or more windows which are produced based on timing information.
  	   * @param {Number} timeSpan Length of each window (specified as an integer denoting milliseconds).
  	   * @param {Mixed} [timeShiftOrScheduler]  Interval between creation of consecutive windows (specified as an integer denoting milliseconds), or an optional scheduler parameter. If not specified, the time shift corresponds to the timeSpan parameter, resulting in non-overlapping adjacent windows.
  	   * @param {Scheduler} [scheduler]  Scheduler to run windowing timers on. If not specified, the timeout scheduler is used.
  	   * @returns {Observable} An observable sequence of windows.
  	   */
  	  observableProto.windowWithTime = function (timeSpan, timeShiftOrScheduler, scheduler) {
  	    var source = this, timeShift;
  	    timeShiftOrScheduler == null && (timeShift = timeSpan);
  	    isScheduler(scheduler) || (scheduler = timeoutScheduler);
  	    if (typeof timeShiftOrScheduler === 'number') {
  	      timeShift = timeShiftOrScheduler;
  	    } else if (isScheduler(timeShiftOrScheduler)) {
  	      timeShift = timeSpan;
  	      scheduler = timeShiftOrScheduler;
  	    }
  	    return new AnonymousObservable(function (observer) {
  	      var groupDisposable,
  	        nextShift = timeShift,
  	        nextSpan = timeSpan,
  	        q = [],
  	        refCountDisposable,
  	        timerD = new SerialDisposable(),
  	        totalTime = 0;
  	        groupDisposable = new CompositeDisposable(timerD),
  	        refCountDisposable = new RefCountDisposable(groupDisposable);
  	
  	       function createTimer () {
  	        var m = new SingleAssignmentDisposable(),
  	          isSpan = false,
  	          isShift = false;
  	        timerD.setDisposable(m);
  	        if (nextSpan === nextShift) {
  	          isSpan = true;
  	          isShift = true;
  	        } else if (nextSpan < nextShift) {
  	            isSpan = true;
  	        } else {
  	          isShift = true;
  	        }
  	        var newTotalTime = isSpan ? nextSpan : nextShift,
  	          ts = newTotalTime - totalTime;
  	        totalTime = newTotalTime;
  	        if (isSpan) {
  	          nextSpan += timeShift;
  	        }
  	        if (isShift) {
  	          nextShift += timeShift;
  	        }
  	        m.setDisposable(scheduler.scheduleWithRelative(ts, function () {
  	          if (isShift) {
  	            var s = new Subject();
  	            q.push(s);
  	            observer.onNext(addRef(s, refCountDisposable));
  	          }
  	          isSpan && q.shift().onCompleted();
  	          createTimer();
  	        }));
  	      };
  	      q.push(new Subject());
  	      observer.onNext(addRef(q[0], refCountDisposable));
  	      createTimer();
  	      groupDisposable.add(source.subscribe(
  	        function (x) {
  	          for (var i = 0, len = q.length; i < len; i++) { q[i].onNext(x); }
  	        },
  	        function (e) {
  	          for (var i = 0, len = q.length; i < len; i++) { q[i].onError(e); }
  	          observer.onError(e);
  	        },
  	        function () {
  	          for (var i = 0, len = q.length; i < len; i++) { q[i].onCompleted(); }
  	          observer.onCompleted();
  	        }
  	      ));
  	      return refCountDisposable;
  	    }, source);
  	  };
  	
  	  /**
  	   *  Projects each element of an observable sequence into a window that is completed when either it's full or a given amount of time has elapsed.
  	   * @param {Number} timeSpan Maximum time length of a window.
  	   * @param {Number} count Maximum element count of a window.
  	   * @param {Scheduler} [scheduler]  Scheduler to run windowing timers on. If not specified, the timeout scheduler is used.
  	   * @returns {Observable} An observable sequence of windows.
  	   */
  	  observableProto.windowWithTimeOrCount = function (timeSpan, count, scheduler) {
  	    var source = this;
  	    isScheduler(scheduler) || (scheduler = timeoutScheduler);
  	    return new AnonymousObservable(function (observer) {
  	      var timerD = new SerialDisposable(),
  	          groupDisposable = new CompositeDisposable(timerD),
  	          refCountDisposable = new RefCountDisposable(groupDisposable),
  	          n = 0,
  	          windowId = 0,
  	          s = new Subject();
  	
  	      function createTimer(id) {
  	        var m = new SingleAssignmentDisposable();
  	        timerD.setDisposable(m);
  	        m.setDisposable(scheduler.scheduleWithRelative(timeSpan, function () {
  	          if (id !== windowId) { return; }
  	          n = 0;
  	          var newId = ++windowId;
  	          s.onCompleted();
  	          s = new Subject();
  	          observer.onNext(addRef(s, refCountDisposable));
  	          createTimer(newId);
  	        }));
  	      }
  	
  	      observer.onNext(addRef(s, refCountDisposable));
  	      createTimer(0);
  	
  	      groupDisposable.add(source.subscribe(
  	        function (x) {
  	          var newId = 0, newWindow = false;
  	          s.onNext(x);
  	          if (++n === count) {
  	            newWindow = true;
  	            n = 0;
  	            newId = ++windowId;
  	            s.onCompleted();
  	            s = new Subject();
  	            observer.onNext(addRef(s, refCountDisposable));
  	          }
  	          newWindow && createTimer(newId);
  	        },
  	        function (e) {
  	          s.onError(e);
  	          observer.onError(e);
  	        }, function () {
  	          s.onCompleted();
  	          observer.onCompleted();
  	        }
  	      ));
  	      return refCountDisposable;
  	    }, source);
  	  };
  	
  	    /**
  	     *  Projects each element of an observable sequence into zero or more buffers which are produced based on timing information.
  	     *
  	     * @example
  	     *  1 - res = xs.bufferWithTime(1000, scheduler); // non-overlapping segments of 1 second
  	     *  2 - res = xs.bufferWithTime(1000, 500, scheduler; // segments of 1 second with time shift 0.5 seconds
  	     *
  	     * @param {Number} timeSpan Length of each buffer (specified as an integer denoting milliseconds).
  	     * @param {Mixed} [timeShiftOrScheduler]  Interval between creation of consecutive buffers (specified as an integer denoting milliseconds), or an optional scheduler parameter. If not specified, the time shift corresponds to the timeSpan parameter, resulting in non-overlapping adjacent buffers.
  	     * @param {Scheduler} [scheduler]  Scheduler to run buffer timers on. If not specified, the timeout scheduler is used.
  	     * @returns {Observable} An observable sequence of buffers.
  	     */
  	    observableProto.bufferWithTime = function (timeSpan, timeShiftOrScheduler, scheduler) {
  	        return this.windowWithTime.apply(this, arguments).selectMany(function (x) { return x.toArray(); });
  	    };
  	
  	    /**
  	     *  Projects each element of an observable sequence into a buffer that is completed when either it's full or a given amount of time has elapsed.
  	     *
  	     * @example
  	     *  1 - res = source.bufferWithTimeOrCount(5000, 50); // 5s or 50 items in an array
  	     *  2 - res = source.bufferWithTimeOrCount(5000, 50, scheduler); // 5s or 50 items in an array
  	     *
  	     * @param {Number} timeSpan Maximum time length of a buffer.
  	     * @param {Number} count Maximum element count of a buffer.
  	     * @param {Scheduler} [scheduler]  Scheduler to run bufferin timers on. If not specified, the timeout scheduler is used.
  	     * @returns {Observable} An observable sequence of buffers.
  	     */
  	    observableProto.bufferWithTimeOrCount = function (timeSpan, count, scheduler) {
  	        return this.windowWithTimeOrCount(timeSpan, count, scheduler).selectMany(function (x) {
  	            return x.toArray();
  	        });
  	    };
  	
  	  /**
  	   *  Records the time interval between consecutive values in an observable sequence.
  	   *
  	   * @example
  	   *  1 - res = source.timeInterval();
  	   *  2 - res = source.timeInterval(Rx.Scheduler.timeout);
  	   *
  	   * @param [scheduler]  Scheduler used to compute time intervals. If not specified, the timeout scheduler is used.
  	   * @returns {Observable} An observable sequence with time interval information on values.
  	   */
  	  observableProto.timeInterval = function (scheduler) {
  	    var source = this;
  	    isScheduler(scheduler) || (scheduler = timeoutScheduler);
  	    return observableDefer(function () {
  	      var last = scheduler.now();
  	      return source.map(function (x) {
  	        var now = scheduler.now(), span = now - last;
  	        last = now;
  	        return { value: x, interval: span };
  	      });
  	    });
  	  };
  	
  	  /**
  	   *  Records the timestamp for each value in an observable sequence.
  	   *
  	   * @example
  	   *  1 - res = source.timestamp(); // produces { value: x, timestamp: ts }
  	   *  2 - res = source.timestamp(Rx.Scheduler.default);
  	   *
  	   * @param {Scheduler} [scheduler]  Scheduler used to compute timestamps. If not specified, the default scheduler is used.
  	   * @returns {Observable} An observable sequence with timestamp information on values.
  	   */
  	  observableProto.timestamp = function (scheduler) {
  	    isScheduler(scheduler) || (scheduler = timeoutScheduler);
  	    return this.map(function (x) {
  	      return { value: x, timestamp: scheduler.now() };
  	    });
  	  };
  	
  	  function sampleObservable(source, sampler) {
  	    return new AnonymousObservable(function (o) {
  	      var atEnd = false, value, hasValue = false;
  	
  	      function sampleSubscribe() {
  	        if (hasValue) {
  	          hasValue = false;
  	          o.onNext(value);
  	        }
  	        atEnd && o.onCompleted();
  	      }
  	
  	      var sourceSubscription = new SingleAssignmentDisposable();
  	      sourceSubscription.setDisposable(source.subscribe(
  	        function (newValue) {
  	          hasValue = true;
  	          value = newValue;
  	        },
  	        function (e) { o.onError(e); },
  	        function () {
  	          atEnd = true;
  	          sourceSubscription.dispose(); 
  	        }
  	      ));
  	
  	      return new CompositeDisposable(
  	        sourceSubscription,
  	        sampler.subscribe(sampleSubscribe, function (e) { o.onError(e); }, sampleSubscribe)
  	      );
  	    }, source);
  	  }
  	
  	  /**
  	   *  Samples the observable sequence at each interval.
  	   *
  	   * @example
  	   *  1 - res = source.sample(sampleObservable); // Sampler tick sequence
  	   *  2 - res = source.sample(5000); // 5 seconds
  	   *  2 - res = source.sample(5000, Rx.Scheduler.timeout); // 5 seconds
  	   *
  	   * @param {Mixed} intervalOrSampler Interval at which to sample (specified as an integer denoting milliseconds) or Sampler Observable.
  	   * @param {Scheduler} [scheduler]  Scheduler to run the sampling timer on. If not specified, the timeout scheduler is used.
  	   * @returns {Observable} Sampled observable sequence.
  	   */
  	  observableProto.sample = observableProto.throttleLatest = function (intervalOrSampler, scheduler) {
  	    isScheduler(scheduler) || (scheduler = timeoutScheduler);
  	    return typeof intervalOrSampler === 'number' ?
  	      sampleObservable(this, observableinterval(intervalOrSampler, scheduler)) :
  	      sampleObservable(this, intervalOrSampler);
  	  };
  	
  	  /**
  	   *  Returns the source observable sequence or the other observable sequence if dueTime elapses.
  	   * @param {Number} dueTime Absolute (specified as a Date object) or relative time (specified as an integer denoting milliseconds) when a timeout occurs.
  	   * @param {Observable} [other]  Sequence to return in case of a timeout. If not specified, a timeout error throwing sequence will be used.
  	   * @param {Scheduler} [scheduler]  Scheduler to run the timeout timers on. If not specified, the timeout scheduler is used.
  	   * @returns {Observable} The source sequence switching to the other sequence in case of a timeout.
  	   */
  	  observableProto.timeout = function (dueTime, other, scheduler) {
  	    (other == null || typeof other === 'string') && (other = observableThrow(new Error(other || 'Timeout')));
  	    isScheduler(scheduler) || (scheduler = timeoutScheduler);
  	
  	    var source = this, schedulerMethod = dueTime instanceof Date ?
  	      'scheduleWithAbsolute' :
  	      'scheduleWithRelative';
  	
  	    return new AnonymousObservable(function (observer) {
  	      var id = 0,
  	        original = new SingleAssignmentDisposable(),
  	        subscription = new SerialDisposable(),
  	        switched = false,
  	        timer = new SerialDisposable();
  	
  	      subscription.setDisposable(original);
  	
  	      function createTimer() {
  	        var myId = id;
  	        timer.setDisposable(scheduler[schedulerMethod](dueTime, function () {
  	          if (id === myId) {
  	            isPromise(other) && (other = observableFromPromise(other));
  	            subscription.setDisposable(other.subscribe(observer));
  	          }
  	        }));
  	      }
  	
  	      createTimer();
  	
  	      original.setDisposable(source.subscribe(function (x) {
  	        if (!switched) {
  	          id++;
  	          observer.onNext(x);
  	          createTimer();
  	        }
  	      }, function (e) {
  	        if (!switched) {
  	          id++;
  	          observer.onError(e);
  	        }
  	      }, function () {
  	        if (!switched) {
  	          id++;
  	          observer.onCompleted();
  	        }
  	      }));
  	      return new CompositeDisposable(subscription, timer);
  	    }, source);
  	  };
  	
  	  /**
  	   *  Generates an observable sequence by iterating a state from an initial state until the condition fails.
  	   *
  	   * @example
  	   *  res = source.generateWithAbsoluteTime(0,
  	   *      function (x) { return return true; },
  	   *      function (x) { return x + 1; },
  	   *      function (x) { return x; },
  	   *      function (x) { return new Date(); }
  	   *  });
  	   *
  	   * @param {Mixed} initialState Initial state.
  	   * @param {Function} condition Condition to terminate generation (upon returning false).
  	   * @param {Function} iterate Iteration step function.
  	   * @param {Function} resultSelector Selector function for results produced in the sequence.
  	   * @param {Function} timeSelector Time selector function to control the speed of values being produced each iteration, returning Date values.
  	   * @param {Scheduler} [scheduler]  Scheduler on which to run the generator loop. If not specified, the timeout scheduler is used.
  	   * @returns {Observable} The generated sequence.
  	   */
  	  Observable.generateWithAbsoluteTime = function (initialState, condition, iterate, resultSelector, timeSelector, scheduler) {
  	    isScheduler(scheduler) || (scheduler = timeoutScheduler);
  	    return new AnonymousObservable(function (observer) {
  	      var first = true,
  	        hasResult = false;
  	      return scheduler.scheduleRecursiveWithAbsoluteAndState(initialState, scheduler.now(), function (state, self) {
  	        hasResult && observer.onNext(state);
  	
  	        try {
  	          if (first) {
  	            first = false;
  	          } else {
  	            state = iterate(state);
  	          }
  	          hasResult = condition(state);
  	          if (hasResult) {
  	            var result = resultSelector(state);
  	            var time = timeSelector(state);
  	          }
  	        } catch (e) {
  	          observer.onError(e);
  	          return;
  	        }
  	        if (hasResult) {
  	          self(result, time);
  	        } else {
  	          observer.onCompleted();
  	        }
  	      });
  	    });
  	  };
  	
  	  /**
  	   *  Generates an observable sequence by iterating a state from an initial state until the condition fails.
  	   *
  	   * @example
  	   *  res = source.generateWithRelativeTime(0,
  	   *      function (x) { return return true; },
  	   *      function (x) { return x + 1; },
  	   *      function (x) { return x; },
  	   *      function (x) { return 500; }
  	   *  );
  	   *
  	   * @param {Mixed} initialState Initial state.
  	   * @param {Function} condition Condition to terminate generation (upon returning false).
  	   * @param {Function} iterate Iteration step function.
  	   * @param {Function} resultSelector Selector function for results produced in the sequence.
  	   * @param {Function} timeSelector Time selector function to control the speed of values being produced each iteration, returning integer values denoting milliseconds.
  	   * @param {Scheduler} [scheduler]  Scheduler on which to run the generator loop. If not specified, the timeout scheduler is used.
  	   * @returns {Observable} The generated sequence.
  	   */
  	  Observable.generateWithRelativeTime = function (initialState, condition, iterate, resultSelector, timeSelector, scheduler) {
  	    isScheduler(scheduler) || (scheduler = timeoutScheduler);
  	    return new AnonymousObservable(function (observer) {
  	      var first = true,
  	        hasResult = false;
  	      return scheduler.scheduleRecursiveWithRelativeAndState(initialState, 0, function (state, self) {
  	        hasResult && observer.onNext(state);
  	
  	        try {
  	          if (first) {
  	            first = false;
  	          } else {
  	            state = iterate(state);
  	          }
  	          hasResult = condition(state);
  	          if (hasResult) {
  	            var result = resultSelector(state);
  	            var time = timeSelector(state);
  	          }
  	        } catch (e) {
  	          observer.onError(e);
  	          return;
  	        }
  	        if (hasResult) {
  	          self(result, time);
  	        } else {
  	          observer.onCompleted();
  	        }
  	      });
  	    });
  	  };
  	
  	  /**
  	   *  Time shifts the observable sequence by delaying the subscription with the specified relative time duration, using the specified scheduler to run timers.
  	   *
  	   * @example
  	   *  1 - res = source.delaySubscription(5000); // 5s
  	   *  2 - res = source.delaySubscription(5000, Rx.Scheduler.default); // 5 seconds
  	   *
  	   * @param {Number} dueTime Relative or absolute time shift of the subscription.
  	   * @param {Scheduler} [scheduler]  Scheduler to run the subscription delay timer on. If not specified, the timeout scheduler is used.
  	   * @returns {Observable} Time-shifted sequence.
  	   */
  	  observableProto.delaySubscription = function (dueTime, scheduler) {
  	    var scheduleMethod = dueTime instanceof Date ? 'scheduleWithAbsolute' : 'scheduleWithRelative';
  	    var source = this;
  	    isScheduler(scheduler) || (scheduler = timeoutScheduler);
  	    return new AnonymousObservable(function (o) {
  	      var d = new SerialDisposable();
  	
  	      d.setDisposable(scheduler[scheduleMethod](dueTime, function() {
  	        d.setDisposable(source.subscribe(o));
  	      }));
  	
  	      return d;
  	    }, this);
  	  };
  	
  	  /**
  	   *  Time shifts the observable sequence based on a subscription delay and a delay selector function for each element.
  	   *
  	   * @example
  	   *  1 - res = source.delayWithSelector(function (x) { return Rx.Scheduler.timer(5000); }); // with selector only
  	   *  1 - res = source.delayWithSelector(Rx.Observable.timer(2000), function (x) { return Rx.Observable.timer(x); }); // with delay and selector
  	   *
  	   * @param {Observable} [subscriptionDelay]  Sequence indicating the delay for the subscription to the source.
  	   * @param {Function} delayDurationSelector Selector function to retrieve a sequence indicating the delay for each given element.
  	   * @returns {Observable} Time-shifted sequence.
  	   */
  	  observableProto.delayWithSelector = function (subscriptionDelay, delayDurationSelector) {
  	    var source = this, subDelay, selector;
  	    if (isFunction(subscriptionDelay)) {
  	      selector = subscriptionDelay;
  	    } else {
  	      subDelay = subscriptionDelay;
  	      selector = delayDurationSelector;
  	    }
  	    return new AnonymousObservable(function (observer) {
  	      var delays = new CompositeDisposable(), atEnd = false, subscription = new SerialDisposable();
  	
  	      function start() {
  	        subscription.setDisposable(source.subscribe(
  	          function (x) {
  	            var delay = tryCatch(selector)(x);
  	            if (delay === errorObj) { return observer.onError(delay.e); }
  	            var d = new SingleAssignmentDisposable();
  	            delays.add(d);
  	            d.setDisposable(delay.subscribe(
  	              function () {
  	                observer.onNext(x);
  	                delays.remove(d);
  	                done();
  	              },
  	              function (e) { observer.onError(e); },
  	              function () {
  	                observer.onNext(x);
  	                delays.remove(d);
  	                done();
  	              }
  	            ))
  	          },
  	          function (e) { observer.onError(e); },
  	          function () {
  	            atEnd = true;
  	            subscription.dispose();
  	            done();
  	          }
  	        ))
  	      }
  	
  	      function done () {
  	        atEnd && delays.length === 0 && observer.onCompleted();
  	      }
  	
  	      if (!subDelay) {
  	        start();
  	      } else {
  	        subscription.setDisposable(subDelay.subscribe(start, function (e) { observer.onError(e); }, start));
  	      }
  	
  	      return new CompositeDisposable(subscription, delays);
  	    }, this);
  	  };
  	
  	    /**
  	     *  Returns the source observable sequence, switching to the other observable sequence if a timeout is signaled.
  	     * @param {Observable} [firstTimeout]  Observable sequence that represents the timeout for the first element. If not provided, this defaults to Observable.never().
  	     * @param {Function} timeoutDurationSelector Selector to retrieve an observable sequence that represents the timeout between the current element and the next element.
  	     * @param {Observable} [other]  Sequence to return in case of a timeout. If not provided, this is set to Observable.throwException().
  	     * @returns {Observable} The source sequence switching to the other sequence in case of a timeout.
  	     */
  	    observableProto.timeoutWithSelector = function (firstTimeout, timeoutdurationSelector, other) {
  	      if (arguments.length === 1) {
  	          timeoutdurationSelector = firstTimeout;
  	          firstTimeout = observableNever();
  	      }
  	      other || (other = observableThrow(new Error('Timeout')));
  	      var source = this;
  	      return new AnonymousObservable(function (observer) {
  	        var subscription = new SerialDisposable(), timer = new SerialDisposable(), original = new SingleAssignmentDisposable();
  	
  	        subscription.setDisposable(original);
  	
  	        var id = 0, switched = false;
  	
  	        function setTimer(timeout) {
  	          var myId = id;
  	
  	          function timerWins () {
  	            return id === myId;
  	          }
  	
  	          var d = new SingleAssignmentDisposable();
  	          timer.setDisposable(d);
  	          d.setDisposable(timeout.subscribe(function () {
  	            timerWins() && subscription.setDisposable(other.subscribe(observer));
  	            d.dispose();
  	          }, function (e) {
  	            timerWins() && observer.onError(e);
  	          }, function () {
  	            timerWins() && subscription.setDisposable(other.subscribe(observer));
  	          }));
  	        };
  	
  	        setTimer(firstTimeout);
  	
  	        function observerWins() {
  	          var res = !switched;
  	          if (res) { id++; }
  	          return res;
  	        }
  	
  	        original.setDisposable(source.subscribe(function (x) {
  	          if (observerWins()) {
  	            observer.onNext(x);
  	            var timeout;
  	            try {
  	              timeout = timeoutdurationSelector(x);
  	            } catch (e) {
  	              observer.onError(e);
  	              return;
  	            }
  	            setTimer(isPromise(timeout) ? observableFromPromise(timeout) : timeout);
  	          }
  	        }, function (e) {
  	          observerWins() && observer.onError(e);
  	        }, function () {
  	          observerWins() && observer.onCompleted();
  	        }));
  	        return new CompositeDisposable(subscription, timer);
  	      }, source);
  	    };
  	
  	  /**
  	   * Ignores values from an observable sequence which are followed by another value within a computed throttle duration.
  	   * @param {Function} durationSelector Selector function to retrieve a sequence indicating the throttle duration for each given element.
  	   * @returns {Observable} The debounced sequence.
  	   */
  	  observableProto.debounceWithSelector = function (durationSelector) {
  	    var source = this;
  	    return new AnonymousObservable(function (observer) {
  	      var value, hasValue = false, cancelable = new SerialDisposable(), id = 0;
  	      var subscription = source.subscribe(function (x) {
  	        var throttle;
  	        try {
  	          throttle = durationSelector(x);
  	        } catch (e) {
  	          observer.onError(e);
  	          return;
  	        }
  	
  	        isPromise(throttle) && (throttle = observableFromPromise(throttle));
  	
  	        hasValue = true;
  	        value = x;
  	        id++;
  	        var currentid = id, d = new SingleAssignmentDisposable();
  	        cancelable.setDisposable(d);
  	        d.setDisposable(throttle.subscribe(function () {
  	          hasValue && id === currentid && observer.onNext(value);
  	          hasValue = false;
  	          d.dispose();
  	        }, observer.onError.bind(observer), function () {
  	          hasValue && id === currentid && observer.onNext(value);
  	          hasValue = false;
  	          d.dispose();
  	        }));
  	      }, function (e) {
  	        cancelable.dispose();
  	        observer.onError(e);
  	        hasValue = false;
  	        id++;
  	      }, function () {
  	        cancelable.dispose();
  	        hasValue && observer.onNext(value);
  	        observer.onCompleted();
  	        hasValue = false;
  	        id++;
  	      });
  	      return new CompositeDisposable(subscription, cancelable);
  	    }, source);
  	  };
  	
  	  /**
  	   * @deprecated use #debounceWithSelector instead.
  	   */
  	  observableProto.throttleWithSelector = function (durationSelector) {
  	    //deprecate('throttleWithSelector', 'debounceWithSelector');
  	    return this.debounceWithSelector(durationSelector);
  	  };
  	
  	  /**
  	   *  Skips elements for the specified duration from the end of the observable source sequence, using the specified scheduler to run timers.
  	   *
  	   *  1 - res = source.skipLastWithTime(5000);
  	   *  2 - res = source.skipLastWithTime(5000, scheduler);
  	   *
  	   * @description
  	   *  This operator accumulates a queue with a length enough to store elements received during the initial duration window.
  	   *  As more elements are received, elements older than the specified duration are taken from the queue and produced on the
  	   *  result sequence. This causes elements to be delayed with duration.
  	   * @param {Number} duration Duration for skipping elements from the end of the sequence.
  	   * @param {Scheduler} [scheduler]  Scheduler to run the timer on. If not specified, defaults to Rx.Scheduler.timeout
  	   * @returns {Observable} An observable sequence with the elements skipped during the specified duration from the end of the source sequence.
  	   */
  	  observableProto.skipLastWithTime = function (duration, scheduler) {
  	    isScheduler(scheduler) || (scheduler = timeoutScheduler);
  	    var source = this;
  	    return new AnonymousObservable(function (o) {
  	      var q = [];
  	      return source.subscribe(function (x) {
  	        var now = scheduler.now();
  	        q.push({ interval: now, value: x });
  	        while (q.length > 0 && now - q[0].interval >= duration) {
  	          o.onNext(q.shift().value);
  	        }
  	      }, function (e) { o.onError(e); }, function () {
  	        var now = scheduler.now();
  	        while (q.length > 0 && now - q[0].interval >= duration) {
  	          o.onNext(q.shift().value);
  	        }
  	        o.onCompleted();
  	      });
  	    }, source);
  	  };
  	
  	  /**
  	   *  Returns elements within the specified duration from the end of the observable source sequence, using the specified schedulers to run timers and to drain the collected elements.
  	   * @description
  	   *  This operator accumulates a queue with a length enough to store elements received during the initial duration window.
  	   *  As more elements are received, elements older than the specified duration are taken from the queue and produced on the
  	   *  result sequence. This causes elements to be delayed with duration.
  	   * @param {Number} duration Duration for taking elements from the end of the sequence.
  	   * @param {Scheduler} [scheduler]  Scheduler to run the timer on. If not specified, defaults to Rx.Scheduler.timeout.
  	   * @returns {Observable} An observable sequence with the elements taken during the specified duration from the end of the source sequence.
  	   */
  	  observableProto.takeLastWithTime = function (duration, scheduler) {
  	    var source = this;
  	    isScheduler(scheduler) || (scheduler = timeoutScheduler);
  	    return new AnonymousObservable(function (o) {
  	      var q = [];
  	      return source.subscribe(function (x) {
  	        var now = scheduler.now();
  	        q.push({ interval: now, value: x });
  	        while (q.length > 0 && now - q[0].interval >= duration) {
  	          q.shift();
  	        }
  	      }, function (e) { o.onError(e); }, function () {
  	        var now = scheduler.now();
  	        while (q.length > 0) {
  	          var next = q.shift();
  	          if (now - next.interval <= duration) { o.onNext(next.value); }
  	        }
  	        o.onCompleted();
  	      });
  	    }, source);
  	  };
  	
  	  /**
  	   *  Returns an array with the elements within the specified duration from the end of the observable source sequence, using the specified scheduler to run timers.
  	   * @description
  	   *  This operator accumulates a queue with a length enough to store elements received during the initial duration window.
  	   *  As more elements are received, elements older than the specified duration are taken from the queue and produced on the
  	   *  result sequence. This causes elements to be delayed with duration.
  	   * @param {Number} duration Duration for taking elements from the end of the sequence.
  	   * @param {Scheduler} scheduler Scheduler to run the timer on. If not specified, defaults to Rx.Scheduler.timeout.
  	   * @returns {Observable} An observable sequence containing a single array with the elements taken during the specified duration from the end of the source sequence.
  	   */
  	  observableProto.takeLastBufferWithTime = function (duration, scheduler) {
  	    var source = this;
  	    isScheduler(scheduler) || (scheduler = timeoutScheduler);
  	    return new AnonymousObservable(function (o) {
  	      var q = [];
  	      return source.subscribe(function (x) {
  	        var now = scheduler.now();
  	        q.push({ interval: now, value: x });
  	        while (q.length > 0 && now - q[0].interval >= duration) {
  	          q.shift();
  	        }
  	      }, function (e) { o.onError(e); }, function () {
  	        var now = scheduler.now(), res = [];
  	        while (q.length > 0) {
  	          var next = q.shift();
  	          now - next.interval <= duration && res.push(next.value);
  	        }
  	        o.onNext(res);
  	        o.onCompleted();
  	      });
  	    }, source);
  	  };
  	
  	  /**
  	   *  Takes elements for the specified duration from the start of the observable source sequence, using the specified scheduler to run timers.
  	   *
  	   * @example
  	   *  1 - res = source.takeWithTime(5000,  [optional scheduler]);
  	   * @description
  	   *  This operator accumulates a queue with a length enough to store elements received during the initial duration window.
  	   *  As more elements are received, elements older than the specified duration are taken from the queue and produced on the
  	   *  result sequence. This causes elements to be delayed with duration.
  	   * @param {Number} duration Duration for taking elements from the start of the sequence.
  	   * @param {Scheduler} scheduler Scheduler to run the timer on. If not specified, defaults to Rx.Scheduler.timeout.
  	   * @returns {Observable} An observable sequence with the elements taken during the specified duration from the start of the source sequence.
  	   */
  	  observableProto.takeWithTime = function (duration, scheduler) {
  	    var source = this;
  	    isScheduler(scheduler) || (scheduler = timeoutScheduler);
  	    return new AnonymousObservable(function (o) {
  	      return new CompositeDisposable(scheduler.scheduleWithRelative(duration, function () { o.onCompleted(); }), source.subscribe(o));
  	    }, source);
  	  };
  	
  	  /**
  	   *  Skips elements for the specified duration from the start of the observable source sequence, using the specified scheduler to run timers.
  	   *
  	   * @example
  	   *  1 - res = source.skipWithTime(5000, [optional scheduler]);
  	   *
  	   * @description
  	   *  Specifying a zero value for duration doesn't guarantee no elements will be dropped from the start of the source sequence.
  	   *  This is a side-effect of the asynchrony introduced by the scheduler, where the action that causes callbacks from the source sequence to be forwarded
  	   *  may not execute immediately, despite the zero due time.
  	   *
  	   *  Errors produced by the source sequence are always forwarded to the result sequence, even if the error occurs before the duration.
  	   * @param {Number} duration Duration for skipping elements from the start of the sequence.
  	   * @param {Scheduler} scheduler Scheduler to run the timer on. If not specified, defaults to Rx.Scheduler.timeout.
  	   * @returns {Observable} An observable sequence with the elements skipped during the specified duration from the start of the source sequence.
  	   */
  	  observableProto.skipWithTime = function (duration, scheduler) {
  	    var source = this;
  	    isScheduler(scheduler) || (scheduler = timeoutScheduler);
  	    return new AnonymousObservable(function (observer) {
  	      var open = false;
  	      return new CompositeDisposable(
  	        scheduler.scheduleWithRelative(duration, function () { open = true; }),
  	        source.subscribe(function (x) { open && observer.onNext(x); }, observer.onError.bind(observer), observer.onCompleted.bind(observer)));
  	    }, source);
  	  };
  	
  	  /**
  	   *  Skips elements from the observable source sequence until the specified start time, using the specified scheduler to run timers.
  	   *  Errors produced by the source sequence are always forwarded to the result sequence, even if the error occurs before the start time.
  	   *
  	   * @examples
  	   *  1 - res = source.skipUntilWithTime(new Date(), [scheduler]);
  	   *  2 - res = source.skipUntilWithTime(5000, [scheduler]);
  	   * @param {Date|Number} startTime Time to start taking elements from the source sequence. If this value is less than or equal to Date(), no elements will be skipped.
  	   * @param {Scheduler} [scheduler] Scheduler to run the timer on. If not specified, defaults to Rx.Scheduler.timeout.
  	   * @returns {Observable} An observable sequence with the elements skipped until the specified start time.
  	   */
  	  observableProto.skipUntilWithTime = function (startTime, scheduler) {
  	    isScheduler(scheduler) || (scheduler = timeoutScheduler);
  	    var source = this, schedulerMethod = startTime instanceof Date ?
  	      'scheduleWithAbsolute' :
  	      'scheduleWithRelative';
  	    return new AnonymousObservable(function (o) {
  	      var open = false;
  	
  	      return new CompositeDisposable(
  	        scheduler[schedulerMethod](startTime, function () { open = true; }),
  	        source.subscribe(
  	          function (x) { open && o.onNext(x); },
  	          function (e) { o.onError(e); }, function () { o.onCompleted(); }));
  	    }, source);
  	  };
  	
  	  /**
  	   *  Takes elements for the specified duration until the specified end time, using the specified scheduler to run timers.
  	   * @param {Number | Date} endTime Time to stop taking elements from the source sequence. If this value is less than or equal to new Date(), the result stream will complete immediately.
  	   * @param {Scheduler} [scheduler] Scheduler to run the timer on.
  	   * @returns {Observable} An observable sequence with the elements taken until the specified end time.
  	   */
  	  observableProto.takeUntilWithTime = function (endTime, scheduler) {
  	    isScheduler(scheduler) || (scheduler = timeoutScheduler);
  	    var source = this, schedulerMethod = endTime instanceof Date ?
  	      'scheduleWithAbsolute' :
  	      'scheduleWithRelative';
  	    return new AnonymousObservable(function (o) {
  	      return new CompositeDisposable(
  	        scheduler[schedulerMethod](endTime, function () { o.onCompleted(); }),
  	        source.subscribe(o));
  	    }, source);
  	  };
  	
  	  /**
  	   * Returns an Observable that emits only the first item emitted by the source Observable during sequential time windows of a specified duration.
  	   * @param {Number} windowDuration time to wait before emitting another item after emitting the last item
  	   * @param {Scheduler} [scheduler] the Scheduler to use internally to manage the timers that handle timeout for each item. If not provided, defaults to Scheduler.timeout.
  	   * @returns {Observable} An Observable that performs the throttle operation.
  	   */
  	  observableProto.throttleFirst = function (windowDuration, scheduler) {
  	    isScheduler(scheduler) || (scheduler = timeoutScheduler);
  	    var duration = +windowDuration || 0;
  	    if (duration <= 0) { throw new RangeError('windowDuration cannot be less or equal zero.'); }
  	    var source = this;
  	    return new AnonymousObservable(function (o) {
  	      var lastOnNext = 0;
  	      return source.subscribe(
  	        function (x) {
  	          var now = scheduler.now();
  	          if (lastOnNext === 0 || now - lastOnNext >= duration) {
  	            lastOnNext = now;
  	            o.onNext(x);
  	          }
  	        },function (e) { o.onError(e); }, function () { o.onCompleted(); }
  	      );
  	    }, source);
  	  };
  	
  	  /**
  	   * Executes a transducer to transform the observable sequence
  	   * @param {Transducer} transducer A transducer to execute
  	   * @returns {Observable} An Observable sequence containing the results from the transducer.
  	   */
  	  observableProto.transduce = function(transducer) {
  	    var source = this;
  	
  	    function transformForObserver(o) {
  	      return {
  	        '@@transducer/init': function() {
  	          return o;
  	        },
  	        '@@transducer/step': function(obs, input) {
  	          return obs.onNext(input);
  	        },
  	        '@@transducer/result': function(obs) {
  	          return obs.onCompleted();
  	        }
  	      };
  	    }
  	
  	    return new AnonymousObservable(function(o) {
  	      var xform = transducer(transformForObserver(o));
  	      return source.subscribe(
  	        function(v) {
  	          try {
  	            xform['@@transducer/step'](o, v);
  	          } catch (e) {
  	            o.onError(e);
  	          }
  	        },
  	        function (e) { o.onError(e); },
  	        function() { xform['@@transducer/result'](o); }
  	      );
  	    }, source);
  	  };
  	
  	  /*
  	   * Performs a exclusive waiting for the first to finish before subscribing to another observable.
  	   * Observables that come in between subscriptions will be dropped on the floor.
  	   * @returns {Observable} A exclusive observable with only the results that happen when subscribed.
  	   */
  	  observableProto.exclusive = function () {
  	    var sources = this;
  	    return new AnonymousObservable(function (observer) {
  	      var hasCurrent = false,
  	        isStopped = false,
  	        m = new SingleAssignmentDisposable(),
  	        g = new CompositeDisposable();
  	
  	      g.add(m);
  	
  	      m.setDisposable(sources.subscribe(
  	        function (innerSource) {
  	          if (!hasCurrent) {
  	            hasCurrent = true;
  	
  	            isPromise(innerSource) && (innerSource = observableFromPromise(innerSource));
  	
  	            var innerSubscription = new SingleAssignmentDisposable();
  	            g.add(innerSubscription);
  	
  	            innerSubscription.setDisposable(innerSource.subscribe(
  	              observer.onNext.bind(observer),
  	              observer.onError.bind(observer),
  	              function () {
  	                g.remove(innerSubscription);
  	                hasCurrent = false;
  	                if (isStopped && g.length === 1) {
  	                  observer.onCompleted();
  	                }
  	            }));
  	          }
  	        },
  	        observer.onError.bind(observer),
  	        function () {
  	          isStopped = true;
  	          if (!hasCurrent && g.length === 1) {
  	            observer.onCompleted();
  	          }
  	        }));
  	
  	      return g;
  	    }, this);
  	  };
  	
  	  /*
  	   * Performs a exclusive map waiting for the first to finish before subscribing to another observable.
  	   * Observables that come in between subscriptions will be dropped on the floor.
  	   * @param {Function} selector Selector to invoke for every item in the current subscription.
  	   * @param {Any} [thisArg] An optional context to invoke with the selector parameter.
  	   * @returns {Observable} An exclusive observable with only the results that happen when subscribed.
  	   */
  	  observableProto.exclusiveMap = function (selector, thisArg) {
  	    var sources = this,
  	        selectorFunc = bindCallback(selector, thisArg, 3);
  	    return new AnonymousObservable(function (observer) {
  	      var index = 0,
  	        hasCurrent = false,
  	        isStopped = true,
  	        m = new SingleAssignmentDisposable(),
  	        g = new CompositeDisposable();
  	
  	      g.add(m);
  	
  	      m.setDisposable(sources.subscribe(
  	        function (innerSource) {
  	
  	          if (!hasCurrent) {
  	            hasCurrent = true;
  	
  	            innerSubscription = new SingleAssignmentDisposable();
  	            g.add(innerSubscription);
  	
  	            isPromise(innerSource) && (innerSource = observableFromPromise(innerSource));
  	
  	            innerSubscription.setDisposable(innerSource.subscribe(
  	              function (x) {
  	                var result;
  	                try {
  	                  result = selectorFunc(x, index++, innerSource);
  	                } catch (e) {
  	                  observer.onError(e);
  	                  return;
  	                }
  	
  	                observer.onNext(result);
  	              },
  	              function (e) { observer.onError(e); },
  	              function () {
  	                g.remove(innerSubscription);
  	                hasCurrent = false;
  	
  	                if (isStopped && g.length === 1) {
  	                  observer.onCompleted();
  	                }
  	              }));
  	          }
  	        },
  	        function (e) { observer.onError(e); },
  	        function () {
  	          isStopped = true;
  	          if (g.length === 1 && !hasCurrent) {
  	            observer.onCompleted();
  	          }
  	        }));
  	      return g;
  	    }, this);
  	  };
  	
  	  /** Provides a set of extension methods for virtual time scheduling. */
  	  Rx.VirtualTimeScheduler = (function (__super__) {
  	
  	    function localNow() {
  	      return this.toDateTimeOffset(this.clock);
  	    }
  	
  	    function scheduleNow(state, action) {
  	      return this.scheduleAbsoluteWithState(state, this.clock, action);
  	    }
  	
  	    function scheduleRelative(state, dueTime, action) {
  	      return this.scheduleRelativeWithState(state, this.toRelative(dueTime), action);
  	    }
  	
  	    function scheduleAbsolute(state, dueTime, action) {
  	      return this.scheduleRelativeWithState(state, this.toRelative(dueTime - this.now()), action);
  	    }
  	
  	    function invokeAction(scheduler, action) {
  	      action();
  	      return disposableEmpty;
  	    }
  	
  	    inherits(VirtualTimeScheduler, __super__);
  	
  	    /**
  	     * Creates a new virtual time scheduler with the specified initial clock value and absolute time comparer.
  	     *
  	     * @constructor
  	     * @param {Number} initialClock Initial value for the clock.
  	     * @param {Function} comparer Comparer to determine causality of events based on absolute time.
  	     */
  	    function VirtualTimeScheduler(initialClock, comparer) {
  	      this.clock = initialClock;
  	      this.comparer = comparer;
  	      this.isEnabled = false;
  	      this.queue = new PriorityQueue(1024);
  	      __super__.call(this, localNow, scheduleNow, scheduleRelative, scheduleAbsolute);
  	    }
  	
  	    var VirtualTimeSchedulerPrototype = VirtualTimeScheduler.prototype;
  	
  	    /**
  	     * Adds a relative time value to an absolute time value.
  	     * @param {Number} absolute Absolute virtual time value.
  	     * @param {Number} relative Relative virtual time value to add.
  	     * @return {Number} Resulting absolute virtual time sum value.
  	     */
  	    VirtualTimeSchedulerPrototype.add = notImplemented;
  	
  	    /**
  	     * Converts an absolute time to a number
  	     * @param {Any} The absolute time.
  	     * @returns {Number} The absolute time in ms
  	     */
  	    VirtualTimeSchedulerPrototype.toDateTimeOffset = notImplemented;
  	
  	    /**
  	     * Converts the TimeSpan value to a relative virtual time value.
  	     * @param {Number} timeSpan TimeSpan value to convert.
  	     * @return {Number} Corresponding relative virtual time value.
  	     */
  	    VirtualTimeSchedulerPrototype.toRelative = notImplemented;
  	
  	    /**
  	     * Schedules a periodic piece of work by dynamically discovering the scheduler's capabilities. The periodic task will be emulated using recursive scheduling.
  	     * @param {Mixed} state Initial state passed to the action upon the first iteration.
  	     * @param {Number} period Period for running the work periodically.
  	     * @param {Function} action Action to be executed, potentially updating the state.
  	     * @returns {Disposable} The disposable object used to cancel the scheduled recurring action (best effort).
  	     */
  	    VirtualTimeSchedulerPrototype.schedulePeriodicWithState = function (state, period, action) {
  	      var s = new SchedulePeriodicRecursive(this, state, period, action);
  	      return s.start();
  	    };
  	
  	    /**
  	     * Schedules an action to be executed after dueTime.
  	     * @param {Mixed} state State passed to the action to be executed.
  	     * @param {Number} dueTime Relative time after which to execute the action.
  	     * @param {Function} action Action to be executed.
  	     * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
  	     */
  	    VirtualTimeSchedulerPrototype.scheduleRelativeWithState = function (state, dueTime, action) {
  	      var runAt = this.add(this.clock, dueTime);
  	      return this.scheduleAbsoluteWithState(state, runAt, action);
  	    };
  	
  	    /**
  	     * Schedules an action to be executed at dueTime.
  	     * @param {Number} dueTime Relative time after which to execute the action.
  	     * @param {Function} action Action to be executed.
  	     * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
  	     */
  	    VirtualTimeSchedulerPrototype.scheduleRelative = function (dueTime, action) {
  	      return this.scheduleRelativeWithState(action, dueTime, invokeAction);
  	    };
  	
  	    /**
  	     * Starts the virtual time scheduler.
  	     */
  	    VirtualTimeSchedulerPrototype.start = function () {
  	      if (!this.isEnabled) {
  	        this.isEnabled = true;
  	        do {
  	          var next = this.getNext();
  	          if (next !== null) {
  	            this.comparer(next.dueTime, this.clock) > 0 && (this.clock = next.dueTime);
  	            next.invoke();
  	          } else {
  	            this.isEnabled = false;
  	          }
  	        } while (this.isEnabled);
  	      }
  	    };
  	
  	    /**
  	     * Stops the virtual time scheduler.
  	     */
  	    VirtualTimeSchedulerPrototype.stop = function () {
  	      this.isEnabled = false;
  	    };
  	
  	    /**
  	     * Advances the scheduler's clock to the specified time, running all work till that point.
  	     * @param {Number} time Absolute time to advance the scheduler's clock to.
  	     */
  	    VirtualTimeSchedulerPrototype.advanceTo = function (time) {
  	      var dueToClock = this.comparer(this.clock, time);
  	      if (this.comparer(this.clock, time) > 0) { throw new ArgumentOutOfRangeError(); }
  	      if (dueToClock === 0) { return; }
  	      if (!this.isEnabled) {
  	        this.isEnabled = true;
  	        do {
  	          var next = this.getNext();
  	          if (next !== null && this.comparer(next.dueTime, time) <= 0) {
  	            this.comparer(next.dueTime, this.clock) > 0 && (this.clock = next.dueTime);
  	            next.invoke();
  	          } else {
  	            this.isEnabled = false;
  	          }
  	        } while (this.isEnabled);
  	        this.clock = time;
  	      }
  	    };
  	
  	    /**
  	     * Advances the scheduler's clock by the specified relative time, running all work scheduled for that timespan.
  	     * @param {Number} time Relative time to advance the scheduler's clock by.
  	     */
  	    VirtualTimeSchedulerPrototype.advanceBy = function (time) {
  	      var dt = this.add(this.clock, time),
  	          dueToClock = this.comparer(this.clock, dt);
  	      if (dueToClock > 0) { throw new ArgumentOutOfRangeError(); }
  	      if (dueToClock === 0) {  return; }
  	
  	      this.advanceTo(dt);
  	    };
  	
  	    /**
  	     * Advances the scheduler's clock by the specified relative time.
  	     * @param {Number} time Relative time to advance the scheduler's clock by.
  	     */
  	    VirtualTimeSchedulerPrototype.sleep = function (time) {
  	      var dt = this.add(this.clock, time);
  	      if (this.comparer(this.clock, dt) >= 0) { throw new ArgumentOutOfRangeError(); }
  	
  	      this.clock = dt;
  	    };
  	
  	    /**
  	     * Gets the next scheduled item to be executed.
  	     * @returns {ScheduledItem} The next scheduled item.
  	     */
  	    VirtualTimeSchedulerPrototype.getNext = function () {
  	      while (this.queue.length > 0) {
  	        var next = this.queue.peek();
  	        if (next.isCancelled()) {
  	          this.queue.dequeue();
  	        } else {
  	          return next;
  	        }
  	      }
  	      return null;
  	    };
  	
  	    /**
  	     * Schedules an action to be executed at dueTime.
  	     * @param {Scheduler} scheduler Scheduler to execute the action on.
  	     * @param {Number} dueTime Absolute time at which to execute the action.
  	     * @param {Function} action Action to be executed.
  	     * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
  	     */
  	    VirtualTimeSchedulerPrototype.scheduleAbsolute = function (dueTime, action) {
  	      return this.scheduleAbsoluteWithState(action, dueTime, invokeAction);
  	    };
  	
  	    /**
  	     * Schedules an action to be executed at dueTime.
  	     * @param {Mixed} state State passed to the action to be executed.
  	     * @param {Number} dueTime Absolute time at which to execute the action.
  	     * @param {Function} action Action to be executed.
  	     * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
  	     */
  	    VirtualTimeSchedulerPrototype.scheduleAbsoluteWithState = function (state, dueTime, action) {
  	      var self = this;
  	
  	      function run(scheduler, state1) {
  	        self.queue.remove(si);
  	        return action(scheduler, state1);
  	      }
  	
  	      var si = new ScheduledItem(this, state, run, dueTime, this.comparer);
  	      this.queue.enqueue(si);
  	
  	      return si.disposable;
  	    };
  	
  	    return VirtualTimeScheduler;
  	  }(Scheduler));
  	
  	  /** Provides a virtual time scheduler that uses Date for absolute time and number for relative time. */
  	  Rx.HistoricalScheduler = (function (__super__) {
  	    inherits(HistoricalScheduler, __super__);
  	
  	    /**
  	     * Creates a new historical scheduler with the specified initial clock value.
  	     * @constructor
  	     * @param {Number} initialClock Initial value for the clock.
  	     * @param {Function} comparer Comparer to determine causality of events based on absolute time.
  	     */
  	    function HistoricalScheduler(initialClock, comparer) {
  	      var clock = initialClock == null ? 0 : initialClock;
  	      var cmp = comparer || defaultSubComparer;
  	      __super__.call(this, clock, cmp);
  	    }
  	
  	    var HistoricalSchedulerProto = HistoricalScheduler.prototype;
  	
  	    /**
  	     * Adds a relative time value to an absolute time value.
  	     * @param {Number} absolute Absolute virtual time value.
  	     * @param {Number} relative Relative virtual time value to add.
  	     * @return {Number} Resulting absolute virtual time sum value.
  	     */
  	    HistoricalSchedulerProto.add = function (absolute, relative) {
  	      return absolute + relative;
  	    };
  	
  	    HistoricalSchedulerProto.toDateTimeOffset = function (absolute) {
  	      return new Date(absolute).getTime();
  	    };
  	
  	    /**
  	     * Converts the TimeSpan value to a relative virtual time value.
  	     * @memberOf HistoricalScheduler
  	     * @param {Number} timeSpan TimeSpan value to convert.
  	     * @return {Number} Corresponding relative virtual time value.
  	     */
  	    HistoricalSchedulerProto.toRelative = function (timeSpan) {
  	      return timeSpan;
  	    };
  	
  	    return HistoricalScheduler;
  	  }(Rx.VirtualTimeScheduler));
  	
  	  var AnonymousObservable = Rx.AnonymousObservable = (function (__super__) {
  	    inherits(AnonymousObservable, __super__);
  	
  	    // Fix subscriber to check for undefined or function returned to decorate as Disposable
  	    function fixSubscriber(subscriber) {
  	      return subscriber && isFunction(subscriber.dispose) ? subscriber :
  	        isFunction(subscriber) ? disposableCreate(subscriber) : disposableEmpty;
  	    }
  	
  	    function setDisposable(s, state) {
  	      var ado = state[0], subscribe = state[1];
  	      var sub = tryCatch(subscribe)(ado);
  	
  	      if (sub === errorObj) {
  	        if(!ado.fail(errorObj.e)) { return thrower(errorObj.e); }
  	      }
  	      ado.setDisposable(fixSubscriber(sub));
  	    }
  	
  	    function AnonymousObservable(subscribe, parent) {
  	      this.source = parent;
  	
  	      function s(observer) {
  	        var ado = new AutoDetachObserver(observer), state = [ado, subscribe];
  	
  	        if (currentThreadScheduler.scheduleRequired()) {
  	          currentThreadScheduler.scheduleWithState(state, setDisposable);
  	        } else {
  	          setDisposable(null, state);
  	        }
  	        return ado;
  	      }
  	
  	      __super__.call(this, s);
  	    }
  	
  	    return AnonymousObservable;
  	
  	  }(Observable));
  	
  	  var AutoDetachObserver = (function (__super__) {
  	    inherits(AutoDetachObserver, __super__);
  	
  	    function AutoDetachObserver(observer) {
  	      __super__.call(this);
  	      this.observer = observer;
  	      this.m = new SingleAssignmentDisposable();
  	    }
  	
  	    var AutoDetachObserverPrototype = AutoDetachObserver.prototype;
  	
  	    AutoDetachObserverPrototype.next = function (value) {
  	      var result = tryCatch(this.observer.onNext).call(this.observer, value);
  	      if (result === errorObj) {
  	        this.dispose();
  	        thrower(result.e);
  	      }
  	    };
  	
  	    AutoDetachObserverPrototype.error = function (err) {
  	      var result = tryCatch(this.observer.onError).call(this.observer, err);
  	      this.dispose();
  	      result === errorObj && thrower(result.e);
  	    };
  	
  	    AutoDetachObserverPrototype.completed = function () {
  	      var result = tryCatch(this.observer.onCompleted).call(this.observer);
  	      this.dispose();
  	      result === errorObj && thrower(result.e);
  	    };
  	
  	    AutoDetachObserverPrototype.setDisposable = function (value) { this.m.setDisposable(value); };
  	    AutoDetachObserverPrototype.getDisposable = function () { return this.m.getDisposable(); };
  	
  	    AutoDetachObserverPrototype.dispose = function () {
  	      __super__.prototype.dispose.call(this);
  	      this.m.dispose();
  	    };
  	
  	    return AutoDetachObserver;
  	  }(AbstractObserver));
  	
  	  var GroupedObservable = (function (__super__) {
  	    inherits(GroupedObservable, __super__);
  	
  	    function subscribe(observer) {
  	      return this.underlyingObservable.subscribe(observer);
  	    }
  	
  	    function GroupedObservable(key, underlyingObservable, mergedDisposable) {
  	      __super__.call(this, subscribe);
  	      this.key = key;
  	      this.underlyingObservable = !mergedDisposable ?
  	        underlyingObservable :
  	        new AnonymousObservable(function (observer) {
  	          return new CompositeDisposable(mergedDisposable.getDisposable(), underlyingObservable.subscribe(observer));
  	        });
  	    }
  	
  	    return GroupedObservable;
  	  }(Observable));
  	
  	  /**
  	   *  Represents an object that is both an observable sequence as well as an observer.
  	   *  Each notification is broadcasted to all subscribed observers.
  	   */
  	  var Subject = Rx.Subject = (function (__super__) {
  	    function subscribe(observer) {
  	      checkDisposed(this);
  	      if (!this.isStopped) {
  	        this.observers.push(observer);
  	        return new InnerSubscription(this, observer);
  	      }
  	      if (this.hasError) {
  	        observer.onError(this.error);
  	        return disposableEmpty;
  	      }
  	      observer.onCompleted();
  	      return disposableEmpty;
  	    }
  	
  	    inherits(Subject, __super__);
  	
  	    /**
  	     * Creates a subject.
  	     */
  	    function Subject() {
  	      __super__.call(this, subscribe);
  	      this.isDisposed = false,
  	      this.isStopped = false,
  	      this.observers = [];
  	      this.hasError = false;
  	    }
  	
  	    addProperties(Subject.prototype, Observer.prototype, {
  	      /**
  	       * Indicates whether the subject has observers subscribed to it.
  	       * @returns {Boolean} Indicates whether the subject has observers subscribed to it.
  	       */
  	      hasObservers: function () { return this.observers.length > 0; },
  	      /**
  	       * Notifies all subscribed observers about the end of the sequence.
  	       */
  	      onCompleted: function () {
  	        checkDisposed(this);
  	        if (!this.isStopped) {
  	          this.isStopped = true;
  	          for (var i = 0, os = cloneArray(this.observers), len = os.length; i < len; i++) {
  	            os[i].onCompleted();
  	          }
  	
  	          this.observers.length = 0;
  	        }
  	      },
  	      /**
  	       * Notifies all subscribed observers about the exception.
  	       * @param {Mixed} error The exception to send to all observers.
  	       */
  	      onError: function (error) {
  	        checkDisposed(this);
  	        if (!this.isStopped) {
  	          this.isStopped = true;
  	          this.error = error;
  	          this.hasError = true;
  	          for (var i = 0, os = cloneArray(this.observers), len = os.length; i < len; i++) {
  	            os[i].onError(error);
  	          }
  	
  	          this.observers.length = 0;
  	        }
  	      },
  	      /**
  	       * Notifies all subscribed observers about the arrival of the specified element in the sequence.
  	       * @param {Mixed} value The value to send to all observers.
  	       */
  	      onNext: function (value) {
  	        checkDisposed(this);
  	        if (!this.isStopped) {
  	          for (var i = 0, os = cloneArray(this.observers), len = os.length; i < len; i++) {
  	            os[i].onNext(value);
  	          }
  	        }
  	      },
  	      /**
  	       * Unsubscribe all observers and release resources.
  	       */
  	      dispose: function () {
  	        this.isDisposed = true;
  	        this.observers = null;
  	      }
  	    });
  	
  	    /**
  	     * Creates a subject from the specified observer and observable.
  	     * @param {Observer} observer The observer used to send messages to the subject.
  	     * @param {Observable} observable The observable used to subscribe to messages sent from the subject.
  	     * @returns {Subject} Subject implemented using the given observer and observable.
  	     */
  	    Subject.create = function (observer, observable) {
  	      return new AnonymousSubject(observer, observable);
  	    };
  	
  	    return Subject;
  	  }(Observable));
  	
  	  /**
  	   *  Represents the result of an asynchronous operation.
  	   *  The last value before the OnCompleted notification, or the error received through OnError, is sent to all subscribed observers.
  	   */
  	  var AsyncSubject = Rx.AsyncSubject = (function (__super__) {
  	
  	    function subscribe(observer) {
  	      checkDisposed(this);
  	
  	      if (!this.isStopped) {
  	        this.observers.push(observer);
  	        return new InnerSubscription(this, observer);
  	      }
  	
  	      if (this.hasError) {
  	        observer.onError(this.error);
  	      } else if (this.hasValue) {
  	        observer.onNext(this.value);
  	        observer.onCompleted();
  	      } else {
  	        observer.onCompleted();
  	      }
  	
  	      return disposableEmpty;
  	    }
  	
  	    inherits(AsyncSubject, __super__);
  	
  	    /**
  	     * Creates a subject that can only receive one value and that value is cached for all future observations.
  	     * @constructor
  	     */
  	    function AsyncSubject() {
  	      __super__.call(this, subscribe);
  	
  	      this.isDisposed = false;
  	      this.isStopped = false;
  	      this.hasValue = false;
  	      this.observers = [];
  	      this.hasError = false;
  	    }
  	
  	    addProperties(AsyncSubject.prototype, Observer, {
  	      /**
  	       * Indicates whether the subject has observers subscribed to it.
  	       * @returns {Boolean} Indicates whether the subject has observers subscribed to it.
  	       */
  	      hasObservers: function () {
  	        checkDisposed(this);
  	        return this.observers.length > 0;
  	      },
  	      /**
  	       * Notifies all subscribed observers about the end of the sequence, also causing the last received value to be sent out (if any).
  	       */
  	      onCompleted: function () {
  	        var i, len;
  	        checkDisposed(this);
  	        if (!this.isStopped) {
  	          this.isStopped = true;
  	          var os = cloneArray(this.observers), len = os.length;
  	
  	          if (this.hasValue) {
  	            for (i = 0; i < len; i++) {
  	              var o = os[i];
  	              o.onNext(this.value);
  	              o.onCompleted();
  	            }
  	          } else {
  	            for (i = 0; i < len; i++) {
  	              os[i].onCompleted();
  	            }
  	          }
  	
  	          this.observers.length = 0;
  	        }
  	      },
  	      /**
  	       * Notifies all subscribed observers about the error.
  	       * @param {Mixed} error The Error to send to all observers.
  	       */
  	      onError: function (error) {
  	        checkDisposed(this);
  	        if (!this.isStopped) {
  	          this.isStopped = true;
  	          this.hasError = true;
  	          this.error = error;
  	
  	          for (var i = 0, os = cloneArray(this.observers), len = os.length; i < len; i++) {
  	            os[i].onError(error);
  	          }
  	
  	          this.observers.length = 0;
  	        }
  	      },
  	      /**
  	       * Sends a value to the subject. The last value received before successful termination will be sent to all subscribed and future observers.
  	       * @param {Mixed} value The value to store in the subject.
  	       */
  	      onNext: function (value) {
  	        checkDisposed(this);
  	        if (this.isStopped) { return; }
  	        this.value = value;
  	        this.hasValue = true;
  	      },
  	      /**
  	       * Unsubscribe all observers and release resources.
  	       */
  	      dispose: function () {
  	        this.isDisposed = true;
  	        this.observers = null;
  	        this.exception = null;
  	        this.value = null;
  	      }
  	    });
  	
  	    return AsyncSubject;
  	  }(Observable));
  	
  	  var AnonymousSubject = Rx.AnonymousSubject = (function (__super__) {
  	    inherits(AnonymousSubject, __super__);
  	
  	    function subscribe(observer) {
  	      return this.observable.subscribe(observer);
  	    }
  	
  	    function AnonymousSubject(observer, observable) {
  	      this.observer = observer;
  	      this.observable = observable;
  	      __super__.call(this, subscribe);
  	    }
  	
  	    addProperties(AnonymousSubject.prototype, Observer.prototype, {
  	      onCompleted: function () {
  	        this.observer.onCompleted();
  	      },
  	      onError: function (error) {
  	        this.observer.onError(error);
  	      },
  	      onNext: function (value) {
  	        this.observer.onNext(value);
  	      }
  	    });
  	
  	    return AnonymousSubject;
  	  }(Observable));
  	
  	  /**
  	  * Used to pause and resume streams.
  	  */
  	  Rx.Pauser = (function (__super__) {
  	    inherits(Pauser, __super__);
  	
  	    function Pauser() {
  	      __super__.call(this);
  	    }
  	
  	    /**
  	     * Pauses the underlying sequence.
  	     */
  	    Pauser.prototype.pause = function () { this.onNext(false); };
  	
  	    /**
  	    * Resumes the underlying sequence.
  	    */
  	    Pauser.prototype.resume = function () { this.onNext(true); };
  	
  	    return Pauser;
  	  }(Subject));
  	
  	  if (true) {
  	    root.Rx = Rx;
  	
  	    !(__WEBPACK_AMD_DEFINE_RESULT__ = function() {
  	      return Rx;
  	    }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
  	  } else if (freeExports && freeModule) {
  	    // in Node.js or RingoJS
  	    if (moduleExports) {
  	      (freeModule.exports = Rx).Rx = Rx;
  	    } else {
  	      freeExports.Rx = Rx;
  	    }
  	  } else {
  	    // in a browser or Rhino
  	    root.Rx = Rx;
  	  }
  	
  	  // All code before this point will be filtered from stack traces.
  	  var rEndingLine = captureLine();
  	
  	}.call(this));
  	
  	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! (webpack)/buildin/module.js */ 2)(module), (function() { return this; }()), __webpack_require__(/*! ./~/node-libs-browser/~/process/browser.js */ 3)))
  
  /***/ },
  /* 2 */
  /*!***********************************!*\
    !*** (webpack)/buildin/module.js ***!
    \***********************************/
  /***/ function(module, exports) {
  
  	module.exports = function(module) {
  		if(!module.webpackPolyfill) {
  			module.deprecate = function() {};
  			module.paths = [];
  			// module.parent = undefined by default
  			module.children = [];
  			module.webpackPolyfill = 1;
  		}
  		return module;
  	}
  
  
  /***/ },
  /* 3 */
  /*!**************************************************!*\
    !*** ./~/node-libs-browser/~/process/browser.js ***!
    \**************************************************/
  /***/ function(module, exports) {
  
  	// shim for using process in browser
  	
  	var process = module.exports = {};
  	var queue = [];
  	var draining = false;
  	var currentQueue;
  	var queueIndex = -1;
  	
  	function cleanUpNextTick() {
  	    draining = false;
  	    if (currentQueue.length) {
  	        queue = currentQueue.concat(queue);
  	    } else {
  	        queueIndex = -1;
  	    }
  	    if (queue.length) {
  	        drainQueue();
  	    }
  	}
  	
  	function drainQueue() {
  	    if (draining) {
  	        return;
  	    }
  	    var timeout = setTimeout(cleanUpNextTick);
  	    draining = true;
  	
  	    var len = queue.length;
  	    while(len) {
  	        currentQueue = queue;
  	        queue = [];
  	        while (++queueIndex < len) {
  	            currentQueue[queueIndex].run();
  	        }
  	        queueIndex = -1;
  	        len = queue.length;
  	    }
  	    currentQueue = null;
  	    draining = false;
  	    clearTimeout(timeout);
  	}
  	
  	process.nextTick = function (fun) {
  	    var args = new Array(arguments.length - 1);
  	    if (arguments.length > 1) {
  	        for (var i = 1; i < arguments.length; i++) {
  	            args[i - 1] = arguments[i];
  	        }
  	    }
  	    queue.push(new Item(fun, args));
  	    if (queue.length === 1 && !draining) {
  	        setTimeout(drainQueue, 0);
  	    }
  	};
  	
  	// v8 likes predictible objects
  	function Item(fun, array) {
  	    this.fun = fun;
  	    this.array = array;
  	}
  	Item.prototype.run = function () {
  	    this.fun.apply(null, this.array);
  	};
  	process.title = 'browser';
  	process.browser = true;
  	process.env = {};
  	process.argv = [];
  	process.version = ''; // empty string to avoid regexp issues
  	process.versions = {};
  	
  	function noop() {}
  	
  	process.on = noop;
  	process.addListener = noop;
  	process.once = noop;
  	process.off = noop;
  	process.removeListener = noop;
  	process.removeAllListeners = noop;
  	process.emit = noop;
  	
  	process.binding = function (name) {
  	    throw new Error('process.binding is not supported');
  	};
  	
  	// TODO(shtylman)
  	process.cwd = function () { return '/' };
  	process.chdir = function (dir) {
  	    throw new Error('process.chdir is not supported');
  	};
  	process.umask = function() { return 0; };
  
  
  /***/ },
  /* 4 */
  /*!*********************************!*\
    !*** ./~/jquery/dist/jquery.js ***!
    \*********************************/
  /***/ function(module, exports, __webpack_require__) {
  
  	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
  	 * jQuery JavaScript Library v2.1.4
  	 * http://jquery.com/
  	 *
  	 * Includes Sizzle.js
  	 * http://sizzlejs.com/
  	 *
  	 * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
  	 * Released under the MIT license
  	 * http://jquery.org/license
  	 *
  	 * Date: 2015-04-28T16:01Z
  	 */
  	
  	(function( global, factory ) {
  	
  		if ( typeof module === "object" && typeof module.exports === "object" ) {
  			// For CommonJS and CommonJS-like environments where a proper `window`
  			// is present, execute the factory and get jQuery.
  			// For environments that do not have a `window` with a `document`
  			// (such as Node.js), expose a factory as module.exports.
  			// This accentuates the need for the creation of a real `window`.
  			// e.g. var jQuery = require("jquery")(window);
  			// See ticket #14549 for more info.
  			module.exports = global.document ?
  				factory( global, true ) :
  				function( w ) {
  					if ( !w.document ) {
  						throw new Error( "jQuery requires a window with a document" );
  					}
  					return factory( w );
  				};
  		} else {
  			factory( global );
  		}
  	
  	// Pass this if window is not defined yet
  	}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
  	
  	// Support: Firefox 18+
  	// Can't be in strict mode, several libs including ASP.NET trace
  	// the stack via arguments.caller.callee and Firefox dies if
  	// you try to trace through "use strict" call chains. (#13335)
  	//
  	
  	var arr = [];
  	
  	var slice = arr.slice;
  	
  	var concat = arr.concat;
  	
  	var push = arr.push;
  	
  	var indexOf = arr.indexOf;
  	
  	var class2type = {};
  	
  	var toString = class2type.toString;
  	
  	var hasOwn = class2type.hasOwnProperty;
  	
  	var support = {};
  	
  	
  	
  	var
  		// Use the correct document accordingly with window argument (sandbox)
  		document = window.document,
  	
  		version = "2.1.4",
  	
  		// Define a local copy of jQuery
  		jQuery = function( selector, context ) {
  			// The jQuery object is actually just the init constructor 'enhanced'
  			// Need init if jQuery is called (just allow error to be thrown if not included)
  			return new jQuery.fn.init( selector, context );
  		},
  	
  		// Support: Android<4.1
  		// Make sure we trim BOM and NBSP
  		rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
  	
  		// Matches dashed string for camelizing
  		rmsPrefix = /^-ms-/,
  		rdashAlpha = /-([\da-z])/gi,
  	
  		// Used by jQuery.camelCase as callback to replace()
  		fcamelCase = function( all, letter ) {
  			return letter.toUpperCase();
  		};
  	
  	jQuery.fn = jQuery.prototype = {
  		// The current version of jQuery being used
  		jquery: version,
  	
  		constructor: jQuery,
  	
  		// Start with an empty selector
  		selector: "",
  	
  		// The default length of a jQuery object is 0
  		length: 0,
  	
  		toArray: function() {
  			return slice.call( this );
  		},
  	
  		// Get the Nth element in the matched element set OR
  		// Get the whole matched element set as a clean array
  		get: function( num ) {
  			return num != null ?
  	
  				// Return just the one element from the set
  				( num < 0 ? this[ num + this.length ] : this[ num ] ) :
  	
  				// Return all the elements in a clean array
  				slice.call( this );
  		},
  	
  		// Take an array of elements and push it onto the stack
  		// (returning the new matched element set)
  		pushStack: function( elems ) {
  	
  			// Build a new jQuery matched element set
  			var ret = jQuery.merge( this.constructor(), elems );
  	
  			// Add the old object onto the stack (as a reference)
  			ret.prevObject = this;
  			ret.context = this.context;
  	
  			// Return the newly-formed element set
  			return ret;
  		},
  	
  		// Execute a callback for every element in the matched set.
  		// (You can seed the arguments with an array of args, but this is
  		// only used internally.)
  		each: function( callback, args ) {
  			return jQuery.each( this, callback, args );
  		},
  	
  		map: function( callback ) {
  			return this.pushStack( jQuery.map(this, function( elem, i ) {
  				return callback.call( elem, i, elem );
  			}));
  		},
  	
  		slice: function() {
  			return this.pushStack( slice.apply( this, arguments ) );
  		},
  	
  		first: function() {
  			return this.eq( 0 );
  		},
  	
  		last: function() {
  			return this.eq( -1 );
  		},
  	
  		eq: function( i ) {
  			var len = this.length,
  				j = +i + ( i < 0 ? len : 0 );
  			return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
  		},
  	
  		end: function() {
  			return this.prevObject || this.constructor(null);
  		},
  	
  		// For internal use only.
  		// Behaves like an Array's method, not like a jQuery method.
  		push: push,
  		sort: arr.sort,
  		splice: arr.splice
  	};
  	
  	jQuery.extend = jQuery.fn.extend = function() {
  		var options, name, src, copy, copyIsArray, clone,
  			target = arguments[0] || {},
  			i = 1,
  			length = arguments.length,
  			deep = false;
  	
  		// Handle a deep copy situation
  		if ( typeof target === "boolean" ) {
  			deep = target;
  	
  			// Skip the boolean and the target
  			target = arguments[ i ] || {};
  			i++;
  		}
  	
  		// Handle case when target is a string or something (possible in deep copy)
  		if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
  			target = {};
  		}
  	
  		// Extend jQuery itself if only one argument is passed
  		if ( i === length ) {
  			target = this;
  			i--;
  		}
  	
  		for ( ; i < length; i++ ) {
  			// Only deal with non-null/undefined values
  			if ( (options = arguments[ i ]) != null ) {
  				// Extend the base object
  				for ( name in options ) {
  					src = target[ name ];
  					copy = options[ name ];
  	
  					// Prevent never-ending loop
  					if ( target === copy ) {
  						continue;
  					}
  	
  					// Recurse if we're merging plain objects or arrays
  					if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
  						if ( copyIsArray ) {
  							copyIsArray = false;
  							clone = src && jQuery.isArray(src) ? src : [];
  	
  						} else {
  							clone = src && jQuery.isPlainObject(src) ? src : {};
  						}
  	
  						// Never move original objects, clone them
  						target[ name ] = jQuery.extend( deep, clone, copy );
  	
  					// Don't bring in undefined values
  					} else if ( copy !== undefined ) {
  						target[ name ] = copy;
  					}
  				}
  			}
  		}
  	
  		// Return the modified object
  		return target;
  	};
  	
  	jQuery.extend({
  		// Unique for each copy of jQuery on the page
  		expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
  	
  		// Assume jQuery is ready without the ready module
  		isReady: true,
  	
  		error: function( msg ) {
  			throw new Error( msg );
  		},
  	
  		noop: function() {},
  	
  		isFunction: function( obj ) {
  			return jQuery.type(obj) === "function";
  		},
  	
  		isArray: Array.isArray,
  	
  		isWindow: function( obj ) {
  			return obj != null && obj === obj.window;
  		},
  	
  		isNumeric: function( obj ) {
  			// parseFloat NaNs numeric-cast false positives (null|true|false|"")
  			// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
  			// subtraction forces infinities to NaN
  			// adding 1 corrects loss of precision from parseFloat (#15100)
  			return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;
  		},
  	
  		isPlainObject: function( obj ) {
  			// Not plain objects:
  			// - Any object or value whose internal [[Class]] property is not "[object Object]"
  			// - DOM nodes
  			// - window
  			if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
  				return false;
  			}
  	
  			if ( obj.constructor &&
  					!hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) {
  				return false;
  			}
  	
  			// If the function hasn't returned already, we're confident that
  			// |obj| is a plain object, created by {} or constructed with new Object
  			return true;
  		},
  	
  		isEmptyObject: function( obj ) {
  			var name;
  			for ( name in obj ) {
  				return false;
  			}
  			return true;
  		},
  	
  		type: function( obj ) {
  			if ( obj == null ) {
  				return obj + "";
  			}
  			// Support: Android<4.0, iOS<6 (functionish RegExp)
  			return typeof obj === "object" || typeof obj === "function" ?
  				class2type[ toString.call(obj) ] || "object" :
  				typeof obj;
  		},
  	
  		// Evaluates a script in a global context
  		globalEval: function( code ) {
  			var script,
  				indirect = eval;
  	
  			code = jQuery.trim( code );
  	
  			if ( code ) {
  				// If the code includes a valid, prologue position
  				// strict mode pragma, execute code by injecting a
  				// script tag into the document.
  				if ( code.indexOf("use strict") === 1 ) {
  					script = document.createElement("script");
  					script.text = code;
  					document.head.appendChild( script ).parentNode.removeChild( script );
  				} else {
  				// Otherwise, avoid the DOM node creation, insertion
  				// and removal by using an indirect global eval
  					indirect( code );
  				}
  			}
  		},
  	
  		// Convert dashed to camelCase; used by the css and data modules
  		// Support: IE9-11+
  		// Microsoft forgot to hump their vendor prefix (#9572)
  		camelCase: function( string ) {
  			return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
  		},
  	
  		nodeName: function( elem, name ) {
  			return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
  		},
  	
  		// args is for internal usage only
  		each: function( obj, callback, args ) {
  			var value,
  				i = 0,
  				length = obj.length,
  				isArray = isArraylike( obj );
  	
  			if ( args ) {
  				if ( isArray ) {
  					for ( ; i < length; i++ ) {
  						value = callback.apply( obj[ i ], args );
  	
  						if ( value === false ) {
  							break;
  						}
  					}
  				} else {
  					for ( i in obj ) {
  						value = callback.apply( obj[ i ], args );
  	
  						if ( value === false ) {
  							break;
  						}
  					}
  				}
  	
  			// A special, fast, case for the most common use of each
  			} else {
  				if ( isArray ) {
  					for ( ; i < length; i++ ) {
  						value = callback.call( obj[ i ], i, obj[ i ] );
  	
  						if ( value === false ) {
  							break;
  						}
  					}
  				} else {
  					for ( i in obj ) {
  						value = callback.call( obj[ i ], i, obj[ i ] );
  	
  						if ( value === false ) {
  							break;
  						}
  					}
  				}
  			}
  	
  			return obj;
  		},
  	
  		// Support: Android<4.1
  		trim: function( text ) {
  			return text == null ?
  				"" :
  				( text + "" ).replace( rtrim, "" );
  		},
  	
  		// results is for internal usage only
  		makeArray: function( arr, results ) {
  			var ret = results || [];
  	
  			if ( arr != null ) {
  				if ( isArraylike( Object(arr) ) ) {
  					jQuery.merge( ret,
  						typeof arr === "string" ?
  						[ arr ] : arr
  					);
  				} else {
  					push.call( ret, arr );
  				}
  			}
  	
  			return ret;
  		},
  	
  		inArray: function( elem, arr, i ) {
  			return arr == null ? -1 : indexOf.call( arr, elem, i );
  		},
  	
  		merge: function( first, second ) {
  			var len = +second.length,
  				j = 0,
  				i = first.length;
  	
  			for ( ; j < len; j++ ) {
  				first[ i++ ] = second[ j ];
  			}
  	
  			first.length = i;
  	
  			return first;
  		},
  	
  		grep: function( elems, callback, invert ) {
  			var callbackInverse,
  				matches = [],
  				i = 0,
  				length = elems.length,
  				callbackExpect = !invert;
  	
  			// Go through the array, only saving the items
  			// that pass the validator function
  			for ( ; i < length; i++ ) {
  				callbackInverse = !callback( elems[ i ], i );
  				if ( callbackInverse !== callbackExpect ) {
  					matches.push( elems[ i ] );
  				}
  			}
  	
  			return matches;
  		},
  	
  		// arg is for internal usage only
  		map: function( elems, callback, arg ) {
  			var value,
  				i = 0,
  				length = elems.length,
  				isArray = isArraylike( elems ),
  				ret = [];
  	
  			// Go through the array, translating each of the items to their new values
  			if ( isArray ) {
  				for ( ; i < length; i++ ) {
  					value = callback( elems[ i ], i, arg );
  	
  					if ( value != null ) {
  						ret.push( value );
  					}
  				}
  	
  			// Go through every key on the object,
  			} else {
  				for ( i in elems ) {
  					value = callback( elems[ i ], i, arg );
  	
  					if ( value != null ) {
  						ret.push( value );
  					}
  				}
  			}
  	
  			// Flatten any nested arrays
  			return concat.apply( [], ret );
  		},
  	
  		// A global GUID counter for objects
  		guid: 1,
  	
  		// Bind a function to a context, optionally partially applying any
  		// arguments.
  		proxy: function( fn, context ) {
  			var tmp, args, proxy;
  	
  			if ( typeof context === "string" ) {
  				tmp = fn[ context ];
  				context = fn;
  				fn = tmp;
  			}
  	
  			// Quick check to determine if target is callable, in the spec
  			// this throws a TypeError, but we will just return undefined.
  			if ( !jQuery.isFunction( fn ) ) {
  				return undefined;
  			}
  	
  			// Simulated bind
  			args = slice.call( arguments, 2 );
  			proxy = function() {
  				return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
  			};
  	
  			// Set the guid of unique handler to the same of original handler, so it can be removed
  			proxy.guid = fn.guid = fn.guid || jQuery.guid++;
  	
  			return proxy;
  		},
  	
  		now: Date.now,
  	
  		// jQuery.support is not used in Core but other projects attach their
  		// properties to it so it needs to exist.
  		support: support
  	});
  	
  	// Populate the class2type map
  	jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
  		class2type[ "[object " + name + "]" ] = name.toLowerCase();
  	});
  	
  	function isArraylike( obj ) {
  	
  		// Support: iOS 8.2 (not reproducible in simulator)
  		// `in` check used to prevent JIT error (gh-2145)
  		// hasOwn isn't used here due to false negatives
  		// regarding Nodelist length in IE
  		var length = "length" in obj && obj.length,
  			type = jQuery.type( obj );
  	
  		if ( type === "function" || jQuery.isWindow( obj ) ) {
  			return false;
  		}
  	
  		if ( obj.nodeType === 1 && length ) {
  			return true;
  		}
  	
  		return type === "array" || length === 0 ||
  			typeof length === "number" && length > 0 && ( length - 1 ) in obj;
  	}
  	var Sizzle =
  	/*!
  	 * Sizzle CSS Selector Engine v2.2.0-pre
  	 * http://sizzlejs.com/
  	 *
  	 * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors
  	 * Released under the MIT license
  	 * http://jquery.org/license
  	 *
  	 * Date: 2014-12-16
  	 */
  	(function( window ) {
  	
  	var i,
  		support,
  		Expr,
  		getText,
  		isXML,
  		tokenize,
  		compile,
  		select,
  		outermostContext,
  		sortInput,
  		hasDuplicate,
  	
  		// Local document vars
  		setDocument,
  		document,
  		docElem,
  		documentIsHTML,
  		rbuggyQSA,
  		rbuggyMatches,
  		matches,
  		contains,
  	
  		// Instance-specific data
  		expando = "sizzle" + 1 * new Date(),
  		preferredDoc = window.document,
  		dirruns = 0,
  		done = 0,
  		classCache = createCache(),
  		tokenCache = createCache(),
  		compilerCache = createCache(),
  		sortOrder = function( a, b ) {
  			if ( a === b ) {
  				hasDuplicate = true;
  			}
  			return 0;
  		},
  	
  		// General-purpose constants
  		MAX_NEGATIVE = 1 << 31,
  	
  		// Instance methods
  		hasOwn = ({}).hasOwnProperty,
  		arr = [],
  		pop = arr.pop,
  		push_native = arr.push,
  		push = arr.push,
  		slice = arr.slice,
  		// Use a stripped-down indexOf as it's faster than native
  		// http://jsperf.com/thor-indexof-vs-for/5
  		indexOf = function( list, elem ) {
  			var i = 0,
  				len = list.length;
  			for ( ; i < len; i++ ) {
  				if ( list[i] === elem ) {
  					return i;
  				}
  			}
  			return -1;
  		},
  	
  		booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
  	
  		// Regular expressions
  	
  		// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
  		whitespace = "[\\x20\\t\\r\\n\\f]",
  		// http://www.w3.org/TR/css3-syntax/#characters
  		characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
  	
  		// Loosely modeled on CSS identifier characters
  		// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
  		// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
  		identifier = characterEncoding.replace( "w", "w#" ),
  	
  		// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
  		attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
  			// Operator (capture 2)
  			"*([*^$|!~]?=)" + whitespace +
  			// "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
  			"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
  			"*\\]",
  	
  		pseudos = ":(" + characterEncoding + ")(?:\\((" +
  			// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
  			// 1. quoted (capture 3; capture 4 or capture 5)
  			"('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
  			// 2. simple (capture 6)
  			"((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
  			// 3. anything else (capture 2)
  			".*" +
  			")\\)|)",
  	
  		// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
  		rwhitespace = new RegExp( whitespace + "+", "g" ),
  		rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
  	
  		rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
  		rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
  	
  		rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
  	
  		rpseudo = new RegExp( pseudos ),
  		ridentifier = new RegExp( "^" + identifier + "$" ),
  	
  		matchExpr = {
  			"ID": new RegExp( "^#(" + characterEncoding + ")" ),
  			"CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
  			"TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
  			"ATTR": new RegExp( "^" + attributes ),
  			"PSEUDO": new RegExp( "^" + pseudos ),
  			"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
  				"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
  				"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
  			"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
  			// For use in libraries implementing .is()
  			// We use this for POS matching in `select`
  			"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
  				whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
  		},
  	
  		rinputs = /^(?:input|select|textarea|button)$/i,
  		rheader = /^h\d$/i,
  	
  		rnative = /^[^{]+\{\s*\[native \w/,
  	
  		// Easily-parseable/retrievable ID or TAG or CLASS selectors
  		rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
  	
  		rsibling = /[+~]/,
  		rescape = /'|\\/g,
  	
  		// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
  		runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
  		funescape = function( _, escaped, escapedWhitespace ) {
  			var high = "0x" + escaped - 0x10000;
  			// NaN means non-codepoint
  			// Support: Firefox<24
  			// Workaround erroneous numeric interpretation of +"0x"
  			return high !== high || escapedWhitespace ?
  				escaped :
  				high < 0 ?
  					// BMP codepoint
  					String.fromCharCode( high + 0x10000 ) :
  					// Supplemental Plane codepoint (surrogate pair)
  					String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
  		},
  	
  		// Used for iframes
  		// See setDocument()
  		// Removing the function wrapper causes a "Permission Denied"
  		// error in IE
  		unloadHandler = function() {
  			setDocument();
  		};
  	
  	// Optimize for push.apply( _, NodeList )
  	try {
  		push.apply(
  			(arr = slice.call( preferredDoc.childNodes )),
  			preferredDoc.childNodes
  		);
  		// Support: Android<4.0
  		// Detect silently failing push.apply
  		arr[ preferredDoc.childNodes.length ].nodeType;
  	} catch ( e ) {
  		push = { apply: arr.length ?
  	
  			// Leverage slice if possible
  			function( target, els ) {
  				push_native.apply( target, slice.call(els) );
  			} :
  	
  			// Support: IE<9
  			// Otherwise append directly
  			function( target, els ) {
  				var j = target.length,
  					i = 0;
  				// Can't trust NodeList.length
  				while ( (target[j++] = els[i++]) ) {}
  				target.length = j - 1;
  			}
  		};
  	}
  	
  	function Sizzle( selector, context, results, seed ) {
  		var match, elem, m, nodeType,
  			// QSA vars
  			i, groups, old, nid, newContext, newSelector;
  	
  		if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
  			setDocument( context );
  		}
  	
  		context = context || document;
  		results = results || [];
  		nodeType = context.nodeType;
  	
  		if ( typeof selector !== "string" || !selector ||
  			nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
  	
  			return results;
  		}
  	
  		if ( !seed && documentIsHTML ) {
  	
  			// Try to shortcut find operations when possible (e.g., not under DocumentFragment)
  			if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
  				// Speed-up: Sizzle("#ID")
  				if ( (m = match[1]) ) {
  					if ( nodeType === 9 ) {
  						elem = context.getElementById( m );
  						// Check parentNode to catch when Blackberry 4.6 returns
  						// nodes that are no longer in the document (jQuery #6963)
  						if ( elem && elem.parentNode ) {
  							// Handle the case where IE, Opera, and Webkit return items
  							// by name instead of ID
  							if ( elem.id === m ) {
  								results.push( elem );
  								return results;
  							}
  						} else {
  							return results;
  						}
  					} else {
  						// Context is not a document
  						if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
  							contains( context, elem ) && elem.id === m ) {
  							results.push( elem );
  							return results;
  						}
  					}
  	
  				// Speed-up: Sizzle("TAG")
  				} else if ( match[2] ) {
  					push.apply( results, context.getElementsByTagName( selector ) );
  					return results;
  	
  				// Speed-up: Sizzle(".CLASS")
  				} else if ( (m = match[3]) && support.getElementsByClassName ) {
  					push.apply( results, context.getElementsByClassName( m ) );
  					return results;
  				}
  			}
  	
  			// QSA path
  			if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
  				nid = old = expando;
  				newContext = context;
  				newSelector = nodeType !== 1 && selector;
  	
  				// qSA works strangely on Element-rooted queries
  				// We can work around this by specifying an extra ID on the root
  				// and working up from there (Thanks to Andrew Dupont for the technique)
  				// IE 8 doesn't work on object elements
  				if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
  					groups = tokenize( selector );
  	
  					if ( (old = context.getAttribute("id")) ) {
  						nid = old.replace( rescape, "\\$&" );
  					} else {
  						context.setAttribute( "id", nid );
  					}
  					nid = "[id='" + nid + "'] ";
  	
  					i = groups.length;
  					while ( i-- ) {
  						groups[i] = nid + toSelector( groups[i] );
  					}
  					newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
  					newSelector = groups.join(",");
  				}
  	
  				if ( newSelector ) {
  					try {
  						push.apply( results,
  							newContext.querySelectorAll( newSelector )
  						);
  						return results;
  					} catch(qsaError) {
  					} finally {
  						if ( !old ) {
  							context.removeAttribute("id");
  						}
  					}
  				}
  			}
  		}
  	
  		// All others
  		return select( selector.replace( rtrim, "$1" ), context, results, seed );
  	}
  	
  	/**
  	 * Create key-value caches of limited size
  	 * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
  	 *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
  	 *	deleting the oldest entry
  	 */
  	function createCache() {
  		var keys = [];
  	
  		function cache( key, value ) {
  			// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
  			if ( keys.push( key + " " ) > Expr.cacheLength ) {
  				// Only keep the most recent entries
  				delete cache[ keys.shift() ];
  			}
  			return (cache[ key + " " ] = value);
  		}
  		return cache;
  	}
  	
  	/**
  	 * Mark a function for special use by Sizzle
  	 * @param {Function} fn The function to mark
  	 */
  	function markFunction( fn ) {
  		fn[ expando ] = true;
  		return fn;
  	}
  	
  	/**
  	 * Support testing using an element
  	 * @param {Function} fn Passed the created div and expects a boolean result
  	 */
  	function assert( fn ) {
  		var div = document.createElement("div");
  	
  		try {
  			return !!fn( div );
  		} catch (e) {
  			return false;
  		} finally {
  			// Remove from its parent by default
  			if ( div.parentNode ) {
  				div.parentNode.removeChild( div );
  			}
  			// release memory in IE
  			div = null;
  		}
  	}
  	
  	/**
  	 * Adds the same handler for all of the specified attrs
  	 * @param {String} attrs Pipe-separated list of attributes
  	 * @param {Function} handler The method that will be applied
  	 */
  	function addHandle( attrs, handler ) {
  		var arr = attrs.split("|"),
  			i = attrs.length;
  	
  		while ( i-- ) {
  			Expr.attrHandle[ arr[i] ] = handler;
  		}
  	}
  	
  	/**
  	 * Checks document order of two siblings
  	 * @param {Element} a
  	 * @param {Element} b
  	 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
  	 */
  	function siblingCheck( a, b ) {
  		var cur = b && a,
  			diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
  				( ~b.sourceIndex || MAX_NEGATIVE ) -
  				( ~a.sourceIndex || MAX_NEGATIVE );
  	
  		// Use IE sourceIndex if available on both nodes
  		if ( diff ) {
  			return diff;
  		}
  	
  		// Check if b follows a
  		if ( cur ) {
  			while ( (cur = cur.nextSibling) ) {
  				if ( cur === b ) {
  					return -1;
  				}
  			}
  		}
  	
  		return a ? 1 : -1;
  	}
  	
  	/**
  	 * Returns a function to use in pseudos for input types
  	 * @param {String} type
  	 */
  	function createInputPseudo( type ) {
  		return function( elem ) {
  			var name = elem.nodeName.toLowerCase();
  			return name === "input" && elem.type === type;
  		};
  	}
  	
  	/**
  	 * Returns a function to use in pseudos for buttons
  	 * @param {String} type
  	 */
  	function createButtonPseudo( type ) {
  		return function( elem ) {
  			var name = elem.nodeName.toLowerCase();
  			return (name === "input" || name === "button") && elem.type === type;
  		};
  	}
  	
  	/**
  	 * Returns a function to use in pseudos for positionals
  	 * @param {Function} fn
  	 */
  	function createPositionalPseudo( fn ) {
  		return markFunction(function( argument ) {
  			argument = +argument;
  			return markFunction(function( seed, matches ) {
  				var j,
  					matchIndexes = fn( [], seed.length, argument ),
  					i = matchIndexes.length;
  	
  				// Match elements found at the specified indexes
  				while ( i-- ) {
  					if ( seed[ (j = matchIndexes[i]) ] ) {
  						seed[j] = !(matches[j] = seed[j]);
  					}
  				}
  			});
  		});
  	}
  	
  	/**
  	 * Checks a node for validity as a Sizzle context
  	 * @param {Element|Object=} context
  	 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
  	 */
  	function testContext( context ) {
  		return context && typeof context.getElementsByTagName !== "undefined" && context;
  	}
  	
  	// Expose support vars for convenience
  	support = Sizzle.support = {};
  	
  	/**
  	 * Detects XML nodes
  	 * @param {Element|Object} elem An element or a document
  	 * @returns {Boolean} True iff elem is a non-HTML XML node
  	 */
  	isXML = Sizzle.isXML = function( elem ) {
  		// documentElement is verified for cases where it doesn't yet exist
  		// (such as loading iframes in IE - #4833)
  		var documentElement = elem && (elem.ownerDocument || elem).documentElement;
  		return documentElement ? documentElement.nodeName !== "HTML" : false;
  	};
  	
  	/**
  	 * Sets document-related variables once based on the current document
  	 * @param {Element|Object} [doc] An element or document object to use to set the document
  	 * @returns {Object} Returns the current document
  	 */
  	setDocument = Sizzle.setDocument = function( node ) {
  		var hasCompare, parent,
  			doc = node ? node.ownerDocument || node : preferredDoc;
  	
  		// If no document and documentElement is available, return
  		if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
  			return document;
  		}
  	
  		// Set our document
  		document = doc;
  		docElem = doc.documentElement;
  		parent = doc.defaultView;
  	
  		// Support: IE>8
  		// If iframe document is assigned to "document" variable and if iframe has been reloaded,
  		// IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
  		// IE6-8 do not support the defaultView property so parent will be undefined
  		if ( parent && parent !== parent.top ) {
  			// IE11 does not have attachEvent, so all must suffer
  			if ( parent.addEventListener ) {
  				parent.addEventListener( "unload", unloadHandler, false );
  			} else if ( parent.attachEvent ) {
  				parent.attachEvent( "onunload", unloadHandler );
  			}
  		}
  	
  		/* Support tests
  		---------------------------------------------------------------------- */
  		documentIsHTML = !isXML( doc );
  	
  		/* Attributes
  		---------------------------------------------------------------------- */
  	
  		// Support: IE<8
  		// Verify that getAttribute really returns attributes and not properties
  		// (excepting IE8 booleans)
  		support.attributes = assert(function( div ) {
  			div.className = "i";
  			return !div.getAttribute("className");
  		});
  	
  		/* getElement(s)By*
  		---------------------------------------------------------------------- */
  	
  		// Check if getElementsByTagName("*") returns only elements
  		support.getElementsByTagName = assert(function( div ) {
  			div.appendChild( doc.createComment("") );
  			return !div.getElementsByTagName("*").length;
  		});
  	
  		// Support: IE<9
  		support.getElementsByClassName = rnative.test( doc.getElementsByClassName );
  	
  		// Support: IE<10
  		// Check if getElementById returns elements by name
  		// The broken getElementById methods don't pick up programatically-set names,
  		// so use a roundabout getElementsByName test
  		support.getById = assert(function( div ) {
  			docElem.appendChild( div ).id = expando;
  			return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
  		});
  	
  		// ID find and filter
  		if ( support.getById ) {
  			Expr.find["ID"] = function( id, context ) {
  				if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
  					var m = context.getElementById( id );
  					// Check parentNode to catch when Blackberry 4.6 returns
  					// nodes that are no longer in the document #6963
  					return m && m.parentNode ? [ m ] : [];
  				}
  			};
  			Expr.filter["ID"] = function( id ) {
  				var attrId = id.replace( runescape, funescape );
  				return function( elem ) {
  					return elem.getAttribute("id") === attrId;
  				};
  			};
  		} else {
  			// Support: IE6/7
  			// getElementById is not reliable as a find shortcut
  			delete Expr.find["ID"];
  	
  			Expr.filter["ID"] =  function( id ) {
  				var attrId = id.replace( runescape, funescape );
  				return function( elem ) {
  					var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
  					return node && node.value === attrId;
  				};
  			};
  		}
  	
  		// Tag
  		Expr.find["TAG"] = support.getElementsByTagName ?
  			function( tag, context ) {
  				if ( typeof context.getElementsByTagName !== "undefined" ) {
  					return context.getElementsByTagName( tag );
  	
  				// DocumentFragment nodes don't have gEBTN
  				} else if ( support.qsa ) {
  					return context.querySelectorAll( tag );
  				}
  			} :
  	
  			function( tag, context ) {
  				var elem,
  					tmp = [],
  					i = 0,
  					// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
  					results = context.getElementsByTagName( tag );
  	
  				// Filter out possible comments
  				if ( tag === "*" ) {
  					while ( (elem = results[i++]) ) {
  						if ( elem.nodeType === 1 ) {
  							tmp.push( elem );
  						}
  					}
  	
  					return tmp;
  				}
  				return results;
  			};
  	
  		// Class
  		Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
  			if ( documentIsHTML ) {
  				return context.getElementsByClassName( className );
  			}
  		};
  	
  		/* QSA/matchesSelector
  		---------------------------------------------------------------------- */
  	
  		// QSA and matchesSelector support
  	
  		// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
  		rbuggyMatches = [];
  	
  		// qSa(:focus) reports false when true (Chrome 21)
  		// We allow this because of a bug in IE8/9 that throws an error
  		// whenever `document.activeElement` is accessed on an iframe
  		// So, we allow :focus to pass through QSA all the time to avoid the IE error
  		// See http://bugs.jquery.com/ticket/13378
  		rbuggyQSA = [];
  	
  		if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
  			// Build QSA regex
  			// Regex strategy adopted from Diego Perini
  			assert(function( div ) {
  				// Select is set to empty string on purpose
  				// This is to test IE's treatment of not explicitly
  				// setting a boolean content attribute,
  				// since its presence should be enough
  				// http://bugs.jquery.com/ticket/12359
  				docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
  					"<select id='" + expando + "-\f]' msallowcapture=''>" +
  					"<option selected=''></option></select>";
  	
  				// Support: IE8, Opera 11-12.16
  				// Nothing should be selected when empty strings follow ^= or $= or *=
  				// The test attribute must be unknown in Opera but "safe" for WinRT
  				// http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
  				if ( div.querySelectorAll("[msallowcapture^='']").length ) {
  					rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
  				}
  	
  				// Support: IE8
  				// Boolean attributes and "value" are not treated correctly
  				if ( !div.querySelectorAll("[selected]").length ) {
  					rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
  				}
  	
  				// Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+
  				if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
  					rbuggyQSA.push("~=");
  				}
  	
  				// Webkit/Opera - :checked should return selected option elements
  				// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
  				// IE8 throws error here and will not see later tests
  				if ( !div.querySelectorAll(":checked").length ) {
  					rbuggyQSA.push(":checked");
  				}
  	
  				// Support: Safari 8+, iOS 8+
  				// https://bugs.webkit.org/show_bug.cgi?id=136851
  				// In-page `selector#id sibing-combinator selector` fails
  				if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
  					rbuggyQSA.push(".#.+[+~]");
  				}
  			});
  	
  			assert(function( div ) {
  				// Support: Windows 8 Native Apps
  				// The type and name attributes are restricted during .innerHTML assignment
  				var input = doc.createElement("input");
  				input.setAttribute( "type", "hidden" );
  				div.appendChild( input ).setAttribute( "name", "D" );
  	
  				// Support: IE8
  				// Enforce case-sensitivity of name attribute
  				if ( div.querySelectorAll("[name=d]").length ) {
  					rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
  				}
  	
  				// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
  				// IE8 throws error here and will not see later tests
  				if ( !div.querySelectorAll(":enabled").length ) {
  					rbuggyQSA.push( ":enabled", ":disabled" );
  				}
  	
  				// Opera 10-11 does not throw on post-comma invalid pseudos
  				div.querySelectorAll("*,:x");
  				rbuggyQSA.push(",.*:");
  			});
  		}
  	
  		if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
  			docElem.webkitMatchesSelector ||
  			docElem.mozMatchesSelector ||
  			docElem.oMatchesSelector ||
  			docElem.msMatchesSelector) )) ) {
  	
  			assert(function( div ) {
  				// Check to see if it's possible to do matchesSelector
  				// on a disconnected node (IE 9)
  				support.disconnectedMatch = matches.call( div, "div" );
  	
  				// This should fail with an exception
  				// Gecko does not error, returns false instead
  				matches.call( div, "[s!='']:x" );
  				rbuggyMatches.push( "!=", pseudos );
  			});
  		}
  	
  		rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
  		rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
  	
  		/* Contains
  		---------------------------------------------------------------------- */
  		hasCompare = rnative.test( docElem.compareDocumentPosition );
  	
  		// Element contains another
  		// Purposefully does not implement inclusive descendent
  		// As in, an element does not contain itself
  		contains = hasCompare || rnative.test( docElem.contains ) ?
  			function( a, b ) {
  				var adown = a.nodeType === 9 ? a.documentElement : a,
  					bup = b && b.parentNode;
  				return a === bup || !!( bup && bup.nodeType === 1 && (
  					adown.contains ?
  						adown.contains( bup ) :
  						a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
  				));
  			} :
  			function( a, b ) {
  				if ( b ) {
  					while ( (b = b.parentNode) ) {
  						if ( b === a ) {
  							return true;
  						}
  					}
  				}
  				return false;
  			};
  	
  		/* Sorting
  		---------------------------------------------------------------------- */
  	
  		// Document order sorting
  		sortOrder = hasCompare ?
  		function( a, b ) {
  	
  			// Flag for duplicate removal
  			if ( a === b ) {
  				hasDuplicate = true;
  				return 0;
  			}
  	
  			// Sort on method existence if only one input has compareDocumentPosition
  			var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
  			if ( compare ) {
  				return compare;
  			}
  	
  			// Calculate position if both inputs belong to the same document
  			compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
  				a.compareDocumentPosition( b ) :
  	
  				// Otherwise we know they are disconnected
  				1;
  	
  			// Disconnected nodes
  			if ( compare & 1 ||
  				(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
  	
  				// Choose the first element that is related to our preferred document
  				if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
  					return -1;
  				}
  				if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
  					return 1;
  				}
  	
  				// Maintain original order
  				return sortInput ?
  					( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
  					0;
  			}
  	
  			return compare & 4 ? -1 : 1;
  		} :
  		function( a, b ) {
  			// Exit early if the nodes are identical
  			if ( a === b ) {
  				hasDuplicate = true;
  				return 0;
  			}
  	
  			var cur,
  				i = 0,
  				aup = a.parentNode,
  				bup = b.parentNode,
  				ap = [ a ],
  				bp = [ b ];
  	
  			// Parentless nodes are either documents or disconnected
  			if ( !aup || !bup ) {
  				return a === doc ? -1 :
  					b === doc ? 1 :
  					aup ? -1 :
  					bup ? 1 :
  					sortInput ?
  					( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
  					0;
  	
  			// If the nodes are siblings, we can do a quick check
  			} else if ( aup === bup ) {
  				return siblingCheck( a, b );
  			}
  	
  			// Otherwise we need full lists of their ancestors for comparison
  			cur = a;
  			while ( (cur = cur.parentNode) ) {
  				ap.unshift( cur );
  			}
  			cur = b;
  			while ( (cur = cur.parentNode) ) {
  				bp.unshift( cur );
  			}
  	
  			// Walk down the tree looking for a discrepancy
  			while ( ap[i] === bp[i] ) {
  				i++;
  			}
  	
  			return i ?
  				// Do a sibling check if the nodes have a common ancestor
  				siblingCheck( ap[i], bp[i] ) :
  	
  				// Otherwise nodes in our document sort first
  				ap[i] === preferredDoc ? -1 :
  				bp[i] === preferredDoc ? 1 :
  				0;
  		};
  	
  		return doc;
  	};
  	
  	Sizzle.matches = function( expr, elements ) {
  		return Sizzle( expr, null, null, elements );
  	};
  	
  	Sizzle.matchesSelector = function( elem, expr ) {
  		// Set document vars if needed
  		if ( ( elem.ownerDocument || elem ) !== document ) {
  			setDocument( elem );
  		}
  	
  		// Make sure that attribute selectors are quoted
  		expr = expr.replace( rattributeQuotes, "='$1']" );
  	
  		if ( support.matchesSelector && documentIsHTML &&
  			( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
  			( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {
  	
  			try {
  				var ret = matches.call( elem, expr );
  	
  				// IE 9's matchesSelector returns false on disconnected nodes
  				if ( ret || support.disconnectedMatch ||
  						// As well, disconnected nodes are said to be in a document
  						// fragment in IE 9
  						elem.document && elem.document.nodeType !== 11 ) {
  					return ret;
  				}
  			} catch (e) {}
  		}
  	
  		return Sizzle( expr, document, null, [ elem ] ).length > 0;
  	};
  	
  	Sizzle.contains = function( context, elem ) {
  		// Set document vars if needed
  		if ( ( context.ownerDocument || context ) !== document ) {
  			setDocument( context );
  		}
  		return contains( context, elem );
  	};
  	
  	Sizzle.attr = function( elem, name ) {
  		// Set document vars if needed
  		if ( ( elem.ownerDocument || elem ) !== document ) {
  			setDocument( elem );
  		}
  	
  		var fn = Expr.attrHandle[ name.toLowerCase() ],
  			// Don't get fooled by Object.prototype properties (jQuery #13807)
  			val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
  				fn( elem, name, !documentIsHTML ) :
  				undefined;
  	
  		return val !== undefined ?
  			val :
  			support.attributes || !documentIsHTML ?
  				elem.getAttribute( name ) :
  				(val = elem.getAttributeNode(name)) && val.specified ?
  					val.value :
  					null;
  	};
  	
  	Sizzle.error = function( msg ) {
  		throw new Error( "Syntax error, unrecognized expression: " + msg );
  	};
  	
  	/**
  	 * Document sorting and removing duplicates
  	 * @param {ArrayLike} results
  	 */
  	Sizzle.uniqueSort = function( results ) {
  		var elem,
  			duplicates = [],
  			j = 0,
  			i = 0;
  	
  		// Unless we *know* we can detect duplicates, assume their presence
  		hasDuplicate = !support.detectDuplicates;
  		sortInput = !support.sortStable && results.slice( 0 );
  		results.sort( sortOrder );
  	
  		if ( hasDuplicate ) {
  			while ( (elem = results[i++]) ) {
  				if ( elem === results[ i ] ) {
  					j = duplicates.push( i );
  				}
  			}
  			while ( j-- ) {
  				results.splice( duplicates[ j ], 1 );
  			}
  		}
  	
  		// Clear input after sorting to release objects
  		// See https://github.com/jquery/sizzle/pull/225
  		sortInput = null;
  	
  		return results;
  	};
  	
  	/**
  	 * Utility function for retrieving the text value of an array of DOM nodes
  	 * @param {Array|Element} elem
  	 */
  	getText = Sizzle.getText = function( elem ) {
  		var node,
  			ret = "",
  			i = 0,
  			nodeType = elem.nodeType;
  	
  		if ( !nodeType ) {
  			// If no nodeType, this is expected to be an array
  			while ( (node = elem[i++]) ) {
  				// Do not traverse comment nodes
  				ret += getText( node );
  			}
  		} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
  			// Use textContent for elements
  			// innerText usage removed for consistency of new lines (jQuery #11153)
  			if ( typeof elem.textContent === "string" ) {
  				return elem.textContent;
  			} else {
  				// Traverse its children
  				for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
  					ret += getText( elem );
  				}
  			}
  		} else if ( nodeType === 3 || nodeType === 4 ) {
  			return elem.nodeValue;
  		}
  		// Do not include comment or processing instruction nodes
  	
  		return ret;
  	};
  	
  	Expr = Sizzle.selectors = {
  	
  		// Can be adjusted by the user
  		cacheLength: 50,
  	
  		createPseudo: markFunction,
  	
  		match: matchExpr,
  	
  		attrHandle: {},
  	
  		find: {},
  	
  		relative: {
  			">": { dir: "parentNode", first: true },
  			" ": { dir: "parentNode" },
  			"+": { dir: "previousSibling", first: true },
  			"~": { dir: "previousSibling" }
  		},
  	
  		preFilter: {
  			"ATTR": function( match ) {
  				match[1] = match[1].replace( runescape, funescape );
  	
  				// Move the given value to match[3] whether quoted or unquoted
  				match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
  	
  				if ( match[2] === "~=" ) {
  					match[3] = " " + match[3] + " ";
  				}
  	
  				return match.slice( 0, 4 );
  			},
  	
  			"CHILD": function( match ) {
  				/* matches from matchExpr["CHILD"]
  					1 type (only|nth|...)
  					2 what (child|of-type)
  					3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
  					4 xn-component of xn+y argument ([+-]?\d*n|)
  					5 sign of xn-component
  					6 x of xn-component
  					7 sign of y-component
  					8 y of y-component
  				*/
  				match[1] = match[1].toLowerCase();
  	
  				if ( match[1].slice( 0, 3 ) === "nth" ) {
  					// nth-* requires argument
  					if ( !match[3] ) {
  						Sizzle.error( match[0] );
  					}
  	
  					// numeric x and y parameters for Expr.filter.CHILD
  					// remember that false/true cast respectively to 0/1
  					match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
  					match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
  	
  				// other types prohibit arguments
  				} else if ( match[3] ) {
  					Sizzle.error( match[0] );
  				}
  	
  				return match;
  			},
  	
  			"PSEUDO": function( match ) {
  				var excess,
  					unquoted = !match[6] && match[2];
  	
  				if ( matchExpr["CHILD"].test( match[0] ) ) {
  					return null;
  				}
  	
  				// Accept quoted arguments as-is
  				if ( match[3] ) {
  					match[2] = match[4] || match[5] || "";
  	
  				// Strip excess characters from unquoted arguments
  				} else if ( unquoted && rpseudo.test( unquoted ) &&
  					// Get excess from tokenize (recursively)
  					(excess = tokenize( unquoted, true )) &&
  					// advance to the next closing parenthesis
  					(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
  	
  					// excess is a negative index
  					match[0] = match[0].slice( 0, excess );
  					match[2] = unquoted.slice( 0, excess );
  				}
  	
  				// Return only captures needed by the pseudo filter method (type and argument)
  				return match.slice( 0, 3 );
  			}
  		},
  	
  		filter: {
  	
  			"TAG": function( nodeNameSelector ) {
  				var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
  				return nodeNameSelector === "*" ?
  					function() { return true; } :
  					function( elem ) {
  						return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
  					};
  			},
  	
  			"CLASS": function( className ) {
  				var pattern = classCache[ className + " " ];
  	
  				return pattern ||
  					(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
  					classCache( className, function( elem ) {
  						return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
  					});
  			},
  	
  			"ATTR": function( name, operator, check ) {
  				return function( elem ) {
  					var result = Sizzle.attr( elem, name );
  	
  					if ( result == null ) {
  						return operator === "!=";
  					}
  					if ( !operator ) {
  						return true;
  					}
  	
  					result += "";
  	
  					return operator === "=" ? result === check :
  						operator === "!=" ? result !== check :
  						operator === "^=" ? check && result.indexOf( check ) === 0 :
  						operator === "*=" ? check && result.indexOf( check ) > -1 :
  						operator === "$=" ? check && result.slice( -check.length ) === check :
  						operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
  						operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
  						false;
  				};
  			},
  	
  			"CHILD": function( type, what, argument, first, last ) {
  				var simple = type.slice( 0, 3 ) !== "nth",
  					forward = type.slice( -4 ) !== "last",
  					ofType = what === "of-type";
  	
  				return first === 1 && last === 0 ?
  	
  					// Shortcut for :nth-*(n)
  					function( elem ) {
  						return !!elem.parentNode;
  					} :
  	
  					function( elem, context, xml ) {
  						var cache, outerCache, node, diff, nodeIndex, start,
  							dir = simple !== forward ? "nextSibling" : "previousSibling",
  							parent = elem.parentNode,
  							name = ofType && elem.nodeName.toLowerCase(),
  							useCache = !xml && !ofType;
  	
  						if ( parent ) {
  	
  							// :(first|last|only)-(child|of-type)
  							if ( simple ) {
  								while ( dir ) {
  									node = elem;
  									while ( (node = node[ dir ]) ) {
  										if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
  											return false;
  										}
  									}
  									// Reverse direction for :only-* (if we haven't yet done so)
  									start = dir = type === "only" && !start && "nextSibling";
  								}
  								return true;
  							}
  	
  							start = [ forward ? parent.firstChild : parent.lastChild ];
  	
  							// non-xml :nth-child(...) stores cache data on `parent`
  							if ( forward && useCache ) {
  								// Seek `elem` from a previously-cached index
  								outerCache = parent[ expando ] || (parent[ expando ] = {});
  								cache = outerCache[ type ] || [];
  								nodeIndex = cache[0] === dirruns && cache[1];
  								diff = cache[0] === dirruns && cache[2];
  								node = nodeIndex && parent.childNodes[ nodeIndex ];
  	
  								while ( (node = ++nodeIndex && node && node[ dir ] ||
  	
  									// Fallback to seeking `elem` from the start
  									(diff = nodeIndex = 0) || start.pop()) ) {
  	
  									// When found, cache indexes on `parent` and break
  									if ( node.nodeType === 1 && ++diff && node === elem ) {
  										outerCache[ type ] = [ dirruns, nodeIndex, diff ];
  										break;
  									}
  								}
  	
  							// Use previously-cached element index if available
  							} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
  								diff = cache[1];
  	
  							// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
  							} else {
  								// Use the same loop as above to seek `elem` from the start
  								while ( (node = ++nodeIndex && node && node[ dir ] ||
  									(diff = nodeIndex = 0) || start.pop()) ) {
  	
  									if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
  										// Cache the index of each encountered element
  										if ( useCache ) {
  											(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
  										}
  	
  										if ( node === elem ) {
  											break;
  										}
  									}
  								}
  							}
  	
  							// Incorporate the offset, then check against cycle size
  							diff -= last;
  							return diff === first || ( diff % first === 0 && diff / first >= 0 );
  						}
  					};
  			},
  	
  			"PSEUDO": function( pseudo, argument ) {
  				// pseudo-class names are case-insensitive
  				// http://www.w3.org/TR/selectors/#pseudo-classes
  				// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
  				// Remember that setFilters inherits from pseudos
  				var args,
  					fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
  						Sizzle.error( "unsupported pseudo: " + pseudo );
  	
  				// The user may use createPseudo to indicate that
  				// arguments are needed to create the filter function
  				// just as Sizzle does
  				if ( fn[ expando ] ) {
  					return fn( argument );
  				}
  	
  				// But maintain support for old signatures
  				if ( fn.length > 1 ) {
  					args = [ pseudo, pseudo, "", argument ];
  					return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
  						markFunction(function( seed, matches ) {
  							var idx,
  								matched = fn( seed, argument ),
  								i = matched.length;
  							while ( i-- ) {
  								idx = indexOf( seed, matched[i] );
  								seed[ idx ] = !( matches[ idx ] = matched[i] );
  							}
  						}) :
  						function( elem ) {
  							return fn( elem, 0, args );
  						};
  				}
  	
  				return fn;
  			}
  		},
  	
  		pseudos: {
  			// Potentially complex pseudos
  			"not": markFunction(function( selector ) {
  				// Trim the selector passed to compile
  				// to avoid treating leading and trailing
  				// spaces as combinators
  				var input = [],
  					results = [],
  					matcher = compile( selector.replace( rtrim, "$1" ) );
  	
  				return matcher[ expando ] ?
  					markFunction(function( seed, matches, context, xml ) {
  						var elem,
  							unmatched = matcher( seed, null, xml, [] ),
  							i = seed.length;
  	
  						// Match elements unmatched by `matcher`
  						while ( i-- ) {
  							if ( (elem = unmatched[i]) ) {
  								seed[i] = !(matches[i] = elem);
  							}
  						}
  					}) :
  					function( elem, context, xml ) {
  						input[0] = elem;
  						matcher( input, null, xml, results );
  						// Don't keep the element (issue #299)
  						input[0] = null;
  						return !results.pop();
  					};
  			}),
  	
  			"has": markFunction(function( selector ) {
  				return function( elem ) {
  					return Sizzle( selector, elem ).length > 0;
  				};
  			}),
  	
  			"contains": markFunction(function( text ) {
  				text = text.replace( runescape, funescape );
  				return function( elem ) {
  					return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
  				};
  			}),
  	
  			// "Whether an element is represented by a :lang() selector
  			// is based solely on the element's language value
  			// being equal to the identifier C,
  			// or beginning with the identifier C immediately followed by "-".
  			// The matching of C against the element's language value is performed case-insensitively.
  			// The identifier C does not have to be a valid language name."
  			// http://www.w3.org/TR/selectors/#lang-pseudo
  			"lang": markFunction( function( lang ) {
  				// lang value must be a valid identifier
  				if ( !ridentifier.test(lang || "") ) {
  					Sizzle.error( "unsupported lang: " + lang );
  				}
  				lang = lang.replace( runescape, funescape ).toLowerCase();
  				return function( elem ) {
  					var elemLang;
  					do {
  						if ( (elemLang = documentIsHTML ?
  							elem.lang :
  							elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
  	
  							elemLang = elemLang.toLowerCase();
  							return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
  						}
  					} while ( (elem = elem.parentNode) && elem.nodeType === 1 );
  					return false;
  				};
  			}),
  	
  			// Miscellaneous
  			"target": function( elem ) {
  				var hash = window.location && window.location.hash;
  				return hash && hash.slice( 1 ) === elem.id;
  			},
  	
  			"root": function( elem ) {
  				return elem === docElem;
  			},
  	
  			"focus": function( elem ) {
  				return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
  			},
  	
  			// Boolean properties
  			"enabled": function( elem ) {
  				return elem.disabled === false;
  			},
  	
  			"disabled": function( elem ) {
  				return elem.disabled === true;
  			},
  	
  			"checked": function( elem ) {
  				// In CSS3, :checked should return both checked and selected elements
  				// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
  				var nodeName = elem.nodeName.toLowerCase();
  				return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
  			},
  	
  			"selected": function( elem ) {
  				// Accessing this property makes selected-by-default
  				// options in Safari work properly
  				if ( elem.parentNode ) {
  					elem.parentNode.selectedIndex;
  				}
  	
  				return elem.selected === true;
  			},
  	
  			// Contents
  			"empty": function( elem ) {
  				// http://www.w3.org/TR/selectors/#empty-pseudo
  				// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
  				//   but not by others (comment: 8; processing instruction: 7; etc.)
  				// nodeType < 6 works because attributes (2) do not appear as children
  				for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
  					if ( elem.nodeType < 6 ) {
  						return false;
  					}
  				}
  				return true;
  			},
  	
  			"parent": function( elem ) {
  				return !Expr.pseudos["empty"]( elem );
  			},
  	
  			// Element/input types
  			"header": function( elem ) {
  				return rheader.test( elem.nodeName );
  			},
  	
  			"input": function( elem ) {
  				return rinputs.test( elem.nodeName );
  			},
  	
  			"button": function( elem ) {
  				var name = elem.nodeName.toLowerCase();
  				return name === "input" && elem.type === "button" || name === "button";
  			},
  	
  			"text": function( elem ) {
  				var attr;
  				return elem.nodeName.toLowerCase() === "input" &&
  					elem.type === "text" &&
  	
  					// Support: IE<8
  					// New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
  					( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
  			},
  	
  			// Position-in-collection
  			"first": createPositionalPseudo(function() {
  				return [ 0 ];
  			}),
  	
  			"last": createPositionalPseudo(function( matchIndexes, length ) {
  				return [ length - 1 ];
  			}),
  	
  			"eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
  				return [ argument < 0 ? argument + length : argument ];
  			}),
  	
  			"even": createPositionalPseudo(function( matchIndexes, length ) {
  				var i = 0;
  				for ( ; i < length; i += 2 ) {
  					matchIndexes.push( i );
  				}
  				return matchIndexes;
  			}),
  	
  			"odd": createPositionalPseudo(function( matchIndexes, length ) {
  				var i = 1;
  				for ( ; i < length; i += 2 ) {
  					matchIndexes.push( i );
  				}
  				return matchIndexes;
  			}),
  	
  			"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
  				var i = argument < 0 ? argument + length : argument;
  				for ( ; --i >= 0; ) {
  					matchIndexes.push( i );
  				}
  				return matchIndexes;
  			}),
  	
  			"gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
  				var i = argument < 0 ? argument + length : argument;
  				for ( ; ++i < length; ) {
  					matchIndexes.push( i );
  				}
  				return matchIndexes;
  			})
  		}
  	};
  	
  	Expr.pseudos["nth"] = Expr.pseudos["eq"];
  	
  	// Add button/input type pseudos
  	for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
  		Expr.pseudos[ i ] = createInputPseudo( i );
  	}
  	for ( i in { submit: true, reset: true } ) {
  		Expr.pseudos[ i ] = createButtonPseudo( i );
  	}
  	
  	// Easy API for creating new setFilters
  	function setFilters() {}
  	setFilters.prototype = Expr.filters = Expr.pseudos;
  	Expr.setFilters = new setFilters();
  	
  	tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
  		var matched, match, tokens, type,
  			soFar, groups, preFilters,
  			cached = tokenCache[ selector + " " ];
  	
  		if ( cached ) {
  			return parseOnly ? 0 : cached.slice( 0 );
  		}
  	
  		soFar = selector;
  		groups = [];
  		preFilters = Expr.preFilter;
  	
  		while ( soFar ) {
  	
  			// Comma and first run
  			if ( !matched || (match = rcomma.exec( soFar )) ) {
  				if ( match ) {
  					// Don't consume trailing commas as valid
  					soFar = soFar.slice( match[0].length ) || soFar;
  				}
  				groups.push( (tokens = []) );
  			}
  	
  			matched = false;
  	
  			// Combinators
  			if ( (match = rcombinators.exec( soFar )) ) {
  				matched = match.shift();
  				tokens.push({
  					value: matched,
  					// Cast descendant combinators to space
  					type: match[0].replace( rtrim, " " )
  				});
  				soFar = soFar.slice( matched.length );
  			}
  	
  			// Filters
  			for ( type in Expr.filter ) {
  				if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
  					(match = preFilters[ type ]( match ))) ) {
  					matched = match.shift();
  					tokens.push({
  						value: matched,
  						type: type,
  						matches: match
  					});
  					soFar = soFar.slice( matched.length );
  				}
  			}
  	
  			if ( !matched ) {
  				break;
  			}
  		}
  	
  		// Return the length of the invalid excess
  		// if we're just parsing
  		// Otherwise, throw an error or return tokens
  		return parseOnly ?
  			soFar.length :
  			soFar ?
  				Sizzle.error( selector ) :
  				// Cache the tokens
  				tokenCache( selector, groups ).slice( 0 );
  	};
  	
  	function toSelector( tokens ) {
  		var i = 0,
  			len = tokens.length,
  			selector = "";
  		for ( ; i < len; i++ ) {
  			selector += tokens[i].value;
  		}
  		return selector;
  	}
  	
  	function addCombinator( matcher, combinator, base ) {
  		var dir = combinator.dir,
  			checkNonElements = base && dir === "parentNode",
  			doneName = done++;
  	
  		return combinator.first ?
  			// Check against closest ancestor/preceding element
  			function( elem, context, xml ) {
  				while ( (elem = elem[ dir ]) ) {
  					if ( elem.nodeType === 1 || checkNonElements ) {
  						return matcher( elem, context, xml );
  					}
  				}
  			} :
  	
  			// Check against all ancestor/preceding elements
  			function( elem, context, xml ) {
  				var oldCache, outerCache,
  					newCache = [ dirruns, doneName ];
  	
  				// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
  				if ( xml ) {
  					while ( (elem = elem[ dir ]) ) {
  						if ( elem.nodeType === 1 || checkNonElements ) {
  							if ( matcher( elem, context, xml ) ) {
  								return true;
  							}
  						}
  					}
  				} else {
  					while ( (elem = elem[ dir ]) ) {
  						if ( elem.nodeType === 1 || checkNonElements ) {
  							outerCache = elem[ expando ] || (elem[ expando ] = {});
  							if ( (oldCache = outerCache[ dir ]) &&
  								oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
  	
  								// Assign to newCache so results back-propagate to previous elements
  								return (newCache[ 2 ] = oldCache[ 2 ]);
  							} else {
  								// Reuse newcache so results back-propagate to previous elements
  								outerCache[ dir ] = newCache;
  	
  								// A match means we're done; a fail means we have to keep checking
  								if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
  									return true;
  								}
  							}
  						}
  					}
  				}
  			};
  	}
  	
  	function elementMatcher( matchers ) {
  		return matchers.length > 1 ?
  			function( elem, context, xml ) {
  				var i = matchers.length;
  				while ( i-- ) {
  					if ( !matchers[i]( elem, context, xml ) ) {
  						return false;
  					}
  				}
  				return true;
  			} :
  			matchers[0];
  	}
  	
  	function multipleContexts( selector, contexts, results ) {
  		var i = 0,
  			len = contexts.length;
  		for ( ; i < len; i++ ) {
  			Sizzle( selector, contexts[i], results );
  		}
  		return results;
  	}
  	
  	function condense( unmatched, map, filter, context, xml ) {
  		var elem,
  			newUnmatched = [],
  			i = 0,
  			len = unmatched.length,
  			mapped = map != null;
  	
  		for ( ; i < len; i++ ) {
  			if ( (elem = unmatched[i]) ) {
  				if ( !filter || filter( elem, context, xml ) ) {
  					newUnmatched.push( elem );
  					if ( mapped ) {
  						map.push( i );
  					}
  				}
  			}
  		}
  	
  		return newUnmatched;
  	}
  	
  	function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
  		if ( postFilter && !postFilter[ expando ] ) {
  			postFilter = setMatcher( postFilter );
  		}
  		if ( postFinder && !postFinder[ expando ] ) {
  			postFinder = setMatcher( postFinder, postSelector );
  		}
  		return markFunction(function( seed, results, context, xml ) {
  			var temp, i, elem,
  				preMap = [],
  				postMap = [],
  				preexisting = results.length,
  	
  				// Get initial elements from seed or context
  				elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
  	
  				// Prefilter to get matcher input, preserving a map for seed-results synchronization
  				matcherIn = preFilter && ( seed || !selector ) ?
  					condense( elems, preMap, preFilter, context, xml ) :
  					elems,
  	
  				matcherOut = matcher ?
  					// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
  					postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
  	
  						// ...intermediate processing is necessary
  						[] :
  	
  						// ...otherwise use results directly
  						results :
  					matcherIn;
  	
  			// Find primary matches
  			if ( matcher ) {
  				matcher( matcherIn, matcherOut, context, xml );
  			}
  	
  			// Apply postFilter
  			if ( postFilter ) {
  				temp = condense( matcherOut, postMap );
  				postFilter( temp, [], context, xml );
  	
  				// Un-match failing elements by moving them back to matcherIn
  				i = temp.length;
  				while ( i-- ) {
  					if ( (elem = temp[i]) ) {
  						matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
  					}
  				}
  			}
  	
  			if ( seed ) {
  				if ( postFinder || preFilter ) {
  					if ( postFinder ) {
  						// Get the final matcherOut by condensing this intermediate into postFinder contexts
  						temp = [];
  						i = matcherOut.length;
  						while ( i-- ) {
  							if ( (elem = matcherOut[i]) ) {
  								// Restore matcherIn since elem is not yet a final match
  								temp.push( (matcherIn[i] = elem) );
  							}
  						}
  						postFinder( null, (matcherOut = []), temp, xml );
  					}
  	
  					// Move matched elements from seed to results to keep them synchronized
  					i = matcherOut.length;
  					while ( i-- ) {
  						if ( (elem = matcherOut[i]) &&
  							(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
  	
  							seed[temp] = !(results[temp] = elem);
  						}
  					}
  				}
  	
  			// Add elements to results, through postFinder if defined
  			} else {
  				matcherOut = condense(
  					matcherOut === results ?
  						matcherOut.splice( preexisting, matcherOut.length ) :
  						matcherOut
  				);
  				if ( postFinder ) {
  					postFinder( null, results, matcherOut, xml );
  				} else {
  					push.apply( results, matcherOut );
  				}
  			}
  		});
  	}
  	
  	function matcherFromTokens( tokens ) {
  		var checkContext, matcher, j,
  			len = tokens.length,
  			leadingRelative = Expr.relative[ tokens[0].type ],
  			implicitRelative = leadingRelative || Expr.relative[" "],
  			i = leadingRelative ? 1 : 0,
  	
  			// The foundational matcher ensures that elements are reachable from top-level context(s)
  			matchContext = addCombinator( function( elem ) {
  				return elem === checkContext;
  			}, implicitRelative, true ),
  			matchAnyContext = addCombinator( function( elem ) {
  				return indexOf( checkContext, elem ) > -1;
  			}, implicitRelative, true ),
  			matchers = [ function( elem, context, xml ) {
  				var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
  					(checkContext = context).nodeType ?
  						matchContext( elem, context, xml ) :
  						matchAnyContext( elem, context, xml ) );
  				// Avoid hanging onto element (issue #299)
  				checkContext = null;
  				return ret;
  			} ];
  	
  		for ( ; i < len; i++ ) {
  			if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
  				matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
  			} else {
  				matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
  	
  				// Return special upon seeing a positional matcher
  				if ( matcher[ expando ] ) {
  					// Find the next relative operator (if any) for proper handling
  					j = ++i;
  					for ( ; j < len; j++ ) {
  						if ( Expr.relative[ tokens[j].type ] ) {
  							break;
  						}
  					}
  					return setMatcher(
  						i > 1 && elementMatcher( matchers ),
  						i > 1 && toSelector(
  							// If the preceding token was a descendant combinator, insert an implicit any-element `*`
  							tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
  						).replace( rtrim, "$1" ),
  						matcher,
  						i < j && matcherFromTokens( tokens.slice( i, j ) ),
  						j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
  						j < len && toSelector( tokens )
  					);
  				}
  				matchers.push( matcher );
  			}
  		}
  	
  		return elementMatcher( matchers );
  	}
  	
  	function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
  		var bySet = setMatchers.length > 0,
  			byElement = elementMatchers.length > 0,
  			superMatcher = function( seed, context, xml, results, outermost ) {
  				var elem, j, matcher,
  					matchedCount = 0,
  					i = "0",
  					unmatched = seed && [],
  					setMatched = [],
  					contextBackup = outermostContext,
  					// We must always have either seed elements or outermost context
  					elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
  					// Use integer dirruns iff this is the outermost matcher
  					dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
  					len = elems.length;
  	
  				if ( outermost ) {
  					outermostContext = context !== document && context;
  				}
  	
  				// Add elements passing elementMatchers directly to results
  				// Keep `i` a string if there are no elements so `matchedCount` will be "00" below
  				// Support: IE<9, Safari
  				// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
  				for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
  					if ( byElement && elem ) {
  						j = 0;
  						while ( (matcher = elementMatchers[j++]) ) {
  							if ( matcher( elem, context, xml ) ) {
  								results.push( elem );
  								break;
  							}
  						}
  						if ( outermost ) {
  							dirruns = dirrunsUnique;
  						}
  					}
  	
  					// Track unmatched elements for set filters
  					if ( bySet ) {
  						// They will have gone through all possible matchers
  						if ( (elem = !matcher && elem) ) {
  							matchedCount--;
  						}
  	
  						// Lengthen the array for every element, matched or not
  						if ( seed ) {
  							unmatched.push( elem );
  						}
  					}
  				}
  	
  				// Apply set filters to unmatched elements
  				matchedCount += i;
  				if ( bySet && i !== matchedCount ) {
  					j = 0;
  					while ( (matcher = setMatchers[j++]) ) {
  						matcher( unmatched, setMatched, context, xml );
  					}
  	
  					if ( seed ) {
  						// Reintegrate element matches to eliminate the need for sorting
  						if ( matchedCount > 0 ) {
  							while ( i-- ) {
  								if ( !(unmatched[i] || setMatched[i]) ) {
  									setMatched[i] = pop.call( results );
  								}
  							}
  						}
  	
  						// Discard index placeholder values to get only actual matches
  						setMatched = condense( setMatched );
  					}
  	
  					// Add matches to results
  					push.apply( results, setMatched );
  	
  					// Seedless set matches succeeding multiple successful matchers stipulate sorting
  					if ( outermost && !seed && setMatched.length > 0 &&
  						( matchedCount + setMatchers.length ) > 1 ) {
  	
  						Sizzle.uniqueSort( results );
  					}
  				}
  	
  				// Override manipulation of globals by nested matchers
  				if ( outermost ) {
  					dirruns = dirrunsUnique;
  					outermostContext = contextBackup;
  				}
  	
  				return unmatched;
  			};
  	
  		return bySet ?
  			markFunction( superMatcher ) :
  			superMatcher;
  	}
  	
  	compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
  		var i,
  			setMatchers = [],
  			elementMatchers = [],
  			cached = compilerCache[ selector + " " ];
  	
  		if ( !cached ) {
  			// Generate a function of recursive functions that can be used to check each element
  			if ( !match ) {
  				match = tokenize( selector );
  			}
  			i = match.length;
  			while ( i-- ) {
  				cached = matcherFromTokens( match[i] );
  				if ( cached[ expando ] ) {
  					setMatchers.push( cached );
  				} else {
  					elementMatchers.push( cached );
  				}
  			}
  	
  			// Cache the compiled function
  			cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
  	
  			// Save selector and tokenization
  			cached.selector = selector;
  		}
  		return cached;
  	};
  	
  	/**
  	 * A low-level selection function that works with Sizzle's compiled
  	 *  selector functions
  	 * @param {String|Function} selector A selector or a pre-compiled
  	 *  selector function built with Sizzle.compile
  	 * @param {Element} context
  	 * @param {Array} [results]
  	 * @param {Array} [seed] A set of elements to match against
  	 */
  	select = Sizzle.select = function( selector, context, results, seed ) {
  		var i, tokens, token, type, find,
  			compiled = typeof selector === "function" && selector,
  			match = !seed && tokenize( (selector = compiled.selector || selector) );
  	
  		results = results || [];
  	
  		// Try to minimize operations if there is no seed and only one group
  		if ( match.length === 1 ) {
  	
  			// Take a shortcut and set the context if the root selector is an ID
  			tokens = match[0] = match[0].slice( 0 );
  			if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
  					support.getById && context.nodeType === 9 && documentIsHTML &&
  					Expr.relative[ tokens[1].type ] ) {
  	
  				context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
  				if ( !context ) {
  					return results;
  	
  				// Precompiled matchers will still verify ancestry, so step up a level
  				} else if ( compiled ) {
  					context = context.parentNode;
  				}
  	
  				selector = selector.slice( tokens.shift().value.length );
  			}
  	
  			// Fetch a seed set for right-to-left matching
  			i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
  			while ( i-- ) {
  				token = tokens[i];
  	
  				// Abort if we hit a combinator
  				if ( Expr.relative[ (type = token.type) ] ) {
  					break;
  				}
  				if ( (find = Expr.find[ type ]) ) {
  					// Search, expanding context for leading sibling combinators
  					if ( (seed = find(
  						token.matches[0].replace( runescape, funescape ),
  						rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
  					)) ) {
  	
  						// If seed is empty or no tokens remain, we can return early
  						tokens.splice( i, 1 );
  						selector = seed.length && toSelector( tokens );
  						if ( !selector ) {
  							push.apply( results, seed );
  							return results;
  						}
  	
  						break;
  					}
  				}
  			}
  		}
  	
  		// Compile and execute a filtering function if one is not provided
  		// Provide `match` to avoid retokenization if we modified the selector above
  		( compiled || compile( selector, match ) )(
  			seed,
  			context,
  			!documentIsHTML,
  			results,
  			rsibling.test( selector ) && testContext( context.parentNode ) || context
  		);
  		return results;
  	};
  	
  	// One-time assignments
  	
  	// Sort stability
  	support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
  	
  	// Support: Chrome 14-35+
  	// Always assume duplicates if they aren't passed to the comparison function
  	support.detectDuplicates = !!hasDuplicate;
  	
  	// Initialize against the default document
  	setDocument();
  	
  	// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
  	// Detached nodes confoundingly follow *each other*
  	support.sortDetached = assert(function( div1 ) {
  		// Should return 1, but returns 4 (following)
  		return div1.compareDocumentPosition( document.createElement("div") ) & 1;
  	});
  	
  	// Support: IE<8
  	// Prevent attribute/property "interpolation"
  	// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
  	if ( !assert(function( div ) {
  		div.innerHTML = "<a href='#'></a>";
  		return div.firstChild.getAttribute("href") === "#" ;
  	}) ) {
  		addHandle( "type|href|height|width", function( elem, name, isXML ) {
  			if ( !isXML ) {
  				return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
  			}
  		});
  	}
  	
  	// Support: IE<9
  	// Use defaultValue in place of getAttribute("value")
  	if ( !support.attributes || !assert(function( div ) {
  		div.innerHTML = "<input/>";
  		div.firstChild.setAttribute( "value", "" );
  		return div.firstChild.getAttribute( "value" ) === "";
  	}) ) {
  		addHandle( "value", function( elem, name, isXML ) {
  			if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
  				return elem.defaultValue;
  			}
  		});
  	}
  	
  	// Support: IE<9
  	// Use getAttributeNode to fetch booleans when getAttribute lies
  	if ( !assert(function( div ) {
  		return div.getAttribute("disabled") == null;
  	}) ) {
  		addHandle( booleans, function( elem, name, isXML ) {
  			var val;
  			if ( !isXML ) {
  				return elem[ name ] === true ? name.toLowerCase() :
  						(val = elem.getAttributeNode( name )) && val.specified ?
  						val.value :
  					null;
  			}
  		});
  	}
  	
  	return Sizzle;
  	
  	})( window );
  	
  	
  	
  	jQuery.find = Sizzle;
  	jQuery.expr = Sizzle.selectors;
  	jQuery.expr[":"] = jQuery.expr.pseudos;
  	jQuery.unique = Sizzle.uniqueSort;
  	jQuery.text = Sizzle.getText;
  	jQuery.isXMLDoc = Sizzle.isXML;
  	jQuery.contains = Sizzle.contains;
  	
  	
  	
  	var rneedsContext = jQuery.expr.match.needsContext;
  	
  	var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
  	
  	
  	
  	var risSimple = /^.[^:#\[\.,]*$/;
  	
  	// Implement the identical functionality for filter and not
  	function winnow( elements, qualifier, not ) {
  		if ( jQuery.isFunction( qualifier ) ) {
  			return jQuery.grep( elements, function( elem, i ) {
  				/* jshint -W018 */
  				return !!qualifier.call( elem, i, elem ) !== not;
  			});
  	
  		}
  	
  		if ( qualifier.nodeType ) {
  			return jQuery.grep( elements, function( elem ) {
  				return ( elem === qualifier ) !== not;
  			});
  	
  		}
  	
  		if ( typeof qualifier === "string" ) {
  			if ( risSimple.test( qualifier ) ) {
  				return jQuery.filter( qualifier, elements, not );
  			}
  	
  			qualifier = jQuery.filter( qualifier, elements );
  		}
  	
  		return jQuery.grep( elements, function( elem ) {
  			return ( indexOf.call( qualifier, elem ) >= 0 ) !== not;
  		});
  	}
  	
  	jQuery.filter = function( expr, elems, not ) {
  		var elem = elems[ 0 ];
  	
  		if ( not ) {
  			expr = ":not(" + expr + ")";
  		}
  	
  		return elems.length === 1 && elem.nodeType === 1 ?
  			jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
  			jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
  				return elem.nodeType === 1;
  			}));
  	};
  	
  	jQuery.fn.extend({
  		find: function( selector ) {
  			var i,
  				len = this.length,
  				ret = [],
  				self = this;
  	
  			if ( typeof selector !== "string" ) {
  				return this.pushStack( jQuery( selector ).filter(function() {
  					for ( i = 0; i < len; i++ ) {
  						if ( jQuery.contains( self[ i ], this ) ) {
  							return true;
  						}
  					}
  				}) );
  			}
  	
  			for ( i = 0; i < len; i++ ) {
  				jQuery.find( selector, self[ i ], ret );
  			}
  	
  			// Needed because $( selector, context ) becomes $( context ).find( selector )
  			ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
  			ret.selector = this.selector ? this.selector + " " + selector : selector;
  			return ret;
  		},
  		filter: function( selector ) {
  			return this.pushStack( winnow(this, selector || [], false) );
  		},
  		not: function( selector ) {
  			return this.pushStack( winnow(this, selector || [], true) );
  		},
  		is: function( selector ) {
  			return !!winnow(
  				this,
  	
  				// If this is a positional/relative selector, check membership in the returned set
  				// so $("p:first").is("p:last") won't return true for a doc with two "p".
  				typeof selector === "string" && rneedsContext.test( selector ) ?
  					jQuery( selector ) :
  					selector || [],
  				false
  			).length;
  		}
  	});
  	
  	
  	// Initialize a jQuery object
  	
  	
  	// A central reference to the root jQuery(document)
  	var rootjQuery,
  	
  		// A simple way to check for HTML strings
  		// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
  		// Strict HTML recognition (#11290: must start with <)
  		rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
  	
  		init = jQuery.fn.init = function( selector, context ) {
  			var match, elem;
  	
  			// HANDLE: $(""), $(null), $(undefined), $(false)
  			if ( !selector ) {
  				return this;
  			}
  	
  			// Handle HTML strings
  			if ( typeof selector === "string" ) {
  				if ( selector[0] === "<" && selector[ selector.length - 1 ] === ">" && selector.length >= 3 ) {
  					// Assume that strings that start and end with <> are HTML and skip the regex check
  					match = [ null, selector, null ];
  	
  				} else {
  					match = rquickExpr.exec( selector );
  				}
  	
  				// Match html or make sure no context is specified for #id
  				if ( match && (match[1] || !context) ) {
  	
  					// HANDLE: $(html) -> $(array)
  					if ( match[1] ) {
  						context = context instanceof jQuery ? context[0] : context;
  	
  						// Option to run scripts is true for back-compat
  						// Intentionally let the error be thrown if parseHTML is not present
  						jQuery.merge( this, jQuery.parseHTML(
  							match[1],
  							context && context.nodeType ? context.ownerDocument || context : document,
  							true
  						) );
  	
  						// HANDLE: $(html, props)
  						if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
  							for ( match in context ) {
  								// Properties of context are called as methods if possible
  								if ( jQuery.isFunction( this[ match ] ) ) {
  									this[ match ]( context[ match ] );
  	
  								// ...and otherwise set as attributes
  								} else {
  									this.attr( match, context[ match ] );
  								}
  							}
  						}
  	
  						return this;
  	
  					// HANDLE: $(#id)
  					} else {
  						elem = document.getElementById( match[2] );
  	
  						// Support: Blackberry 4.6
  						// gEBID returns nodes no longer in the document (#6963)
  						if ( elem && elem.parentNode ) {
  							// Inject the element directly into the jQuery object
  							this.length = 1;
  							this[0] = elem;
  						}
  	
  						this.context = document;
  						this.selector = selector;
  						return this;
  					}
  	
  				// HANDLE: $(expr, $(...))
  				} else if ( !context || context.jquery ) {
  					return ( context || rootjQuery ).find( selector );
  	
  				// HANDLE: $(expr, context)
  				// (which is just equivalent to: $(context).find(expr)
  				} else {
  					return this.constructor( context ).find( selector );
  				}
  	
  			// HANDLE: $(DOMElement)
  			} else if ( selector.nodeType ) {
  				this.context = this[0] = selector;
  				this.length = 1;
  				return this;
  	
  			// HANDLE: $(function)
  			// Shortcut for document ready
  			} else if ( jQuery.isFunction( selector ) ) {
  				return typeof rootjQuery.ready !== "undefined" ?
  					rootjQuery.ready( selector ) :
  					// Execute immediately if ready is not present
  					selector( jQuery );
  			}
  	
  			if ( selector.selector !== undefined ) {
  				this.selector = selector.selector;
  				this.context = selector.context;
  			}
  	
  			return jQuery.makeArray( selector, this );
  		};
  	
  	// Give the init function the jQuery prototype for later instantiation
  	init.prototype = jQuery.fn;
  	
  	// Initialize central reference
  	rootjQuery = jQuery( document );
  	
  	
  	var rparentsprev = /^(?:parents|prev(?:Until|All))/,
  		// Methods guaranteed to produce a unique set when starting from a unique set
  		guaranteedUnique = {
  			children: true,
  			contents: true,
  			next: true,
  			prev: true
  		};
  	
  	jQuery.extend({
  		dir: function( elem, dir, until ) {
  			var matched = [],
  				truncate = until !== undefined;
  	
  			while ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) {
  				if ( elem.nodeType === 1 ) {
  					if ( truncate && jQuery( elem ).is( until ) ) {
  						break;
  					}
  					matched.push( elem );
  				}
  			}
  			return matched;
  		},
  	
  		sibling: function( n, elem ) {
  			var matched = [];
  	
  			for ( ; n; n = n.nextSibling ) {
  				if ( n.nodeType === 1 && n !== elem ) {
  					matched.push( n );
  				}
  			}
  	
  			return matched;
  		}
  	});
  	
  	jQuery.fn.extend({
  		has: function( target ) {
  			var targets = jQuery( target, this ),
  				l = targets.length;
  	
  			return this.filter(function() {
  				var i = 0;
  				for ( ; i < l; i++ ) {
  					if ( jQuery.contains( this, targets[i] ) ) {
  						return true;
  					}
  				}
  			});
  		},
  	
  		closest: function( selectors, context ) {
  			var cur,
  				i = 0,
  				l = this.length,
  				matched = [],
  				pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
  					jQuery( selectors, context || this.context ) :
  					0;
  	
  			for ( ; i < l; i++ ) {
  				for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
  					// Always skip document fragments
  					if ( cur.nodeType < 11 && (pos ?
  						pos.index(cur) > -1 :
  	
  						// Don't pass non-elements to Sizzle
  						cur.nodeType === 1 &&
  							jQuery.find.matchesSelector(cur, selectors)) ) {
  	
  						matched.push( cur );
  						break;
  					}
  				}
  			}
  	
  			return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
  		},
  	
  		// Determine the position of an element within the set
  		index: function( elem ) {
  	
  			// No argument, return index in parent
  			if ( !elem ) {
  				return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
  			}
  	
  			// Index in selector
  			if ( typeof elem === "string" ) {
  				return indexOf.call( jQuery( elem ), this[ 0 ] );
  			}
  	
  			// Locate the position of the desired element
  			return indexOf.call( this,
  	
  				// If it receives a jQuery object, the first element is used
  				elem.jquery ? elem[ 0 ] : elem
  			);
  		},
  	
  		add: function( selector, context ) {
  			return this.pushStack(
  				jQuery.unique(
  					jQuery.merge( this.get(), jQuery( selector, context ) )
  				)
  			);
  		},
  	
  		addBack: function( selector ) {
  			return this.add( selector == null ?
  				this.prevObject : this.prevObject.filter(selector)
  			);
  		}
  	});
  	
  	function sibling( cur, dir ) {
  		while ( (cur = cur[dir]) && cur.nodeType !== 1 ) {}
  		return cur;
  	}
  	
  	jQuery.each({
  		parent: function( elem ) {
  			var parent = elem.parentNode;
  			return parent && parent.nodeType !== 11 ? parent : null;
  		},
  		parents: function( elem ) {
  			return jQuery.dir( elem, "parentNode" );
  		},
  		parentsUntil: function( elem, i, until ) {
  			return jQuery.dir( elem, "parentNode", until );
  		},
  		next: function( elem ) {
  			return sibling( elem, "nextSibling" );
  		},
  		prev: function( elem ) {
  			return sibling( elem, "previousSibling" );
  		},
  		nextAll: function( elem ) {
  			return jQuery.dir( elem, "nextSibling" );
  		},
  		prevAll: function( elem ) {
  			return jQuery.dir( elem, "previousSibling" );
  		},
  		nextUntil: function( elem, i, until ) {
  			return jQuery.dir( elem, "nextSibling", until );
  		},
  		prevUntil: function( elem, i, until ) {
  			return jQuery.dir( elem, "previousSibling", until );
  		},
  		siblings: function( elem ) {
  			return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
  		},
  		children: function( elem ) {
  			return jQuery.sibling( elem.firstChild );
  		},
  		contents: function( elem ) {
  			return elem.contentDocument || jQuery.merge( [], elem.childNodes );
  		}
  	}, function( name, fn ) {
  		jQuery.fn[ name ] = function( until, selector ) {
  			var matched = jQuery.map( this, fn, until );
  	
  			if ( name.slice( -5 ) !== "Until" ) {
  				selector = until;
  			}
  	
  			if ( selector && typeof selector === "string" ) {
  				matched = jQuery.filter( selector, matched );
  			}
  	
  			if ( this.length > 1 ) {
  				// Remove duplicates
  				if ( !guaranteedUnique[ name ] ) {
  					jQuery.unique( matched );
  				}
  	
  				// Reverse order for parents* and prev-derivatives
  				if ( rparentsprev.test( name ) ) {
  					matched.reverse();
  				}
  			}
  	
  			return this.pushStack( matched );
  		};
  	});
  	var rnotwhite = (/\S+/g);
  	
  	
  	
  	// String to Object options format cache
  	var optionsCache = {};
  	
  	// Convert String-formatted options into Object-formatted ones and store in cache
  	function createOptions( options ) {
  		var object = optionsCache[ options ] = {};
  		jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
  			object[ flag ] = true;
  		});
  		return object;
  	}
  	
  	/*
  	 * Create a callback list using the following parameters:
  	 *
  	 *	options: an optional list of space-separated options that will change how
  	 *			the callback list behaves or a more traditional option object
  	 *
  	 * By default a callback list will act like an event callback list and can be
  	 * "fired" multiple times.
  	 *
  	 * Possible options:
  	 *
  	 *	once:			will ensure the callback list can only be fired once (like a Deferred)
  	 *
  	 *	memory:			will keep track of previous values and will call any callback added
  	 *					after the list has been fired right away with the latest "memorized"
  	 *					values (like a Deferred)
  	 *
  	 *	unique:			will ensure a callback can only be added once (no duplicate in the list)
  	 *
  	 *	stopOnFalse:	interrupt callings when a callback returns false
  	 *
  	 */
  	jQuery.Callbacks = function( options ) {
  	
  		// Convert options from String-formatted to Object-formatted if needed
  		// (we check in cache first)
  		options = typeof options === "string" ?
  			( optionsCache[ options ] || createOptions( options ) ) :
  			jQuery.extend( {}, options );
  	
  		var // Last fire value (for non-forgettable lists)
  			memory,
  			// Flag to know if list was already fired
  			fired,
  			// Flag to know if list is currently firing
  			firing,
  			// First callback to fire (used internally by add and fireWith)
  			firingStart,
  			// End of the loop when firing
  			firingLength,
  			// Index of currently firing callback (modified by remove if needed)
  			firingIndex,
  			// Actual callback list
  			list = [],
  			// Stack of fire calls for repeatable lists
  			stack = !options.once && [],
  			// Fire callbacks
  			fire = function( data ) {
  				memory = options.memory && data;
  				fired = true;
  				firingIndex = firingStart || 0;
  				firingStart = 0;
  				firingLength = list.length;
  				firing = true;
  				for ( ; list && firingIndex < firingLength; firingIndex++ ) {
  					if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
  						memory = false; // To prevent further calls using add
  						break;
  					}
  				}
  				firing = false;
  				if ( list ) {
  					if ( stack ) {
  						if ( stack.length ) {
  							fire( stack.shift() );
  						}
  					} else if ( memory ) {
  						list = [];
  					} else {
  						self.disable();
  					}
  				}
  			},
  			// Actual Callbacks object
  			self = {
  				// Add a callback or a collection of callbacks to the list
  				add: function() {
  					if ( list ) {
  						// First, we save the current length
  						var start = list.length;
  						(function add( args ) {
  							jQuery.each( args, function( _, arg ) {
  								var type = jQuery.type( arg );
  								if ( type === "function" ) {
  									if ( !options.unique || !self.has( arg ) ) {
  										list.push( arg );
  									}
  								} else if ( arg && arg.length && type !== "string" ) {
  									// Inspect recursively
  									add( arg );
  								}
  							});
  						})( arguments );
  						// Do we need to add the callbacks to the
  						// current firing batch?
  						if ( firing ) {
  							firingLength = list.length;
  						// With memory, if we're not firing then
  						// we should call right away
  						} else if ( memory ) {
  							firingStart = start;
  							fire( memory );
  						}
  					}
  					return this;
  				},
  				// Remove a callback from the list
  				remove: function() {
  					if ( list ) {
  						jQuery.each( arguments, function( _, arg ) {
  							var index;
  							while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
  								list.splice( index, 1 );
  								// Handle firing indexes
  								if ( firing ) {
  									if ( index <= firingLength ) {
  										firingLength--;
  									}
  									if ( index <= firingIndex ) {
  										firingIndex--;
  									}
  								}
  							}
  						});
  					}
  					return this;
  				},
  				// Check if a given callback is in the list.
  				// If no argument is given, return whether or not list has callbacks attached.
  				has: function( fn ) {
  					return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
  				},
  				// Remove all callbacks from the list
  				empty: function() {
  					list = [];
  					firingLength = 0;
  					return this;
  				},
  				// Have the list do nothing anymore
  				disable: function() {
  					list = stack = memory = undefined;
  					return this;
  				},
  				// Is it disabled?
  				disabled: function() {
  					return !list;
  				},
  				// Lock the list in its current state
  				lock: function() {
  					stack = undefined;
  					if ( !memory ) {
  						self.disable();
  					}
  					return this;
  				},
  				// Is it locked?
  				locked: function() {
  					return !stack;
  				},
  				// Call all callbacks with the given context and arguments
  				fireWith: function( context, args ) {
  					if ( list && ( !fired || stack ) ) {
  						args = args || [];
  						args = [ context, args.slice ? args.slice() : args ];
  						if ( firing ) {
  							stack.push( args );
  						} else {
  							fire( args );
  						}
  					}
  					return this;
  				},
  				// Call all the callbacks with the given arguments
  				fire: function() {
  					self.fireWith( this, arguments );
  					return this;
  				},
  				// To know if the callbacks have already been called at least once
  				fired: function() {
  					return !!fired;
  				}
  			};
  	
  		return self;
  	};
  	
  	
  	jQuery.extend({
  	
  		Deferred: function( func ) {
  			var tuples = [
  					// action, add listener, listener list, final state
  					[ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
  					[ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
  					[ "notify", "progress", jQuery.Callbacks("memory") ]
  				],
  				state = "pending",
  				promise = {
  					state: function() {
  						return state;
  					},
  					always: function() {
  						deferred.done( arguments ).fail( arguments );
  						return this;
  					},
  					then: function( /* fnDone, fnFail, fnProgress */ ) {
  						var fns = arguments;
  						return jQuery.Deferred(function( newDefer ) {
  							jQuery.each( tuples, function( i, tuple ) {
  								var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
  								// deferred[ done | fail | progress ] for forwarding actions to newDefer
  								deferred[ tuple[1] ](function() {
  									var returned = fn && fn.apply( this, arguments );
  									if ( returned && jQuery.isFunction( returned.promise ) ) {
  										returned.promise()
  											.done( newDefer.resolve )
  											.fail( newDefer.reject )
  											.progress( newDefer.notify );
  									} else {
  										newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
  									}
  								});
  							});
  							fns = null;
  						}).promise();
  					},
  					// Get a promise for this deferred
  					// If obj is provided, the promise aspect is added to the object
  					promise: function( obj ) {
  						return obj != null ? jQuery.extend( obj, promise ) : promise;
  					}
  				},
  				deferred = {};
  	
  			// Keep pipe for back-compat
  			promise.pipe = promise.then;
  	
  			// Add list-specific methods
  			jQuery.each( tuples, function( i, tuple ) {
  				var list = tuple[ 2 ],
  					stateString = tuple[ 3 ];
  	
  				// promise[ done | fail | progress ] = list.add
  				promise[ tuple[1] ] = list.add;
  	
  				// Handle state
  				if ( stateString ) {
  					list.add(function() {
  						// state = [ resolved | rejected ]
  						state = stateString;
  	
  					// [ reject_list | resolve_list ].disable; progress_list.lock
  					}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
  				}
  	
  				// deferred[ resolve | reject | notify ]
  				deferred[ tuple[0] ] = function() {
  					deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
  					return this;
  				};
  				deferred[ tuple[0] + "With" ] = list.fireWith;
  			});
  	
  			// Make the deferred a promise
  			promise.promise( deferred );
  	
  			// Call given func if any
  			if ( func ) {
  				func.call( deferred, deferred );
  			}
  	
  			// All done!
  			return deferred;
  		},
  	
  		// Deferred helper
  		when: function( subordinate /* , ..., subordinateN */ ) {
  			var i = 0,
  				resolveValues = slice.call( arguments ),
  				length = resolveValues.length,
  	
  				// the count of uncompleted subordinates
  				remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
  	
  				// the master Deferred. If resolveValues consist of only a single Deferred, just use that.
  				deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
  	
  				// Update function for both resolve and progress values
  				updateFunc = function( i, contexts, values ) {
  					return function( value ) {
  						contexts[ i ] = this;
  						values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
  						if ( values === progressValues ) {
  							deferred.notifyWith( contexts, values );
  						} else if ( !( --remaining ) ) {
  							deferred.resolveWith( contexts, values );
  						}
  					};
  				},
  	
  				progressValues, progressContexts, resolveContexts;
  	
  			// Add listeners to Deferred subordinates; treat others as resolved
  			if ( length > 1 ) {
  				progressValues = new Array( length );
  				progressContexts = new Array( length );
  				resolveContexts = new Array( length );
  				for ( ; i < length; i++ ) {
  					if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
  						resolveValues[ i ].promise()
  							.done( updateFunc( i, resolveContexts, resolveValues ) )
  							.fail( deferred.reject )
  							.progress( updateFunc( i, progressContexts, progressValues ) );
  					} else {
  						--remaining;
  					}
  				}
  			}
  	
  			// If we're not waiting on anything, resolve the master
  			if ( !remaining ) {
  				deferred.resolveWith( resolveContexts, resolveValues );
  			}
  	
  			return deferred.promise();
  		}
  	});
  	
  	
  	// The deferred used on DOM ready
  	var readyList;
  	
  	jQuery.fn.ready = function( fn ) {
  		// Add the callback
  		jQuery.ready.promise().done( fn );
  	
  		return this;
  	};
  	
  	jQuery.extend({
  		// Is the DOM ready to be used? Set to true once it occurs.
  		isReady: false,
  	
  		// A counter to track how many items to wait for before
  		// the ready event fires. See #6781
  		readyWait: 1,
  	
  		// Hold (or release) the ready event
  		holdReady: function( hold ) {
  			if ( hold ) {
  				jQuery.readyWait++;
  			} else {
  				jQuery.ready( true );
  			}
  		},
  	
  		// Handle when the DOM is ready
  		ready: function( wait ) {
  	
  			// Abort if there are pending holds or we're already ready
  			if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
  				return;
  			}
  	
  			// Remember that the DOM is ready
  			jQuery.isReady = true;
  	
  			// If a normal DOM Ready event fired, decrement, and wait if need be
  			if ( wait !== true && --jQuery.readyWait > 0 ) {
  				return;
  			}
  	
  			// If there are functions bound, to execute
  			readyList.resolveWith( document, [ jQuery ] );
  	
  			// Trigger any bound ready events
  			if ( jQuery.fn.triggerHandler ) {
  				jQuery( document ).triggerHandler( "ready" );
  				jQuery( document ).off( "ready" );
  			}
  		}
  	});
  	
  	/**
  	 * The ready event handler and self cleanup method
  	 */
  	function completed() {
  		document.removeEventListener( "DOMContentLoaded", completed, false );
  		window.removeEventListener( "load", completed, false );
  		jQuery.ready();
  	}
  	
  	jQuery.ready.promise = function( obj ) {
  		if ( !readyList ) {
  	
  			readyList = jQuery.Deferred();
  	
  			// Catch cases where $(document).ready() is called after the browser event has already occurred.
  			// We once tried to use readyState "interactive" here, but it caused issues like the one
  			// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
  			if ( document.readyState === "complete" ) {
  				// Handle it asynchronously to allow scripts the opportunity to delay ready
  				setTimeout( jQuery.ready );
  	
  			} else {
  	
  				// Use the handy event callback
  				document.addEventListener( "DOMContentLoaded", completed, false );
  	
  				// A fallback to window.onload, that will always work
  				window.addEventListener( "load", completed, false );
  			}
  		}
  		return readyList.promise( obj );
  	};
  	
  	// Kick off the DOM ready check even if the user does not
  	jQuery.ready.promise();
  	
  	
  	
  	
  	// Multifunctional method to get and set values of a collection
  	// The value/s can optionally be executed if it's a function
  	var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
  		var i = 0,
  			len = elems.length,
  			bulk = key == null;
  	
  		// Sets many values
  		if ( jQuery.type( key ) === "object" ) {
  			chainable = true;
  			for ( i in key ) {
  				jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
  			}
  	
  		// Sets one value
  		} else if ( value !== undefined ) {
  			chainable = true;
  	
  			if ( !jQuery.isFunction( value ) ) {
  				raw = true;
  			}
  	
  			if ( bulk ) {
  				// Bulk operations run against the entire set
  				if ( raw ) {
  					fn.call( elems, value );
  					fn = null;
  	
  				// ...except when executing function values
  				} else {
  					bulk = fn;
  					fn = function( elem, key, value ) {
  						return bulk.call( jQuery( elem ), value );
  					};
  				}
  			}
  	
  			if ( fn ) {
  				for ( ; i < len; i++ ) {
  					fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
  				}
  			}
  		}
  	
  		return chainable ?
  			elems :
  	
  			// Gets
  			bulk ?
  				fn.call( elems ) :
  				len ? fn( elems[0], key ) : emptyGet;
  	};
  	
  	
  	/**
  	 * Determines whether an object can have data
  	 */
  	jQuery.acceptData = function( owner ) {
  		// Accepts only:
  		//  - Node
  		//    - Node.ELEMENT_NODE
  		//    - Node.DOCUMENT_NODE
  		//  - Object
  		//    - Any
  		/* jshint -W018 */
  		return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
  	};
  	
  	
  	function Data() {
  		// Support: Android<4,
  		// Old WebKit does not have Object.preventExtensions/freeze method,
  		// return new empty object instead with no [[set]] accessor
  		Object.defineProperty( this.cache = {}, 0, {
  			get: function() {
  				return {};
  			}
  		});
  	
  		this.expando = jQuery.expando + Data.uid++;
  	}
  	
  	Data.uid = 1;
  	Data.accepts = jQuery.acceptData;
  	
  	Data.prototype = {
  		key: function( owner ) {
  			// We can accept data for non-element nodes in modern browsers,
  			// but we should not, see #8335.
  			// Always return the key for a frozen object.
  			if ( !Data.accepts( owner ) ) {
  				return 0;
  			}
  	
  			var descriptor = {},
  				// Check if the owner object already has a cache key
  				unlock = owner[ this.expando ];
  	
  			// If not, create one
  			if ( !unlock ) {
  				unlock = Data.uid++;
  	
  				// Secure it in a non-enumerable, non-writable property
  				try {
  					descriptor[ this.expando ] = { value: unlock };
  					Object.defineProperties( owner, descriptor );
  	
  				// Support: Android<4
  				// Fallback to a less secure definition
  				} catch ( e ) {
  					descriptor[ this.expando ] = unlock;
  					jQuery.extend( owner, descriptor );
  				}
  			}
  	
  			// Ensure the cache object
  			if ( !this.cache[ unlock ] ) {
  				this.cache[ unlock ] = {};
  			}
  	
  			return unlock;
  		},
  		set: function( owner, data, value ) {
  			var prop,
  				// There may be an unlock assigned to this node,
  				// if there is no entry for this "owner", create one inline
  				// and set the unlock as though an owner entry had always existed
  				unlock = this.key( owner ),
  				cache = this.cache[ unlock ];
  	
  			// Handle: [ owner, key, value ] args
  			if ( typeof data === "string" ) {
  				cache[ data ] = value;
  	
  			// Handle: [ owner, { properties } ] args
  			} else {
  				// Fresh assignments by object are shallow copied
  				if ( jQuery.isEmptyObject( cache ) ) {
  					jQuery.extend( this.cache[ unlock ], data );
  				// Otherwise, copy the properties one-by-one to the cache object
  				} else {
  					for ( prop in data ) {
  						cache[ prop ] = data[ prop ];
  					}
  				}
  			}
  			return cache;
  		},
  		get: function( owner, key ) {
  			// Either a valid cache is found, or will be created.
  			// New caches will be created and the unlock returned,
  			// allowing direct access to the newly created
  			// empty data object. A valid owner object must be provided.
  			var cache = this.cache[ this.key( owner ) ];
  	
  			return key === undefined ?
  				cache : cache[ key ];
  		},
  		access: function( owner, key, value ) {
  			var stored;
  			// In cases where either:
  			//
  			//   1. No key was specified
  			//   2. A string key was specified, but no value provided
  			//
  			// Take the "read" path and allow the get method to determine
  			// which value to return, respectively either:
  			//
  			//   1. The entire cache object
  			//   2. The data stored at the key
  			//
  			if ( key === undefined ||
  					((key && typeof key === "string") && value === undefined) ) {
  	
  				stored = this.get( owner, key );
  	
  				return stored !== undefined ?
  					stored : this.get( owner, jQuery.camelCase(key) );
  			}
  	
  			// [*]When the key is not a string, or both a key and value
  			// are specified, set or extend (existing objects) with either:
  			//
  			//   1. An object of properties
  			//   2. A key and value
  			//
  			this.set( owner, key, value );
  	
  			// Since the "set" path can have two possible entry points
  			// return the expected data based on which path was taken[*]
  			return value !== undefined ? value : key;
  		},
  		remove: function( owner, key ) {
  			var i, name, camel,
  				unlock = this.key( owner ),
  				cache = this.cache[ unlock ];
  	
  			if ( key === undefined ) {
  				this.cache[ unlock ] = {};
  	
  			} else {
  				// Support array or space separated string of keys
  				if ( jQuery.isArray( key ) ) {
  					// If "name" is an array of keys...
  					// When data is initially created, via ("key", "val") signature,
  					// keys will be converted to camelCase.
  					// Since there is no way to tell _how_ a key was added, remove
  					// both plain key and camelCase key. #12786
  					// This will only penalize the array argument path.
  					name = key.concat( key.map( jQuery.camelCase ) );
  				} else {
  					camel = jQuery.camelCase( key );
  					// Try the string as a key before any manipulation
  					if ( key in cache ) {
  						name = [ key, camel ];
  					} else {
  						// If a key with the spaces exists, use it.
  						// Otherwise, create an array by matching non-whitespace
  						name = camel;
  						name = name in cache ?
  							[ name ] : ( name.match( rnotwhite ) || [] );
  					}
  				}
  	
  				i = name.length;
  				while ( i-- ) {
  					delete cache[ name[ i ] ];
  				}
  			}
  		},
  		hasData: function( owner ) {
  			return !jQuery.isEmptyObject(
  				this.cache[ owner[ this.expando ] ] || {}
  			);
  		},
  		discard: function( owner ) {
  			if ( owner[ this.expando ] ) {
  				delete this.cache[ owner[ this.expando ] ];
  			}
  		}
  	};
  	var data_priv = new Data();
  	
  	var data_user = new Data();
  	
  	
  	
  	//	Implementation Summary
  	//
  	//	1. Enforce API surface and semantic compatibility with 1.9.x branch
  	//	2. Improve the module's maintainability by reducing the storage
  	//		paths to a single mechanism.
  	//	3. Use the same single mechanism to support "private" and "user" data.
  	//	4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
  	//	5. Avoid exposing implementation details on user objects (eg. expando properties)
  	//	6. Provide a clear path for implementation upgrade to WeakMap in 2014
  	
  	var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
  		rmultiDash = /([A-Z])/g;
  	
  	function dataAttr( elem, key, data ) {
  		var name;
  	
  		// If nothing was found internally, try to fetch any
  		// data from the HTML5 data-* attribute
  		if ( data === undefined && elem.nodeType === 1 ) {
  			name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
  			data = elem.getAttribute( name );
  	
  			if ( typeof data === "string" ) {
  				try {
  					data = data === "true" ? true :
  						data === "false" ? false :
  						data === "null" ? null :
  						// Only convert to a number if it doesn't change the string
  						+data + "" === data ? +data :
  						rbrace.test( data ) ? jQuery.parseJSON( data ) :
  						data;
  				} catch( e ) {}
  	
  				// Make sure we set the data so it isn't changed later
  				data_user.set( elem, key, data );
  			} else {
  				data = undefined;
  			}
  		}
  		return data;
  	}
  	
  	jQuery.extend({
  		hasData: function( elem ) {
  			return data_user.hasData( elem ) || data_priv.hasData( elem );
  		},
  	
  		data: function( elem, name, data ) {
  			return data_user.access( elem, name, data );
  		},
  	
  		removeData: function( elem, name ) {
  			data_user.remove( elem, name );
  		},
  	
  		// TODO: Now that all calls to _data and _removeData have been replaced
  		// with direct calls to data_priv methods, these can be deprecated.
  		_data: function( elem, name, data ) {
  			return data_priv.access( elem, name, data );
  		},
  	
  		_removeData: function( elem, name ) {
  			data_priv.remove( elem, name );
  		}
  	});
  	
  	jQuery.fn.extend({
  		data: function( key, value ) {
  			var i, name, data,
  				elem = this[ 0 ],
  				attrs = elem && elem.attributes;
  	
  			// Gets all values
  			if ( key === undefined ) {
  				if ( this.length ) {
  					data = data_user.get( elem );
  	
  					if ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) {
  						i = attrs.length;
  						while ( i-- ) {
  	
  							// Support: IE11+
  							// The attrs elements can be null (#14894)
  							if ( attrs[ i ] ) {
  								name = attrs[ i ].name;
  								if ( name.indexOf( "data-" ) === 0 ) {
  									name = jQuery.camelCase( name.slice(5) );
  									dataAttr( elem, name, data[ name ] );
  								}
  							}
  						}
  						data_priv.set( elem, "hasDataAttrs", true );
  					}
  				}
  	
  				return data;
  			}
  	
  			// Sets multiple values
  			if ( typeof key === "object" ) {
  				return this.each(function() {
  					data_user.set( this, key );
  				});
  			}
  	
  			return access( this, function( value ) {
  				var data,
  					camelKey = jQuery.camelCase( key );
  	
  				// The calling jQuery object (element matches) is not empty
  				// (and therefore has an element appears at this[ 0 ]) and the
  				// `value` parameter was not undefined. An empty jQuery object
  				// will result in `undefined` for elem = this[ 0 ] which will
  				// throw an exception if an attempt to read a data cache is made.
  				if ( elem && value === undefined ) {
  					// Attempt to get data from the cache
  					// with the key as-is
  					data = data_user.get( elem, key );
  					if ( data !== undefined ) {
  						return data;
  					}
  	
  					// Attempt to get data from the cache
  					// with the key camelized
  					data = data_user.get( elem, camelKey );
  					if ( data !== undefined ) {
  						return data;
  					}
  	
  					// Attempt to "discover" the data in
  					// HTML5 custom data-* attrs
  					data = dataAttr( elem, camelKey, undefined );
  					if ( data !== undefined ) {
  						return data;
  					}
  	
  					// We tried really hard, but the data doesn't exist.
  					return;
  				}
  	
  				// Set the data...
  				this.each(function() {
  					// First, attempt to store a copy or reference of any
  					// data that might've been store with a camelCased key.
  					var data = data_user.get( this, camelKey );
  	
  					// For HTML5 data-* attribute interop, we have to
  					// store property names with dashes in a camelCase form.
  					// This might not apply to all properties...*
  					data_user.set( this, camelKey, value );
  	
  					// *... In the case of properties that might _actually_
  					// have dashes, we need to also store a copy of that
  					// unchanged property.
  					if ( key.indexOf("-") !== -1 && data !== undefined ) {
  						data_user.set( this, key, value );
  					}
  				});
  			}, null, value, arguments.length > 1, null, true );
  		},
  	
  		removeData: function( key ) {
  			return this.each(function() {
  				data_user.remove( this, key );
  			});
  		}
  	});
  	
  	
  	jQuery.extend({
  		queue: function( elem, type, data ) {
  			var queue;
  	
  			if ( elem ) {
  				type = ( type || "fx" ) + "queue";
  				queue = data_priv.get( elem, type );
  	
  				// Speed up dequeue by getting out quickly if this is just a lookup
  				if ( data ) {
  					if ( !queue || jQuery.isArray( data ) ) {
  						queue = data_priv.access( elem, type, jQuery.makeArray(data) );
  					} else {
  						queue.push( data );
  					}
  				}
  				return queue || [];
  			}
  		},
  	
  		dequeue: function( elem, type ) {
  			type = type || "fx";
  	
  			var queue = jQuery.queue( elem, type ),
  				startLength = queue.length,
  				fn = queue.shift(),
  				hooks = jQuery._queueHooks( elem, type ),
  				next = function() {
  					jQuery.dequeue( elem, type );
  				};
  	
  			// If the fx queue is dequeued, always remove the progress sentinel
  			if ( fn === "inprogress" ) {
  				fn = queue.shift();
  				startLength--;
  			}
  	
  			if ( fn ) {
  	
  				// Add a progress sentinel to prevent the fx queue from being
  				// automatically dequeued
  				if ( type === "fx" ) {
  					queue.unshift( "inprogress" );
  				}
  	
  				// Clear up the last queue stop function
  				delete hooks.stop;
  				fn.call( elem, next, hooks );
  			}
  	
  			if ( !startLength && hooks ) {
  				hooks.empty.fire();
  			}
  		},
  	
  		// Not public - generate a queueHooks object, or return the current one
  		_queueHooks: function( elem, type ) {
  			var key = type + "queueHooks";
  			return data_priv.get( elem, key ) || data_priv.access( elem, key, {
  				empty: jQuery.Callbacks("once memory").add(function() {
  					data_priv.remove( elem, [ type + "queue", key ] );
  				})
  			});
  		}
  	});
  	
  	jQuery.fn.extend({
  		queue: function( type, data ) {
  			var setter = 2;
  	
  			if ( typeof type !== "string" ) {
  				data = type;
  				type = "fx";
  				setter--;
  			}
  	
  			if ( arguments.length < setter ) {
  				return jQuery.queue( this[0], type );
  			}
  	
  			return data === undefined ?
  				this :
  				this.each(function() {
  					var queue = jQuery.queue( this, type, data );
  	
  					// Ensure a hooks for this queue
  					jQuery._queueHooks( this, type );
  	
  					if ( type === "fx" && queue[0] !== "inprogress" ) {
  						jQuery.dequeue( this, type );
  					}
  				});
  		},
  		dequeue: function( type ) {
  			return this.each(function() {
  				jQuery.dequeue( this, type );
  			});
  		},
  		clearQueue: function( type ) {
  			return this.queue( type || "fx", [] );
  		},
  		// Get a promise resolved when queues of a certain type
  		// are emptied (fx is the type by default)
  		promise: function( type, obj ) {
  			var tmp,
  				count = 1,
  				defer = jQuery.Deferred(),
  				elements = this,
  				i = this.length,
  				resolve = function() {
  					if ( !( --count ) ) {
  						defer.resolveWith( elements, [ elements ] );
  					}
  				};
  	
  			if ( typeof type !== "string" ) {
  				obj = type;
  				type = undefined;
  			}
  			type = type || "fx";
  	
  			while ( i-- ) {
  				tmp = data_priv.get( elements[ i ], type + "queueHooks" );
  				if ( tmp && tmp.empty ) {
  					count++;
  					tmp.empty.add( resolve );
  				}
  			}
  			resolve();
  			return defer.promise( obj );
  		}
  	});
  	var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
  	
  	var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
  	
  	var isHidden = function( elem, el ) {
  			// isHidden might be called from jQuery#filter function;
  			// in that case, element will be second argument
  			elem = el || elem;
  			return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
  		};
  	
  	var rcheckableType = (/^(?:checkbox|radio)$/i);
  	
  	
  	
  	(function() {
  		var fragment = document.createDocumentFragment(),
  			div = fragment.appendChild( document.createElement( "div" ) ),
  			input = document.createElement( "input" );
  	
  		// Support: Safari<=5.1
  		// Check state lost if the name is set (#11217)
  		// Support: Windows Web Apps (WWA)
  		// `name` and `type` must use .setAttribute for WWA (#14901)
  		input.setAttribute( "type", "radio" );
  		input.setAttribute( "checked", "checked" );
  		input.setAttribute( "name", "t" );
  	
  		div.appendChild( input );
  	
  		// Support: Safari<=5.1, Android<4.2
  		// Older WebKit doesn't clone checked state correctly in fragments
  		support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
  	
  		// Support: IE<=11+
  		// Make sure textarea (and checkbox) defaultValue is properly cloned
  		div.innerHTML = "<textarea>x</textarea>";
  		support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
  	})();
  	var strundefined = typeof undefined;
  	
  	
  	
  	support.focusinBubbles = "onfocusin" in window;
  	
  	
  	var
  		rkeyEvent = /^key/,
  		rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,
  		rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
  		rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
  	
  	function returnTrue() {
  		return true;
  	}
  	
  	function returnFalse() {
  		return false;
  	}
  	
  	function safeActiveElement() {
  		try {
  			return document.activeElement;
  		} catch ( err ) { }
  	}
  	
  	/*
  	 * Helper functions for managing events -- not part of the public interface.
  	 * Props to Dean Edwards' addEvent library for many of the ideas.
  	 */
  	jQuery.event = {
  	
  		global: {},
  	
  		add: function( elem, types, handler, data, selector ) {
  	
  			var handleObjIn, eventHandle, tmp,
  				events, t, handleObj,
  				special, handlers, type, namespaces, origType,
  				elemData = data_priv.get( elem );
  	
  			// Don't attach events to noData or text/comment nodes (but allow plain objects)
  			if ( !elemData ) {
  				return;
  			}
  	
  			// Caller can pass in an object of custom data in lieu of the handler
  			if ( handler.handler ) {
  				handleObjIn = handler;
  				handler = handleObjIn.handler;
  				selector = handleObjIn.selector;
  			}
  	
  			// Make sure that the handler has a unique ID, used to find/remove it later
  			if ( !handler.guid ) {
  				handler.guid = jQuery.guid++;
  			}
  	
  			// Init the element's event structure and main handler, if this is the first
  			if ( !(events = elemData.events) ) {
  				events = elemData.events = {};
  			}
  			if ( !(eventHandle = elemData.handle) ) {
  				eventHandle = elemData.handle = function( e ) {
  					// Discard the second event of a jQuery.event.trigger() and
  					// when an event is called after a page has unloaded
  					return typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ?
  						jQuery.event.dispatch.apply( elem, arguments ) : undefined;
  				};
  			}
  	
  			// Handle multiple events separated by a space
  			types = ( types || "" ).match( rnotwhite ) || [ "" ];
  			t = types.length;
  			while ( t-- ) {
  				tmp = rtypenamespace.exec( types[t] ) || [];
  				type = origType = tmp[1];
  				namespaces = ( tmp[2] || "" ).split( "." ).sort();
  	
  				// There *must* be a type, no attaching namespace-only handlers
  				if ( !type ) {
  					continue;
  				}
  	
  				// If event changes its type, use the special event handlers for the changed type
  				special = jQuery.event.special[ type ] || {};
  	
  				// If selector defined, determine special event api type, otherwise given type
  				type = ( selector ? special.delegateType : special.bindType ) || type;
  	
  				// Update special based on newly reset type
  				special = jQuery.event.special[ type ] || {};
  	
  				// handleObj is passed to all event handlers
  				handleObj = jQuery.extend({
  					type: type,
  					origType: origType,
  					data: data,
  					handler: handler,
  					guid: handler.guid,
  					selector: selector,
  					needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
  					namespace: namespaces.join(".")
  				}, handleObjIn );
  	
  				// Init the event handler queue if we're the first
  				if ( !(handlers = events[ type ]) ) {
  					handlers = events[ type ] = [];
  					handlers.delegateCount = 0;
  	
  					// Only use addEventListener if the special events handler returns false
  					if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
  						if ( elem.addEventListener ) {
  							elem.addEventListener( type, eventHandle, false );
  						}
  					}
  				}
  	
  				if ( special.add ) {
  					special.add.call( elem, handleObj );
  	
  					if ( !handleObj.handler.guid ) {
  						handleObj.handler.guid = handler.guid;
  					}
  				}
  	
  				// Add to the element's handler list, delegates in front
  				if ( selector ) {
  					handlers.splice( handlers.delegateCount++, 0, handleObj );
  				} else {
  					handlers.push( handleObj );
  				}
  	
  				// Keep track of which events have ever been used, for event optimization
  				jQuery.event.global[ type ] = true;
  			}
  	
  		},
  	
  		// Detach an event or set of events from an element
  		remove: function( elem, types, handler, selector, mappedTypes ) {
  	
  			var j, origCount, tmp,
  				events, t, handleObj,
  				special, handlers, type, namespaces, origType,
  				elemData = data_priv.hasData( elem ) && data_priv.get( elem );
  	
  			if ( !elemData || !(events = elemData.events) ) {
  				return;
  			}
  	
  			// Once for each type.namespace in types; type may be omitted
  			types = ( types || "" ).match( rnotwhite ) || [ "" ];
  			t = types.length;
  			while ( t-- ) {
  				tmp = rtypenamespace.exec( types[t] ) || [];
  				type = origType = tmp[1];
  				namespaces = ( tmp[2] || "" ).split( "." ).sort();
  	
  				// Unbind all events (on this namespace, if provided) for the element
  				if ( !type ) {
  					for ( type in events ) {
  						jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
  					}
  					continue;
  				}
  	
  				special = jQuery.event.special[ type ] || {};
  				type = ( selector ? special.delegateType : special.bindType ) || type;
  				handlers = events[ type ] || [];
  				tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
  	
  				// Remove matching events
  				origCount = j = handlers.length;
  				while ( j-- ) {
  					handleObj = handlers[ j ];
  	
  					if ( ( mappedTypes || origType === handleObj.origType ) &&
  						( !handler || handler.guid === handleObj.guid ) &&
  						( !tmp || tmp.test( handleObj.namespace ) ) &&
  						( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
  						handlers.splice( j, 1 );
  	
  						if ( handleObj.selector ) {
  							handlers.delegateCount--;
  						}
  						if ( special.remove ) {
  							special.remove.call( elem, handleObj );
  						}
  					}
  				}
  	
  				// Remove generic event handler if we removed something and no more handlers exist
  				// (avoids potential for endless recursion during removal of special event handlers)
  				if ( origCount && !handlers.length ) {
  					if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
  						jQuery.removeEvent( elem, type, elemData.handle );
  					}
  	
  					delete events[ type ];
  				}
  			}
  	
  			// Remove the expando if it's no longer used
  			if ( jQuery.isEmptyObject( events ) ) {
  				delete elemData.handle;
  				data_priv.remove( elem, "events" );
  			}
  		},
  	
  		trigger: function( event, data, elem, onlyHandlers ) {
  	
  			var i, cur, tmp, bubbleType, ontype, handle, special,
  				eventPath = [ elem || document ],
  				type = hasOwn.call( event, "type" ) ? event.type : event,
  				namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
  	
  			cur = tmp = elem = elem || document;
  	
  			// Don't do events on text and comment nodes
  			if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
  				return;
  			}
  	
  			// focus/blur morphs to focusin/out; ensure we're not firing them right now
  			if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
  				return;
  			}
  	
  			if ( type.indexOf(".") >= 0 ) {
  				// Namespaced trigger; create a regexp to match event type in handle()
  				namespaces = type.split(".");
  				type = namespaces.shift();
  				namespaces.sort();
  			}
  			ontype = type.indexOf(":") < 0 && "on" + type;
  	
  			// Caller can pass in a jQuery.Event object, Object, or just an event type string
  			event = event[ jQuery.expando ] ?
  				event :
  				new jQuery.Event( type, typeof event === "object" && event );
  	
  			// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
  			event.isTrigger = onlyHandlers ? 2 : 3;
  			event.namespace = namespaces.join(".");
  			event.namespace_re = event.namespace ?
  				new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
  				null;
  	
  			// Clean up the event in case it is being reused
  			event.result = undefined;
  			if ( !event.target ) {
  				event.target = elem;
  			}
  	
  			// Clone any incoming data and prepend the event, creating the handler arg list
  			data = data == null ?
  				[ event ] :
  				jQuery.makeArray( data, [ event ] );
  	
  			// Allow special events to draw outside the lines
  			special = jQuery.event.special[ type ] || {};
  			if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
  				return;
  			}
  	
  			// Determine event propagation path in advance, per W3C events spec (#9951)
  			// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
  			if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
  	
  				bubbleType = special.delegateType || type;
  				if ( !rfocusMorph.test( bubbleType + type ) ) {
  					cur = cur.parentNode;
  				}
  				for ( ; cur; cur = cur.parentNode ) {
  					eventPath.push( cur );
  					tmp = cur;
  				}
  	
  				// Only add window if we got to document (e.g., not plain obj or detached DOM)
  				if ( tmp === (elem.ownerDocument || document) ) {
  					eventPath.push( tmp.defaultView || tmp.parentWindow || window );
  				}
  			}
  	
  			// Fire handlers on the event path
  			i = 0;
  			while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
  	
  				event.type = i > 1 ?
  					bubbleType :
  					special.bindType || type;
  	
  				// jQuery handler
  				handle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" );
  				if ( handle ) {
  					handle.apply( cur, data );
  				}
  	
  				// Native handler
  				handle = ontype && cur[ ontype ];
  				if ( handle && handle.apply && jQuery.acceptData( cur ) ) {
  					event.result = handle.apply( cur, data );
  					if ( event.result === false ) {
  						event.preventDefault();
  					}
  				}
  			}
  			event.type = type;
  	
  			// If nobody prevented the default action, do it now
  			if ( !onlyHandlers && !event.isDefaultPrevented() ) {
  	
  				if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
  					jQuery.acceptData( elem ) ) {
  	
  					// Call a native DOM method on the target with the same name name as the event.
  					// Don't do default actions on window, that's where global variables be (#6170)
  					if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {
  	
  						// Don't re-trigger an onFOO event when we call its FOO() method
  						tmp = elem[ ontype ];
  	
  						if ( tmp ) {
  							elem[ ontype ] = null;
  						}
  	
  						// Prevent re-triggering of the same event, since we already bubbled it above
  						jQuery.event.triggered = type;
  						elem[ type ]();
  						jQuery.event.triggered = undefined;
  	
  						if ( tmp ) {
  							elem[ ontype ] = tmp;
  						}
  					}
  				}
  			}
  	
  			return event.result;
  		},
  	
  		dispatch: function( event ) {
  	
  			// Make a writable jQuery.Event from the native event object
  			event = jQuery.event.fix( event );
  	
  			var i, j, ret, matched, handleObj,
  				handlerQueue = [],
  				args = slice.call( arguments ),
  				handlers = ( data_priv.get( this, "events" ) || {} )[ event.type ] || [],
  				special = jQuery.event.special[ event.type ] || {};
  	
  			// Use the fix-ed jQuery.Event rather than the (read-only) native event
  			args[0] = event;
  			event.delegateTarget = this;
  	
  			// Call the preDispatch hook for the mapped type, and let it bail if desired
  			if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
  				return;
  			}
  	
  			// Determine handlers
  			handlerQueue = jQuery.event.handlers.call( this, event, handlers );
  	
  			// Run delegates first; they may want to stop propagation beneath us
  			i = 0;
  			while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
  				event.currentTarget = matched.elem;
  	
  				j = 0;
  				while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
  	
  					// Triggered event must either 1) have no namespace, or 2) have namespace(s)
  					// a subset or equal to those in the bound event (both can have no namespace).
  					if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
  	
  						event.handleObj = handleObj;
  						event.data = handleObj.data;
  	
  						ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
  								.apply( matched.elem, args );
  	
  						if ( ret !== undefined ) {
  							if ( (event.result = ret) === false ) {
  								event.preventDefault();
  								event.stopPropagation();
  							}
  						}
  					}
  				}
  			}
  	
  			// Call the postDispatch hook for the mapped type
  			if ( special.postDispatch ) {
  				special.postDispatch.call( this, event );
  			}
  	
  			return event.result;
  		},
  	
  		handlers: function( event, handlers ) {
  			var i, matches, sel, handleObj,
  				handlerQueue = [],
  				delegateCount = handlers.delegateCount,
  				cur = event.target;
  	
  			// Find delegate handlers
  			// Black-hole SVG <use> instance trees (#13180)
  			// Avoid non-left-click bubbling in Firefox (#3861)
  			if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
  	
  				for ( ; cur !== this; cur = cur.parentNode || this ) {
  	
  					// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
  					if ( cur.disabled !== true || event.type !== "click" ) {
  						matches = [];
  						for ( i = 0; i < delegateCount; i++ ) {
  							handleObj = handlers[ i ];
  	
  							// Don't conflict with Object.prototype properties (#13203)
  							sel = handleObj.selector + " ";
  	
  							if ( matches[ sel ] === undefined ) {
  								matches[ sel ] = handleObj.needsContext ?
  									jQuery( sel, this ).index( cur ) >= 0 :
  									jQuery.find( sel, this, null, [ cur ] ).length;
  							}
  							if ( matches[ sel ] ) {
  								matches.push( handleObj );
  							}
  						}
  						if ( matches.length ) {
  							handlerQueue.push({ elem: cur, handlers: matches });
  						}
  					}
  				}
  			}
  	
  			// Add the remaining (directly-bound) handlers
  			if ( delegateCount < handlers.length ) {
  				handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
  			}
  	
  			return handlerQueue;
  		},
  	
  		// Includes some event props shared by KeyEvent and MouseEvent
  		props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
  	
  		fixHooks: {},
  	
  		keyHooks: {
  			props: "char charCode key keyCode".split(" "),
  			filter: function( event, original ) {
  	
  				// Add which for key events
  				if ( event.which == null ) {
  					event.which = original.charCode != null ? original.charCode : original.keyCode;
  				}
  	
  				return event;
  			}
  		},
  	
  		mouseHooks: {
  			props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
  			filter: function( event, original ) {
  				var eventDoc, doc, body,
  					button = original.button;
  	
  				// Calculate pageX/Y if missing and clientX/Y available
  				if ( event.pageX == null && original.clientX != null ) {
  					eventDoc = event.target.ownerDocument || document;
  					doc = eventDoc.documentElement;
  					body = eventDoc.body;
  	
  					event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
  					event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
  				}
  	
  				// Add which for click: 1 === left; 2 === middle; 3 === right
  				// Note: button is not normalized, so don't use it
  				if ( !event.which && button !== undefined ) {
  					event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
  				}
  	
  				return event;
  			}
  		},
  	
  		fix: function( event ) {
  			if ( event[ jQuery.expando ] ) {
  				return event;
  			}
  	
  			// Create a writable copy of the event object and normalize some properties
  			var i, prop, copy,
  				type = event.type,
  				originalEvent = event,
  				fixHook = this.fixHooks[ type ];
  	
  			if ( !fixHook ) {
  				this.fixHooks[ type ] = fixHook =
  					rmouseEvent.test( type ) ? this.mouseHooks :
  					rkeyEvent.test( type ) ? this.keyHooks :
  					{};
  			}
  			copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
  	
  			event = new jQuery.Event( originalEvent );
  	
  			i = copy.length;
  			while ( i-- ) {
  				prop = copy[ i ];
  				event[ prop ] = originalEvent[ prop ];
  			}
  	
  			// Support: Cordova 2.5 (WebKit) (#13255)
  			// All events should have a target; Cordova deviceready doesn't
  			if ( !event.target ) {
  				event.target = document;
  			}
  	
  			// Support: Safari 6.0+, Chrome<28
  			// Target should not be a text node (#504, #13143)
  			if ( event.target.nodeType === 3 ) {
  				event.target = event.target.parentNode;
  			}
  	
  			return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
  		},
  	
  		special: {
  			load: {
  				// Prevent triggered image.load events from bubbling to window.load
  				noBubble: true
  			},
  			focus: {
  				// Fire native event if possible so blur/focus sequence is correct
  				trigger: function() {
  					if ( this !== safeActiveElement() && this.focus ) {
  						this.focus();
  						return false;
  					}
  				},
  				delegateType: "focusin"
  			},
  			blur: {
  				trigger: function() {
  					if ( this === safeActiveElement() && this.blur ) {
  						this.blur();
  						return false;
  					}
  				},
  				delegateType: "focusout"
  			},
  			click: {
  				// For checkbox, fire native event so checked state will be right
  				trigger: function() {
  					if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) {
  						this.click();
  						return false;
  					}
  				},
  	
  				// For cross-browser consistency, don't fire native .click() on links
  				_default: function( event ) {
  					return jQuery.nodeName( event.target, "a" );
  				}
  			},
  	
  			beforeunload: {
  				postDispatch: function( event ) {
  	
  					// Support: Firefox 20+
  					// Firefox doesn't alert if the returnValue field is not set.
  					if ( event.result !== undefined && event.originalEvent ) {
  						event.originalEvent.returnValue = event.result;
  					}
  				}
  			}
  		},
  	
  		simulate: function( type, elem, event, bubble ) {
  			// Piggyback on a donor event to simulate a different one.
  			// Fake originalEvent to avoid donor's stopPropagation, but if the
  			// simulated event prevents default then we do the same on the donor.
  			var e = jQuery.extend(
  				new jQuery.Event(),
  				event,
  				{
  					type: type,
  					isSimulated: true,
  					originalEvent: {}
  				}
  			);
  			if ( bubble ) {
  				jQuery.event.trigger( e, null, elem );
  			} else {
  				jQuery.event.dispatch.call( elem, e );
  			}
  			if ( e.isDefaultPrevented() ) {
  				event.preventDefault();
  			}
  		}
  	};
  	
  	jQuery.removeEvent = function( elem, type, handle ) {
  		if ( elem.removeEventListener ) {
  			elem.removeEventListener( type, handle, false );
  		}
  	};
  	
  	jQuery.Event = function( src, props ) {
  		// Allow instantiation without the 'new' keyword
  		if ( !(this instanceof jQuery.Event) ) {
  			return new jQuery.Event( src, props );
  		}
  	
  		// Event object
  		if ( src && src.type ) {
  			this.originalEvent = src;
  			this.type = src.type;
  	
  			// Events bubbling up the document may have been marked as prevented
  			// by a handler lower down the tree; reflect the correct value.
  			this.isDefaultPrevented = src.defaultPrevented ||
  					src.defaultPrevented === undefined &&
  					// Support: Android<4.0
  					src.returnValue === false ?
  				returnTrue :
  				returnFalse;
  	
  		// Event type
  		} else {
  			this.type = src;
  		}
  	
  		// Put explicitly provided properties onto the event object
  		if ( props ) {
  			jQuery.extend( this, props );
  		}
  	
  		// Create a timestamp if incoming event doesn't have one
  		this.timeStamp = src && src.timeStamp || jQuery.now();
  	
  		// Mark it as fixed
  		this[ jQuery.expando ] = true;
  	};
  	
  	// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
  	// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
  	jQuery.Event.prototype = {
  		isDefaultPrevented: returnFalse,
  		isPropagationStopped: returnFalse,
  		isImmediatePropagationStopped: returnFalse,
  	
  		preventDefault: function() {
  			var e = this.originalEvent;
  	
  			this.isDefaultPrevented = returnTrue;
  	
  			if ( e && e.preventDefault ) {
  				e.preventDefault();
  			}
  		},
  		stopPropagation: function() {
  			var e = this.originalEvent;
  	
  			this.isPropagationStopped = returnTrue;
  	
  			if ( e && e.stopPropagation ) {
  				e.stopPropagation();
  			}
  		},
  		stopImmediatePropagation: function() {
  			var e = this.originalEvent;
  	
  			this.isImmediatePropagationStopped = returnTrue;
  	
  			if ( e && e.stopImmediatePropagation ) {
  				e.stopImmediatePropagation();
  			}
  	
  			this.stopPropagation();
  		}
  	};
  	
  	// Create mouseenter/leave events using mouseover/out and event-time checks
  	// Support: Chrome 15+
  	jQuery.each({
  		mouseenter: "mouseover",
  		mouseleave: "mouseout",
  		pointerenter: "pointerover",
  		pointerleave: "pointerout"
  	}, function( orig, fix ) {
  		jQuery.event.special[ orig ] = {
  			delegateType: fix,
  			bindType: fix,
  	
  			handle: function( event ) {
  				var ret,
  					target = this,
  					related = event.relatedTarget,
  					handleObj = event.handleObj;
  	
  				// For mousenter/leave call the handler if related is outside the target.
  				// NB: No relatedTarget if the mouse left/entered the browser window
  				if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
  					event.type = handleObj.origType;
  					ret = handleObj.handler.apply( this, arguments );
  					event.type = fix;
  				}
  				return ret;
  			}
  		};
  	});
  	
  	// Support: Firefox, Chrome, Safari
  	// Create "bubbling" focus and blur events
  	if ( !support.focusinBubbles ) {
  		jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
  	
  			// Attach a single capturing handler on the document while someone wants focusin/focusout
  			var handler = function( event ) {
  					jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
  				};
  	
  			jQuery.event.special[ fix ] = {
  				setup: function() {
  					var doc = this.ownerDocument || this,
  						attaches = data_priv.access( doc, fix );
  	
  					if ( !attaches ) {
  						doc.addEventListener( orig, handler, true );
  					}
  					data_priv.access( doc, fix, ( attaches || 0 ) + 1 );
  				},
  				teardown: function() {
  					var doc = this.ownerDocument || this,
  						attaches = data_priv.access( doc, fix ) - 1;
  	
  					if ( !attaches ) {
  						doc.removeEventListener( orig, handler, true );
  						data_priv.remove( doc, fix );
  	
  					} else {
  						data_priv.access( doc, fix, attaches );
  					}
  				}
  			};
  		});
  	}
  	
  	jQuery.fn.extend({
  	
  		on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
  			var origFn, type;
  	
  			// Types can be a map of types/handlers
  			if ( typeof types === "object" ) {
  				// ( types-Object, selector, data )
  				if ( typeof selector !== "string" ) {
  					// ( types-Object, data )
  					data = data || selector;
  					selector = undefined;
  				}
  				for ( type in types ) {
  					this.on( type, selector, data, types[ type ], one );
  				}
  				return this;
  			}
  	
  			if ( data == null && fn == null ) {
  				// ( types, fn )
  				fn = selector;
  				data = selector = undefined;
  			} else if ( fn == null ) {
  				if ( typeof selector === "string" ) {
  					// ( types, selector, fn )
  					fn = data;
  					data = undefined;
  				} else {
  					// ( types, data, fn )
  					fn = data;
  					data = selector;
  					selector = undefined;
  				}
  			}
  			if ( fn === false ) {
  				fn = returnFalse;
  			} else if ( !fn ) {
  				return this;
  			}
  	
  			if ( one === 1 ) {
  				origFn = fn;
  				fn = function( event ) {
  					// Can use an empty set, since event contains the info
  					jQuery().off( event );
  					return origFn.apply( this, arguments );
  				};
  				// Use same guid so caller can remove using origFn
  				fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
  			}
  			return this.each( function() {
  				jQuery.event.add( this, types, fn, data, selector );
  			});
  		},
  		one: function( types, selector, data, fn ) {
  			return this.on( types, selector, data, fn, 1 );
  		},
  		off: function( types, selector, fn ) {
  			var handleObj, type;
  			if ( types && types.preventDefault && types.handleObj ) {
  				// ( event )  dispatched jQuery.Event
  				handleObj = types.handleObj;
  				jQuery( types.delegateTarget ).off(
  					handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
  					handleObj.selector,
  					handleObj.handler
  				);
  				return this;
  			}
  			if ( typeof types === "object" ) {
  				// ( types-object [, selector] )
  				for ( type in types ) {
  					this.off( type, selector, types[ type ] );
  				}
  				return this;
  			}
  			if ( selector === false || typeof selector === "function" ) {
  				// ( types [, fn] )
  				fn = selector;
  				selector = undefined;
  			}
  			if ( fn === false ) {
  				fn = returnFalse;
  			}
  			return this.each(function() {
  				jQuery.event.remove( this, types, fn, selector );
  			});
  		},
  	
  		trigger: function( type, data ) {
  			return this.each(function() {
  				jQuery.event.trigger( type, data, this );
  			});
  		},
  		triggerHandler: function( type, data ) {
  			var elem = this[0];
  			if ( elem ) {
  				return jQuery.event.trigger( type, data, elem, true );
  			}
  		}
  	});
  	
  	
  	var
  		rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
  		rtagName = /<([\w:]+)/,
  		rhtml = /<|&#?\w+;/,
  		rnoInnerhtml = /<(?:script|style|link)/i,
  		// checked="checked" or checked
  		rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
  		rscriptType = /^$|\/(?:java|ecma)script/i,
  		rscriptTypeMasked = /^true\/(.*)/,
  		rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
  	
  		// We have to close these tags to support XHTML (#13200)
  		wrapMap = {
  	
  			// Support: IE9
  			option: [ 1, "<select multiple='multiple'>", "</select>" ],
  	
  			thead: [ 1, "<table>", "</table>" ],
  			col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
  			tr: [ 2, "<table><tbody>", "</tbody></table>" ],
  			td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
  	
  			_default: [ 0, "", "" ]
  		};
  	
  	// Support: IE9
  	wrapMap.optgroup = wrapMap.option;
  	
  	wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
  	wrapMap.th = wrapMap.td;
  	
  	// Support: 1.x compatibility
  	// Manipulating tables requires a tbody
  	function manipulationTarget( elem, content ) {
  		return jQuery.nodeName( elem, "table" ) &&
  			jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?
  	
  			elem.getElementsByTagName("tbody")[0] ||
  				elem.appendChild( elem.ownerDocument.createElement("tbody") ) :
  			elem;
  	}
  	
  	// Replace/restore the type attribute of script elements for safe DOM manipulation
  	function disableScript( elem ) {
  		elem.type = (elem.getAttribute("type") !== null) + "/" + elem.type;
  		return elem;
  	}
  	function restoreScript( elem ) {
  		var match = rscriptTypeMasked.exec( elem.type );
  	
  		if ( match ) {
  			elem.type = match[ 1 ];
  		} else {
  			elem.removeAttribute("type");
  		}
  	
  		return elem;
  	}
  	
  	// Mark scripts as having already been evaluated
  	function setGlobalEval( elems, refElements ) {
  		var i = 0,
  			l = elems.length;
  	
  		for ( ; i < l; i++ ) {
  			data_priv.set(
  				elems[ i ], "globalEval", !refElements || data_priv.get( refElements[ i ], "globalEval" )
  			);
  		}
  	}
  	
  	function cloneCopyEvent( src, dest ) {
  		var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
  	
  		if ( dest.nodeType !== 1 ) {
  			return;
  		}
  	
  		// 1. Copy private data: events, handlers, etc.
  		if ( data_priv.hasData( src ) ) {
  			pdataOld = data_priv.access( src );
  			pdataCur = data_priv.set( dest, pdataOld );
  			events = pdataOld.events;
  	
  			if ( events ) {
  				delete pdataCur.handle;
  				pdataCur.events = {};
  	
  				for ( type in events ) {
  					for ( i = 0, l = events[ type ].length; i < l; i++ ) {
  						jQuery.event.add( dest, type, events[ type ][ i ] );
  					}
  				}
  			}
  		}
  	
  		// 2. Copy user data
  		if ( data_user.hasData( src ) ) {
  			udataOld = data_user.access( src );
  			udataCur = jQuery.extend( {}, udataOld );
  	
  			data_user.set( dest, udataCur );
  		}
  	}
  	
  	function getAll( context, tag ) {
  		var ret = context.getElementsByTagName ? context.getElementsByTagName( tag || "*" ) :
  				context.querySelectorAll ? context.querySelectorAll( tag || "*" ) :
  				[];
  	
  		return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
  			jQuery.merge( [ context ], ret ) :
  			ret;
  	}
  	
  	// Fix IE bugs, see support tests
  	function fixInput( src, dest ) {
  		var nodeName = dest.nodeName.toLowerCase();
  	
  		// Fails to persist the checked state of a cloned checkbox or radio button.
  		if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
  			dest.checked = src.checked;
  	
  		// Fails to return the selected option to the default selected state when cloning options
  		} else if ( nodeName === "input" || nodeName === "textarea" ) {
  			dest.defaultValue = src.defaultValue;
  		}
  	}
  	
  	jQuery.extend({
  		clone: function( elem, dataAndEvents, deepDataAndEvents ) {
  			var i, l, srcElements, destElements,
  				clone = elem.cloneNode( true ),
  				inPage = jQuery.contains( elem.ownerDocument, elem );
  	
  			// Fix IE cloning issues
  			if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
  					!jQuery.isXMLDoc( elem ) ) {
  	
  				// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
  				destElements = getAll( clone );
  				srcElements = getAll( elem );
  	
  				for ( i = 0, l = srcElements.length; i < l; i++ ) {
  					fixInput( srcElements[ i ], destElements[ i ] );
  				}
  			}
  	
  			// Copy the events from the original to the clone
  			if ( dataAndEvents ) {
  				if ( deepDataAndEvents ) {
  					srcElements = srcElements || getAll( elem );
  					destElements = destElements || getAll( clone );
  	
  					for ( i = 0, l = srcElements.length; i < l; i++ ) {
  						cloneCopyEvent( srcElements[ i ], destElements[ i ] );
  					}
  				} else {
  					cloneCopyEvent( elem, clone );
  				}
  			}
  	
  			// Preserve script evaluation history
  			destElements = getAll( clone, "script" );
  			if ( destElements.length > 0 ) {
  				setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
  			}
  	
  			// Return the cloned set
  			return clone;
  		},
  	
  		buildFragment: function( elems, context, scripts, selection ) {
  			var elem, tmp, tag, wrap, contains, j,
  				fragment = context.createDocumentFragment(),
  				nodes = [],
  				i = 0,
  				l = elems.length;
  	
  			for ( ; i < l; i++ ) {
  				elem = elems[ i ];
  	
  				if ( elem || elem === 0 ) {
  	
  					// Add nodes directly
  					if ( jQuery.type( elem ) === "object" ) {
  						// Support: QtWebKit, PhantomJS
  						// push.apply(_, arraylike) throws on ancient WebKit
  						jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
  	
  					// Convert non-html into a text node
  					} else if ( !rhtml.test( elem ) ) {
  						nodes.push( context.createTextNode( elem ) );
  	
  					// Convert html into DOM nodes
  					} else {
  						tmp = tmp || fragment.appendChild( context.createElement("div") );
  	
  						// Deserialize a standard representation
  						tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
  						wrap = wrapMap[ tag ] || wrapMap._default;
  						tmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[ 2 ];
  	
  						// Descend through wrappers to the right content
  						j = wrap[ 0 ];
  						while ( j-- ) {
  							tmp = tmp.lastChild;
  						}
  	
  						// Support: QtWebKit, PhantomJS
  						// push.apply(_, arraylike) throws on ancient WebKit
  						jQuery.merge( nodes, tmp.childNodes );
  	
  						// Remember the top-level container
  						tmp = fragment.firstChild;
  	
  						// Ensure the created nodes are orphaned (#12392)
  						tmp.textContent = "";
  					}
  				}
  			}
  	
  			// Remove wrapper from fragment
  			fragment.textContent = "";
  	
  			i = 0;
  			while ( (elem = nodes[ i++ ]) ) {
  	
  				// #4087 - If origin and destination elements are the same, and this is
  				// that element, do not do anything
  				if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
  					continue;
  				}
  	
  				contains = jQuery.contains( elem.ownerDocument, elem );
  	
  				// Append to fragment
  				tmp = getAll( fragment.appendChild( elem ), "script" );
  	
  				// Preserve script evaluation history
  				if ( contains ) {
  					setGlobalEval( tmp );
  				}
  	
  				// Capture executables
  				if ( scripts ) {
  					j = 0;
  					while ( (elem = tmp[ j++ ]) ) {
  						if ( rscriptType.test( elem.type || "" ) ) {
  							scripts.push( elem );
  						}
  					}
  				}
  			}
  	
  			return fragment;
  		},
  	
  		cleanData: function( elems ) {
  			var data, elem, type, key,
  				special = jQuery.event.special,
  				i = 0;
  	
  			for ( ; (elem = elems[ i ]) !== undefined; i++ ) {
  				if ( jQuery.acceptData( elem ) ) {
  					key = elem[ data_priv.expando ];
  	
  					if ( key && (data = data_priv.cache[ key ]) ) {
  						if ( data.events ) {
  							for ( type in data.events ) {
  								if ( special[ type ] ) {
  									jQuery.event.remove( elem, type );
  	
  								// This is a shortcut to avoid jQuery.event.remove's overhead
  								} else {
  									jQuery.removeEvent( elem, type, data.handle );
  								}
  							}
  						}
  						if ( data_priv.cache[ key ] ) {
  							// Discard any remaining `private` data
  							delete data_priv.cache[ key ];
  						}
  					}
  				}
  				// Discard any remaining `user` data
  				delete data_user.cache[ elem[ data_user.expando ] ];
  			}
  		}
  	});
  	
  	jQuery.fn.extend({
  		text: function( value ) {
  			return access( this, function( value ) {
  				return value === undefined ?
  					jQuery.text( this ) :
  					this.empty().each(function() {
  						if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
  							this.textContent = value;
  						}
  					});
  			}, null, value, arguments.length );
  		},
  	
  		append: function() {
  			return this.domManip( arguments, function( elem ) {
  				if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
  					var target = manipulationTarget( this, elem );
  					target.appendChild( elem );
  				}
  			});
  		},
  	
  		prepend: function() {
  			return this.domManip( arguments, function( elem ) {
  				if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
  					var target = manipulationTarget( this, elem );
  					target.insertBefore( elem, target.firstChild );
  				}
  			});
  		},
  	
  		before: function() {
  			return this.domManip( arguments, function( elem ) {
  				if ( this.parentNode ) {
  					this.parentNode.insertBefore( elem, this );
  				}
  			});
  		},
  	
  		after: function() {
  			return this.domManip( arguments, function( elem ) {
  				if ( this.parentNode ) {
  					this.parentNode.insertBefore( elem, this.nextSibling );
  				}
  			});
  		},
  	
  		remove: function( selector, keepData /* Internal Use Only */ ) {
  			var elem,
  				elems = selector ? jQuery.filter( selector, this ) : this,
  				i = 0;
  	
  			for ( ; (elem = elems[i]) != null; i++ ) {
  				if ( !keepData && elem.nodeType === 1 ) {
  					jQuery.cleanData( getAll( elem ) );
  				}
  	
  				if ( elem.parentNode ) {
  					if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
  						setGlobalEval( getAll( elem, "script" ) );
  					}
  					elem.parentNode.removeChild( elem );
  				}
  			}
  	
  			return this;
  		},
  	
  		empty: function() {
  			var elem,
  				i = 0;
  	
  			for ( ; (elem = this[i]) != null; i++ ) {
  				if ( elem.nodeType === 1 ) {
  	
  					// Prevent memory leaks
  					jQuery.cleanData( getAll( elem, false ) );
  	
  					// Remove any remaining nodes
  					elem.textContent = "";
  				}
  			}
  	
  			return this;
  		},
  	
  		clone: function( dataAndEvents, deepDataAndEvents ) {
  			dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
  			deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
  	
  			return this.map(function() {
  				return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
  			});
  		},
  	
  		html: function( value ) {
  			return access( this, function( value ) {
  				var elem = this[ 0 ] || {},
  					i = 0,
  					l = this.length;
  	
  				if ( value === undefined && elem.nodeType === 1 ) {
  					return elem.innerHTML;
  				}
  	
  				// See if we can take a shortcut and just use innerHTML
  				if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
  					!wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
  	
  					value = value.replace( rxhtmlTag, "<$1></$2>" );
  	
  					try {
  						for ( ; i < l; i++ ) {
  							elem = this[ i ] || {};
  	
  							// Remove element nodes and prevent memory leaks
  							if ( elem.nodeType === 1 ) {
  								jQuery.cleanData( getAll( elem, false ) );
  								elem.innerHTML = value;
  							}
  						}
  	
  						elem = 0;
  	
  					// If using innerHTML throws an exception, use the fallback method
  					} catch( e ) {}
  				}
  	
  				if ( elem ) {
  					this.empty().append( value );
  				}
  			}, null, value, arguments.length );
  		},
  	
  		replaceWith: function() {
  			var arg = arguments[ 0 ];
  	
  			// Make the changes, replacing each context element with the new content
  			this.domManip( arguments, function( elem ) {
  				arg = this.parentNode;
  	
  				jQuery.cleanData( getAll( this ) );
  	
  				if ( arg ) {
  					arg.replaceChild( elem, this );
  				}
  			});
  	
  			// Force removal if there was no new content (e.g., from empty arguments)
  			return arg && (arg.length || arg.nodeType) ? this : this.remove();
  		},
  	
  		detach: function( selector ) {
  			return this.remove( selector, true );
  		},
  	
  		domManip: function( args, callback ) {
  	
  			// Flatten any nested arrays
  			args = concat.apply( [], args );
  	
  			var fragment, first, scripts, hasScripts, node, doc,
  				i = 0,
  				l = this.length,
  				set = this,
  				iNoClone = l - 1,
  				value = args[ 0 ],
  				isFunction = jQuery.isFunction( value );
  	
  			// We can't cloneNode fragments that contain checked, in WebKit
  			if ( isFunction ||
  					( l > 1 && typeof value === "string" &&
  						!support.checkClone && rchecked.test( value ) ) ) {
  				return this.each(function( index ) {
  					var self = set.eq( index );
  					if ( isFunction ) {
  						args[ 0 ] = value.call( this, index, self.html() );
  					}
  					self.domManip( args, callback );
  				});
  			}
  	
  			if ( l ) {
  				fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
  				first = fragment.firstChild;
  	
  				if ( fragment.childNodes.length === 1 ) {
  					fragment = first;
  				}
  	
  				if ( first ) {
  					scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
  					hasScripts = scripts.length;
  	
  					// Use the original fragment for the last item instead of the first because it can end up
  					// being emptied incorrectly in certain situations (#8070).
  					for ( ; i < l; i++ ) {
  						node = fragment;
  	
  						if ( i !== iNoClone ) {
  							node = jQuery.clone( node, true, true );
  	
  							// Keep references to cloned scripts for later restoration
  							if ( hasScripts ) {
  								// Support: QtWebKit
  								// jQuery.merge because push.apply(_, arraylike) throws
  								jQuery.merge( scripts, getAll( node, "script" ) );
  							}
  						}
  	
  						callback.call( this[ i ], node, i );
  					}
  	
  					if ( hasScripts ) {
  						doc = scripts[ scripts.length - 1 ].ownerDocument;
  	
  						// Reenable scripts
  						jQuery.map( scripts, restoreScript );
  	
  						// Evaluate executable scripts on first document insertion
  						for ( i = 0; i < hasScripts; i++ ) {
  							node = scripts[ i ];
  							if ( rscriptType.test( node.type || "" ) &&
  								!data_priv.access( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
  	
  								if ( node.src ) {
  									// Optional AJAX dependency, but won't run scripts if not present
  									if ( jQuery._evalUrl ) {
  										jQuery._evalUrl( node.src );
  									}
  								} else {
  									jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) );
  								}
  							}
  						}
  					}
  				}
  			}
  	
  			return this;
  		}
  	});
  	
  	jQuery.each({
  		appendTo: "append",
  		prependTo: "prepend",
  		insertBefore: "before",
  		insertAfter: "after",
  		replaceAll: "replaceWith"
  	}, function( name, original ) {
  		jQuery.fn[ name ] = function( selector ) {
  			var elems,
  				ret = [],
  				insert = jQuery( selector ),
  				last = insert.length - 1,
  				i = 0;
  	
  			for ( ; i <= last; i++ ) {
  				elems = i === last ? this : this.clone( true );
  				jQuery( insert[ i ] )[ original ]( elems );
  	
  				// Support: QtWebKit
  				// .get() because push.apply(_, arraylike) throws
  				push.apply( ret, elems.get() );
  			}
  	
  			return this.pushStack( ret );
  		};
  	});
  	
  	
  	var iframe,
  		elemdisplay = {};
  	
  	/**
  	 * Retrieve the actual display of a element
  	 * @param {String} name nodeName of the element
  	 * @param {Object} doc Document object
  	 */
  	// Called only from within defaultDisplay
  	function actualDisplay( name, doc ) {
  		var style,
  			elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
  	
  			// getDefaultComputedStyle might be reliably used only on attached element
  			display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?
  	
  				// Use of this method is a temporary fix (more like optimization) until something better comes along,
  				// since it was removed from specification and supported only in FF
  				style.display : jQuery.css( elem[ 0 ], "display" );
  	
  		// We don't have any data stored on the element,
  		// so use "detach" method as fast way to get rid of the element
  		elem.detach();
  	
  		return display;
  	}
  	
  	/**
  	 * Try to determine the default display value of an element
  	 * @param {String} nodeName
  	 */
  	function defaultDisplay( nodeName ) {
  		var doc = document,
  			display = elemdisplay[ nodeName ];
  	
  		if ( !display ) {
  			display = actualDisplay( nodeName, doc );
  	
  			// If the simple way fails, read from inside an iframe
  			if ( display === "none" || !display ) {
  	
  				// Use the already-created iframe if possible
  				iframe = (iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement );
  	
  				// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
  				doc = iframe[ 0 ].contentDocument;
  	
  				// Support: IE
  				doc.write();
  				doc.close();
  	
  				display = actualDisplay( nodeName, doc );
  				iframe.detach();
  			}
  	
  			// Store the correct default display
  			elemdisplay[ nodeName ] = display;
  		}
  	
  		return display;
  	}
  	var rmargin = (/^margin/);
  	
  	var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
  	
  	var getStyles = function( elem ) {
  			// Support: IE<=11+, Firefox<=30+ (#15098, #14150)
  			// IE throws on elements created in popups
  			// FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
  			if ( elem.ownerDocument.defaultView.opener ) {
  				return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
  			}
  	
  			return window.getComputedStyle( elem, null );
  		};
  	
  	
  	
  	function curCSS( elem, name, computed ) {
  		var width, minWidth, maxWidth, ret,
  			style = elem.style;
  	
  		computed = computed || getStyles( elem );
  	
  		// Support: IE9
  		// getPropertyValue is only needed for .css('filter') (#12537)
  		if ( computed ) {
  			ret = computed.getPropertyValue( name ) || computed[ name ];
  		}
  	
  		if ( computed ) {
  	
  			if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
  				ret = jQuery.style( elem, name );
  			}
  	
  			// Support: iOS < 6
  			// A tribute to the "awesome hack by Dean Edwards"
  			// iOS < 6 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
  			// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
  			if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
  	
  				// Remember the original values
  				width = style.width;
  				minWidth = style.minWidth;
  				maxWidth = style.maxWidth;
  	
  				// Put in the new values to get a computed value out
  				style.minWidth = style.maxWidth = style.width = ret;
  				ret = computed.width;
  	
  				// Revert the changed values
  				style.width = width;
  				style.minWidth = minWidth;
  				style.maxWidth = maxWidth;
  			}
  		}
  	
  		return ret !== undefined ?
  			// Support: IE
  			// IE returns zIndex value as an integer.
  			ret + "" :
  			ret;
  	}
  	
  	
  	function addGetHookIf( conditionFn, hookFn ) {
  		// Define the hook, we'll check on the first run if it's really needed.
  		return {
  			get: function() {
  				if ( conditionFn() ) {
  					// Hook not needed (or it's not possible to use it due
  					// to missing dependency), remove it.
  					delete this.get;
  					return;
  				}
  	
  				// Hook needed; redefine it so that the support test is not executed again.
  				return (this.get = hookFn).apply( this, arguments );
  			}
  		};
  	}
  	
  	
  	(function() {
  		var pixelPositionVal, boxSizingReliableVal,
  			docElem = document.documentElement,
  			container = document.createElement( "div" ),
  			div = document.createElement( "div" );
  	
  		if ( !div.style ) {
  			return;
  		}
  	
  		// Support: IE9-11+
  		// Style of cloned element affects source element cloned (#8908)
  		div.style.backgroundClip = "content-box";
  		div.cloneNode( true ).style.backgroundClip = "";
  		support.clearCloneStyle = div.style.backgroundClip === "content-box";
  	
  		container.style.cssText = "border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;" +
  			"position:absolute";
  		container.appendChild( div );
  	
  		// Executing both pixelPosition & boxSizingReliable tests require only one layout
  		// so they're executed at the same time to save the second computation.
  		function computePixelPositionAndBoxSizingReliable() {
  			div.style.cssText =
  				// Support: Firefox<29, Android 2.3
  				// Vendor-prefix box-sizing
  				"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" +
  				"box-sizing:border-box;display:block;margin-top:1%;top:1%;" +
  				"border:1px;padding:1px;width:4px;position:absolute";
  			div.innerHTML = "";
  			docElem.appendChild( container );
  	
  			var divStyle = window.getComputedStyle( div, null );
  			pixelPositionVal = divStyle.top !== "1%";
  			boxSizingReliableVal = divStyle.width === "4px";
  	
  			docElem.removeChild( container );
  		}
  	
  		// Support: node.js jsdom
  		// Don't assume that getComputedStyle is a property of the global object
  		if ( window.getComputedStyle ) {
  			jQuery.extend( support, {
  				pixelPosition: function() {
  	
  					// This test is executed only once but we still do memoizing
  					// since we can use the boxSizingReliable pre-computing.
  					// No need to check if the test was already performed, though.
  					computePixelPositionAndBoxSizingReliable();
  					return pixelPositionVal;
  				},
  				boxSizingReliable: function() {
  					if ( boxSizingReliableVal == null ) {
  						computePixelPositionAndBoxSizingReliable();
  					}
  					return boxSizingReliableVal;
  				},
  				reliableMarginRight: function() {
  	
  					// Support: Android 2.3
  					// Check if div with explicit width and no margin-right incorrectly
  					// gets computed margin-right based on width of container. (#3333)
  					// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
  					// This support function is only executed once so no memoizing is needed.
  					var ret,
  						marginDiv = div.appendChild( document.createElement( "div" ) );
  	
  					// Reset CSS: box-sizing; display; margin; border; padding
  					marginDiv.style.cssText = div.style.cssText =
  						// Support: Firefox<29, Android 2.3
  						// Vendor-prefix box-sizing
  						"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
  						"box-sizing:content-box;display:block;margin:0;border:0;padding:0";
  					marginDiv.style.marginRight = marginDiv.style.width = "0";
  					div.style.width = "1px";
  					docElem.appendChild( container );
  	
  					ret = !parseFloat( window.getComputedStyle( marginDiv, null ).marginRight );
  	
  					docElem.removeChild( container );
  					div.removeChild( marginDiv );
  	
  					return ret;
  				}
  			});
  		}
  	})();
  	
  	
  	// A method for quickly swapping in/out CSS properties to get correct calculations.
  	jQuery.swap = function( elem, options, callback, args ) {
  		var ret, name,
  			old = {};
  	
  		// Remember the old values, and insert the new ones
  		for ( name in options ) {
  			old[ name ] = elem.style[ name ];
  			elem.style[ name ] = options[ name ];
  		}
  	
  		ret = callback.apply( elem, args || [] );
  	
  		// Revert the old values
  		for ( name in options ) {
  			elem.style[ name ] = old[ name ];
  		}
  	
  		return ret;
  	};
  	
  	
  	var
  		// Swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
  		// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
  		rdisplayswap = /^(none|table(?!-c[ea]).+)/,
  		rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
  		rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ),
  	
  		cssShow = { position: "absolute", visibility: "hidden", display: "block" },
  		cssNormalTransform = {
  			letterSpacing: "0",
  			fontWeight: "400"
  		},
  	
  		cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
  	
  	// Return a css property mapped to a potentially vendor prefixed property
  	function vendorPropName( style, name ) {
  	
  		// Shortcut for names that are not vendor prefixed
  		if ( name in style ) {
  			return name;
  		}
  	
  		// Check for vendor prefixed names
  		var capName = name[0].toUpperCase() + name.slice(1),
  			origName = name,
  			i = cssPrefixes.length;
  	
  		while ( i-- ) {
  			name = cssPrefixes[ i ] + capName;
  			if ( name in style ) {
  				return name;
  			}
  		}
  	
  		return origName;
  	}
  	
  	function setPositiveNumber( elem, value, subtract ) {
  		var matches = rnumsplit.exec( value );
  		return matches ?
  			// Guard against undefined "subtract", e.g., when used as in cssHooks
  			Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
  			value;
  	}
  	
  	function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
  		var i = extra === ( isBorderBox ? "border" : "content" ) ?
  			// If we already have the right measurement, avoid augmentation
  			4 :
  			// Otherwise initialize for horizontal or vertical properties
  			name === "width" ? 1 : 0,
  	
  			val = 0;
  	
  		for ( ; i < 4; i += 2 ) {
  			// Both box models exclude margin, so add it if we want it
  			if ( extra === "margin" ) {
  				val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
  			}
  	
  			if ( isBorderBox ) {
  				// border-box includes padding, so remove it if we want content
  				if ( extra === "content" ) {
  					val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
  				}
  	
  				// At this point, extra isn't border nor margin, so remove border
  				if ( extra !== "margin" ) {
  					val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
  				}
  			} else {
  				// At this point, extra isn't content, so add padding
  				val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
  	
  				// At this point, extra isn't content nor padding, so add border
  				if ( extra !== "padding" ) {
  					val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
  				}
  			}
  		}
  	
  		return val;
  	}
  	
  	function getWidthOrHeight( elem, name, extra ) {
  	
  		// Start with offset property, which is equivalent to the border-box value
  		var valueIsBorderBox = true,
  			val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
  			styles = getStyles( elem ),
  			isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
  	
  		// Some non-html elements return undefined for offsetWidth, so check for null/undefined
  		// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
  		// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
  		if ( val <= 0 || val == null ) {
  			// Fall back to computed then uncomputed css if necessary
  			val = curCSS( elem, name, styles );
  			if ( val < 0 || val == null ) {
  				val = elem.style[ name ];
  			}
  	
  			// Computed unit is not pixels. Stop here and return.
  			if ( rnumnonpx.test(val) ) {
  				return val;
  			}
  	
  			// Check for style in case a browser which returns unreliable values
  			// for getComputedStyle silently falls back to the reliable elem.style
  			valueIsBorderBox = isBorderBox &&
  				( support.boxSizingReliable() || val === elem.style[ name ] );
  	
  			// Normalize "", auto, and prepare for extra
  			val = parseFloat( val ) || 0;
  		}
  	
  		// Use the active box-sizing model to add/subtract irrelevant styles
  		return ( val +
  			augmentWidthOrHeight(
  				elem,
  				name,
  				extra || ( isBorderBox ? "border" : "content" ),
  				valueIsBorderBox,
  				styles
  			)
  		) + "px";
  	}
  	
  	function showHide( elements, show ) {
  		var display, elem, hidden,
  			values = [],
  			index = 0,
  			length = elements.length;
  	
  		for ( ; index < length; index++ ) {
  			elem = elements[ index ];
  			if ( !elem.style ) {
  				continue;
  			}
  	
  			values[ index ] = data_priv.get( elem, "olddisplay" );
  			display = elem.style.display;
  			if ( show ) {
  				// Reset the inline display of this element to learn if it is
  				// being hidden by cascaded rules or not
  				if ( !values[ index ] && display === "none" ) {
  					elem.style.display = "";
  				}
  	
  				// Set elements which have been overridden with display: none
  				// in a stylesheet to whatever the default browser style is
  				// for such an element
  				if ( elem.style.display === "" && isHidden( elem ) ) {
  					values[ index ] = data_priv.access( elem, "olddisplay", defaultDisplay(elem.nodeName) );
  				}
  			} else {
  				hidden = isHidden( elem );
  	
  				if ( display !== "none" || !hidden ) {
  					data_priv.set( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
  				}
  			}
  		}
  	
  		// Set the display of most of the elements in a second loop
  		// to avoid the constant reflow
  		for ( index = 0; index < length; index++ ) {
  			elem = elements[ index ];
  			if ( !elem.style ) {
  				continue;
  			}
  			if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
  				elem.style.display = show ? values[ index ] || "" : "none";
  			}
  		}
  	
  		return elements;
  	}
  	
  	jQuery.extend({
  	
  		// Add in style property hooks for overriding the default
  		// behavior of getting and setting a style property
  		cssHooks: {
  			opacity: {
  				get: function( elem, computed ) {
  					if ( computed ) {
  	
  						// We should always get a number back from opacity
  						var ret = curCSS( elem, "opacity" );
  						return ret === "" ? "1" : ret;
  					}
  				}
  			}
  		},
  	
  		// Don't automatically add "px" to these possibly-unitless properties
  		cssNumber: {
  			"columnCount": true,
  			"fillOpacity": true,
  			"flexGrow": true,
  			"flexShrink": true,
  			"fontWeight": true,
  			"lineHeight": true,
  			"opacity": true,
  			"order": true,
  			"orphans": true,
  			"widows": true,
  			"zIndex": true,
  			"zoom": true
  		},
  	
  		// Add in properties whose names you wish to fix before
  		// setting or getting the value
  		cssProps: {
  			"float": "cssFloat"
  		},
  	
  		// Get and set the style property on a DOM Node
  		style: function( elem, name, value, extra ) {
  	
  			// Don't set styles on text and comment nodes
  			if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
  				return;
  			}
  	
  			// Make sure that we're working with the right name
  			var ret, type, hooks,
  				origName = jQuery.camelCase( name ),
  				style = elem.style;
  	
  			name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
  	
  			// Gets hook for the prefixed version, then unprefixed version
  			hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
  	
  			// Check if we're setting a value
  			if ( value !== undefined ) {
  				type = typeof value;
  	
  				// Convert "+=" or "-=" to relative numbers (#7345)
  				if ( type === "string" && (ret = rrelNum.exec( value )) ) {
  					value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
  					// Fixes bug #9237
  					type = "number";
  				}
  	
  				// Make sure that null and NaN values aren't set (#7116)
  				if ( value == null || value !== value ) {
  					return;
  				}
  	
  				// If a number, add 'px' to the (except for certain CSS properties)
  				if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
  					value += "px";
  				}
  	
  				// Support: IE9-11+
  				// background-* props affect original clone's values
  				if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
  					style[ name ] = "inherit";
  				}
  	
  				// If a hook was provided, use that value, otherwise just set the specified value
  				if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
  					style[ name ] = value;
  				}
  	
  			} else {
  				// If a hook was provided get the non-computed value from there
  				if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
  					return ret;
  				}
  	
  				// Otherwise just get the value from the style object
  				return style[ name ];
  			}
  		},
  	
  		css: function( elem, name, extra, styles ) {
  			var val, num, hooks,
  				origName = jQuery.camelCase( name );
  	
  			// Make sure that we're working with the right name
  			name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
  	
  			// Try prefixed name followed by the unprefixed name
  			hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
  	
  			// If a hook was provided get the computed value from there
  			if ( hooks && "get" in hooks ) {
  				val = hooks.get( elem, true, extra );
  			}
  	
  			// Otherwise, if a way to get the computed value exists, use that
  			if ( val === undefined ) {
  				val = curCSS( elem, name, styles );
  			}
  	
  			// Convert "normal" to computed value
  			if ( val === "normal" && name in cssNormalTransform ) {
  				val = cssNormalTransform[ name ];
  			}
  	
  			// Make numeric if forced or a qualifier was provided and val looks numeric
  			if ( extra === "" || extra ) {
  				num = parseFloat( val );
  				return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
  			}
  			return val;
  		}
  	});
  	
  	jQuery.each([ "height", "width" ], function( i, name ) {
  		jQuery.cssHooks[ name ] = {
  			get: function( elem, computed, extra ) {
  				if ( computed ) {
  	
  					// Certain elements can have dimension info if we invisibly show them
  					// but it must have a current display style that would benefit
  					return rdisplayswap.test( jQuery.css( elem, "display" ) ) && elem.offsetWidth === 0 ?
  						jQuery.swap( elem, cssShow, function() {
  							return getWidthOrHeight( elem, name, extra );
  						}) :
  						getWidthOrHeight( elem, name, extra );
  				}
  			},
  	
  			set: function( elem, value, extra ) {
  				var styles = extra && getStyles( elem );
  				return setPositiveNumber( elem, value, extra ?
  					augmentWidthOrHeight(
  						elem,
  						name,
  						extra,
  						jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
  						styles
  					) : 0
  				);
  			}
  		};
  	});
  	
  	// Support: Android 2.3
  	jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
  		function( elem, computed ) {
  			if ( computed ) {
  				return jQuery.swap( elem, { "display": "inline-block" },
  					curCSS, [ elem, "marginRight" ] );
  			}
  		}
  	);
  	
  	// These hooks are used by animate to expand properties
  	jQuery.each({
  		margin: "",
  		padding: "",
  		border: "Width"
  	}, function( prefix, suffix ) {
  		jQuery.cssHooks[ prefix + suffix ] = {
  			expand: function( value ) {
  				var i = 0,
  					expanded = {},
  	
  					// Assumes a single number if not a string
  					parts = typeof value === "string" ? value.split(" ") : [ value ];
  	
  				for ( ; i < 4; i++ ) {
  					expanded[ prefix + cssExpand[ i ] + suffix ] =
  						parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
  				}
  	
  				return expanded;
  			}
  		};
  	
  		if ( !rmargin.test( prefix ) ) {
  			jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
  		}
  	});
  	
  	jQuery.fn.extend({
  		css: function( name, value ) {
  			return access( this, function( elem, name, value ) {
  				var styles, len,
  					map = {},
  					i = 0;
  	
  				if ( jQuery.isArray( name ) ) {
  					styles = getStyles( elem );
  					len = name.length;
  	
  					for ( ; i < len; i++ ) {
  						map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
  					}
  	
  					return map;
  				}
  	
  				return value !== undefined ?
  					jQuery.style( elem, name, value ) :
  					jQuery.css( elem, name );
  			}, name, value, arguments.length > 1 );
  		},
  		show: function() {
  			return showHide( this, true );
  		},
  		hide: function() {
  			return showHide( this );
  		},
  		toggle: function( state ) {
  			if ( typeof state === "boolean" ) {
  				return state ? this.show() : this.hide();
  			}
  	
  			return this.each(function() {
  				if ( isHidden( this ) ) {
  					jQuery( this ).show();
  				} else {
  					jQuery( this ).hide();
  				}
  			});
  		}
  	});
  	
  	
  	function Tween( elem, options, prop, end, easing ) {
  		return new Tween.prototype.init( elem, options, prop, end, easing );
  	}
  	jQuery.Tween = Tween;
  	
  	Tween.prototype = {
  		constructor: Tween,
  		init: function( elem, options, prop, end, easing, unit ) {
  			this.elem = elem;
  			this.prop = prop;
  			this.easing = easing || "swing";
  			this.options = options;
  			this.start = this.now = this.cur();
  			this.end = end;
  			this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
  		},
  		cur: function() {
  			var hooks = Tween.propHooks[ this.prop ];
  	
  			return hooks && hooks.get ?
  				hooks.get( this ) :
  				Tween.propHooks._default.get( this );
  		},
  		run: function( percent ) {
  			var eased,
  				hooks = Tween.propHooks[ this.prop ];
  	
  			if ( this.options.duration ) {
  				this.pos = eased = jQuery.easing[ this.easing ](
  					percent, this.options.duration * percent, 0, 1, this.options.duration
  				);
  			} else {
  				this.pos = eased = percent;
  			}
  			this.now = ( this.end - this.start ) * eased + this.start;
  	
  			if ( this.options.step ) {
  				this.options.step.call( this.elem, this.now, this );
  			}
  	
  			if ( hooks && hooks.set ) {
  				hooks.set( this );
  			} else {
  				Tween.propHooks._default.set( this );
  			}
  			return this;
  		}
  	};
  	
  	Tween.prototype.init.prototype = Tween.prototype;
  	
  	Tween.propHooks = {
  		_default: {
  			get: function( tween ) {
  				var result;
  	
  				if ( tween.elem[ tween.prop ] != null &&
  					(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
  					return tween.elem[ tween.prop ];
  				}
  	
  				// Passing an empty string as a 3rd parameter to .css will automatically
  				// attempt a parseFloat and fallback to a string if the parse fails.
  				// Simple values such as "10px" are parsed to Float;
  				// complex values such as "rotate(1rad)" are returned as-is.
  				result = jQuery.css( tween.elem, tween.prop, "" );
  				// Empty strings, null, undefined and "auto" are converted to 0.
  				return !result || result === "auto" ? 0 : result;
  			},
  			set: function( tween ) {
  				// Use step hook for back compat.
  				// Use cssHook if its there.
  				// Use .style if available and use plain properties where available.
  				if ( jQuery.fx.step[ tween.prop ] ) {
  					jQuery.fx.step[ tween.prop ]( tween );
  				} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
  					jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
  				} else {
  					tween.elem[ tween.prop ] = tween.now;
  				}
  			}
  		}
  	};
  	
  	// Support: IE9
  	// Panic based approach to setting things on disconnected nodes
  	Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
  		set: function( tween ) {
  			if ( tween.elem.nodeType && tween.elem.parentNode ) {
  				tween.elem[ tween.prop ] = tween.now;
  			}
  		}
  	};
  	
  	jQuery.easing = {
  		linear: function( p ) {
  			return p;
  		},
  		swing: function( p ) {
  			return 0.5 - Math.cos( p * Math.PI ) / 2;
  		}
  	};
  	
  	jQuery.fx = Tween.prototype.init;
  	
  	// Back Compat <1.8 extension point
  	jQuery.fx.step = {};
  	
  	
  	
  	
  	var
  		fxNow, timerId,
  		rfxtypes = /^(?:toggle|show|hide)$/,
  		rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ),
  		rrun = /queueHooks$/,
  		animationPrefilters = [ defaultPrefilter ],
  		tweeners = {
  			"*": [ function( prop, value ) {
  				var tween = this.createTween( prop, value ),
  					target = tween.cur(),
  					parts = rfxnum.exec( value ),
  					unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
  	
  					// Starting value computation is required for potential unit mismatches
  					start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&
  						rfxnum.exec( jQuery.css( tween.elem, prop ) ),
  					scale = 1,
  					maxIterations = 20;
  	
  				if ( start && start[ 3 ] !== unit ) {
  					// Trust units reported by jQuery.css
  					unit = unit || start[ 3 ];
  	
  					// Make sure we update the tween properties later on
  					parts = parts || [];
  	
  					// Iteratively approximate from a nonzero starting point
  					start = +target || 1;
  	
  					do {
  						// If previous iteration zeroed out, double until we get *something*.
  						// Use string for doubling so we don't accidentally see scale as unchanged below
  						scale = scale || ".5";
  	
  						// Adjust and apply
  						start = start / scale;
  						jQuery.style( tween.elem, prop, start + unit );
  	
  					// Update scale, tolerating zero or NaN from tween.cur(),
  					// break the loop if scale is unchanged or perfect, or if we've just had enough
  					} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
  				}
  	
  				// Update tween properties
  				if ( parts ) {
  					start = tween.start = +start || +target || 0;
  					tween.unit = unit;
  					// If a +=/-= token was provided, we're doing a relative animation
  					tween.end = parts[ 1 ] ?
  						start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
  						+parts[ 2 ];
  				}
  	
  				return tween;
  			} ]
  		};
  	
  	// Animations created synchronously will run synchronously
  	function createFxNow() {
  		setTimeout(function() {
  			fxNow = undefined;
  		});
  		return ( fxNow = jQuery.now() );
  	}
  	
  	// Generate parameters to create a standard animation
  	function genFx( type, includeWidth ) {
  		var which,
  			i = 0,
  			attrs = { height: type };
  	
  		// If we include width, step value is 1 to do all cssExpand values,
  		// otherwise step value is 2 to skip over Left and Right
  		includeWidth = includeWidth ? 1 : 0;
  		for ( ; i < 4 ; i += 2 - includeWidth ) {
  			which = cssExpand[ i ];
  			attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
  		}
  	
  		if ( includeWidth ) {
  			attrs.opacity = attrs.width = type;
  		}
  	
  		return attrs;
  	}
  	
  	function createTween( value, prop, animation ) {
  		var tween,
  			collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
  			index = 0,
  			length = collection.length;
  		for ( ; index < length; index++ ) {
  			if ( (tween = collection[ index ].call( animation, prop, value )) ) {
  	
  				// We're done with this property
  				return tween;
  			}
  		}
  	}
  	
  	function defaultPrefilter( elem, props, opts ) {
  		/* jshint validthis: true */
  		var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
  			anim = this,
  			orig = {},
  			style = elem.style,
  			hidden = elem.nodeType && isHidden( elem ),
  			dataShow = data_priv.get( elem, "fxshow" );
  	
  		// Handle queue: false promises
  		if ( !opts.queue ) {
  			hooks = jQuery._queueHooks( elem, "fx" );
  			if ( hooks.unqueued == null ) {
  				hooks.unqueued = 0;
  				oldfire = hooks.empty.fire;
  				hooks.empty.fire = function() {
  					if ( !hooks.unqueued ) {
  						oldfire();
  					}
  				};
  			}
  			hooks.unqueued++;
  	
  			anim.always(function() {
  				// Ensure the complete handler is called before this completes
  				anim.always(function() {
  					hooks.unqueued--;
  					if ( !jQuery.queue( elem, "fx" ).length ) {
  						hooks.empty.fire();
  					}
  				});
  			});
  		}
  	
  		// Height/width overflow pass
  		if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
  			// Make sure that nothing sneaks out
  			// Record all 3 overflow attributes because IE9-10 do not
  			// change the overflow attribute when overflowX and
  			// overflowY are set to the same value
  			opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
  	
  			// Set display property to inline-block for height/width
  			// animations on inline elements that are having width/height animated
  			display = jQuery.css( elem, "display" );
  	
  			// Test default display if display is currently "none"
  			checkDisplay = display === "none" ?
  				data_priv.get( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;
  	
  			if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) {
  				style.display = "inline-block";
  			}
  		}
  	
  		if ( opts.overflow ) {
  			style.overflow = "hidden";
  			anim.always(function() {
  				style.overflow = opts.overflow[ 0 ];
  				style.overflowX = opts.overflow[ 1 ];
  				style.overflowY = opts.overflow[ 2 ];
  			});
  		}
  	
  		// show/hide pass
  		for ( prop in props ) {
  			value = props[ prop ];
  			if ( rfxtypes.exec( value ) ) {
  				delete props[ prop ];
  				toggle = toggle || value === "toggle";
  				if ( value === ( hidden ? "hide" : "show" ) ) {
  	
  					// If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden
  					if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
  						hidden = true;
  					} else {
  						continue;
  					}
  				}
  				orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
  	
  			// Any non-fx value stops us from restoring the original display value
  			} else {
  				display = undefined;
  			}
  		}
  	
  		if ( !jQuery.isEmptyObject( orig ) ) {
  			if ( dataShow ) {
  				if ( "hidden" in dataShow ) {
  					hidden = dataShow.hidden;
  				}
  			} else {
  				dataShow = data_priv.access( elem, "fxshow", {} );
  			}
  	
  			// Store state if its toggle - enables .stop().toggle() to "reverse"
  			if ( toggle ) {
  				dataShow.hidden = !hidden;
  			}
  			if ( hidden ) {
  				jQuery( elem ).show();
  			} else {
  				anim.done(function() {
  					jQuery( elem ).hide();
  				});
  			}
  			anim.done(function() {
  				var prop;
  	
  				data_priv.remove( elem, "fxshow" );
  				for ( prop in orig ) {
  					jQuery.style( elem, prop, orig[ prop ] );
  				}
  			});
  			for ( prop in orig ) {
  				tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
  	
  				if ( !( prop in dataShow ) ) {
  					dataShow[ prop ] = tween.start;
  					if ( hidden ) {
  						tween.end = tween.start;
  						tween.start = prop === "width" || prop === "height" ? 1 : 0;
  					}
  				}
  			}
  	
  		// If this is a noop like .hide().hide(), restore an overwritten display value
  		} else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) {
  			style.display = display;
  		}
  	}
  	
  	function propFilter( props, specialEasing ) {
  		var index, name, easing, value, hooks;
  	
  		// camelCase, specialEasing and expand cssHook pass
  		for ( index in props ) {
  			name = jQuery.camelCase( index );
  			easing = specialEasing[ name ];
  			value = props[ index ];
  			if ( jQuery.isArray( value ) ) {
  				easing = value[ 1 ];
  				value = props[ index ] = value[ 0 ];
  			}
  	
  			if ( index !== name ) {
  				props[ name ] = value;
  				delete props[ index ];
  			}
  	
  			hooks = jQuery.cssHooks[ name ];
  			if ( hooks && "expand" in hooks ) {
  				value = hooks.expand( value );
  				delete props[ name ];
  	
  				// Not quite $.extend, this won't overwrite existing keys.
  				// Reusing 'index' because we have the correct "name"
  				for ( index in value ) {
  					if ( !( index in props ) ) {
  						props[ index ] = value[ index ];
  						specialEasing[ index ] = easing;
  					}
  				}
  			} else {
  				specialEasing[ name ] = easing;
  			}
  		}
  	}
  	
  	function Animation( elem, properties, options ) {
  		var result,
  			stopped,
  			index = 0,
  			length = animationPrefilters.length,
  			deferred = jQuery.Deferred().always( function() {
  				// Don't match elem in the :animated selector
  				delete tick.elem;
  			}),
  			tick = function() {
  				if ( stopped ) {
  					return false;
  				}
  				var currentTime = fxNow || createFxNow(),
  					remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
  					// Support: Android 2.3
  					// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
  					temp = remaining / animation.duration || 0,
  					percent = 1 - temp,
  					index = 0,
  					length = animation.tweens.length;
  	
  				for ( ; index < length ; index++ ) {
  					animation.tweens[ index ].run( percent );
  				}
  	
  				deferred.notifyWith( elem, [ animation, percent, remaining ]);
  	
  				if ( percent < 1 && length ) {
  					return remaining;
  				} else {
  					deferred.resolveWith( elem, [ animation ] );
  					return false;
  				}
  			},
  			animation = deferred.promise({
  				elem: elem,
  				props: jQuery.extend( {}, properties ),
  				opts: jQuery.extend( true, { specialEasing: {} }, options ),
  				originalProperties: properties,
  				originalOptions: options,
  				startTime: fxNow || createFxNow(),
  				duration: options.duration,
  				tweens: [],
  				createTween: function( prop, end ) {
  					var tween = jQuery.Tween( elem, animation.opts, prop, end,
  							animation.opts.specialEasing[ prop ] || animation.opts.easing );
  					animation.tweens.push( tween );
  					return tween;
  				},
  				stop: function( gotoEnd ) {
  					var index = 0,
  						// If we are going to the end, we want to run all the tweens
  						// otherwise we skip this part
  						length = gotoEnd ? animation.tweens.length : 0;
  					if ( stopped ) {
  						return this;
  					}
  					stopped = true;
  					for ( ; index < length ; index++ ) {
  						animation.tweens[ index ].run( 1 );
  					}
  	
  					// Resolve when we played the last frame; otherwise, reject
  					if ( gotoEnd ) {
  						deferred.resolveWith( elem, [ animation, gotoEnd ] );
  					} else {
  						deferred.rejectWith( elem, [ animation, gotoEnd ] );
  					}
  					return this;
  				}
  			}),
  			props = animation.props;
  	
  		propFilter( props, animation.opts.specialEasing );
  	
  		for ( ; index < length ; index++ ) {
  			result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
  			if ( result ) {
  				return result;
  			}
  		}
  	
  		jQuery.map( props, createTween, animation );
  	
  		if ( jQuery.isFunction( animation.opts.start ) ) {
  			animation.opts.start.call( elem, animation );
  		}
  	
  		jQuery.fx.timer(
  			jQuery.extend( tick, {
  				elem: elem,
  				anim: animation,
  				queue: animation.opts.queue
  			})
  		);
  	
  		// attach callbacks from options
  		return animation.progress( animation.opts.progress )
  			.done( animation.opts.done, animation.opts.complete )
  			.fail( animation.opts.fail )
  			.always( animation.opts.always );
  	}
  	
  	jQuery.Animation = jQuery.extend( Animation, {
  	
  		tweener: function( props, callback ) {
  			if ( jQuery.isFunction( props ) ) {
  				callback = props;
  				props = [ "*" ];
  			} else {
  				props = props.split(" ");
  			}
  	
  			var prop,
  				index = 0,
  				length = props.length;
  	
  			for ( ; index < length ; index++ ) {
  				prop = props[ index ];
  				tweeners[ prop ] = tweeners[ prop ] || [];
  				tweeners[ prop ].unshift( callback );
  			}
  		},
  	
  		prefilter: function( callback, prepend ) {
  			if ( prepend ) {
  				animationPrefilters.unshift( callback );
  			} else {
  				animationPrefilters.push( callback );
  			}
  		}
  	});
  	
  	jQuery.speed = function( speed, easing, fn ) {
  		var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
  			complete: fn || !fn && easing ||
  				jQuery.isFunction( speed ) && speed,
  			duration: speed,
  			easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
  		};
  	
  		opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
  			opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
  	
  		// Normalize opt.queue - true/undefined/null -> "fx"
  		if ( opt.queue == null || opt.queue === true ) {
  			opt.queue = "fx";
  		}
  	
  		// Queueing
  		opt.old = opt.complete;
  	
  		opt.complete = function() {
  			if ( jQuery.isFunction( opt.old ) ) {
  				opt.old.call( this );
  			}
  	
  			if ( opt.queue ) {
  				jQuery.dequeue( this, opt.queue );
  			}
  		};
  	
  		return opt;
  	};
  	
  	jQuery.fn.extend({
  		fadeTo: function( speed, to, easing, callback ) {
  	
  			// Show any hidden elements after setting opacity to 0
  			return this.filter( isHidden ).css( "opacity", 0 ).show()
  	
  				// Animate to the value specified
  				.end().animate({ opacity: to }, speed, easing, callback );
  		},
  		animate: function( prop, speed, easing, callback ) {
  			var empty = jQuery.isEmptyObject( prop ),
  				optall = jQuery.speed( speed, easing, callback ),
  				doAnimation = function() {
  					// Operate on a copy of prop so per-property easing won't be lost
  					var anim = Animation( this, jQuery.extend( {}, prop ), optall );
  	
  					// Empty animations, or finishing resolves immediately
  					if ( empty || data_priv.get( this, "finish" ) ) {
  						anim.stop( true );
  					}
  				};
  				doAnimation.finish = doAnimation;
  	
  			return empty || optall.queue === false ?
  				this.each( doAnimation ) :
  				this.queue( optall.queue, doAnimation );
  		},
  		stop: function( type, clearQueue, gotoEnd ) {
  			var stopQueue = function( hooks ) {
  				var stop = hooks.stop;
  				delete hooks.stop;
  				stop( gotoEnd );
  			};
  	
  			if ( typeof type !== "string" ) {
  				gotoEnd = clearQueue;
  				clearQueue = type;
  				type = undefined;
  			}
  			if ( clearQueue && type !== false ) {
  				this.queue( type || "fx", [] );
  			}
  	
  			return this.each(function() {
  				var dequeue = true,
  					index = type != null && type + "queueHooks",
  					timers = jQuery.timers,
  					data = data_priv.get( this );
  	
  				if ( index ) {
  					if ( data[ index ] && data[ index ].stop ) {
  						stopQueue( data[ index ] );
  					}
  				} else {
  					for ( index in data ) {
  						if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
  							stopQueue( data[ index ] );
  						}
  					}
  				}
  	
  				for ( index = timers.length; index--; ) {
  					if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
  						timers[ index ].anim.stop( gotoEnd );
  						dequeue = false;
  						timers.splice( index, 1 );
  					}
  				}
  	
  				// Start the next in the queue if the last step wasn't forced.
  				// Timers currently will call their complete callbacks, which
  				// will dequeue but only if they were gotoEnd.
  				if ( dequeue || !gotoEnd ) {
  					jQuery.dequeue( this, type );
  				}
  			});
  		},
  		finish: function( type ) {
  			if ( type !== false ) {
  				type = type || "fx";
  			}
  			return this.each(function() {
  				var index,
  					data = data_priv.get( this ),
  					queue = data[ type + "queue" ],
  					hooks = data[ type + "queueHooks" ],
  					timers = jQuery.timers,
  					length = queue ? queue.length : 0;
  	
  				// Enable finishing flag on private data
  				data.finish = true;
  	
  				// Empty the queue first
  				jQuery.queue( this, type, [] );
  	
  				if ( hooks && hooks.stop ) {
  					hooks.stop.call( this, true );
  				}
  	
  				// Look for any active animations, and finish them
  				for ( index = timers.length; index--; ) {
  					if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
  						timers[ index ].anim.stop( true );
  						timers.splice( index, 1 );
  					}
  				}
  	
  				// Look for any animations in the old queue and finish them
  				for ( index = 0; index < length; index++ ) {
  					if ( queue[ index ] && queue[ index ].finish ) {
  						queue[ index ].finish.call( this );
  					}
  				}
  	
  				// Turn off finishing flag
  				delete data.finish;
  			});
  		}
  	});
  	
  	jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
  		var cssFn = jQuery.fn[ name ];
  		jQuery.fn[ name ] = function( speed, easing, callback ) {
  			return speed == null || typeof speed === "boolean" ?
  				cssFn.apply( this, arguments ) :
  				this.animate( genFx( name, true ), speed, easing, callback );
  		};
  	});
  	
  	// Generate shortcuts for custom animations
  	jQuery.each({
  		slideDown: genFx("show"),
  		slideUp: genFx("hide"),
  		slideToggle: genFx("toggle"),
  		fadeIn: { opacity: "show" },
  		fadeOut: { opacity: "hide" },
  		fadeToggle: { opacity: "toggle" }
  	}, function( name, props ) {
  		jQuery.fn[ name ] = function( speed, easing, callback ) {
  			return this.animate( props, speed, easing, callback );
  		};
  	});
  	
  	jQuery.timers = [];
  	jQuery.fx.tick = function() {
  		var timer,
  			i = 0,
  			timers = jQuery.timers;
  	
  		fxNow = jQuery.now();
  	
  		for ( ; i < timers.length; i++ ) {
  			timer = timers[ i ];
  			// Checks the timer has not already been removed
  			if ( !timer() && timers[ i ] === timer ) {
  				timers.splice( i--, 1 );
  			}
  		}
  	
  		if ( !timers.length ) {
  			jQuery.fx.stop();
  		}
  		fxNow = undefined;
  	};
  	
  	jQuery.fx.timer = function( timer ) {
  		jQuery.timers.push( timer );
  		if ( timer() ) {
  			jQuery.fx.start();
  		} else {
  			jQuery.timers.pop();
  		}
  	};
  	
  	jQuery.fx.interval = 13;
  	
  	jQuery.fx.start = function() {
  		if ( !timerId ) {
  			timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
  		}
  	};
  	
  	jQuery.fx.stop = function() {
  		clearInterval( timerId );
  		timerId = null;
  	};
  	
  	jQuery.fx.speeds = {
  		slow: 600,
  		fast: 200,
  		// Default speed
  		_default: 400
  	};
  	
  	
  	// Based off of the plugin by Clint Helfers, with permission.
  	// http://blindsignals.com/index.php/2009/07/jquery-delay/
  	jQuery.fn.delay = function( time, type ) {
  		time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
  		type = type || "fx";
  	
  		return this.queue( type, function( next, hooks ) {
  			var timeout = setTimeout( next, time );
  			hooks.stop = function() {
  				clearTimeout( timeout );
  			};
  		});
  	};
  	
  	
  	(function() {
  		var input = document.createElement( "input" ),
  			select = document.createElement( "select" ),
  			opt = select.appendChild( document.createElement( "option" ) );
  	
  		input.type = "checkbox";
  	
  		// Support: iOS<=5.1, Android<=4.2+
  		// Default value for a checkbox should be "on"
  		support.checkOn = input.value !== "";
  	
  		// Support: IE<=11+
  		// Must access selectedIndex to make default options select
  		support.optSelected = opt.selected;
  	
  		// Support: Android<=2.3
  		// Options inside disabled selects are incorrectly marked as disabled
  		select.disabled = true;
  		support.optDisabled = !opt.disabled;
  	
  		// Support: IE<=11+
  		// An input loses its value after becoming a radio
  		input = document.createElement( "input" );
  		input.value = "t";
  		input.type = "radio";
  		support.radioValue = input.value === "t";
  	})();
  	
  	
  	var nodeHook, boolHook,
  		attrHandle = jQuery.expr.attrHandle;
  	
  	jQuery.fn.extend({
  		attr: function( name, value ) {
  			return access( this, jQuery.attr, name, value, arguments.length > 1 );
  		},
  	
  		removeAttr: function( name ) {
  			return this.each(function() {
  				jQuery.removeAttr( this, name );
  			});
  		}
  	});
  	
  	jQuery.extend({
  		attr: function( elem, name, value ) {
  			var hooks, ret,
  				nType = elem.nodeType;
  	
  			// don't get/set attributes on text, comment and attribute nodes
  			if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
  				return;
  			}
  	
  			// Fallback to prop when attributes are not supported
  			if ( typeof elem.getAttribute === strundefined ) {
  				return jQuery.prop( elem, name, value );
  			}
  	
  			// All attributes are lowercase
  			// Grab necessary hook if one is defined
  			if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
  				name = name.toLowerCase();
  				hooks = jQuery.attrHooks[ name ] ||
  					( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
  			}
  	
  			if ( value !== undefined ) {
  	
  				if ( value === null ) {
  					jQuery.removeAttr( elem, name );
  	
  				} else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
  					return ret;
  	
  				} else {
  					elem.setAttribute( name, value + "" );
  					return value;
  				}
  	
  			} else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
  				return ret;
  	
  			} else {
  				ret = jQuery.find.attr( elem, name );
  	
  				// Non-existent attributes return null, we normalize to undefined
  				return ret == null ?
  					undefined :
  					ret;
  			}
  		},
  	
  		removeAttr: function( elem, value ) {
  			var name, propName,
  				i = 0,
  				attrNames = value && value.match( rnotwhite );
  	
  			if ( attrNames && elem.nodeType === 1 ) {
  				while ( (name = attrNames[i++]) ) {
  					propName = jQuery.propFix[ name ] || name;
  	
  					// Boolean attributes get special treatment (#10870)
  					if ( jQuery.expr.match.bool.test( name ) ) {
  						// Set corresponding property to false
  						elem[ propName ] = false;
  					}
  	
  					elem.removeAttribute( name );
  				}
  			}
  		},
  	
  		attrHooks: {
  			type: {
  				set: function( elem, value ) {
  					if ( !support.radioValue && value === "radio" &&
  						jQuery.nodeName( elem, "input" ) ) {
  						var val = elem.value;
  						elem.setAttribute( "type", value );
  						if ( val ) {
  							elem.value = val;
  						}
  						return value;
  					}
  				}
  			}
  		}
  	});
  	
  	// Hooks for boolean attributes
  	boolHook = {
  		set: function( elem, value, name ) {
  			if ( value === false ) {
  				// Remove boolean attributes when set to false
  				jQuery.removeAttr( elem, name );
  			} else {
  				elem.setAttribute( name, name );
  			}
  			return name;
  		}
  	};
  	jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
  		var getter = attrHandle[ name ] || jQuery.find.attr;
  	
  		attrHandle[ name ] = function( elem, name, isXML ) {
  			var ret, handle;
  			if ( !isXML ) {
  				// Avoid an infinite loop by temporarily removing this function from the getter
  				handle = attrHandle[ name ];
  				attrHandle[ name ] = ret;
  				ret = getter( elem, name, isXML ) != null ?
  					name.toLowerCase() :
  					null;
  				attrHandle[ name ] = handle;
  			}
  			return ret;
  		};
  	});
  	
  	
  	
  	
  	var rfocusable = /^(?:input|select|textarea|button)$/i;
  	
  	jQuery.fn.extend({
  		prop: function( name, value ) {
  			return access( this, jQuery.prop, name, value, arguments.length > 1 );
  		},
  	
  		removeProp: function( name ) {
  			return this.each(function() {
  				delete this[ jQuery.propFix[ name ] || name ];
  			});
  		}
  	});
  	
  	jQuery.extend({
  		propFix: {
  			"for": "htmlFor",
  			"class": "className"
  		},
  	
  		prop: function( elem, name, value ) {
  			var ret, hooks, notxml,
  				nType = elem.nodeType;
  	
  			// Don't get/set properties on text, comment and attribute nodes
  			if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
  				return;
  			}
  	
  			notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
  	
  			if ( notxml ) {
  				// Fix name and attach hooks
  				name = jQuery.propFix[ name ] || name;
  				hooks = jQuery.propHooks[ name ];
  			}
  	
  			if ( value !== undefined ) {
  				return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
  					ret :
  					( elem[ name ] = value );
  	
  			} else {
  				return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
  					ret :
  					elem[ name ];
  			}
  		},
  	
  		propHooks: {
  			tabIndex: {
  				get: function( elem ) {
  					return elem.hasAttribute( "tabindex" ) || rfocusable.test( elem.nodeName ) || elem.href ?
  						elem.tabIndex :
  						-1;
  				}
  			}
  		}
  	});
  	
  	if ( !support.optSelected ) {
  		jQuery.propHooks.selected = {
  			get: function( elem ) {
  				var parent = elem.parentNode;
  				if ( parent && parent.parentNode ) {
  					parent.parentNode.selectedIndex;
  				}
  				return null;
  			}
  		};
  	}
  	
  	jQuery.each([
  		"tabIndex",
  		"readOnly",
  		"maxLength",
  		"cellSpacing",
  		"cellPadding",
  		"rowSpan",
  		"colSpan",
  		"useMap",
  		"frameBorder",
  		"contentEditable"
  	], function() {
  		jQuery.propFix[ this.toLowerCase() ] = this;
  	});
  	
  	
  	
  	
  	var rclass = /[\t\r\n\f]/g;
  	
  	jQuery.fn.extend({
  		addClass: function( value ) {
  			var classes, elem, cur, clazz, j, finalValue,
  				proceed = typeof value === "string" && value,
  				i = 0,
  				len = this.length;
  	
  			if ( jQuery.isFunction( value ) ) {
  				return this.each(function( j ) {
  					jQuery( this ).addClass( value.call( this, j, this.className ) );
  				});
  			}
  	
  			if ( proceed ) {
  				// The disjunction here is for better compressibility (see removeClass)
  				classes = ( value || "" ).match( rnotwhite ) || [];
  	
  				for ( ; i < len; i++ ) {
  					elem = this[ i ];
  					cur = elem.nodeType === 1 && ( elem.className ?
  						( " " + elem.className + " " ).replace( rclass, " " ) :
  						" "
  					);
  	
  					if ( cur ) {
  						j = 0;
  						while ( (clazz = classes[j++]) ) {
  							if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
  								cur += clazz + " ";
  							}
  						}
  	
  						// only assign if different to avoid unneeded rendering.
  						finalValue = jQuery.trim( cur );
  						if ( elem.className !== finalValue ) {
  							elem.className = finalValue;
  						}
  					}
  				}
  			}
  	
  			return this;
  		},
  	
  		removeClass: function( value ) {
  			var classes, elem, cur, clazz, j, finalValue,
  				proceed = arguments.length === 0 || typeof value === "string" && value,
  				i = 0,
  				len = this.length;
  	
  			if ( jQuery.isFunction( value ) ) {
  				return this.each(function( j ) {
  					jQuery( this ).removeClass( value.call( this, j, this.className ) );
  				});
  			}
  			if ( proceed ) {
  				classes = ( value || "" ).match( rnotwhite ) || [];
  	
  				for ( ; i < len; i++ ) {
  					elem = this[ i ];
  					// This expression is here for better compressibility (see addClass)
  					cur = elem.nodeType === 1 && ( elem.className ?
  						( " " + elem.className + " " ).replace( rclass, " " ) :
  						""
  					);
  	
  					if ( cur ) {
  						j = 0;
  						while ( (clazz = classes[j++]) ) {
  							// Remove *all* instances
  							while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
  								cur = cur.replace( " " + clazz + " ", " " );
  							}
  						}
  	
  						// Only assign if different to avoid unneeded rendering.
  						finalValue = value ? jQuery.trim( cur ) : "";
  						if ( elem.className !== finalValue ) {
  							elem.className = finalValue;
  						}
  					}
  				}
  			}
  	
  			return this;
  		},
  	
  		toggleClass: function( value, stateVal ) {
  			var type = typeof value;
  	
  			if ( typeof stateVal === "boolean" && type === "string" ) {
  				return stateVal ? this.addClass( value ) : this.removeClass( value );
  			}
  	
  			if ( jQuery.isFunction( value ) ) {
  				return this.each(function( i ) {
  					jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
  				});
  			}
  	
  			return this.each(function() {
  				if ( type === "string" ) {
  					// Toggle individual class names
  					var className,
  						i = 0,
  						self = jQuery( this ),
  						classNames = value.match( rnotwhite ) || [];
  	
  					while ( (className = classNames[ i++ ]) ) {
  						// Check each className given, space separated list
  						if ( self.hasClass( className ) ) {
  							self.removeClass( className );
  						} else {
  							self.addClass( className );
  						}
  					}
  	
  				// Toggle whole class name
  				} else if ( type === strundefined || type === "boolean" ) {
  					if ( this.className ) {
  						// store className if set
  						data_priv.set( this, "__className__", this.className );
  					}
  	
  					// If the element has a class name or if we're passed `false`,
  					// then remove the whole classname (if there was one, the above saved it).
  					// Otherwise bring back whatever was previously saved (if anything),
  					// falling back to the empty string if nothing was stored.
  					this.className = this.className || value === false ? "" : data_priv.get( this, "__className__" ) || "";
  				}
  			});
  		},
  	
  		hasClass: function( selector ) {
  			var className = " " + selector + " ",
  				i = 0,
  				l = this.length;
  			for ( ; i < l; i++ ) {
  				if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
  					return true;
  				}
  			}
  	
  			return false;
  		}
  	});
  	
  	
  	
  	
  	var rreturn = /\r/g;
  	
  	jQuery.fn.extend({
  		val: function( value ) {
  			var hooks, ret, isFunction,
  				elem = this[0];
  	
  			if ( !arguments.length ) {
  				if ( elem ) {
  					hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
  	
  					if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
  						return ret;
  					}
  	
  					ret = elem.value;
  	
  					return typeof ret === "string" ?
  						// Handle most common string cases
  						ret.replace(rreturn, "") :
  						// Handle cases where value is null/undef or number
  						ret == null ? "" : ret;
  				}
  	
  				return;
  			}
  	
  			isFunction = jQuery.isFunction( value );
  	
  			return this.each(function( i ) {
  				var val;
  	
  				if ( this.nodeType !== 1 ) {
  					return;
  				}
  	
  				if ( isFunction ) {
  					val = value.call( this, i, jQuery( this ).val() );
  				} else {
  					val = value;
  				}
  	
  				// Treat null/undefined as ""; convert numbers to string
  				if ( val == null ) {
  					val = "";
  	
  				} else if ( typeof val === "number" ) {
  					val += "";
  	
  				} else if ( jQuery.isArray( val ) ) {
  					val = jQuery.map( val, function( value ) {
  						return value == null ? "" : value + "";
  					});
  				}
  	
  				hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
  	
  				// If set returns undefined, fall back to normal setting
  				if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
  					this.value = val;
  				}
  			});
  		}
  	});
  	
  	jQuery.extend({
  		valHooks: {
  			option: {
  				get: function( elem ) {
  					var val = jQuery.find.attr( elem, "value" );
  					return val != null ?
  						val :
  						// Support: IE10-11+
  						// option.text throws exceptions (#14686, #14858)
  						jQuery.trim( jQuery.text( elem ) );
  				}
  			},
  			select: {
  				get: function( elem ) {
  					var value, option,
  						options = elem.options,
  						index = elem.selectedIndex,
  						one = elem.type === "select-one" || index < 0,
  						values = one ? null : [],
  						max = one ? index + 1 : options.length,
  						i = index < 0 ?
  							max :
  							one ? index : 0;
  	
  					// Loop through all the selected options
  					for ( ; i < max; i++ ) {
  						option = options[ i ];
  	
  						// IE6-9 doesn't update selected after form reset (#2551)
  						if ( ( option.selected || i === index ) &&
  								// Don't return options that are disabled or in a disabled optgroup
  								( support.optDisabled ? !option.disabled : option.getAttribute( "disabled" ) === null ) &&
  								( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
  	
  							// Get the specific value for the option
  							value = jQuery( option ).val();
  	
  							// We don't need an array for one selects
  							if ( one ) {
  								return value;
  							}
  	
  							// Multi-Selects return an array
  							values.push( value );
  						}
  					}
  	
  					return values;
  				},
  	
  				set: function( elem, value ) {
  					var optionSet, option,
  						options = elem.options,
  						values = jQuery.makeArray( value ),
  						i = options.length;
  	
  					while ( i-- ) {
  						option = options[ i ];
  						if ( (option.selected = jQuery.inArray( option.value, values ) >= 0) ) {
  							optionSet = true;
  						}
  					}
  	
  					// Force browsers to behave consistently when non-matching value is set
  					if ( !optionSet ) {
  						elem.selectedIndex = -1;
  					}
  					return values;
  				}
  			}
  		}
  	});
  	
  	// Radios and checkboxes getter/setter
  	jQuery.each([ "radio", "checkbox" ], function() {
  		jQuery.valHooks[ this ] = {
  			set: function( elem, value ) {
  				if ( jQuery.isArray( value ) ) {
  					return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
  				}
  			}
  		};
  		if ( !support.checkOn ) {
  			jQuery.valHooks[ this ].get = function( elem ) {
  				return elem.getAttribute("value") === null ? "on" : elem.value;
  			};
  		}
  	});
  	
  	
  	
  	
  	// Return jQuery for attributes-only inclusion
  	
  	
  	jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
  		"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
  		"change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
  	
  		// Handle event binding
  		jQuery.fn[ name ] = function( data, fn ) {
  			return arguments.length > 0 ?
  				this.on( name, null, data, fn ) :
  				this.trigger( name );
  		};
  	});
  	
  	jQuery.fn.extend({
  		hover: function( fnOver, fnOut ) {
  			return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
  		},
  	
  		bind: function( types, data, fn ) {
  			return this.on( types, null, data, fn );
  		},
  		unbind: function( types, fn ) {
  			return this.off( types, null, fn );
  		},
  	
  		delegate: function( selector, types, data, fn ) {
  			return this.on( types, selector, data, fn );
  		},
  		undelegate: function( selector, types, fn ) {
  			// ( namespace ) or ( selector, types [, fn] )
  			return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
  		}
  	});
  	
  	
  	var nonce = jQuery.now();
  	
  	var rquery = (/\?/);
  	
  	
  	
  	// Support: Android 2.3
  	// Workaround failure to string-cast null input
  	jQuery.parseJSON = function( data ) {
  		return JSON.parse( data + "" );
  	};
  	
  	
  	// Cross-browser xml parsing
  	jQuery.parseXML = function( data ) {
  		var xml, tmp;
  		if ( !data || typeof data !== "string" ) {
  			return null;
  		}
  	
  		// Support: IE9
  		try {
  			tmp = new DOMParser();
  			xml = tmp.parseFromString( data, "text/xml" );
  		} catch ( e ) {
  			xml = undefined;
  		}
  	
  		if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
  			jQuery.error( "Invalid XML: " + data );
  		}
  		return xml;
  	};
  	
  	
  	var
  		rhash = /#.*$/,
  		rts = /([?&])_=[^&]*/,
  		rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
  		// #7653, #8125, #8152: local protocol detection
  		rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
  		rnoContent = /^(?:GET|HEAD)$/,
  		rprotocol = /^\/\//,
  		rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,
  	
  		/* Prefilters
  		 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
  		 * 2) These are called:
  		 *    - BEFORE asking for a transport
  		 *    - AFTER param serialization (s.data is a string if s.processData is true)
  		 * 3) key is the dataType
  		 * 4) the catchall symbol "*" can be used
  		 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
  		 */
  		prefilters = {},
  	
  		/* Transports bindings
  		 * 1) key is the dataType
  		 * 2) the catchall symbol "*" can be used
  		 * 3) selection will start with transport dataType and THEN go to "*" if needed
  		 */
  		transports = {},
  	
  		// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
  		allTypes = "*/".concat( "*" ),
  	
  		// Document location
  		ajaxLocation = window.location.href,
  	
  		// Segment location into parts
  		ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
  	
  	// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
  	function addToPrefiltersOrTransports( structure ) {
  	
  		// dataTypeExpression is optional and defaults to "*"
  		return function( dataTypeExpression, func ) {
  	
  			if ( typeof dataTypeExpression !== "string" ) {
  				func = dataTypeExpression;
  				dataTypeExpression = "*";
  			}
  	
  			var dataType,
  				i = 0,
  				dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
  	
  			if ( jQuery.isFunction( func ) ) {
  				// For each dataType in the dataTypeExpression
  				while ( (dataType = dataTypes[i++]) ) {
  					// Prepend if requested
  					if ( dataType[0] === "+" ) {
  						dataType = dataType.slice( 1 ) || "*";
  						(structure[ dataType ] = structure[ dataType ] || []).unshift( func );
  	
  					// Otherwise append
  					} else {
  						(structure[ dataType ] = structure[ dataType ] || []).push( func );
  					}
  				}
  			}
  		};
  	}
  	
  	// Base inspection function for prefilters and transports
  	function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
  	
  		var inspected = {},
  			seekingTransport = ( structure === transports );
  	
  		function inspect( dataType ) {
  			var selected;
  			inspected[ dataType ] = true;
  			jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
  				var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
  				if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
  					options.dataTypes.unshift( dataTypeOrTransport );
  					inspect( dataTypeOrTransport );
  					return false;
  				} else if ( seekingTransport ) {
  					return !( selected = dataTypeOrTransport );
  				}
  			});
  			return selected;
  		}
  	
  		return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
  	}
  	
  	// A special extend for ajax options
  	// that takes "flat" options (not to be deep extended)
  	// Fixes #9887
  	function ajaxExtend( target, src ) {
  		var key, deep,
  			flatOptions = jQuery.ajaxSettings.flatOptions || {};
  	
  		for ( key in src ) {
  			if ( src[ key ] !== undefined ) {
  				( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
  			}
  		}
  		if ( deep ) {
  			jQuery.extend( true, target, deep );
  		}
  	
  		return target;
  	}
  	
  	/* Handles responses to an ajax request:
  	 * - finds the right dataType (mediates between content-type and expected dataType)
  	 * - returns the corresponding response
  	 */
  	function ajaxHandleResponses( s, jqXHR, responses ) {
  	
  		var ct, type, finalDataType, firstDataType,
  			contents = s.contents,
  			dataTypes = s.dataTypes;
  	
  		// Remove auto dataType and get content-type in the process
  		while ( dataTypes[ 0 ] === "*" ) {
  			dataTypes.shift();
  			if ( ct === undefined ) {
  				ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
  			}
  		}
  	
  		// Check if we're dealing with a known content-type
  		if ( ct ) {
  			for ( type in contents ) {
  				if ( contents[ type ] && contents[ type ].test( ct ) ) {
  					dataTypes.unshift( type );
  					break;
  				}
  			}
  		}
  	
  		// Check to see if we have a response for the expected dataType
  		if ( dataTypes[ 0 ] in responses ) {
  			finalDataType = dataTypes[ 0 ];
  		} else {
  			// Try convertible dataTypes
  			for ( type in responses ) {
  				if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
  					finalDataType = type;
  					break;
  				}
  				if ( !firstDataType ) {
  					firstDataType = type;
  				}
  			}
  			// Or just use first one
  			finalDataType = finalDataType || firstDataType;
  		}
  	
  		// If we found a dataType
  		// We add the dataType to the list if needed
  		// and return the corresponding response
  		if ( finalDataType ) {
  			if ( finalDataType !== dataTypes[ 0 ] ) {
  				dataTypes.unshift( finalDataType );
  			}
  			return responses[ finalDataType ];
  		}
  	}
  	
  	/* Chain conversions given the request and the original response
  	 * Also sets the responseXXX fields on the jqXHR instance
  	 */
  	function ajaxConvert( s, response, jqXHR, isSuccess ) {
  		var conv2, current, conv, tmp, prev,
  			converters = {},
  			// Work with a copy of dataTypes in case we need to modify it for conversion
  			dataTypes = s.dataTypes.slice();
  	
  		// Create converters map with lowercased keys
  		if ( dataTypes[ 1 ] ) {
  			for ( conv in s.converters ) {
  				converters[ conv.toLowerCase() ] = s.converters[ conv ];
  			}
  		}
  	
  		current = dataTypes.shift();
  	
  		// Convert to each sequential dataType
  		while ( current ) {
  	
  			if ( s.responseFields[ current ] ) {
  				jqXHR[ s.responseFields[ current ] ] = response;
  			}
  	
  			// Apply the dataFilter if provided
  			if ( !prev && isSuccess && s.dataFilter ) {
  				response = s.dataFilter( response, s.dataType );
  			}
  	
  			prev = current;
  			current = dataTypes.shift();
  	
  			if ( current ) {
  	
  			// There's only work to do if current dataType is non-auto
  				if ( current === "*" ) {
  	
  					current = prev;
  	
  				// Convert response if prev dataType is non-auto and differs from current
  				} else if ( prev !== "*" && prev !== current ) {
  	
  					// Seek a direct converter
  					conv = converters[ prev + " " + current ] || converters[ "* " + current ];
  	
  					// If none found, seek a pair
  					if ( !conv ) {
  						for ( conv2 in converters ) {
  	
  							// If conv2 outputs current
  							tmp = conv2.split( " " );
  							if ( tmp[ 1 ] === current ) {
  	
  								// If prev can be converted to accepted input
  								conv = converters[ prev + " " + tmp[ 0 ] ] ||
  									converters[ "* " + tmp[ 0 ] ];
  								if ( conv ) {
  									// Condense equivalence converters
  									if ( conv === true ) {
  										conv = converters[ conv2 ];
  	
  									// Otherwise, insert the intermediate dataType
  									} else if ( converters[ conv2 ] !== true ) {
  										current = tmp[ 0 ];
  										dataTypes.unshift( tmp[ 1 ] );
  									}
  									break;
  								}
  							}
  						}
  					}
  	
  					// Apply converter (if not an equivalence)
  					if ( conv !== true ) {
  	
  						// Unless errors are allowed to bubble, catch and return them
  						if ( conv && s[ "throws" ] ) {
  							response = conv( response );
  						} else {
  							try {
  								response = conv( response );
  							} catch ( e ) {
  								return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
  							}
  						}
  					}
  				}
  			}
  		}
  	
  		return { state: "success", data: response };
  	}
  	
  	jQuery.extend({
  	
  		// Counter for holding the number of active queries
  		active: 0,
  	
  		// Last-Modified header cache for next request
  		lastModified: {},
  		etag: {},
  	
  		ajaxSettings: {
  			url: ajaxLocation,
  			type: "GET",
  			isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
  			global: true,
  			processData: true,
  			async: true,
  			contentType: "application/x-www-form-urlencoded; charset=UTF-8",
  			/*
  			timeout: 0,
  			data: null,
  			dataType: null,
  			username: null,
  			password: null,
  			cache: null,
  			throws: false,
  			traditional: false,
  			headers: {},
  			*/
  	
  			accepts: {
  				"*": allTypes,
  				text: "text/plain",
  				html: "text/html",
  				xml: "application/xml, text/xml",
  				json: "application/json, text/javascript"
  			},
  	
  			contents: {
  				xml: /xml/,
  				html: /html/,
  				json: /json/
  			},
  	
  			responseFields: {
  				xml: "responseXML",
  				text: "responseText",
  				json: "responseJSON"
  			},
  	
  			// Data converters
  			// Keys separate source (or catchall "*") and destination types with a single space
  			converters: {
  	
  				// Convert anything to text
  				"* text": String,
  	
  				// Text to html (true = no transformation)
  				"text html": true,
  	
  				// Evaluate text as a json expression
  				"text json": jQuery.parseJSON,
  	
  				// Parse text as xml
  				"text xml": jQuery.parseXML
  			},
  	
  			// For options that shouldn't be deep extended:
  			// you can add your own custom options here if
  			// and when you create one that shouldn't be
  			// deep extended (see ajaxExtend)
  			flatOptions: {
  				url: true,
  				context: true
  			}
  		},
  	
  		// Creates a full fledged settings object into target
  		// with both ajaxSettings and settings fields.
  		// If target is omitted, writes into ajaxSettings.
  		ajaxSetup: function( target, settings ) {
  			return settings ?
  	
  				// Building a settings object
  				ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
  	
  				// Extending ajaxSettings
  				ajaxExtend( jQuery.ajaxSettings, target );
  		},
  	
  		ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
  		ajaxTransport: addToPrefiltersOrTransports( transports ),
  	
  		// Main method
  		ajax: function( url, options ) {
  	
  			// If url is an object, simulate pre-1.5 signature
  			if ( typeof url === "object" ) {
  				options = url;
  				url = undefined;
  			}
  	
  			// Force options to be an object
  			options = options || {};
  	
  			var transport,
  				// URL without anti-cache param
  				cacheURL,
  				// Response headers
  				responseHeadersString,
  				responseHeaders,
  				// timeout handle
  				timeoutTimer,
  				// Cross-domain detection vars
  				parts,
  				// To know if global events are to be dispatched
  				fireGlobals,
  				// Loop variable
  				i,
  				// Create the final options object
  				s = jQuery.ajaxSetup( {}, options ),
  				// Callbacks context
  				callbackContext = s.context || s,
  				// Context for global events is callbackContext if it is a DOM node or jQuery collection
  				globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
  					jQuery( callbackContext ) :
  					jQuery.event,
  				// Deferreds
  				deferred = jQuery.Deferred(),
  				completeDeferred = jQuery.Callbacks("once memory"),
  				// Status-dependent callbacks
  				statusCode = s.statusCode || {},
  				// Headers (they are sent all at once)
  				requestHeaders = {},
  				requestHeadersNames = {},
  				// The jqXHR state
  				state = 0,
  				// Default abort message
  				strAbort = "canceled",
  				// Fake xhr
  				jqXHR = {
  					readyState: 0,
  	
  					// Builds headers hashtable if needed
  					getResponseHeader: function( key ) {
  						var match;
  						if ( state === 2 ) {
  							if ( !responseHeaders ) {
  								responseHeaders = {};
  								while ( (match = rheaders.exec( responseHeadersString )) ) {
  									responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
  								}
  							}
  							match = responseHeaders[ key.toLowerCase() ];
  						}
  						return match == null ? null : match;
  					},
  	
  					// Raw string
  					getAllResponseHeaders: function() {
  						return state === 2 ? responseHeadersString : null;
  					},
  	
  					// Caches the header
  					setRequestHeader: function( name, value ) {
  						var lname = name.toLowerCase();
  						if ( !state ) {
  							name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
  							requestHeaders[ name ] = value;
  						}
  						return this;
  					},
  	
  					// Overrides response content-type header
  					overrideMimeType: function( type ) {
  						if ( !state ) {
  							s.mimeType = type;
  						}
  						return this;
  					},
  	
  					// Status-dependent callbacks
  					statusCode: function( map ) {
  						var code;
  						if ( map ) {
  							if ( state < 2 ) {
  								for ( code in map ) {
  									// Lazy-add the new callback in a way that preserves old ones
  									statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
  								}
  							} else {
  								// Execute the appropriate callbacks
  								jqXHR.always( map[ jqXHR.status ] );
  							}
  						}
  						return this;
  					},
  	
  					// Cancel the request
  					abort: function( statusText ) {
  						var finalText = statusText || strAbort;
  						if ( transport ) {
  							transport.abort( finalText );
  						}
  						done( 0, finalText );
  						return this;
  					}
  				};
  	
  			// Attach deferreds
  			deferred.promise( jqXHR ).complete = completeDeferred.add;
  			jqXHR.success = jqXHR.done;
  			jqXHR.error = jqXHR.fail;
  	
  			// Remove hash character (#7531: and string promotion)
  			// Add protocol if not provided (prefilters might expect it)
  			// Handle falsy url in the settings object (#10093: consistency with old signature)
  			// We also use the url parameter if available
  			s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" )
  				.replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
  	
  			// Alias method option to type as per ticket #12004
  			s.type = options.method || options.type || s.method || s.type;
  	
  			// Extract dataTypes list
  			s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
  	
  			// A cross-domain request is in order when we have a protocol:host:port mismatch
  			if ( s.crossDomain == null ) {
  				parts = rurl.exec( s.url.toLowerCase() );
  				s.crossDomain = !!( parts &&
  					( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
  						( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
  							( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
  				);
  			}
  	
  			// Convert data if not already a string
  			if ( s.data && s.processData && typeof s.data !== "string" ) {
  				s.data = jQuery.param( s.data, s.traditional );
  			}
  	
  			// Apply prefilters
  			inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
  	
  			// If request was aborted inside a prefilter, stop there
  			if ( state === 2 ) {
  				return jqXHR;
  			}
  	
  			// We can fire global events as of now if asked to
  			// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
  			fireGlobals = jQuery.event && s.global;
  	
  			// Watch for a new set of requests
  			if ( fireGlobals && jQuery.active++ === 0 ) {
  				jQuery.event.trigger("ajaxStart");
  			}
  	
  			// Uppercase the type
  			s.type = s.type.toUpperCase();
  	
  			// Determine if request has content
  			s.hasContent = !rnoContent.test( s.type );
  	
  			// Save the URL in case we're toying with the If-Modified-Since
  			// and/or If-None-Match header later on
  			cacheURL = s.url;
  	
  			// More options handling for requests with no content
  			if ( !s.hasContent ) {
  	
  				// If data is available, append data to url
  				if ( s.data ) {
  					cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
  					// #9682: remove data so that it's not used in an eventual retry
  					delete s.data;
  				}
  	
  				// Add anti-cache in url if needed
  				if ( s.cache === false ) {
  					s.url = rts.test( cacheURL ) ?
  	
  						// If there is already a '_' parameter, set its value
  						cacheURL.replace( rts, "$1_=" + nonce++ ) :
  	
  						// Otherwise add one to the end
  						cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
  				}
  			}
  	
  			// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
  			if ( s.ifModified ) {
  				if ( jQuery.lastModified[ cacheURL ] ) {
  					jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
  				}
  				if ( jQuery.etag[ cacheURL ] ) {
  					jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
  				}
  			}
  	
  			// Set the correct header, if data is being sent
  			if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
  				jqXHR.setRequestHeader( "Content-Type", s.contentType );
  			}
  	
  			// Set the Accepts header for the server, depending on the dataType
  			jqXHR.setRequestHeader(
  				"Accept",
  				s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
  					s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
  					s.accepts[ "*" ]
  			);
  	
  			// Check for headers option
  			for ( i in s.headers ) {
  				jqXHR.setRequestHeader( i, s.headers[ i ] );
  			}
  	
  			// Allow custom headers/mimetypes and early abort
  			if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
  				// Abort if not done already and return
  				return jqXHR.abort();
  			}
  	
  			// Aborting is no longer a cancellation
  			strAbort = "abort";
  	
  			// Install callbacks on deferreds
  			for ( i in { success: 1, error: 1, complete: 1 } ) {
  				jqXHR[ i ]( s[ i ] );
  			}
  	
  			// Get transport
  			transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
  	
  			// If no transport, we auto-abort
  			if ( !transport ) {
  				done( -1, "No Transport" );
  			} else {
  				jqXHR.readyState = 1;
  	
  				// Send global event
  				if ( fireGlobals ) {
  					globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
  				}
  				// Timeout
  				if ( s.async && s.timeout > 0 ) {
  					timeoutTimer = setTimeout(function() {
  						jqXHR.abort("timeout");
  					}, s.timeout );
  				}
  	
  				try {
  					state = 1;
  					transport.send( requestHeaders, done );
  				} catch ( e ) {
  					// Propagate exception as error if not done
  					if ( state < 2 ) {
  						done( -1, e );
  					// Simply rethrow otherwise
  					} else {
  						throw e;
  					}
  				}
  			}
  	
  			// Callback for when everything is done
  			function done( status, nativeStatusText, responses, headers ) {
  				var isSuccess, success, error, response, modified,
  					statusText = nativeStatusText;
  	
  				// Called once
  				if ( state === 2 ) {
  					return;
  				}
  	
  				// State is "done" now
  				state = 2;
  	
  				// Clear timeout if it exists
  				if ( timeoutTimer ) {
  					clearTimeout( timeoutTimer );
  				}
  	
  				// Dereference transport for early garbage collection
  				// (no matter how long the jqXHR object will be used)
  				transport = undefined;
  	
  				// Cache response headers
  				responseHeadersString = headers || "";
  	
  				// Set readyState
  				jqXHR.readyState = status > 0 ? 4 : 0;
  	
  				// Determine if successful
  				isSuccess = status >= 200 && status < 300 || status === 304;
  	
  				// Get response data
  				if ( responses ) {
  					response = ajaxHandleResponses( s, jqXHR, responses );
  				}
  	
  				// Convert no matter what (that way responseXXX fields are always set)
  				response = ajaxConvert( s, response, jqXHR, isSuccess );
  	
  				// If successful, handle type chaining
  				if ( isSuccess ) {
  	
  					// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
  					if ( s.ifModified ) {
  						modified = jqXHR.getResponseHeader("Last-Modified");
  						if ( modified ) {
  							jQuery.lastModified[ cacheURL ] = modified;
  						}
  						modified = jqXHR.getResponseHeader("etag");
  						if ( modified ) {
  							jQuery.etag[ cacheURL ] = modified;
  						}
  					}
  	
  					// if no content
  					if ( status === 204 || s.type === "HEAD" ) {
  						statusText = "nocontent";
  	
  					// if not modified
  					} else if ( status === 304 ) {
  						statusText = "notmodified";
  	
  					// If we have data, let's convert it
  					} else {
  						statusText = response.state;
  						success = response.data;
  						error = response.error;
  						isSuccess = !error;
  					}
  				} else {
  					// Extract error from statusText and normalize for non-aborts
  					error = statusText;
  					if ( status || !statusText ) {
  						statusText = "error";
  						if ( status < 0 ) {
  							status = 0;
  						}
  					}
  				}
  	
  				// Set data for the fake xhr object
  				jqXHR.status = status;
  				jqXHR.statusText = ( nativeStatusText || statusText ) + "";
  	
  				// Success/Error
  				if ( isSuccess ) {
  					deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
  				} else {
  					deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
  				}
  	
  				// Status-dependent callbacks
  				jqXHR.statusCode( statusCode );
  				statusCode = undefined;
  	
  				if ( fireGlobals ) {
  					globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
  						[ jqXHR, s, isSuccess ? success : error ] );
  				}
  	
  				// Complete
  				completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
  	
  				if ( fireGlobals ) {
  					globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
  					// Handle the global AJAX counter
  					if ( !( --jQuery.active ) ) {
  						jQuery.event.trigger("ajaxStop");
  					}
  				}
  			}
  	
  			return jqXHR;
  		},
  	
  		getJSON: function( url, data, callback ) {
  			return jQuery.get( url, data, callback, "json" );
  		},
  	
  		getScript: function( url, callback ) {
  			return jQuery.get( url, undefined, callback, "script" );
  		}
  	});
  	
  	jQuery.each( [ "get", "post" ], function( i, method ) {
  		jQuery[ method ] = function( url, data, callback, type ) {
  			// Shift arguments if data argument was omitted
  			if ( jQuery.isFunction( data ) ) {
  				type = type || callback;
  				callback = data;
  				data = undefined;
  			}
  	
  			return jQuery.ajax({
  				url: url,
  				type: method,
  				dataType: type,
  				data: data,
  				success: callback
  			});
  		};
  	});
  	
  	
  	jQuery._evalUrl = function( url ) {
  		return jQuery.ajax({
  			url: url,
  			type: "GET",
  			dataType: "script",
  			async: false,
  			global: false,
  			"throws": true
  		});
  	};
  	
  	
  	jQuery.fn.extend({
  		wrapAll: function( html ) {
  			var wrap;
  	
  			if ( jQuery.isFunction( html ) ) {
  				return this.each(function( i ) {
  					jQuery( this ).wrapAll( html.call(this, i) );
  				});
  			}
  	
  			if ( this[ 0 ] ) {
  	
  				// The elements to wrap the target around
  				wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
  	
  				if ( this[ 0 ].parentNode ) {
  					wrap.insertBefore( this[ 0 ] );
  				}
  	
  				wrap.map(function() {
  					var elem = this;
  	
  					while ( elem.firstElementChild ) {
  						elem = elem.firstElementChild;
  					}
  	
  					return elem;
  				}).append( this );
  			}
  	
  			return this;
  		},
  	
  		wrapInner: function( html ) {
  			if ( jQuery.isFunction( html ) ) {
  				return this.each(function( i ) {
  					jQuery( this ).wrapInner( html.call(this, i) );
  				});
  			}
  	
  			return this.each(function() {
  				var self = jQuery( this ),
  					contents = self.contents();
  	
  				if ( contents.length ) {
  					contents.wrapAll( html );
  	
  				} else {
  					self.append( html );
  				}
  			});
  		},
  	
  		wrap: function( html ) {
  			var isFunction = jQuery.isFunction( html );
  	
  			return this.each(function( i ) {
  				jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
  			});
  		},
  	
  		unwrap: function() {
  			return this.parent().each(function() {
  				if ( !jQuery.nodeName( this, "body" ) ) {
  					jQuery( this ).replaceWith( this.childNodes );
  				}
  			}).end();
  		}
  	});
  	
  	
  	jQuery.expr.filters.hidden = function( elem ) {
  		// Support: Opera <= 12.12
  		// Opera reports offsetWidths and offsetHeights less than zero on some elements
  		return elem.offsetWidth <= 0 && elem.offsetHeight <= 0;
  	};
  	jQuery.expr.filters.visible = function( elem ) {
  		return !jQuery.expr.filters.hidden( elem );
  	};
  	
  	
  	
  	
  	var r20 = /%20/g,
  		rbracket = /\[\]$/,
  		rCRLF = /\r?\n/g,
  		rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
  		rsubmittable = /^(?:input|select|textarea|keygen)/i;
  	
  	function buildParams( prefix, obj, traditional, add ) {
  		var name;
  	
  		if ( jQuery.isArray( obj ) ) {
  			// Serialize array item.
  			jQuery.each( obj, function( i, v ) {
  				if ( traditional || rbracket.test( prefix ) ) {
  					// Treat each array item as a scalar.
  					add( prefix, v );
  	
  				} else {
  					// Item is non-scalar (array or object), encode its numeric index.
  					buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
  				}
  			});
  	
  		} else if ( !traditional && jQuery.type( obj ) === "object" ) {
  			// Serialize object item.
  			for ( name in obj ) {
  				buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
  			}
  	
  		} else {
  			// Serialize scalar item.
  			add( prefix, obj );
  		}
  	}
  	
  	// Serialize an array of form elements or a set of
  	// key/values into a query string
  	jQuery.param = function( a, traditional ) {
  		var prefix,
  			s = [],
  			add = function( key, value ) {
  				// If value is a function, invoke it and return its value
  				value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
  				s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
  			};
  	
  		// Set traditional to true for jQuery <= 1.3.2 behavior.
  		if ( traditional === undefined ) {
  			traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
  		}
  	
  		// If an array was passed in, assume that it is an array of form elements.
  		if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
  			// Serialize the form elements
  			jQuery.each( a, function() {
  				add( this.name, this.value );
  			});
  	
  		} else {
  			// If traditional, encode the "old" way (the way 1.3.2 or older
  			// did it), otherwise encode params recursively.
  			for ( prefix in a ) {
  				buildParams( prefix, a[ prefix ], traditional, add );
  			}
  		}
  	
  		// Return the resulting serialization
  		return s.join( "&" ).replace( r20, "+" );
  	};
  	
  	jQuery.fn.extend({
  		serialize: function() {
  			return jQuery.param( this.serializeArray() );
  		},
  		serializeArray: function() {
  			return this.map(function() {
  				// Can add propHook for "elements" to filter or add form elements
  				var elements = jQuery.prop( this, "elements" );
  				return elements ? jQuery.makeArray( elements ) : this;
  			})
  			.filter(function() {
  				var type = this.type;
  	
  				// Use .is( ":disabled" ) so that fieldset[disabled] works
  				return this.name && !jQuery( this ).is( ":disabled" ) &&
  					rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
  					( this.checked || !rcheckableType.test( type ) );
  			})
  			.map(function( i, elem ) {
  				var val = jQuery( this ).val();
  	
  				return val == null ?
  					null :
  					jQuery.isArray( val ) ?
  						jQuery.map( val, function( val ) {
  							return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
  						}) :
  						{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
  			}).get();
  		}
  	});
  	
  	
  	jQuery.ajaxSettings.xhr = function() {
  		try {
  			return new XMLHttpRequest();
  		} catch( e ) {}
  	};
  	
  	var xhrId = 0,
  		xhrCallbacks = {},
  		xhrSuccessStatus = {
  			// file protocol always yields status code 0, assume 200
  			0: 200,
  			// Support: IE9
  			// #1450: sometimes IE returns 1223 when it should be 204
  			1223: 204
  		},
  		xhrSupported = jQuery.ajaxSettings.xhr();
  	
  	// Support: IE9
  	// Open requests must be manually aborted on unload (#5280)
  	// See https://support.microsoft.com/kb/2856746 for more info
  	if ( window.attachEvent ) {
  		window.attachEvent( "onunload", function() {
  			for ( var key in xhrCallbacks ) {
  				xhrCallbacks[ key ]();
  			}
  		});
  	}
  	
  	support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
  	support.ajax = xhrSupported = !!xhrSupported;
  	
  	jQuery.ajaxTransport(function( options ) {
  		var callback;
  	
  		// Cross domain only allowed if supported through XMLHttpRequest
  		if ( support.cors || xhrSupported && !options.crossDomain ) {
  			return {
  				send: function( headers, complete ) {
  					var i,
  						xhr = options.xhr(),
  						id = ++xhrId;
  	
  					xhr.open( options.type, options.url, options.async, options.username, options.password );
  	
  					// Apply custom fields if provided
  					if ( options.xhrFields ) {
  						for ( i in options.xhrFields ) {
  							xhr[ i ] = options.xhrFields[ i ];
  						}
  					}
  	
  					// Override mime type if needed
  					if ( options.mimeType && xhr.overrideMimeType ) {
  						xhr.overrideMimeType( options.mimeType );
  					}
  	
  					// X-Requested-With header
  					// For cross-domain requests, seeing as conditions for a preflight are
  					// akin to a jigsaw puzzle, we simply never set it to be sure.
  					// (it can always be set on a per-request basis or even using ajaxSetup)
  					// For same-domain requests, won't change header if already provided.
  					if ( !options.crossDomain && !headers["X-Requested-With"] ) {
  						headers["X-Requested-With"] = "XMLHttpRequest";
  					}
  	
  					// Set headers
  					for ( i in headers ) {
  						xhr.setRequestHeader( i, headers[ i ] );
  					}
  	
  					// Callback
  					callback = function( type ) {
  						return function() {
  							if ( callback ) {
  								delete xhrCallbacks[ id ];
  								callback = xhr.onload = xhr.onerror = null;
  	
  								if ( type === "abort" ) {
  									xhr.abort();
  								} else if ( type === "error" ) {
  									complete(
  										// file: protocol always yields status 0; see #8605, #14207
  										xhr.status,
  										xhr.statusText
  									);
  								} else {
  									complete(
  										xhrSuccessStatus[ xhr.status ] || xhr.status,
  										xhr.statusText,
  										// Support: IE9
  										// Accessing binary-data responseText throws an exception
  										// (#11426)
  										typeof xhr.responseText === "string" ? {
  											text: xhr.responseText
  										} : undefined,
  										xhr.getAllResponseHeaders()
  									);
  								}
  							}
  						};
  					};
  	
  					// Listen to events
  					xhr.onload = callback();
  					xhr.onerror = callback("error");
  	
  					// Create the abort callback
  					callback = xhrCallbacks[ id ] = callback("abort");
  	
  					try {
  						// Do send the request (this may raise an exception)
  						xhr.send( options.hasContent && options.data || null );
  					} catch ( e ) {
  						// #14683: Only rethrow if this hasn't been notified as an error yet
  						if ( callback ) {
  							throw e;
  						}
  					}
  				},
  	
  				abort: function() {
  					if ( callback ) {
  						callback();
  					}
  				}
  			};
  		}
  	});
  	
  	
  	
  	
  	// Install script dataType
  	jQuery.ajaxSetup({
  		accepts: {
  			script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
  		},
  		contents: {
  			script: /(?:java|ecma)script/
  		},
  		converters: {
  			"text script": function( text ) {
  				jQuery.globalEval( text );
  				return text;
  			}
  		}
  	});
  	
  	// Handle cache's special case and crossDomain
  	jQuery.ajaxPrefilter( "script", function( s ) {
  		if ( s.cache === undefined ) {
  			s.cache = false;
  		}
  		if ( s.crossDomain ) {
  			s.type = "GET";
  		}
  	});
  	
  	// Bind script tag hack transport
  	jQuery.ajaxTransport( "script", function( s ) {
  		// This transport only deals with cross domain requests
  		if ( s.crossDomain ) {
  			var script, callback;
  			return {
  				send: function( _, complete ) {
  					script = jQuery("<script>").prop({
  						async: true,
  						charset: s.scriptCharset,
  						src: s.url
  					}).on(
  						"load error",
  						callback = function( evt ) {
  							script.remove();
  							callback = null;
  							if ( evt ) {
  								complete( evt.type === "error" ? 404 : 200, evt.type );
  							}
  						}
  					);
  					document.head.appendChild( script[ 0 ] );
  				},
  				abort: function() {
  					if ( callback ) {
  						callback();
  					}
  				}
  			};
  		}
  	});
  	
  	
  	
  	
  	var oldCallbacks = [],
  		rjsonp = /(=)\?(?=&|$)|\?\?/;
  	
  	// Default jsonp settings
  	jQuery.ajaxSetup({
  		jsonp: "callback",
  		jsonpCallback: function() {
  			var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
  			this[ callback ] = true;
  			return callback;
  		}
  	});
  	
  	// Detect, normalize options and install callbacks for jsonp requests
  	jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
  	
  		var callbackName, overwritten, responseContainer,
  			jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
  				"url" :
  				typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
  			);
  	
  		// Handle iff the expected data type is "jsonp" or we have a parameter to set
  		if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
  	
  			// Get callback name, remembering preexisting value associated with it
  			callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
  				s.jsonpCallback() :
  				s.jsonpCallback;
  	
  			// Insert callback into url or form data
  			if ( jsonProp ) {
  				s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
  			} else if ( s.jsonp !== false ) {
  				s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
  			}
  	
  			// Use data converter to retrieve json after script execution
  			s.converters["script json"] = function() {
  				if ( !responseContainer ) {
  					jQuery.error( callbackName + " was not called" );
  				}
  				return responseContainer[ 0 ];
  			};
  	
  			// force json dataType
  			s.dataTypes[ 0 ] = "json";
  	
  			// Install callback
  			overwritten = window[ callbackName ];
  			window[ callbackName ] = function() {
  				responseContainer = arguments;
  			};
  	
  			// Clean-up function (fires after converters)
  			jqXHR.always(function() {
  				// Restore preexisting value
  				window[ callbackName ] = overwritten;
  	
  				// Save back as free
  				if ( s[ callbackName ] ) {
  					// make sure that re-using the options doesn't screw things around
  					s.jsonpCallback = originalSettings.jsonpCallback;
  	
  					// save the callback name for future use
  					oldCallbacks.push( callbackName );
  				}
  	
  				// Call if it was a function and we have a response
  				if ( responseContainer && jQuery.isFunction( overwritten ) ) {
  					overwritten( responseContainer[ 0 ] );
  				}
  	
  				responseContainer = overwritten = undefined;
  			});
  	
  			// Delegate to script
  			return "script";
  		}
  	});
  	
  	
  	
  	
  	// data: string of html
  	// context (optional): If specified, the fragment will be created in this context, defaults to document
  	// keepScripts (optional): If true, will include scripts passed in the html string
  	jQuery.parseHTML = function( data, context, keepScripts ) {
  		if ( !data || typeof data !== "string" ) {
  			return null;
  		}
  		if ( typeof context === "boolean" ) {
  			keepScripts = context;
  			context = false;
  		}
  		context = context || document;
  	
  		var parsed = rsingleTag.exec( data ),
  			scripts = !keepScripts && [];
  	
  		// Single tag
  		if ( parsed ) {
  			return [ context.createElement( parsed[1] ) ];
  		}
  	
  		parsed = jQuery.buildFragment( [ data ], context, scripts );
  	
  		if ( scripts && scripts.length ) {
  			jQuery( scripts ).remove();
  		}
  	
  		return jQuery.merge( [], parsed.childNodes );
  	};
  	
  	
  	// Keep a copy of the old load method
  	var _load = jQuery.fn.load;
  	
  	/**
  	 * Load a url into a page
  	 */
  	jQuery.fn.load = function( url, params, callback ) {
  		if ( typeof url !== "string" && _load ) {
  			return _load.apply( this, arguments );
  		}
  	
  		var selector, type, response,
  			self = this,
  			off = url.indexOf(" ");
  	
  		if ( off >= 0 ) {
  			selector = jQuery.trim( url.slice( off ) );
  			url = url.slice( 0, off );
  		}
  	
  		// If it's a function
  		if ( jQuery.isFunction( params ) ) {
  	
  			// We assume that it's the callback
  			callback = params;
  			params = undefined;
  	
  		// Otherwise, build a param string
  		} else if ( params && typeof params === "object" ) {
  			type = "POST";
  		}
  	
  		// If we have elements to modify, make the request
  		if ( self.length > 0 ) {
  			jQuery.ajax({
  				url: url,
  	
  				// if "type" variable is undefined, then "GET" method will be used
  				type: type,
  				dataType: "html",
  				data: params
  			}).done(function( responseText ) {
  	
  				// Save response for use in complete callback
  				response = arguments;
  	
  				self.html( selector ?
  	
  					// If a selector was specified, locate the right elements in a dummy div
  					// Exclude scripts to avoid IE 'Permission Denied' errors
  					jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
  	
  					// Otherwise use the full result
  					responseText );
  	
  			}).complete( callback && function( jqXHR, status ) {
  				self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
  			});
  		}
  	
  		return this;
  	};
  	
  	
  	
  	
  	// Attach a bunch of functions for handling common AJAX events
  	jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) {
  		jQuery.fn[ type ] = function( fn ) {
  			return this.on( type, fn );
  		};
  	});
  	
  	
  	
  	
  	jQuery.expr.filters.animated = function( elem ) {
  		return jQuery.grep(jQuery.timers, function( fn ) {
  			return elem === fn.elem;
  		}).length;
  	};
  	
  	
  	
  	
  	var docElem = window.document.documentElement;
  	
  	/**
  	 * Gets a window from an element
  	 */
  	function getWindow( elem ) {
  		return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;
  	}
  	
  	jQuery.offset = {
  		setOffset: function( elem, options, i ) {
  			var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
  				position = jQuery.css( elem, "position" ),
  				curElem = jQuery( elem ),
  				props = {};
  	
  			// Set position first, in-case top/left are set even on static elem
  			if ( position === "static" ) {
  				elem.style.position = "relative";
  			}
  	
  			curOffset = curElem.offset();
  			curCSSTop = jQuery.css( elem, "top" );
  			curCSSLeft = jQuery.css( elem, "left" );
  			calculatePosition = ( position === "absolute" || position === "fixed" ) &&
  				( curCSSTop + curCSSLeft ).indexOf("auto") > -1;
  	
  			// Need to be able to calculate position if either
  			// top or left is auto and position is either absolute or fixed
  			if ( calculatePosition ) {
  				curPosition = curElem.position();
  				curTop = curPosition.top;
  				curLeft = curPosition.left;
  	
  			} else {
  				curTop = parseFloat( curCSSTop ) || 0;
  				curLeft = parseFloat( curCSSLeft ) || 0;
  			}
  	
  			if ( jQuery.isFunction( options ) ) {
  				options = options.call( elem, i, curOffset );
  			}
  	
  			if ( options.top != null ) {
  				props.top = ( options.top - curOffset.top ) + curTop;
  			}
  			if ( options.left != null ) {
  				props.left = ( options.left - curOffset.left ) + curLeft;
  			}
  	
  			if ( "using" in options ) {
  				options.using.call( elem, props );
  	
  			} else {
  				curElem.css( props );
  			}
  		}
  	};
  	
  	jQuery.fn.extend({
  		offset: function( options ) {
  			if ( arguments.length ) {
  				return options === undefined ?
  					this :
  					this.each(function( i ) {
  						jQuery.offset.setOffset( this, options, i );
  					});
  			}
  	
  			var docElem, win,
  				elem = this[ 0 ],
  				box = { top: 0, left: 0 },
  				doc = elem && elem.ownerDocument;
  	
  			if ( !doc ) {
  				return;
  			}
  	
  			docElem = doc.documentElement;
  	
  			// Make sure it's not a disconnected DOM node
  			if ( !jQuery.contains( docElem, elem ) ) {
  				return box;
  			}
  	
  			// Support: BlackBerry 5, iOS 3 (original iPhone)
  			// If we don't have gBCR, just use 0,0 rather than error
  			if ( typeof elem.getBoundingClientRect !== strundefined ) {
  				box = elem.getBoundingClientRect();
  			}
  			win = getWindow( doc );
  			return {
  				top: box.top + win.pageYOffset - docElem.clientTop,
  				left: box.left + win.pageXOffset - docElem.clientLeft
  			};
  		},
  	
  		position: function() {
  			if ( !this[ 0 ] ) {
  				return;
  			}
  	
  			var offsetParent, offset,
  				elem = this[ 0 ],
  				parentOffset = { top: 0, left: 0 };
  	
  			// Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
  			if ( jQuery.css( elem, "position" ) === "fixed" ) {
  				// Assume getBoundingClientRect is there when computed position is fixed
  				offset = elem.getBoundingClientRect();
  	
  			} else {
  				// Get *real* offsetParent
  				offsetParent = this.offsetParent();
  	
  				// Get correct offsets
  				offset = this.offset();
  				if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
  					parentOffset = offsetParent.offset();
  				}
  	
  				// Add offsetParent borders
  				parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
  				parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
  			}
  	
  			// Subtract parent offsets and element margins
  			return {
  				top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
  				left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
  			};
  		},
  	
  		offsetParent: function() {
  			return this.map(function() {
  				var offsetParent = this.offsetParent || docElem;
  	
  				while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) {
  					offsetParent = offsetParent.offsetParent;
  				}
  	
  				return offsetParent || docElem;
  			});
  		}
  	});
  	
  	// Create scrollLeft and scrollTop methods
  	jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
  		var top = "pageYOffset" === prop;
  	
  		jQuery.fn[ method ] = function( val ) {
  			return access( this, function( elem, method, val ) {
  				var win = getWindow( elem );
  	
  				if ( val === undefined ) {
  					return win ? win[ prop ] : elem[ method ];
  				}
  	
  				if ( win ) {
  					win.scrollTo(
  						!top ? val : window.pageXOffset,
  						top ? val : window.pageYOffset
  					);
  	
  				} else {
  					elem[ method ] = val;
  				}
  			}, method, val, arguments.length, null );
  		};
  	});
  	
  	// Support: Safari<7+, Chrome<37+
  	// Add the top/left cssHooks using jQuery.fn.position
  	// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
  	// Blink bug: https://code.google.com/p/chromium/issues/detail?id=229280
  	// getComputedStyle returns percent when specified for top/left/bottom/right;
  	// rather than make the css module depend on the offset module, just check for it here
  	jQuery.each( [ "top", "left" ], function( i, prop ) {
  		jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
  			function( elem, computed ) {
  				if ( computed ) {
  					computed = curCSS( elem, prop );
  					// If curCSS returns percentage, fallback to offset
  					return rnumnonpx.test( computed ) ?
  						jQuery( elem ).position()[ prop ] + "px" :
  						computed;
  				}
  			}
  		);
  	});
  	
  	
  	// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
  	jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
  		jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
  			// Margin is only for outerHeight, outerWidth
  			jQuery.fn[ funcName ] = function( margin, value ) {
  				var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
  					extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
  	
  				return access( this, function( elem, type, value ) {
  					var doc;
  	
  					if ( jQuery.isWindow( elem ) ) {
  						// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
  						// isn't a whole lot we can do. See pull request at this URL for discussion:
  						// https://github.com/jquery/jquery/pull/764
  						return elem.document.documentElement[ "client" + name ];
  					}
  	
  					// Get document width or height
  					if ( elem.nodeType === 9 ) {
  						doc = elem.documentElement;
  	
  						// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
  						// whichever is greatest
  						return Math.max(
  							elem.body[ "scroll" + name ], doc[ "scroll" + name ],
  							elem.body[ "offset" + name ], doc[ "offset" + name ],
  							doc[ "client" + name ]
  						);
  					}
  	
  					return value === undefined ?
  						// Get width or height on the element, requesting but not forcing parseFloat
  						jQuery.css( elem, type, extra ) :
  	
  						// Set width or height on the element
  						jQuery.style( elem, type, value, extra );
  				}, type, chainable ? margin : undefined, chainable, null );
  			};
  		});
  	});
  	
  	
  	// The number of elements contained in the matched element set
  	jQuery.fn.size = function() {
  		return this.length;
  	};
  	
  	jQuery.fn.andSelf = jQuery.fn.addBack;
  	
  	
  	
  	
  	// Register as a named AMD module, since jQuery can be concatenated with other
  	// files that may use define, but not via a proper concatenation script that
  	// understands anonymous AMD modules. A named AMD is safest and most robust
  	// way to register. Lowercase jquery is used because AMD module names are
  	// derived from file names, and jQuery is normally delivered in a lowercase
  	// file name. Do this after creating the global so that if an AMD module wants
  	// to call noConflict to hide this version of jQuery, it will work.
  	
  	// Note that for maximum portability, libraries that are not jQuery should
  	// declare themselves as anonymous modules, and avoid setting a global if an
  	// AMD loader is present. jQuery is a special case. For more information, see
  	// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
  	
  	if ( true ) {
  		!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = function() {
  			return jQuery;
  		}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
  	}
  	
  	
  	
  	
  	var
  		// Map over jQuery in case of overwrite
  		_jQuery = window.jQuery,
  	
  		// Map over the $ in case of overwrite
  		_$ = window.$;
  	
  	jQuery.noConflict = function( deep ) {
  		if ( window.$ === jQuery ) {
  			window.$ = _$;
  		}
  	
  		if ( deep && window.jQuery === jQuery ) {
  			window.jQuery = _jQuery;
  		}
  	
  		return jQuery;
  	};
  	
  	// Expose jQuery and $ identifiers, even in AMD
  	// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
  	// and CommonJS for browser emulators (#13566)
  	if ( typeof noGlobal === strundefined ) {
  		window.jQuery = window.$ = jQuery;
  	}
  	
  	
  	
  	
  	return jQuery;
  	
  	}));
  
  
  /***/ }
  /******/ ]);
  //# sourceMappingURL=dragdrop.js.map