├── README.md ├── package.json ├── test ├── a.js ├── all.js ├── amd.html ├── array_is.js ├── array_util.js ├── arrays.js ├── b.js ├── binary.js ├── common.js ├── d.js ├── dep.js ├── events.js ├── expect.js ├── functions.js ├── mocha.css ├── mocha.html ├── mocha.js ├── numbers.js ├── objects.js ├── one.js ├── ready.js ├── strings.js ├── sub.js ├── sub │ ├── add.js │ ├── c.js │ ├── e.js │ ├── four.js │ ├── object_copy.js │ ├── object_get.js │ ├── object_has.js │ ├── object_is.js │ ├── object_union.js │ ├── object_util.js │ ├── three.js │ └── z.js └── time.js └── theory.js /README.md: -------------------------------------------------------------------------------- 1 | Theory 2 | ====== 3 | 4 | Theory is an abstraction layer for server side and client side JavaScript. 5 | 6 | Motivation 7 | ========== 8 | 9 | 1. **Deep existence**. It all started because a program would crash via 10 | `if(obj.x.y.z)` rather than `if(obj && obj.x && obj.x.y && obj.x.y.z)`, so I 11 | wanted an elegant way to check and access deeply nested objects in a safe 12 | yet concise manner. 13 | 14 | 2. **Dependency management**. You should not have to declare dependencies in 15 | another language (HTML) to import required code or rely on globals. Other 16 | tools that solve this foolishly break Node's style in order to make it work 17 | asynchronously. 18 | 19 | 3. **Universal normalization**. Write once, run everywhere. This dream gets 20 | broken when you discover different implementations of JavaScript behave in 21 | unique ways, whether browsers or phones and tablets, or IE6 versus server 22 | side. I needed a reliable yet tiny library (at **7KB** gzipped) that would 23 | normalize everything so any code written would literally work everywhere. 24 | 25 | Require 26 | ======= 27 | 28 | As simple as `npm install theory` on Node and a single `` client side. The brilliant thing is that you do not 30 | have to declare anything else after that, you can handle the rest within your 31 | module. 32 | 33 | module.exports=require('theory') 34 | ('hello', function(a){ 35 | 36 | var say = "Hello World!"; 37 | console.log(say); 38 | return say; 39 | 40 | }, ['./needed', './dependency']); 41 | 42 | This is the beautiful fix that works everywhere. You get your own closure which 43 | executes only after all your dependencies (and all of their sub-dependencies) 44 | have loaded - then whatever you return from your closure gets exported out! 45 | 46 | Say you name this file as 'world.js', all you have to do is run `node world.js` 47 | on the server or put `require('world')` on the client inside the 'theory.js' 48 | script tag (or have a normal 'world.js' script tag below theory.js). All 49 | dependencies are relative to your file, not the HTML page or the parent module! 50 | 51 | If the dependency you require uses some global variable, you can access it from 52 | there (such as `jQuery`) as usual. You can access `theory` as a global, but you 53 | should not use it globally - theory copies itself into the scope of each module 54 | (the `a` argument, henceforth used for the rest of this documentation). 55 | 56 | All dependencies that use exports (normal Node modules and theory specific 57 | modules) get attached to your module's local scope with their base filename 58 | (`a.needed` and `a.dependency` in the example above). If you have conflicting 59 | names or just want a different name then use an object to declare dependencies 60 | instead of an array (`{'./needed': 'foo', './dependency': 'bar'}` become `a.foo` 61 | and `a.bar`). Theory modules also attach to their own namespace, such as 62 | `theory.hello` in above. 63 | 64 | You can also specify sub dependencies, such as `{'./jquery':['./jquery-ui', 65 | './jquery-ext']}`. Define environment specific dependencies by checking for 66 | `root.page` or `root.node`. Finally, [imports.js](https://gist.github.com/amark/6291429) 67 | is an unmaintained version of just the require feature, without anything below. 68 | 69 | *Now let's dive into the API.* 70 | 71 | Binary 72 | ====== 73 | 74 | - **is** `a.bi.is(what)` 75 | 76 | - determines to see if what is a boolean or not. 77 | 78 | - Examples 79 | 80 | - `a.bi.is(false)` → `true` 81 | 82 | - `a.bi.is(true)` → `true` 83 | 84 | - `a.bi.is(0)` → `false` 85 | 86 | - `a.bi.is('yes')` → `false` 87 | 88 | Numbers 89 | ======= 90 | 91 | - **is** `a.num.is(what)` 92 | 93 | - determines to see if what is a number or not. 94 | 95 | - Examples 96 | 97 | - `a.num.is(0)` → `true` 98 | 99 | - `a.num.is(NaN)` → `false` 100 | 101 | - `a.num.is(1.1)` → `true` 102 | 103 | - `a.num.is(Infinity)` → `true` 104 | 105 | - **ify** `a.num.ify(what, opt)` 106 | 107 | - what is the number, text, whatever that needs to be converted into a 108 | number. 109 | 110 | - opt is options parameter. 111 | 112 | - `[]` indicates you want a list of numbers returned. 113 | 114 | - Examples 115 | 116 | - `a.num.ify("A37")` → `37` 117 | 118 | - `a.num("It is -22.7 degrees").ify()` → `-22.7` 119 | 120 | - `a.num("My values are 33, -2.2, and 6.").ify([])` → `[33, -2.2, 6]` 121 | 122 | - **random** `a.num.random(what)` or `a.num.r(what)` 123 | 124 | - if what is a number, it represents how many digits long you want your 125 | random number. 126 | 127 | - if what is a list, it represents the inclusive range you want your 128 | random number to be in. 129 | 130 | - *Note:* Maximum length is 14, what defaults to 6. 131 | 132 | - Examples 133 | 134 | - `a.num.random()` → `583587` 135 | 136 | - `a.num(2).r()` → `64` 137 | 138 | - `a.num([-10,10]).random()` → `-7` 139 | 140 | - `a.num.r([1,99])` → `99` 141 | 142 | Text 143 | ==== 144 | 145 | - **is** `a.text.is(what)` 146 | 147 | - determines to see if what is text or not. 148 | 149 | - Examples 150 | 151 | - `a.text.is("")` → `true` 152 | 153 | - `a.text.is([])` → `false` 154 | 155 | - `a.text.is("Hello World!")` → `true` 156 | 157 | - **ify** `a.text.ify(what)` 158 | 159 | - what is the number, text, list, object, whatever you want to turn into 160 | text. 161 | 162 | - *Note:* Essentially just a wrapper for `JSON.stringify()` for now. 163 | 164 | - Examples 165 | 166 | - `a.text.ify({a:0,b:'1',c:[0,'1'],d:{e:'f'}})` → 167 | `"{a:0,b:'1',c:[0,'1'],d:{e:'f'}}"` 168 | 169 | - **random** `a.text.random(what, length)` or `a.text.r(what, length)` 170 | 171 | - what is a text of allowed characters to be used. Defaults to 172 | alpha-numeric characters. 173 | 174 | - length is how many characters long you want your random text. Defaults 175 | to 16. 176 | 177 | - *Note:* Does not matter what order you call the parameters in. 178 | 179 | - Examples 180 | 181 | - `a.text.random()` → `"uTkphuTCmzQ7Pl3e"` 182 | 183 | - `a.text.r("AaSsDdFf",4)` → `"fDds"` 184 | 185 | - `a.text(4).random("j$k4")` → `"kj$k"` 186 | 187 | - `a.text("randomize").r()` → `"oadomneradnimarz"` 188 | 189 | - **clip** `a.text(what).clip(split, start, end)` 190 | 191 | - what is the text to clip. 192 | 193 | - split is the text or regex to split and rejoin upon. 194 | 195 | - start is the start position of the slice. 196 | 197 | - end is the end position of the slice. 198 | 199 | - Examples 200 | 201 | - `a.text('A B C D').clip(' ',0,-1)` → `"A B C"` 202 | 203 | - `a.text.clip("path/to/awesome.js",'.',-1)` → `"js"` 204 | 205 | - **caps** `a.text.caps(what)` 206 | 207 | - what is the text you want to capitalize. 208 | 209 | - Examples 210 | 211 | - `a.text.caps("shout1")` → `"SHOUT1"` 212 | 213 | - **low** `a.text.low(what)` 214 | 215 | - what is the text you want to make lower case. 216 | 217 | - Examples 218 | 219 | - `a.text.low("HUSH!")` → `"hush!"` 220 | 221 | - **find** a collection of Regular Expressions. 222 | 223 | - *Note:* No guarantee of these working or being available in future 224 | versions. 225 | 226 | Lists 227 | ===== 228 | 229 | - **is** `a.list.is(what)` 230 | 231 | - determines to see if what is a list or not. 232 | 233 | - Examples 234 | 235 | - `a.list.is([])` → `true` 236 | 237 | - `a.list.is("list")` → `false` 238 | 239 | - `a.list.is([0,false])` → `true` 240 | 241 | - **ify** `a.list.ify(what, opt)` 242 | 243 | - what is the text or object that you want to convert into a list. 244 | 245 | - opt is the options parameter. 246 | 247 | - split: what to divide upon for text, whitespace auto handled. `','` 248 | is default. 249 | 250 | - wedge: what token to use as the divider between an object’s key and 251 | value. `':'` default. 252 | 253 | - Examples 254 | 255 | - `a.list.ify("Bob, Joe,Isaac , Fred")` → 256 | `["Bob","Joe","Isaac","Fred"]` 257 | 258 | - `a.list({a:1,b:'c',d:[1,2,3]}).ify()` → `['a:1','b:c','d:0,1,2']` 259 | 260 | - `a.list({session:'AK41795'}).ify({wedge:'='})` → 261 | `['session=AK41795']` 262 | 263 | - `a.list.ify("1,2,3 ; 4,5,6",{split:';'})` → `["1,2,3", "4,5,6"]` 264 | 265 | - **at** `a.list.at(what, index, opt)` 266 | 267 | - what is the list you want to access. 268 | 269 | - index is the where in the list you want to retrieve the value. 270 | 271 | - opt is the options parameter. 272 | 273 | - ebb: causes an over reaching index to cascade till it finds the 274 | closest item. 275 | 276 | - Examples 277 | 278 | - `a.list.at([5,6,7,8,9],-2)` → `8` 279 | 280 | - `a.list([5,6,7,8,9]).at(2)` → `6` 281 | 282 | - `a.list.at([2,3,4],9,{ebb:true})` → `4` 283 | 284 | - `a.list([0,1,2]).at(-9,{ebb:true})` → `0` 285 | 286 | - `a.list.at([5,6,7],-2,{ebb:true})` → `6` 287 | 288 | - **fuse** `a.list.fuse(what, ...)` 289 | 290 | - what is the list that other lists will fuse into. 291 | 292 | - … any number of extra list parameters. 293 | 294 | - Examples 295 | 296 | - `a.list.fuse([2,3],[4,5],[6,7])` → `[2,3,4,5,6,7]` 297 | 298 | - `a.list([2,3]).fuse([3,4],[4,5])` → `[2,3,3,4,4,5]` 299 | 300 | - **less** `a.list.less(what, ...)` 301 | 302 | - what is the list you want to subtract items from. 303 | 304 | - … the items you want to remove from the list, 305 | 306 | - Examples 307 | 308 | - `a.list.less([0,1,false,'a',false],false)` → `[0,1,'a']` 309 | 310 | - `a.list([2,2,7,['a'],1,9,0,31]).less(0,['a'],2)` → `[7, 1, 9, 31]` 311 | 312 | - *Note:* An option to pass a list of items to be removed exists by 313 | indicating you only want `2` parameters, such that 314 | `a.list(2).less([0,1,2,2,3,4],[0,2])` → `[1,3,4]`. 315 | 316 | - **find** `a.list.find(list, what)` 317 | 318 | - list is the list you want to search. 319 | 320 | - what is the item you are looking for. 321 | 322 | - Examples 323 | 324 | - `a.list([4,5]).find(9)` → `0` 325 | 326 | - `a.list([4,5]).find(5)` → `2` 327 | 328 | - `a.list.find([4,5],4)` → `1` 329 | 330 | - **each** `a.list.each(list, function, this)` 331 | 332 | - list is the list you want to iterate through each of its items. 333 | 334 | - function is your callback which gets executed sequentially, on each 335 | item. 336 | 337 | - the first parameter is the current item’s value. 338 | 339 | - the second parameter is the current index of that value in the list. 340 | 341 | - the third parameter is a map function, which when called pushes its 342 | argument into a list that is returned by default by `each`. 343 | 344 | - `return;` or `return undefined;` immediately proceeds to the next 345 | item. 346 | 347 | - return anything else and the loop breaks, then `each` returns the 348 | value you returned instead. 349 | 350 | - this is an optional argument that will become the `this` inside the 351 | function. 352 | 353 | - Examples 354 | 355 | - `a.list([1,2,3]).each(function(val, i, map){ map(val + i) })` → `[2, 356 | 4, 6]` 357 | 358 | - `a.list([1,2,3]).each(function(){ return "Hello World!"; })` → 359 | `"Hello World!"` 360 | 361 | - `a.list([1,2,3]).each(function(val, i, map){ if(val == 2){ return } 362 | map(val); })` → `[1,3]` 363 | 364 | - `a.list([1,2,3]).each(function(val, i, map){ map(val); if(val == 2){ 365 | return val } })` → `2` 366 | 367 | - `a.list([{name:'joe',age:27},{name:'bob',age:42}]).each(function(val, 368 | i, map){ map(val.name) })` → `['joe','bob']` 369 | 370 | - `a.list(['a','b','c']).each(function(){ return this })` → `// 371 | current context` 372 | 373 | - `a.list(['a','b','c']).each(function(){ return this }, {z:1})` → 374 | `{z:1}` 375 | 376 | Notes 377 | ----- 378 | 379 | Theory uses lists and index notation, not arrays and offset notation. Offset 380 | notation is the common practice of describing the position of an element in an 381 | array by its corresponding location in the physically allocated space of 382 | contiguous memory, which logically starts at a zeroth initial. This is otherwise 383 | shortened to "0 based index arrays", despite the misnomer of it actually being 384 | an offset. The author of this library has chosen index notation instead because 385 | it offers the following advantages: 386 | 387 | 1. Naturally, the first element in a list cardinally corresponds to `1`. 388 | Contrarily, even official documentation of JavaScript has explicit 389 | disclaimers that the "first element of an array is actually at index 0" - 390 | this is easily forgotten, especially by novices, and can lead to errors. 391 | 392 | 2. Mathematically, a closed interval is properly represented in code as `for(i 393 | = 1; i <= items.length; i++)`, because it includes its endpoints. Offset 394 | notation instead is technically a left-closed right-open interval set, 395 | represented in code as `for(i = 0; i < items.length; i++)`. This matters 396 | because code deals with integer intervals, because all elements have a fixed 397 | size - you can not access a fractional part of an element. Integer intervals 398 | are closed intervals, thus conclusively proving this importance. 399 | 400 | 3. Mathematically, matrix notation also starts with `1`. 401 | 402 | 4. The last element in a list cardinally corresponds to the length of the list, 403 | thus allowing easy access with `items.length` rather than having frustrating 404 | `(items.length - 1)` arithmetic everywhere in your code. 405 | 406 | 5. Negative indices are symmetric with positive indices. Such that `-1` and `1` 407 | respectively refer to the last and first element, and in the case where 408 | there is only one item in the list, it matches the same element. This 409 | convenience allows for simple left and right access that offset notation 410 | does not provide. 411 | 412 | 6. Non existence of an element can be represented by `0`, which would 413 | conveniently code elegantly as `if( !items.indexOf('z') ) return;`. Rather, 414 | one must decide upon whether `if( items.indexOf('z') == -1 ) return;` is 415 | philosophically more meaningful than `if( items.indexOf('z') < 0 ) return;` 416 | with offset notation despite ignoring the asymmetry of the equation. 417 | 418 | Still irrational? Then switch it back via `a.list.index = 0` in your closure. 419 | 420 | Objects 421 | ======= 422 | 423 | - **is** `a.obj.is(what)` 424 | 425 | - determines to see if what is an object or not. 426 | 427 | - Examples 428 | 429 | - `a.obj.is({})` → `true` 430 | 431 | - `a.obj.is(function(){})` → `false` 432 | 433 | - `a.obj.is([])` → `false` 434 | 435 | - **ify** `a.obj.ify(what)` 436 | 437 | - what is the text-ified object you want to parse into an object. 438 | 439 | - *Note:* Essentially just a wrapper for `JSON.parse()` for now. 440 | 441 | - Examples 442 | 443 | - `a.obj.ify('[0,1]')` → `[0,1]` 444 | 445 | - `a.obj('{"a":false,"b":1,"c":"d","e":[0,1],"f":{"g":"h"}}').ify()` → 446 | `{"a":false,"b":1,"c":"d","e":[0,1],"f":{"g":"h"}}` 447 | 448 | - **has** `a.obj.has(what, key)` 449 | 450 | - what is the object you want to test the existence of a key or property 451 | on. 452 | 453 | - key is the property you want to see if exists in what. 454 | 455 | - Examples 456 | 457 | - `a.obj.has({yay:false},'yay')` → `true` 458 | 459 | - `a.obj({yay:false}).has('toString')` → `false` 460 | 461 | - **empty** `a.obj.empty(what)` 462 | 463 | - what is the object you want to test to see if it is empty. 464 | 465 | - Examples 466 | 467 | - `a.obj.empty({})` → `true` 468 | 469 | - `a.obj({a:0}).empty()` → `false` 470 | 471 | - **copy** `a.obj.copy(what)` 472 | 473 | - what is the object or list that you want to make a deep duplicate of. 474 | 475 | - Examples 476 | 477 | - `a.obj.copy({a:[0,1],b:function(){ return 1 }})` → 478 | `{a:[0,1],b:function(){ return 1 }}` 479 | 480 | - `a.obj([{a:1},{b:2}]).copy()` → `[{a:1},{b:2}]` 481 | 482 | - **union** `a.obj.union(what, ...)` or `a.obj(what).u(...)` 483 | 484 | - what is the object you want to merge into, or a list of objects to 485 | merge. 486 | 487 | - ... are more objects to be merged. 488 | 489 | - *Note:* You can provide a list of objects instead, which will be merged. 490 | 491 | - Examples 492 | 493 | - `a.obj.union({a:'b',c:'d'},{c:1,z:2})` → `{a:'b',c:'d',z:2}` 494 | 495 | - `a.obj([{a:1},{b:2}]).union()` → `{a:1,b:2}` 496 | 497 | - `a.obj({a:'b',c:'d'}).u({c:1,z:2},{x:3,y:4})` → 498 | `{a:'b',c:'d',x:3,y:4,z:2}` 499 | 500 | - `a.obj.u([{a:1,b:2},{b:3,x:4},{y:5}])` → `{a:1,b:2,x:4,y:5}` 501 | 502 | - **get** `a.obj.get(what, where)` or `a(what, where)` 503 | 504 | - what is the object you want to get something from. 505 | 506 | - where is a dot separated text of keys to the thing you want to get. 507 | 508 | - numbers indicate a list index, if not specified it will scan through 509 | the list. 510 | 511 | - "-\>" postfix indicates you will be calling a function, but if not 512 | found it will return a fail safe function. 513 | 514 | - *Note:* Warning, fails if the property name itself contains a '.' dot in 515 | it. 516 | 517 | - Examples 518 | 519 | - `a.obj.get({a:4,b:6,c:8},'b')` → `6` 520 | 521 | - `a.obj({a:4,b:6,c:8}).get('z')` → `undefined` 522 | 523 | - `a.obj({a:{z:{b:{y:{c:{x:'deep'}}}}}}).get('a.z.b.y.c.x')` → 524 | `'deep'` 525 | 526 | - `a.obj({a:[1,[2,{b:{c:'scan'}},3],4]}).get('a.b.c')` → `'scan'` 527 | 528 | - `a.obj({a:[1,{b:'index'},3]}).get('a.2.b')` → `'index'` 529 | 530 | - `a.obj({a:[1,{b:'index'},3]}).get('a.-2.b')` → `'index'` 531 | 532 | - `a.obj({a:{b:function(c){return c*c}}}).get('a.b->')(2)` → `4` 533 | 534 | - `a.obj({a:1}).get('a.b->')(2)` → `undefined // fail safe` 535 | 536 | - `a.obj({a:1}).get('a.b')(2)` → `TypeError: undefined is not a 537 | function` 538 | 539 | - **each** `a.obj.each(object, function, this)` 540 | 541 | - object is the object you want to iterate through each of its key/value 542 | pairs. 543 | 544 | - function is your callback which gets executed on each pair. 545 | 546 | - the first parameter is the current value. 547 | 548 | - the second parameter is the key of the value in the object. 549 | 550 | - the third parameter is a map function, which when called adds a 551 | key/value pair to the object that is returned by default by `each`. 552 | 553 | - `return;` or `return undefined;` immediately proceeds to the next 554 | pair. 555 | 556 | - return anything else and the loop breaks, then `each` returns the 557 | value you returned instead. 558 | 559 | - this is an optional argument that will become the `this` inside the 560 | function. 561 | 562 | - Examples 563 | 564 | - `a.obj({a:'z',b:'y'}).each(function(val, key, map){ map(val,key) })` 565 | → `{y:'b',z:'a'}` 566 | 567 | - `a.obj({a:'z',b:'y'}).each(function(){ return "Hello World!"; })` → 568 | `"Hello World!"` 569 | 570 | - `a.obj({a:1,b:2,c:3}).each(function(val, key, map){ if(val == 2){ 571 | return } map(key,val); })` → `{a:1,c:3}` 572 | 573 | - `a.obj({a:1,b:2,c:3}).each(function(val, key, map){ map(key,val); 574 | if(val == 2){ return val } })` → `2` 575 | 576 | - `a.obj({z:4}).each(function(){ return this })` → `// current 577 | context` 578 | 579 | - `a.obj({z:4}).each(function(){ return this }, [1,2])` → `[1,2]` 580 | 581 | Functions 582 | ========= 583 | 584 | - **is** `a.fns.is(what)` 585 | 586 | - determines to see if what is a function or not. 587 | 588 | - Examples 589 | 590 | - `a.fns.is(function(){})` → `true` 591 | 592 | - `a.fns.is({})` → `false` 593 | 594 | - **pass** `a.fns.pass(function, this)` 595 | 596 | - function is the function that you want this bound to. 597 | 598 | - this will become the `this` inside the function. 599 | 600 | - *Note:* The original function is returned for you to then immediately 601 | call. 602 | 603 | - Examples 604 | 605 | - `a.fns.pass(function(z){ return this.b + z },{b:1})(2)` → `3` 606 | 607 | - `a.fns(function(z){ return this.b + z }).pass({b:2})(3)` → `5` 608 | 609 | - **sort** `a.fns.sort(what)` 610 | 611 | - what is the arguments object of the function you want sorted. 612 | 613 | - *Note:* An object containing the first letter of each type is returned. 614 | The value of these keys is a list with the corresponding arguments of 615 | that type, in the same order as they appeared in the original function 616 | call. 617 | 618 | - *Note:* If something goes wrong, an error type is included, with a text 619 | value explaining why. 620 | 621 | - Examples 622 | 623 | - `(function(){ return a.fns.sort(arguments) })("a",0,"b",1,{z:2})` → 624 | `{b:[],n:[0,1],t:['a','b'],l:[],o:[{z:2}],f:[]}` 625 | 626 | - `a.fns.sort()` → `{e:"Empty"}` 627 | 628 | - **flow** `a.fns.flow(what, function)` 629 | 630 | - what is a sequential list of functions to asynchronously iterate 631 | through. 632 | 633 | - the last parameter of each function is the next function in the 634 | list. 635 | 636 | - at any point, the flow can be canceled by calling `.end()` on the 637 | last parameter. 638 | 639 | - function is the callback to be executed at the end of the operations. 640 | 641 | - Examples 642 | 643 | - `a.fns.flow([function(next){ next(6) },function(six, next){ next(six 644 | / 3) }],function(two){ alert(two) })` 645 | 646 | - `a.fns.flow([function(next){ next.end(2) },function(){ /* skipped */ 647 | }],function(two){ alert(two) })` 648 | 649 | Events 650 | ====== 651 | 652 | - **event** `a.on(what).event(function)` 653 | 654 | - what is a string name of the event you want to listen on. 655 | 656 | - function is the callback function that will be called when the event is 657 | emitted. 658 | 659 | - the `this` object of the callback is the listener object. 660 | 661 | - returns the listener, which you can call `.off()` on to stop receiving 662 | events. 663 | 664 | - Examples 665 | 666 | - `a.on('alarm').event(function(task){ alert('Remember to ' + task); 667 | this.off(); })` 668 | 669 | - **emit** `a.on(what).emit(data, ...)` 670 | 671 | - what is a string name of the event you want to emit on. 672 | 673 | - data and ... are your parameters to emit to the receivers. 674 | 675 | - Examples 676 | 677 | - `a.on('alarm').emit('exercise!')` 678 | 679 | Time 680 | ==== 681 | 682 | - **is** `a.time.is()` 683 | 684 | - timestamp wrapper for `new Date().getTime()`, but if a parameter is 685 | provided it will test if it is an instance of `Date`. 686 | 687 | - Examples 688 | 689 | - `a.time.is()` → `1357457565462` 690 | 691 | - `a.time(new Date()).is()` → `true` 692 | 693 | - **now** `a.time.now()` 694 | 695 | - hyper precise timestamp, up to four decimals longer than the above. 696 | 697 | - Examples 698 | 699 | - `a.time.now()` → `1357457866774.292` 700 | 701 | - **loop** `a.time.loop(function, interval)` 702 | 703 | - repeatedly calls function every interval millisecond, wrapper for 704 | `setInterval`. 705 | 706 | - *Note:* Does not matter what order you call the parameters in. 707 | 708 | - Examples 709 | 710 | - `a.time.loop(function(){ alert('loop') },1000)` → `// returns ID for 711 | clearing` 712 | 713 | - **wait** `a.time.wait(function, delay)` 714 | 715 | - calls function after waiting millisecond delay, wrapper for 716 | `setTimeout`. 717 | 718 | - *Note:* Does not matter what order you call the parameters in. 719 | 720 | - Examples 721 | 722 | - `a.time.wait(1000,function(){ alert('wait') })` → `// returns ID for 723 | clearing` 724 | 725 | - **stop** `a.time.stop(ID)` 726 | 727 | - stops the wait or loop associated with the ID from further being 728 | executed. 729 | 730 | - Examples 731 | 732 | - `a.time.stop(1111)` → `true` 733 | 734 | Tests 735 | ===== 736 | 737 | - **is** `a.test.is(what, thing)` 738 | 739 | - what is what you want to compare equivalency against thing. 740 | 741 | - thing is the thing you want to compare equivalency to what. 742 | 743 | - Examples 744 | 745 | - `a.test.is({a:1,b:'c',d:{f:function(){return 746 | false}}},{a:1,b:'c',d:{f:function(){return false}}})` → `true` 747 | 748 | - `a.test(NaN).is(NaN)` → `true` 749 | 750 | - `a.test.is(function(){return true},function(){ return true; })` → 751 | `false` 752 | 753 | - `a.test(undefined).is(null)` → `false` 754 | 755 | - **test** `a.test(function)()` 756 | 757 | - function is the function that might break, and you want to test. 758 | 759 | - *Note:* all this does is wrap it in a `try{}catch(){}` block. 760 | 761 | - Examples 762 | 763 | - `a.test(function(){ explode_with_spam })()` → `// error object` 764 | 765 | - `a.test(function(){ return 'ok'; })()` → `'ok'` 766 | 767 | Run them! Using mocha, just `mocha` with Node or `./test/mocha.html` in any 768 | browser. 769 | 770 | Crafted with love by Mark Nadal, whom is not responsible for any liabilities 771 | from the use of this code. 772 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { "name": "theory" 2 | , "version": "0.2.8" 3 | , "author": "Mark Nadal" 4 | , "description": "Abstraction layer for server side and client side JavaScript." 5 | , "homepage": "http://github.com/amark/theory" 6 | , "engines": ["node >= 0.6.6"] 7 | , "main": "theory" 8 | } -------------------------------------------------------------------------------- /test/a.js: -------------------------------------------------------------------------------- 1 | describe('seq',function(){ 2 | it('a',function(){ 3 | expect(root.Dep).to.be.ok(); 4 | }); 5 | }); 6 | root.DepA = 2; -------------------------------------------------------------------------------- /test/all.js: -------------------------------------------------------------------------------- 1 | /* 2 | ** tests have relative paths to theory, 3 | ** although you should always use theory as an installed module 4 | */ 5 | 6 | var expect = global.expect = require("./expect"); 7 | require('./common'); -------------------------------------------------------------------------------- /test/amd.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |