├── .gitignore ├── README.md ├── lib ├── chai.js ├── expect.js ├── jquery.js ├── mocha.css ├── mocha.js ├── picomodal.js ├── sinon.js ├── spec.js ├── tweetit.js └── underscore-min.js ├── spec-runner.html └── src.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cryptocurrency 2 | Create your own Cryptocurrency! 3 | 4 | http://www.michaelnielsen.org/ddi/how-the-bitcoin-protocol-actually-works/ 5 | -------------------------------------------------------------------------------- /lib/expect.js: -------------------------------------------------------------------------------- 1 | 2 | (function (global, module) { 3 | 4 | if ('undefined' == typeof module) { 5 | var module = { exports: {} } 6 | , exports = module.exports 7 | } 8 | 9 | /** 10 | * Exports. 11 | */ 12 | 13 | module.exports = expect; 14 | expect.Assertion = Assertion; 15 | 16 | /** 17 | * Exports version. 18 | */ 19 | 20 | expect.version = '0.1.2'; 21 | 22 | /** 23 | * Possible assertion flags. 24 | */ 25 | 26 | var flags = { 27 | not: ['to', 'be', 'have', 'include', 'only'] 28 | , to: ['be', 'have', 'include', 'only', 'not'] 29 | , only: ['have'] 30 | , have: ['own'] 31 | , be: ['an'] 32 | }; 33 | 34 | function expect (obj) { 35 | return new Assertion(obj); 36 | } 37 | 38 | /** 39 | * Constructor 40 | * 41 | * @api private 42 | */ 43 | 44 | function Assertion (obj, flag, parent) { 45 | this.obj = obj; 46 | this.flags = {}; 47 | 48 | if (undefined != parent) { 49 | this.flags[flag] = true; 50 | 51 | for (var i in parent.flags) { 52 | if (parent.flags.hasOwnProperty(i)) { 53 | this.flags[i] = true; 54 | } 55 | } 56 | } 57 | 58 | var $flags = flag ? flags[flag] : keys(flags) 59 | , self = this 60 | 61 | if ($flags) { 62 | for (var i = 0, l = $flags.length; i < l; i++) { 63 | // avoid recursion 64 | if (this.flags[$flags[i]]) continue; 65 | 66 | var name = $flags[i] 67 | , assertion = new Assertion(this.obj, name, this) 68 | 69 | if ('function' == typeof Assertion.prototype[name]) { 70 | // clone the function, make sure we dont touch the prot reference 71 | var old = this[name]; 72 | this[name] = function () { 73 | return old.apply(self, arguments); 74 | } 75 | 76 | for (var fn in Assertion.prototype) { 77 | if (Assertion.prototype.hasOwnProperty(fn) && fn != name) { 78 | this[name][fn] = bind(assertion[fn], assertion); 79 | } 80 | } 81 | } else { 82 | this[name] = assertion; 83 | } 84 | } 85 | } 86 | }; 87 | 88 | /** 89 | * Performs an assertion 90 | * 91 | * @api private 92 | */ 93 | 94 | Assertion.prototype.assert = function (truth, msg, error) { 95 | var msg = this.flags.not ? error : msg 96 | , ok = this.flags.not ? !truth : truth; 97 | 98 | if (!ok) { 99 | throw new Error(msg.call(this)); 100 | } 101 | 102 | this.and = new Assertion(this.obj); 103 | }; 104 | 105 | /** 106 | * Check if the value is truthy 107 | * 108 | * @api public 109 | */ 110 | 111 | Assertion.prototype.ok = function () { 112 | this.assert( 113 | !!this.obj 114 | , function(){ return 'expected ' + i(this.obj) + ' to be truthy' } 115 | , function(){ return 'expected ' + i(this.obj) + ' to be falsy' }); 116 | }; 117 | 118 | /** 119 | * Assert that the function throws. 120 | * 121 | * @param {Function|RegExp} callback, or regexp to match error string against 122 | * @api public 123 | */ 124 | 125 | Assertion.prototype.throwError = 126 | Assertion.prototype.throwException = function (fn) { 127 | expect(this.obj).to.be.a('function'); 128 | 129 | var thrown = false 130 | , not = this.flags.not 131 | 132 | try { 133 | this.obj(); 134 | } catch (e) { 135 | if ('function' == typeof fn) { 136 | fn(e); 137 | } else if ('object' == typeof fn) { 138 | var subject = 'string' == typeof e ? e : e.message; 139 | if (not) { 140 | expect(subject).to.not.match(fn); 141 | } else { 142 | expect(subject).to.match(fn); 143 | } 144 | } 145 | thrown = true; 146 | } 147 | 148 | if ('object' == typeof fn && not) { 149 | // in the presence of a matcher, ensure the `not` only applies to 150 | // the matching. 151 | this.flags.not = false; 152 | } 153 | 154 | var name = this.obj.name || 'fn'; 155 | this.assert( 156 | thrown 157 | , function(){ return 'expected ' + name + ' to throw an exception' } 158 | , function(){ return 'expected ' + name + ' not to throw an exception' }); 159 | }; 160 | 161 | /** 162 | * Checks if the array is empty. 163 | * 164 | * @api public 165 | */ 166 | 167 | Assertion.prototype.empty = function () { 168 | var expectation; 169 | 170 | if ('object' == typeof this.obj && null !== this.obj && !isArray(this.obj)) { 171 | if ('number' == typeof this.obj.length) { 172 | expectation = !this.obj.length; 173 | } else { 174 | expectation = !keys(this.obj).length; 175 | } 176 | } else { 177 | if ('string' != typeof this.obj) { 178 | expect(this.obj).to.be.an('object'); 179 | } 180 | 181 | expect(this.obj).to.have.property('length'); 182 | expectation = !this.obj.length; 183 | } 184 | 185 | this.assert( 186 | expectation 187 | , function(){ return 'expected ' + i(this.obj) + ' to be empty' } 188 | , function(){ return 'expected ' + i(this.obj) + ' to not be empty' }); 189 | return this; 190 | }; 191 | 192 | /** 193 | * Checks if the obj exactly equals another. 194 | * 195 | * @api public 196 | */ 197 | 198 | Assertion.prototype.be = 199 | Assertion.prototype.equal = function (obj) { 200 | this.assert( 201 | obj === this.obj 202 | , function(){ return 'expected ' + i(this.obj) + ' to equal ' + i(obj) } 203 | , function(){ return 'expected ' + i(this.obj) + ' to not equal ' + i(obj) }); 204 | return this; 205 | }; 206 | 207 | /** 208 | * Checks if the obj sortof equals another. 209 | * 210 | * @api public 211 | */ 212 | 213 | Assertion.prototype.eql = function (obj) { 214 | this.assert( 215 | expect.eql(obj, this.obj) 216 | , function(){ return 'expected ' + i(this.obj) + ' to sort of equal ' + i(obj) } 217 | , function(){ return 'expected ' + i(this.obj) + ' to sort of not equal ' + i(obj) }); 218 | return this; 219 | }; 220 | 221 | /** 222 | * Assert within start to finish (inclusive). 223 | * 224 | * @param {Number} start 225 | * @param {Number} finish 226 | * @api public 227 | */ 228 | 229 | Assertion.prototype.within = function (start, finish) { 230 | var range = start + '..' + finish; 231 | this.assert( 232 | this.obj >= start && this.obj <= finish 233 | , function(){ return 'expected ' + i(this.obj) + ' to be within ' + range } 234 | , function(){ return 'expected ' + i(this.obj) + ' to not be within ' + range }); 235 | return this; 236 | }; 237 | 238 | /** 239 | * Assert typeof / instance of 240 | * 241 | * @api public 242 | */ 243 | 244 | Assertion.prototype.a = 245 | Assertion.prototype.an = function (type) { 246 | if ('string' == typeof type) { 247 | // proper english in error msg 248 | var n = /^[aeiou]/.test(type) ? 'n' : ''; 249 | 250 | // typeof with support for 'array' 251 | this.assert( 252 | 'array' == type ? isArray(this.obj) : 253 | 'object' == type 254 | ? 'object' == typeof this.obj && null !== this.obj 255 | : type == typeof this.obj 256 | , function(){ return 'expected ' + i(this.obj) + ' to be a' + n + ' ' + type } 257 | , function(){ return 'expected ' + i(this.obj) + ' not to be a' + n + ' ' + type }); 258 | } else { 259 | // instanceof 260 | var name = type.name || 'supplied constructor'; 261 | this.assert( 262 | this.obj instanceof type 263 | , function(){ return 'expected ' + i(this.obj) + ' to be an instance of ' + name } 264 | , function(){ return 'expected ' + i(this.obj) + ' not to be an instance of ' + name }); 265 | } 266 | 267 | return this; 268 | }; 269 | 270 | /** 271 | * Assert numeric value above _n_. 272 | * 273 | * @param {Number} n 274 | * @api public 275 | */ 276 | 277 | Assertion.prototype.greaterThan = 278 | Assertion.prototype.above = function (n) { 279 | this.assert( 280 | this.obj > n 281 | , function(){ return 'expected ' + i(this.obj) + ' to be above ' + n } 282 | , function(){ return 'expected ' + i(this.obj) + ' to be below ' + n }); 283 | return this; 284 | }; 285 | 286 | /** 287 | * Assert numeric value below _n_. 288 | * 289 | * @param {Number} n 290 | * @api public 291 | */ 292 | 293 | Assertion.prototype.lessThan = 294 | Assertion.prototype.below = function (n) { 295 | this.assert( 296 | this.obj < n 297 | , function(){ return 'expected ' + i(this.obj) + ' to be below ' + n } 298 | , function(){ return 'expected ' + i(this.obj) + ' to be above ' + n }); 299 | return this; 300 | }; 301 | 302 | /** 303 | * Assert string value matches _regexp_. 304 | * 305 | * @param {RegExp} regexp 306 | * @api public 307 | */ 308 | 309 | Assertion.prototype.match = function (regexp) { 310 | this.assert( 311 | regexp.exec(this.obj) 312 | , function(){ return 'expected ' + i(this.obj) + ' to match ' + regexp } 313 | , function(){ return 'expected ' + i(this.obj) + ' not to match ' + regexp }); 314 | return this; 315 | }; 316 | 317 | /** 318 | * Assert property "length" exists and has value of _n_. 319 | * 320 | * @param {Number} n 321 | * @api public 322 | */ 323 | 324 | Assertion.prototype.length = function (n) { 325 | expect(this.obj).to.have.property('length'); 326 | var len = this.obj.length; 327 | this.assert( 328 | n == len 329 | , function(){ return 'expected ' + i(this.obj) + ' to have a length of ' + n + ' but got ' + len } 330 | , function(){ return 'expected ' + i(this.obj) + ' to not have a length of ' + len }); 331 | return this; 332 | }; 333 | 334 | /** 335 | * Assert property _name_ exists, with optional _val_. 336 | * 337 | * @param {String} name 338 | * @param {Mixed} val 339 | * @api public 340 | */ 341 | 342 | Assertion.prototype.property = function (name, val) { 343 | if (this.flags.own) { 344 | this.assert( 345 | Object.prototype.hasOwnProperty.call(this.obj, name) 346 | , function(){ return 'expected ' + i(this.obj) + ' to have own property ' + i(name) } 347 | , function(){ return 'expected ' + i(this.obj) + ' to not have own property ' + i(name) }); 348 | return this; 349 | } 350 | 351 | if (this.flags.not && undefined !== val) { 352 | if (undefined === this.obj[name]) { 353 | throw new Error(i(this.obj) + ' has no property ' + i(name)); 354 | } 355 | } else { 356 | var hasProp; 357 | try { 358 | hasProp = name in this.obj 359 | } catch (e) { 360 | hasProp = undefined !== this.obj[name] 361 | } 362 | 363 | this.assert( 364 | hasProp 365 | , function(){ return 'expected ' + i(this.obj) + ' to have a property ' + i(name) } 366 | , function(){ return 'expected ' + i(this.obj) + ' to not have a property ' + i(name) }); 367 | } 368 | 369 | if (undefined !== val) { 370 | this.assert( 371 | val === this.obj[name] 372 | , function(){ return 'expected ' + i(this.obj) + ' to have a property ' + i(name) 373 | + ' of ' + i(val) + ', but got ' + i(this.obj[name]) } 374 | , function(){ return 'expected ' + i(this.obj) + ' to not have a property ' + i(name) 375 | + ' of ' + i(val) }); 376 | } 377 | 378 | this.obj = this.obj[name]; 379 | return this; 380 | }; 381 | 382 | /** 383 | * Assert that the array contains _obj_ or string contains _obj_. 384 | * 385 | * @param {Mixed} obj|string 386 | * @api public 387 | */ 388 | 389 | Assertion.prototype.string = 390 | Assertion.prototype.contain = function (obj) { 391 | if ('string' == typeof this.obj) { 392 | this.assert( 393 | ~this.obj.indexOf(obj) 394 | , function(){ return 'expected ' + i(this.obj) + ' to contain ' + i(obj) } 395 | , function(){ return 'expected ' + i(this.obj) + ' to not contain ' + i(obj) }); 396 | } else { 397 | this.assert( 398 | ~indexOf(this.obj, obj) 399 | , function(){ return 'expected ' + i(this.obj) + ' to contain ' + i(obj) } 400 | , function(){ return 'expected ' + i(this.obj) + ' to not contain ' + i(obj) }); 401 | } 402 | return this; 403 | }; 404 | 405 | /** 406 | * Assert exact keys or inclusion of keys by using 407 | * the `.own` modifier. 408 | * 409 | * @param {Array|String ...} keys 410 | * @api public 411 | */ 412 | 413 | Assertion.prototype.key = 414 | Assertion.prototype.keys = function ($keys) { 415 | var str 416 | , ok = true; 417 | 418 | $keys = isArray($keys) 419 | ? $keys 420 | : Array.prototype.slice.call(arguments); 421 | 422 | if (!$keys.length) throw new Error('keys required'); 423 | 424 | var actual = keys(this.obj) 425 | , len = $keys.length; 426 | 427 | // Inclusion 428 | ok = every($keys, function (key) { 429 | return ~indexOf(actual, key); 430 | }); 431 | 432 | // Strict 433 | if (!this.flags.not && this.flags.only) { 434 | ok = ok && $keys.length == actual.length; 435 | } 436 | 437 | // Key string 438 | if (len > 1) { 439 | $keys = map($keys, function (key) { 440 | return i(key); 441 | }); 442 | var last = $keys.pop(); 443 | str = $keys.join(', ') + ', and ' + last; 444 | } else { 445 | str = i($keys[0]); 446 | } 447 | 448 | // Form 449 | str = (len > 1 ? 'keys ' : 'key ') + str; 450 | 451 | // Have / include 452 | str = (!this.flags.only ? 'include ' : 'only have ') + str; 453 | 454 | // Assertion 455 | this.assert( 456 | ok 457 | , function(){ return 'expected ' + i(this.obj) + ' to ' + str } 458 | , function(){ return 'expected ' + i(this.obj) + ' to not ' + str }); 459 | 460 | return this; 461 | }; 462 | /** 463 | * Assert a failure. 464 | * 465 | * @param {String ...} custom message 466 | * @api public 467 | */ 468 | Assertion.prototype.fail = function (msg) { 469 | msg = msg || "explicit failure"; 470 | this.assert(false, msg, msg); 471 | return this; 472 | }; 473 | 474 | /** 475 | * Function bind implementation. 476 | */ 477 | 478 | function bind (fn, scope) { 479 | return function () { 480 | return fn.apply(scope, arguments); 481 | } 482 | } 483 | 484 | /** 485 | * Array every compatibility 486 | * 487 | * @see bit.ly/5Fq1N2 488 | * @api public 489 | */ 490 | 491 | function every (arr, fn, thisObj) { 492 | var scope = thisObj || global; 493 | for (var i = 0, j = arr.length; i < j; ++i) { 494 | if (!fn.call(scope, arr[i], i, arr)) { 495 | return false; 496 | } 497 | } 498 | return true; 499 | }; 500 | 501 | /** 502 | * Array indexOf compatibility. 503 | * 504 | * @see bit.ly/a5Dxa2 505 | * @api public 506 | */ 507 | 508 | function indexOf (arr, o, i) { 509 | if (Array.prototype.indexOf) { 510 | return Array.prototype.indexOf.call(arr, o, i); 511 | } 512 | 513 | if (arr.length === undefined) { 514 | return -1; 515 | } 516 | 517 | for (var j = arr.length, i = i < 0 ? i + j < 0 ? 0 : i + j : i || 0 518 | ; i < j && arr[i] !== o; i++); 519 | 520 | return j <= i ? -1 : i; 521 | }; 522 | 523 | // https://gist.github.com/1044128/ 524 | var getOuterHTML = function(element) { 525 | if ('outerHTML' in element) return element.outerHTML; 526 | var ns = "http://www.w3.org/1999/xhtml"; 527 | var container = document.createElementNS(ns, '_'); 528 | var elemProto = (window.HTMLElement || window.Element).prototype; 529 | var xmlSerializer = new XMLSerializer(); 530 | var html; 531 | if (document.xmlVersion) { 532 | return xmlSerializer.serializeToString(element); 533 | } else { 534 | container.appendChild(element.cloneNode(false)); 535 | html = container.innerHTML.replace('><', '>' + element.innerHTML + '<'); 536 | container.innerHTML = ''; 537 | return html; 538 | } 539 | }; 540 | 541 | // Returns true if object is a DOM element. 542 | var isDOMElement = function (object) { 543 | if (typeof HTMLElement === 'object') { 544 | return object instanceof HTMLElement; 545 | } else { 546 | return object && 547 | typeof object === 'object' && 548 | object.nodeType === 1 && 549 | typeof object.nodeName === 'string'; 550 | } 551 | }; 552 | 553 | /** 554 | * Inspects an object. 555 | * 556 | * @see taken from node.js `util` module (copyright Joyent, MIT license) 557 | * @api private 558 | */ 559 | 560 | function i (obj, showHidden, depth) { 561 | var seen = []; 562 | 563 | function stylize (str) { 564 | return str; 565 | }; 566 | 567 | function format (value, recurseTimes) { 568 | // Provide a hook for user-specified inspect functions. 569 | // Check that value is an object with an inspect function on it 570 | if (value && typeof value.inspect === 'function' && 571 | // Filter out the util module, it's inspect function is special 572 | value !== exports && 573 | // Also filter out any prototype objects using the circular check. 574 | !(value.constructor && value.constructor.prototype === value)) { 575 | return value.inspect(recurseTimes); 576 | } 577 | 578 | // Primitive types cannot have properties 579 | switch (typeof value) { 580 | case 'undefined': 581 | return stylize('undefined', 'undefined'); 582 | 583 | case 'string': 584 | var simple = '\'' + json.stringify(value).replace(/^"|"$/g, '') 585 | .replace(/'/g, "\\'") 586 | .replace(/\\"/g, '"') + '\''; 587 | return stylize(simple, 'string'); 588 | 589 | case 'number': 590 | return stylize('' + value, 'number'); 591 | 592 | case 'boolean': 593 | return stylize('' + value, 'boolean'); 594 | } 595 | // For some reason typeof null is "object", so special case here. 596 | if (value === null) { 597 | return stylize('null', 'null'); 598 | } 599 | 600 | if (isDOMElement(value)) { 601 | return getOuterHTML(value); 602 | } 603 | 604 | // Look up the keys of the object. 605 | var visible_keys = keys(value); 606 | var $keys = showHidden ? Object.getOwnPropertyNames(value) : visible_keys; 607 | 608 | // Functions without properties can be shortcutted. 609 | if (typeof value === 'function' && $keys.length === 0) { 610 | if (isRegExp(value)) { 611 | return stylize('' + value, 'regexp'); 612 | } else { 613 | var name = value.name ? ': ' + value.name : ''; 614 | return stylize('[Function' + name + ']', 'special'); 615 | } 616 | } 617 | 618 | // Dates without properties can be shortcutted 619 | if (isDate(value) && $keys.length === 0) { 620 | return stylize(value.toUTCString(), 'date'); 621 | } 622 | 623 | var base, type, braces; 624 | // Determine the object type 625 | if (isArray(value)) { 626 | type = 'Array'; 627 | braces = ['[', ']']; 628 | } else { 629 | type = 'Object'; 630 | braces = ['{', '}']; 631 | } 632 | 633 | // Make functions say that they are functions 634 | if (typeof value === 'function') { 635 | var n = value.name ? ': ' + value.name : ''; 636 | base = (isRegExp(value)) ? ' ' + value : ' [Function' + n + ']'; 637 | } else { 638 | base = ''; 639 | } 640 | 641 | // Make dates with properties first say the date 642 | if (isDate(value)) { 643 | base = ' ' + value.toUTCString(); 644 | } 645 | 646 | if ($keys.length === 0) { 647 | return braces[0] + base + braces[1]; 648 | } 649 | 650 | if (recurseTimes < 0) { 651 | if (isRegExp(value)) { 652 | return stylize('' + value, 'regexp'); 653 | } else { 654 | return stylize('[Object]', 'special'); 655 | } 656 | } 657 | 658 | seen.push(value); 659 | 660 | var output = map($keys, function (key) { 661 | var name, str; 662 | if (value.__lookupGetter__) { 663 | if (value.__lookupGetter__(key)) { 664 | if (value.__lookupSetter__(key)) { 665 | str = stylize('[Getter/Setter]', 'special'); 666 | } else { 667 | str = stylize('[Getter]', 'special'); 668 | } 669 | } else { 670 | if (value.__lookupSetter__(key)) { 671 | str = stylize('[Setter]', 'special'); 672 | } 673 | } 674 | } 675 | if (indexOf(visible_keys, key) < 0) { 676 | name = '[' + key + ']'; 677 | } 678 | if (!str) { 679 | if (indexOf(seen, value[key]) < 0) { 680 | if (recurseTimes === null) { 681 | str = format(value[key]); 682 | } else { 683 | str = format(value[key], recurseTimes - 1); 684 | } 685 | if (str.indexOf('\n') > -1) { 686 | if (isArray(value)) { 687 | str = map(str.split('\n'), function (line) { 688 | return ' ' + line; 689 | }).join('\n').substr(2); 690 | } else { 691 | str = '\n' + map(str.split('\n'), function (line) { 692 | return ' ' + line; 693 | }).join('\n'); 694 | } 695 | } 696 | } else { 697 | str = stylize('[Circular]', 'special'); 698 | } 699 | } 700 | if (typeof name === 'undefined') { 701 | if (type === 'Array' && key.match(/^\d+$/)) { 702 | return str; 703 | } 704 | name = json.stringify('' + key); 705 | if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { 706 | name = name.substr(1, name.length - 2); 707 | name = stylize(name, 'name'); 708 | } else { 709 | name = name.replace(/'/g, "\\'") 710 | .replace(/\\"/g, '"') 711 | .replace(/(^"|"$)/g, "'"); 712 | name = stylize(name, 'string'); 713 | } 714 | } 715 | 716 | return name + ': ' + str; 717 | }); 718 | 719 | seen.pop(); 720 | 721 | var numLinesEst = 0; 722 | var length = reduce(output, function (prev, cur) { 723 | numLinesEst++; 724 | if (indexOf(cur, '\n') >= 0) numLinesEst++; 725 | return prev + cur.length + 1; 726 | }, 0); 727 | 728 | if (length > 50) { 729 | output = braces[0] + 730 | (base === '' ? '' : base + '\n ') + 731 | ' ' + 732 | output.join(',\n ') + 733 | ' ' + 734 | braces[1]; 735 | 736 | } else { 737 | output = braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; 738 | } 739 | 740 | return output; 741 | } 742 | return format(obj, (typeof depth === 'undefined' ? 2 : depth)); 743 | }; 744 | 745 | function isArray (ar) { 746 | return Object.prototype.toString.call(ar) == '[object Array]'; 747 | }; 748 | 749 | function isRegExp(re) { 750 | var s; 751 | try { 752 | s = '' + re; 753 | } catch (e) { 754 | return false; 755 | } 756 | 757 | return re instanceof RegExp || // easy case 758 | // duck-type for context-switching evalcx case 759 | typeof(re) === 'function' && 760 | re.constructor.name === 'RegExp' && 761 | re.compile && 762 | re.test && 763 | re.exec && 764 | s.match(/^\/.*\/[gim]{0,3}$/); 765 | }; 766 | 767 | function isDate(d) { 768 | if (d instanceof Date) return true; 769 | return false; 770 | }; 771 | 772 | function keys (obj) { 773 | if (Object.keys) { 774 | return Object.keys(obj); 775 | } 776 | 777 | var keys = []; 778 | 779 | for (var i in obj) { 780 | if (Object.prototype.hasOwnProperty.call(obj, i)) { 781 | keys.push(i); 782 | } 783 | } 784 | 785 | return keys; 786 | } 787 | 788 | function map (arr, mapper, that) { 789 | if (Array.prototype.map) { 790 | return Array.prototype.map.call(arr, mapper, that); 791 | } 792 | 793 | var other= new Array(arr.length); 794 | 795 | for (var i= 0, n = arr.length; i= 2) { 821 | var rv = arguments[1]; 822 | } else { 823 | do { 824 | if (i in this) { 825 | rv = this[i++]; 826 | break; 827 | } 828 | 829 | // if array contains no values, no initial value to return 830 | if (++i >= len) 831 | throw new TypeError(); 832 | } while (true); 833 | } 834 | 835 | for (; i < len; i++) { 836 | if (i in this) 837 | rv = fun.call(null, rv, this[i], i, this); 838 | } 839 | 840 | return rv; 841 | }; 842 | 843 | /** 844 | * Asserts deep equality 845 | * 846 | * @see taken from node.js `assert` module (copyright Joyent, MIT license) 847 | * @api private 848 | */ 849 | 850 | expect.eql = function eql (actual, expected) { 851 | // 7.1. All identical values are equivalent, as determined by ===. 852 | if (actual === expected) { 853 | return true; 854 | } else if ('undefined' != typeof Buffer 855 | && Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) { 856 | if (actual.length != expected.length) return false; 857 | 858 | for (var i = 0; i < actual.length; i++) { 859 | if (actual[i] !== expected[i]) return false; 860 | } 861 | 862 | return true; 863 | 864 | // 7.2. If the expected value is a Date object, the actual value is 865 | // equivalent if it is also a Date object that refers to the same time. 866 | } else if (actual instanceof Date && expected instanceof Date) { 867 | return actual.getTime() === expected.getTime(); 868 | 869 | // 7.3. Other pairs that do not both pass typeof value == "object", 870 | // equivalence is determined by ==. 871 | } else if (typeof actual != 'object' && typeof expected != 'object') { 872 | return actual == expected; 873 | 874 | // 7.4. For all other Object pairs, including Array objects, equivalence is 875 | // determined by having the same number of owned properties (as verified 876 | // with Object.prototype.hasOwnProperty.call), the same set of keys 877 | // (although not necessarily the same order), equivalent values for every 878 | // corresponding key, and an identical "prototype" property. Note: this 879 | // accounts for both named and indexed properties on Arrays. 880 | } else { 881 | return objEquiv(actual, expected); 882 | } 883 | } 884 | 885 | function isUndefinedOrNull (value) { 886 | return value === null || value === undefined; 887 | } 888 | 889 | function isArguments (object) { 890 | return Object.prototype.toString.call(object) == '[object Arguments]'; 891 | } 892 | 893 | function objEquiv (a, b) { 894 | if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) 895 | return false; 896 | // an identical "prototype" property. 897 | if (a.prototype !== b.prototype) return false; 898 | //~~~I've managed to break Object.keys through screwy arguments passing. 899 | // Converting to array solves the problem. 900 | if (isArguments(a)) { 901 | if (!isArguments(b)) { 902 | return false; 903 | } 904 | a = pSlice.call(a); 905 | b = pSlice.call(b); 906 | return expect.eql(a, b); 907 | } 908 | try{ 909 | var ka = keys(a), 910 | kb = keys(b), 911 | key, i; 912 | } catch (e) {//happens when one is a string literal and the other isn't 913 | return false; 914 | } 915 | // having the same number of owned properties (keys incorporates hasOwnProperty) 916 | if (ka.length != kb.length) 917 | return false; 918 | //the same set of keys (although not necessarily the same order), 919 | ka.sort(); 920 | kb.sort(); 921 | //~~~cheap key test 922 | for (i = ka.length - 1; i >= 0; i--) { 923 | if (ka[i] != kb[i]) 924 | return false; 925 | } 926 | //equivalent values for every corresponding key, and 927 | //~~~possibly expensive deep test 928 | for (i = ka.length - 1; i >= 0; i--) { 929 | key = ka[i]; 930 | if (!expect.eql(a[key], b[key])) 931 | return false; 932 | } 933 | return true; 934 | } 935 | 936 | var json = (function () { 937 | "use strict"; 938 | 939 | if ('object' == typeof JSON && JSON.parse && JSON.stringify) { 940 | return { 941 | parse: nativeJSON.parse 942 | , stringify: nativeJSON.stringify 943 | } 944 | } 945 | 946 | var JSON = {}; 947 | 948 | function f(n) { 949 | // Format integers to have at least two digits. 950 | return n < 10 ? '0' + n : n; 951 | } 952 | 953 | function date(d, key) { 954 | return isFinite(d.valueOf()) ? 955 | d.getUTCFullYear() + '-' + 956 | f(d.getUTCMonth() + 1) + '-' + 957 | f(d.getUTCDate()) + 'T' + 958 | f(d.getUTCHours()) + ':' + 959 | f(d.getUTCMinutes()) + ':' + 960 | f(d.getUTCSeconds()) + 'Z' : null; 961 | }; 962 | 963 | var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, 964 | escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, 965 | gap, 966 | indent, 967 | meta = { // table of character substitutions 968 | '\b': '\\b', 969 | '\t': '\\t', 970 | '\n': '\\n', 971 | '\f': '\\f', 972 | '\r': '\\r', 973 | '"' : '\\"', 974 | '\\': '\\\\' 975 | }, 976 | rep; 977 | 978 | 979 | function quote(string) { 980 | 981 | // If the string contains no control characters, no quote characters, and no 982 | // backslash characters, then we can safely slap some quotes around it. 983 | // Otherwise we must also replace the offending characters with safe escape 984 | // sequences. 985 | 986 | escapable.lastIndex = 0; 987 | return escapable.test(string) ? '"' + string.replace(escapable, function (a) { 988 | var c = meta[a]; 989 | return typeof c === 'string' ? c : 990 | '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); 991 | }) + '"' : '"' + string + '"'; 992 | } 993 | 994 | 995 | function str(key, holder) { 996 | 997 | // Produce a string from holder[key]. 998 | 999 | var i, // The loop counter. 1000 | k, // The member key. 1001 | v, // The member value. 1002 | length, 1003 | mind = gap, 1004 | partial, 1005 | value = holder[key]; 1006 | 1007 | // If the value has a toJSON method, call it to obtain a replacement value. 1008 | 1009 | if (value instanceof Date) { 1010 | value = date(key); 1011 | } 1012 | 1013 | // If we were called with a replacer function, then call the replacer to 1014 | // obtain a replacement value. 1015 | 1016 | if (typeof rep === 'function') { 1017 | value = rep.call(holder, key, value); 1018 | } 1019 | 1020 | // What happens next depends on the value's type. 1021 | 1022 | switch (typeof value) { 1023 | case 'string': 1024 | return quote(value); 1025 | 1026 | case 'number': 1027 | 1028 | // JSON numbers must be finite. Encode non-finite numbers as null. 1029 | 1030 | return isFinite(value) ? String(value) : 'null'; 1031 | 1032 | case 'boolean': 1033 | case 'null': 1034 | 1035 | // If the value is a boolean or null, convert it to a string. Note: 1036 | // typeof null does not produce 'null'. The case is included here in 1037 | // the remote chance that this gets fixed someday. 1038 | 1039 | return String(value); 1040 | 1041 | // If the type is 'object', we might be dealing with an object or an array or 1042 | // null. 1043 | 1044 | case 'object': 1045 | 1046 | // Due to a specification blunder in ECMAScript, typeof null is 'object', 1047 | // so watch out for that case. 1048 | 1049 | if (!value) { 1050 | return 'null'; 1051 | } 1052 | 1053 | // Make an array to hold the partial results of stringifying this object value. 1054 | 1055 | gap += indent; 1056 | partial = []; 1057 | 1058 | // Is the value an array? 1059 | 1060 | if (Object.prototype.toString.apply(value) === '[object Array]') { 1061 | 1062 | // The value is an array. Stringify every element. Use null as a placeholder 1063 | // for non-JSON values. 1064 | 1065 | length = value.length; 1066 | for (i = 0; i < length; i += 1) { 1067 | partial[i] = str(i, value) || 'null'; 1068 | } 1069 | 1070 | // Join all of the elements together, separated with commas, and wrap them in 1071 | // brackets. 1072 | 1073 | v = partial.length === 0 ? '[]' : gap ? 1074 | '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : 1075 | '[' + partial.join(',') + ']'; 1076 | gap = mind; 1077 | return v; 1078 | } 1079 | 1080 | // If the replacer is an array, use it to select the members to be stringified. 1081 | 1082 | if (rep && typeof rep === 'object') { 1083 | length = rep.length; 1084 | for (i = 0; i < length; i += 1) { 1085 | if (typeof rep[i] === 'string') { 1086 | k = rep[i]; 1087 | v = str(k, value); 1088 | if (v) { 1089 | partial.push(quote(k) + (gap ? ': ' : ':') + v); 1090 | } 1091 | } 1092 | } 1093 | } else { 1094 | 1095 | // Otherwise, iterate through all of the keys in the object. 1096 | 1097 | for (k in value) { 1098 | if (Object.prototype.hasOwnProperty.call(value, k)) { 1099 | v = str(k, value); 1100 | if (v) { 1101 | partial.push(quote(k) + (gap ? ': ' : ':') + v); 1102 | } 1103 | } 1104 | } 1105 | } 1106 | 1107 | // Join all of the member texts together, separated with commas, 1108 | // and wrap them in braces. 1109 | 1110 | v = partial.length === 0 ? '{}' : gap ? 1111 | '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : 1112 | '{' + partial.join(',') + '}'; 1113 | gap = mind; 1114 | return v; 1115 | } 1116 | } 1117 | 1118 | // If the JSON object does not yet have a stringify method, give it one. 1119 | 1120 | JSON.stringify = function (value, replacer, space) { 1121 | 1122 | // The stringify method takes a value and an optional replacer, and an optional 1123 | // space parameter, and returns a JSON text. The replacer can be a function 1124 | // that can replace values, or an array of strings that will select the keys. 1125 | // A default replacer method can be provided. Use of the space parameter can 1126 | // produce text that is more easily readable. 1127 | 1128 | var i; 1129 | gap = ''; 1130 | indent = ''; 1131 | 1132 | // If the space parameter is a number, make an indent string containing that 1133 | // many spaces. 1134 | 1135 | if (typeof space === 'number') { 1136 | for (i = 0; i < space; i += 1) { 1137 | indent += ' '; 1138 | } 1139 | 1140 | // If the space parameter is a string, it will be used as the indent string. 1141 | 1142 | } else if (typeof space === 'string') { 1143 | indent = space; 1144 | } 1145 | 1146 | // If there is a replacer, it must be a function or an array. 1147 | // Otherwise, throw an error. 1148 | 1149 | rep = replacer; 1150 | if (replacer && typeof replacer !== 'function' && 1151 | (typeof replacer !== 'object' || 1152 | typeof replacer.length !== 'number')) { 1153 | throw new Error('JSON.stringify'); 1154 | } 1155 | 1156 | // Make a fake root object containing our value under the key of ''. 1157 | // Return the result of stringifying the value. 1158 | 1159 | return str('', {'': value}); 1160 | }; 1161 | 1162 | // If the JSON object does not yet have a parse method, give it one. 1163 | 1164 | JSON.parse = function (text, reviver) { 1165 | // The parse method takes a text and an optional reviver function, and returns 1166 | // a JavaScript value if the text is a valid JSON text. 1167 | 1168 | var j; 1169 | 1170 | function walk(holder, key) { 1171 | 1172 | // The walk method is used to recursively walk the resulting structure so 1173 | // that modifications can be made. 1174 | 1175 | var k, v, value = holder[key]; 1176 | if (value && typeof value === 'object') { 1177 | for (k in value) { 1178 | if (Object.prototype.hasOwnProperty.call(value, k)) { 1179 | v = walk(value, k); 1180 | if (v !== undefined) { 1181 | value[k] = v; 1182 | } else { 1183 | delete value[k]; 1184 | } 1185 | } 1186 | } 1187 | } 1188 | return reviver.call(holder, key, value); 1189 | } 1190 | 1191 | 1192 | // Parsing happens in four stages. In the first stage, we replace certain 1193 | // Unicode characters with escape sequences. JavaScript handles many characters 1194 | // incorrectly, either silently deleting them, or treating them as line endings. 1195 | 1196 | text = String(text); 1197 | cx.lastIndex = 0; 1198 | if (cx.test(text)) { 1199 | text = text.replace(cx, function (a) { 1200 | return '\\u' + 1201 | ('0000' + a.charCodeAt(0).toString(16)).slice(-4); 1202 | }); 1203 | } 1204 | 1205 | // In the second stage, we run the text against regular expressions that look 1206 | // for non-JSON patterns. We are especially concerned with '()' and 'new' 1207 | // because they can cause invocation, and '=' because it can cause mutation. 1208 | // But just to be safe, we want to reject all unexpected forms. 1209 | 1210 | // We split the second stage into 4 regexp operations in order to work around 1211 | // crippling inefficiencies in IE's and Safari's regexp engines. First we 1212 | // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we 1213 | // replace all simple value tokens with ']' characters. Third, we delete all 1214 | // open brackets that follow a colon or comma or that begin the text. Finally, 1215 | // we look to see that the remaining characters are only whitespace or ']' or 1216 | // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. 1217 | 1218 | if (/^[\],:{}\s]*$/ 1219 | .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') 1220 | .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') 1221 | .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { 1222 | 1223 | // In the third stage we use the eval function to compile the text into a 1224 | // JavaScript structure. The '{' operator is subject to a syntactic ambiguity 1225 | // in JavaScript: it can begin a block or an object literal. We wrap the text 1226 | // in parens to eliminate the ambiguity. 1227 | 1228 | j = eval('(' + text + ')'); 1229 | 1230 | // In the optional fourth stage, we recursively walk the new structure, passing 1231 | // each name/value pair to a reviver function for possible transformation. 1232 | 1233 | return typeof reviver === 'function' ? 1234 | walk({'': j}, '') : j; 1235 | } 1236 | 1237 | // If the text is not JSON parseable, then a SyntaxError is thrown. 1238 | 1239 | throw new SyntaxError('JSON.parse'); 1240 | }; 1241 | 1242 | return JSON; 1243 | })(); 1244 | 1245 | if ('undefined' != typeof window) { 1246 | window.expect = module.exports; 1247 | } 1248 | 1249 | })( 1250 | this 1251 | , 'undefined' != typeof module ? module : {} 1252 | , 'undefined' != typeof exports ? exports : {} 1253 | ); 1254 | -------------------------------------------------------------------------------- /lib/jquery.js: -------------------------------------------------------------------------------- 1 | /*! jQuery v1.9.0 | (c) 2005, 2012 jQuery Foundation, Inc. | jquery.org/license */(function(e,t){"use strict";function n(e){var t=e.length,n=st.type(e);return st.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}function r(e){var t=Tt[e]={};return st.each(e.match(lt)||[],function(e,n){t[n]=!0}),t}function i(e,n,r,i){if(st.acceptData(e)){var o,a,s=st.expando,u="string"==typeof n,l=e.nodeType,c=l?st.cache:e,f=l?e[s]:e[s]&&s;if(f&&c[f]&&(i||c[f].data)||!u||r!==t)return f||(l?e[s]=f=K.pop()||st.guid++:f=s),c[f]||(c[f]={},l||(c[f].toJSON=st.noop)),("object"==typeof n||"function"==typeof n)&&(i?c[f]=st.extend(c[f],n):c[f].data=st.extend(c[f].data,n)),o=c[f],i||(o.data||(o.data={}),o=o.data),r!==t&&(o[st.camelCase(n)]=r),u?(a=o[n],null==a&&(a=o[st.camelCase(n)])):a=o,a}}function o(e,t,n){if(st.acceptData(e)){var r,i,o,a=e.nodeType,u=a?st.cache:e,l=a?e[st.expando]:st.expando;if(u[l]){if(t&&(r=n?u[l]:u[l].data)){st.isArray(t)?t=t.concat(st.map(t,st.camelCase)):t in r?t=[t]:(t=st.camelCase(t),t=t in r?[t]:t.split(" "));for(i=0,o=t.length;o>i;i++)delete r[t[i]];if(!(n?s:st.isEmptyObject)(r))return}(n||(delete u[l].data,s(u[l])))&&(a?st.cleanData([e],!0):st.support.deleteExpando||u!=u.window?delete u[l]:u[l]=null)}}}function a(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(Nt,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:wt.test(r)?st.parseJSON(r):r}catch(o){}st.data(e,n,r)}else r=t}return r}function s(e){var t;for(t in e)if(("data"!==t||!st.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}function u(){return!0}function l(){return!1}function c(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}function f(e,t,n){if(t=t||0,st.isFunction(t))return st.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return st.grep(e,function(e){return e===t===n});if("string"==typeof t){var r=st.grep(e,function(e){return 1===e.nodeType});if(Wt.test(t))return st.filter(t,r,!n);t=st.filter(t,r)}return st.grep(e,function(e){return st.inArray(e,t)>=0===n})}function p(e){var t=zt.split("|"),n=e.createDocumentFragment();if(n.createElement)for(;t.length;)n.createElement(t.pop());return n}function d(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function h(e){var t=e.getAttributeNode("type");return e.type=(t&&t.specified)+"/"+e.type,e}function g(e){var t=nn.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function m(e,t){for(var n,r=0;null!=(n=e[r]);r++)st._data(n,"globalEval",!t||st._data(t[r],"globalEval"))}function y(e,t){if(1===t.nodeType&&st.hasData(e)){var n,r,i,o=st._data(e),a=st._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)st.event.add(t,n,s[n][r])}a.data&&(a.data=st.extend({},a.data))}}function v(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!st.support.noCloneEvent&&t[st.expando]){r=st._data(t);for(i in r.events)st.removeEvent(t,i,r.handle);t.removeAttribute(st.expando)}"script"===n&&t.text!==e.text?(h(t).text=e.text,g(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),st.support.html5Clone&&e.innerHTML&&!st.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Zt.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}function b(e,n){var r,i,o=0,a=e.getElementsByTagName!==t?e.getElementsByTagName(n||"*"):e.querySelectorAll!==t?e.querySelectorAll(n||"*"):t;if(!a)for(a=[],r=e.childNodes||e;null!=(i=r[o]);o++)!n||st.nodeName(i,n)?a.push(i):st.merge(a,b(i,n));return n===t||n&&st.nodeName(e,n)?st.merge([e],a):a}function x(e){Zt.test(e.type)&&(e.defaultChecked=e.checked)}function T(e,t){if(t in e)return t;for(var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Nn.length;i--;)if(t=Nn[i]+n,t in e)return t;return r}function w(e,t){return e=t||e,"none"===st.css(e,"display")||!st.contains(e.ownerDocument,e)}function N(e,t){for(var n,r=[],i=0,o=e.length;o>i;i++)n=e[i],n.style&&(r[i]=st._data(n,"olddisplay"),t?(r[i]||"none"!==n.style.display||(n.style.display=""),""===n.style.display&&w(n)&&(r[i]=st._data(n,"olddisplay",S(n.nodeName)))):r[i]||w(n)||st._data(n,"olddisplay",st.css(n,"display")));for(i=0;o>i;i++)n=e[i],n.style&&(t&&"none"!==n.style.display&&""!==n.style.display||(n.style.display=t?r[i]||"":"none"));return e}function C(e,t,n){var r=mn.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function k(e,t,n,r,i){for(var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;4>o;o+=2)"margin"===n&&(a+=st.css(e,n+wn[o],!0,i)),r?("content"===n&&(a-=st.css(e,"padding"+wn[o],!0,i)),"margin"!==n&&(a-=st.css(e,"border"+wn[o]+"Width",!0,i))):(a+=st.css(e,"padding"+wn[o],!0,i),"padding"!==n&&(a+=st.css(e,"border"+wn[o]+"Width",!0,i)));return a}function E(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=ln(e),a=st.support.boxSizing&&"border-box"===st.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=un(e,t,o),(0>i||null==i)&&(i=e.style[t]),yn.test(i))return i;r=a&&(st.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+k(e,t,n||(a?"border":"content"),r,o)+"px"}function S(e){var t=V,n=bn[e];return n||(n=A(e,t),"none"!==n&&n||(cn=(cn||st("