Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

added all the box2d and images. also made a small change in now due t…

…o an error passing remote function params
  • Loading branch information...
commit 3e961af9311382453a253095922c21a4df7aee0d 1 parent 308948a
@zachwe zachwe authored
Showing with 36,933 additions and 0 deletions.
  1. +1 −0  node_modules/now/.gitignore
  2. +19 −0 node_modules/now/LICENSE
  3. +89 −0 node_modules/now/changelog.md
  4. +38 −0 node_modules/now/doc/public/best_practices.md
  5. +8 −0 node_modules/now/doc/public/company.md
  6. +82 −0 node_modules/now/doc/public/getting_started.md
  7. +22 −0 node_modules/now/doc/public/jobs.md
  8. +237 −0 node_modules/now/doc/public/user_manual.md
  9. +47 −0 node_modules/now/examples/express_example/app.js
  10. +24 −0 node_modules/now/examples/express_example/views/chat.ejs
  11. +13 −0 node_modules/now/examples/express_example/views/index.ejs
  12. +11 −0 node_modules/now/examples/express_example/views/layout.ejs
  13. +30 −0 node_modules/now/examples/helloworld_example/helloworld.html
  14. +23 −0 node_modules/now/examples/helloworld_example/helloworld_server.js
  15. +41 −0 node_modules/now/examples/multiroomchat_example/multiroomchat.html
  16. +36 −0 node_modules/now/examples/multiroomchat_example/multiroomchat_server.js
  17. +200 −0 node_modules/now/lib/clientGroup.js
  18. +109 −0 node_modules/now/lib/fileServer.js
  19. +465 −0 node_modules/now/lib/now.js
  20. +361 −0 node_modules/now/lib/nowServerLib.js
  21. +650 −0 node_modules/now/lib/nowUtil.js
  22. +156 −0 node_modules/now/lib/wrap.js
  23. +3 −0  node_modules/now/node_modules/node-proxy/.gitignore
  24. +22 −0 node_modules/now/node_modules/node-proxy/LICENSE.txt
  25. +15 −0 node_modules/now/node_modules/node-proxy/Makefile
  26. +52 −0 node_modules/now/node_modules/node-proxy/README.txt
  27. +120 −0 node_modules/now/node_modules/node-proxy/examples/autoload-namespace/autoload-namespace.js
  28. +39 −0 node_modules/now/node_modules/node-proxy/examples/autoload-namespace/autoload-test.js
  29. +8 −0 node_modules/now/node_modules/node-proxy/examples/autoload-namespace/org/w3c/DOM/Document.js
  30. +1 −0  node_modules/now/node_modules/node-proxy/examples/autoload-namespace/org/w3c/DOM/Document/String/Test.js
  31. +9 −0 node_modules/now/node_modules/node-proxy/install.sh
  32. 0  node_modules/now/node_modules/node-proxy/lib/.gitignore
  33. +37 −0 node_modules/now/node_modules/node-proxy/package.json
  34. +1,573 −0 node_modules/now/node_modules/node-proxy/src/node-proxy.cc
  35. +164 −0 node_modules/now/node_modules/node-proxy/src/node-proxy.h
  36. +15 −0 node_modules/now/node_modules/node-proxy/src/wscript
  37. +575 −0 node_modules/now/node_modules/node-proxy/test/test.js
  38. +8 −0 node_modules/now/node_modules/socket.io/.gitignore
  39. +242 −0 node_modules/now/node_modules/socket.io/History.md
  40. +13 −0 node_modules/now/node_modules/socket.io/Makefile
  41. +229 −0 node_modules/now/node_modules/socket.io/README.md
  42. +61 −0 node_modules/now/node_modules/socket.io/example/benchmark.html
  43. +21 −0 node_modules/now/node_modules/socket.io/example/cert.crt
  44. +61 −0 node_modules/now/node_modules/socket.io/example/chat-ssl.html
  45. +69 −0 node_modules/now/node_modules/socket.io/example/chat.html
  46. +18 −0 node_modules/now/node_modules/socket.io/example/json.js
  47. +27 −0 node_modules/now/node_modules/socket.io/example/key.key
  48. +66 −0 node_modules/now/node_modules/socket.io/example/server-ssl.js
  49. +77 −0 node_modules/now/node_modules/socket.io/example/server.benchmark.js
  50. +63 −0 node_modules/now/node_modules/socket.io/example/server.js
  51. +1 −0  node_modules/now/node_modules/socket.io/index.js
  52. +197 −0 node_modules/now/node_modules/socket.io/lib/socket.io/client.js
  53. +26 −0 node_modules/now/node_modules/socket.io/lib/socket.io/index.js
  54. +166 −0 node_modules/now/node_modules/socket.io/lib/socket.io/listener.js
  55. +89 −0 node_modules/now/node_modules/socket.io/lib/socket.io/transports/flashsocket.js
  56. +49 −0 node_modules/now/node_modules/socket.io/lib/socket.io/transports/htmlfile.js
  57. +35 −0 node_modules/now/node_modules/socket.io/lib/socket.io/transports/jsonp-polling.js
  58. +208 −0 node_modules/now/node_modules/socket.io/lib/socket.io/transports/websocket.js
  59. +67 −0 node_modules/now/node_modules/socket.io/lib/socket.io/transports/xhr-multipart.js
  60. +80 −0 node_modules/now/node_modules/socket.io/lib/socket.io/transports/xhr-polling.js
  61. +52 −0 node_modules/now/node_modules/socket.io/lib/socket.io/utils.js
  62. +21 −0 node_modules/now/node_modules/socket.io/package.json
  63. +3 −0  node_modules/now/node_modules/socket.io/support/expresso/.gitignore
  64. +3 −0  node_modules/now/node_modules/socket.io/support/expresso/.gitmodules
  65. +128 −0 node_modules/now/node_modules/socket.io/support/expresso/History.md
  66. +53 −0 node_modules/now/node_modules/socket.io/support/expresso/Makefile
  67. +61 −0 node_modules/now/node_modules/socket.io/support/expresso/Readme.md
  68. +856 −0 node_modules/now/node_modules/socket.io/support/expresso/bin/expresso
  69. +339 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/COPYING
  70. +81 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/Makefile.am
  71. +884 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/Makefile.in
  72. +8 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/Readme.md
  73. +872 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/aclocal.m4
  74. +1,526 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/config.guess
  75. +92 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/config.h.in
  76. +666 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/config.rpath
  77. +1,658 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/config.sub
  78. +7,971 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/configure
  79. +88 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/configure.ac
  80. +589 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/depcomp
  81. +87 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/demo.html
  82. +45 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/doc.css
  83. +25 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-inverted/index.html
  84. +20 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-inverted/script.js
  85. +50 −0 ...w/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/css/jsUnitStyle.css
  86. +10 −0 ...odules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/css/readme
  87. +11 −0 ...es/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/emptyPage.html
  88. +534 −0 ...les/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitCore.js
  89. +81 −0 .../node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitMockTimeout.js
  90. +705 −0 .../node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTestManager.js
  91. +44 −0 ...ow/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTestSuite.js
  92. +102 −0 ...s/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTracer.js
  93. +59 −0 ...node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitVersionCheck.js
  94. +12 −0 ...de_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-errors.html
  95. +13 −0 ..._modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-failures.html
  96. +13 −0 ...node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-runs.html
  97. +21 −0 .../now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts.html
  98. +189 −0 ...es/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-data.html
  99. +23 −0 .../now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-errors.html
  100. +19 −0 ...s/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-frame.html
  101. +45 −0 .../now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-loader.html
  102. +25 −0 ...ow/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-progress.html
  103. +67 −0 ...now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-results.html
  104. +13 −0 .../now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-status.html
  105. +16 −0 ...ow/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/testContainer.html
  106. +77 −0 ...dules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/testContainerController.html
  107. +306 −0 ...odules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/xbDebug.js
  108. +83 −0 ...s/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/css/jsUnitStyle.css
  109. BIN  ...ules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/green.gif
  110. BIN  ...ow/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/logo_jsunit.gif
  111. BIN  ...modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/powerby-transparent.gif
  112. BIN  ...odules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/red.gif
  113. +56 −0 ...node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/JDOM_license.txt
  114. +213 −0 ...de_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/Jetty_license.html
  115. +470 −0 .../now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/MPL-1.1.txt
  116. +340 −0 ...es/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/gpl-2.txt
  117. +141 −0 ...s/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/index.html
  118. +504 −0 ...now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/lgpl-2.1.txt
  119. +35 −0 ...modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/mpl-tri-license-c.txt
  120. +35 −0 ...ules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/mpl-tri-license-html.txt
  121. +19 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/readme.txt
  122. +167 −0 ...dules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/jsunit/testRunner.html
  123. +7 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/script.js
  124. +25 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example-jsunit/test.html
  125. +24 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example/index.html
  126. +20 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/example/script.js
  127. +164 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/faq.html
  128. BIN  node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/feed-icon-14x14.png
  129. +45 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/help.html
  130. +151 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/index.html
  131. +25 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/instrumented-inverted/index.html
  132. +38 −0 .../node_modules/socket.io/support/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-highlight.css
  133. +89 −0 ...les/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-ie.css
  134. BIN  ...w/node_modules/socket.io/support/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-throbber.gif
  135. +328 −0 ...odules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.css
  136. +125 −0 ...dules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.html
  137. +1,024 −0 ...modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.js
  138. +65 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/instrumented-inverted/script.js
  139. +24 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/instrumented/index.html
  140. +38 −0 ...dules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/instrumented/jscoverage-highlight.css
  141. +89 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/instrumented/jscoverage-ie.css
  142. BIN  ...odules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/instrumented/jscoverage-throbber.gif
  143. +328 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/instrumented/jscoverage.css
  144. +125 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/instrumented/jscoverage.html
  145. +1,024 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/instrumented/jscoverage.js
  146. +65 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/instrumented/script.js
  147. +382 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/license.html
  148. +59 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/links.html
  149. +701 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/manual.html
  150. +214 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/news.html
  151. +7 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/reset-fonts-grids.css
  152. BIN  node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/screenshot.png
  153. BIN  node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/screenshot2.png
  154. BIN  node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/screenshot3.png
  155. BIN  node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/screenshot4.png
  156. BIN  node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/screenshot5.png
  157. BIN  node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/screenshot6.png
  158. BIN  node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/screenshot7.png
  159. +1 −0  node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/sh_html.min.js
  160. +1 −0  node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/sh_javascript.min.js
  161. +4 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/sh_main.min.js
  162. +1 −0  node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/sh_nedit.min.css
  163. BIN  node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/siliconforks-16x16.png
  164. +138 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/style.css
  165. +58 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/doc/users.html
  166. +315 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/encoding.c
  167. +33 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/encoding.h
  168. +58 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/generate-resources.c
  169. +29 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/global.h
  170. +478 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/highlight.c
  171. +37 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/highlight.h
  172. +192 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/http-connection.c
  173. +494 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/http-exchange.c
  174. +95 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/http-host.c
  175. +900 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/http-message.c
  176. +236 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/http-server.c
  177. +208 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/http-server.h
  178. +156 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/http-url.c
  179. +519 −0 node_modules/now/node_modules/socket.io/support/expresso/deps/jscoverage/install-sh
Sorry, we could not display the entire diff because too many files (994) changed.
View
1  node_modules/now/.gitignore
@@ -0,0 +1 @@
+*.DS_Store
View
19 node_modules/now/LICENSE
@@ -0,0 +1,19 @@
+Copyright (C) 2011 by Flotype Inc. <team@nowjs.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
View
89 node_modules/now/changelog.md
@@ -0,0 +1,89 @@
+NowJS Version 0.6.1 - 6/10/2011
+---------------------------
+
+Changes since 0.6:
+
+* Socket.IO dependency updated to 0.6.18.
+* Reconnects implemented.
+* More bug fixes and performance increases.
+
+NowJS Version 0.6 - 5/14/2011
+---------------------------
+
+Changes since 0.5:
+
+* Socket.IO dependency updated to 0.6.17.
+* .hasClient(id) and .count added to ClientGroups.
+* See API documentation for further information.
+* Various bug fixes and performance increases.
+
+NowJS Version 0.5 - 4/8/2011
+---------------------------
+
+Changes since 0.3:
+
+* initialize() optionally accepts `options` parameter.
+* It is possible to set a custom host/port combination in now.js using `options.host` and `options.port`. This overrides the default auto-detected settings.
+* The object set at `options.socketio` is passed to socket.io as a configuration parameter.
+* Clients can optionally be prevented from making changes to their now namespace. To enable, set the `options.clientWrite` flag to `false` in the options parameter to `initialize()`
+* Users can be added to groups other than `everyone`. Usage of this API is documented in the User Manual.
+
+Bug fixes since 0.3:
+
+* IE compatibility enhanced
+* Events properly handled
+
+NowJS Version 0.4
+---------------------------
+* Various bug fixes and performance issues
+
+NowJS Version 0.3 - 3/18/2011
+---------------------------
+
+Changes since version 0.2:
+
+* **Breaks** Remote functions can no longer use return values. Please pass in and use a callback parameter when you need a return value from your remote call
+
+* Internet Explorer IE6/7/8 are now supported! There is lower performance when changing the value of a variable inside now, but function calls and remote calls (pushing/pulling) is 100% realtime
+
+Performance Improvements since 0.2:
+
+* now.js now contains nowUtil.js embedded, reducing number of requests
+
+* Static files (now.js) are now cached in memory on the server-side, reducing disk reads
+
+* Reduced per request latency; internal replacing of server/port info with actual server/port is now only done once on server startup
+
+Bug fixes since version 0.2:
+
+* Safari, IE6/7/8, Android, iOS (iPhone/iPad/iPod Touch) Safari now supported. nowUtil.js now contains a minified json2.js shim
+
+* Rare instances when not all attributes of now on client side would be initialized is now fixed
+
+* Array.isArray replaced with more flexible array check (thanks andref)
+
+* Changed uses of `x in y` to `.hasOwnProperty(prop)`
+
+* Bugs resulting in cross-port setups not working have been fixed
+
+
+NowJS Version 0.2 - 3/11/2011
+---------------------------
+
+Changes since version 0.1:
+
+* Unified nowLib.js was split into nowClientLib.js and nowServerLib.js
+
+* In nowServerLib.js, NowWatcher class was replaced with a Harmony Proxy implementation in proxy.js
+
+* nowClientLib.js continues to use NowWatcher class for namespace traversal.
+
+Known Issues:
+
+* Server crashes with a "hasOwnProperty of undefined" error when a client abruptly connects.
+
+* Library does not expose client connect and disconnect events to the developer.
+
+* Library does not expose any form of unique client ID to the developer.
+
+* Library does not provide a way to select particular clients or a single client based on filters/criteria.
View
38 node_modules/now/doc/public/best_practices.md
@@ -0,0 +1,38 @@
+Coding Patterns and Best Practices
+==================================
+The NowJS syntax and semantics are intended to integrate naturally into your application's existing coding patterns. However, there are some coding patterns and best practices that you may find useful.
+
+The "broadcast and receive" pattern
+-----------------------------------
+When building chatroom-style applications, it is common to broadcast a single user's action to all connected clients. This is commonly done like so:
+**On the client**:
+
+ now.receiveBroadcast = function(message){
+ //Render message in the UI or process it some other way
+ }
+
+**On the server**:
+
+ everyone.now.sendBroadcast = function(message){
+ everyone.now.receiveBroadcast(message);
+ }
+
+
+Efficiency Considerations
+-------------------------
+It is the goal of NowJS to make the shared namespaces as carefree and easy to use as possible. However, if your application is running slowly or you are coding with performance in mind, here are a few considerations.
+
+1. Avoid deeply nested structures inside the `now` namespace
+Setting or modifying variables that lie inside multiple levels of nested objects and arrays is inefficient. NowJS must traverse these deep structures to watch for changes, serialize the structure when a value is changed, deserialize it on the receiving end, and traverse it again to merge the changes on the receiving end. Keep your structures at most 2-3 levels deep.
+
+2. Sync values using remote function calls rather than using synced variables.
+As described above, some amount of traversal is required to synchronize variables in the `now` namespace. If you need to rapidly set a value on one client and then immediately use that value on the other clients, consider using the "broadcast and receive" coding pattern. Function calls are much faster than using variable syncing.
+
+3. The Internet will always be slower than the local machine
+We try to make remote functions and variables as natural to use as local ones. But the reality is that the latency for any remote action is 6 orders of magnitude longer than the same action done locally. Try to execute things locally when possible.
+
+Further Reading
+----------------------
+Now that you've read the Best Practices guide, try the NowJS [User Manual](http://nowjs.com/doc) and [Quick Start](http://nowjs.com/guide)
+
+Have more questions? You can reach us in #nowjs on freenode
View
8 node_modules/now/doc/public/company.md
@@ -0,0 +1,8 @@
+Company
+===============
+
+Based in Berkeley, California, Flotype Inc. was founded by three UC Berkeley computer science dropouts. Funded by Silicon Valley's finest angels and VCs, Flotype has created NowJS, a technology that changes the client-server communication paradigm.
+
+Led by a top-notch engineering and sales team, Flotype sells an enterprise-level, production ready version of NowJS that operates across a cluster of NowJS servers, scaling to hundreds of thousands of concurrent users.
+
+For more information, email team@nowjs.com
View
82 node_modules/now/doc/public/getting_started.md
@@ -0,0 +1,82 @@
+Getting Started with NowJS
+==========================
+Installation
+------------
+NowJS is a node.js module, which means you'll need node installed before proceeding. If you don't, see the [node.js website](http://nodejs.com/) for an introduction and instructions on how to get it.
+
+After installing node, you'll need to grab [npm](http://npmjs.org/) (a node.js package manager). Once npm is installed, you can type "npm install now" at the command line and get access to NowJS.
+
+Understanding How It Works
+--------------------------
+NowJS creates a dropbox object called `now` which is automatically synchronized between a client (typically a browser) and a server. Client and server both share a copy of the same `now`, updated live. The server also gets a special `everyone.now` object that provides a bird's eye view and provides access to all clients simultaneously. `now` and `everyone.now` are both regular JavaScript objects, so they can host any reasonable number of child objects, including functions.
+
+NowJS is vital for simplifying communications that would otherwise require messy AJAX or socket requests. After connecting to a server, a client can access the `now` object at will and use it to store or retrieve data, or invoke server functions (and vice versa).
+
+The simplicity and efficiency of NowJS makes it ideal for all types of web applications including social networking, games, news, search, and even banking.
+
+
+A Simple Chat Client
+--------------------
+Let's demonstrate the 2-way nature of NowJS by running a simple chat server. To follow along, download the two source files [here](https://github.com/downloads/Flotype/now/chat-example.tgz).
+
+### How It Works
+The Hello World chat example uses NowJS to allow client and server to share information, and give each other the ability to invoke functions remotely. The client calls the server's `distributeMessage` function with the message it wants to send. `distributeMessage` in turn calls the `receiveMessage` function held by each client, and the chat message is printed on the screen of each participant.
+
+### On The Server
+For our chat program, the client should be able to tell the server to send a message to everyone else. We'll call this function `distributeMessage`. Since this function needs to run on the server, we'll put it in the server .js file.
+
+ everyone.now.distributeMessage = function(message){
+ everyone.now.receiveMessage(this.now.name, message);
+ };
+
+Don't worry about what's happening inside the function for the moment. What's important is that we put the function into the `everyone.now` object. This means that all currently connected clients and all future clients will get a function called `distributeMessage` added to their `now`.
+
+With that done, the client code can call the `now.distributeMessage` locally and the server will execute the function.
+
+### On The Client
+Let's switch to the client-side code for a moment. We should allow users to set their name, so here's the bit of code that does that:
+
+ now.name = prompt("What's your name?", "");
+
+Notice how we stored it into a variable called `name` in the client's `now` object. This means when this client talks to the server, the server can access this client's name and use it.
+
+That's cool, but how do we send messages?! Here is how:
+
+ $("#send-button").click(function(){
+ now.distributeMessage($("#text-input").val());
+ $("#text-input").val("");
+ });
+
+Remember the `distributeMessage` function that the server put in every client's `now`? When the user clicks the send button, we call the `distributeMessage` function with the message passed in. The server receives the function call, runs the function, and everyone should receive the user's message. Let's see how it does that.
+
+### Back To The Server
+So let's say that a client just called `distributeMessage`. The server runs the function in the "context" of that particular client. This means that the function body has access to all the stuff in the calling client's `now`. We can access all that client's `now` by using `this.now` (i.e. this client's `now`).
+
+In this case, we want to let all the other client's know the name of the user that sent the message. We can get the calling client's name by looking in `this.now.name`. Here's the code for the function in case you forgot it:
+
+ everyone.now.distributeMessage = function(message){
+ everyone.now.receiveMessage(this.now.name, message);
+ };
+
+We pass in that name as well as the user's message to the `receiveMessage` function in `everyone.now`. HOLD UP! `receiveMessage`? Where did that come from? Come along, I'll show you.
+
+### Back To The Client! (last time, I promise)
+The `receiveMessage` function is found in the client code. Here it is for reference:
+
+ now.receiveMessage = function(name, message){
+ $("#messages").append("<br>" + name + ": " + message);
+ }
+
+The client puts its `receiveMessage` function in its `now` object so the server can call it when there are new messages. All it does is append the new chat message to the page.
+
+Because the client defines the `receiveMessage` function in the `now` object, that function also gets added to the server's `everyone.now`. This way, the server can easily call every single client's `receiveMessage` function in one fell swoop. And that is exactly what the server does inside the `distributeMessage` function.
+
+Fin
+---
+That's all there is to building things in NowJS. Armed with this knowledge, you can build all sorts of real-time applications easily and expressively. Happy coding!
+
+Further Reading
+----------------------
+Now that you've read the Getting Started guide, try the NowJS [User Manual](http://nowjs.com/doc) and [Best Practices](http://nowjs.com/bestpractices)
+
+Have more questions? You can reach us in #nowjs on freenode
View
22 node_modules/now/doc/public/jobs.md
@@ -0,0 +1,22 @@
+NowJS is hiring
+===============
+
+#Full Time
+
+We're looking to hire employee #1 at NowJS. We're extremely picky. Experience designing distributed, scalable systems is a must. If you think you have the caliber to join us, shoot us an email.
+
+#Interns
+
+We're also hiring interns, flexible on the time period (summer, co-ops etc.).
+
+###Preferred Skills:
+- Node.js/Socket.io/NowJS experience
+- Strong JavaScript background
+
+###Benefits:
+- Cool project
+- Experienced, fun founders
+- Great pay (free food/swag/monitors etc.)
+- Weekly team events (kayaking, gokart, paintball etc)
+- Beautiful office in Berkeley
+- Rewarding, enjoyable summer
View
237 node_modules/now/doc/public/user_manual.md
@@ -0,0 +1,237 @@
+NowJS User Manual
+==============
+Installing NowJS is very easy. In order to get started, you'll first need to have [node.js](http://nodejs.org) and [npm](http://npmjs.org/).
+
+Installing
+-------------------
+At your command line, simply enter `npm install now`.
+
+Setup on the server
+-------------------
+NowJS needs an instance of a node.js http server in order to communicate. If your application is already using an http server, NowJS can use the existing instance. Otherwise, you will need to create one. Here's an example server:
+
+ var yourHttpServer = require('http').createServer(function(req, response){ /* Serve your static files */ });
+ yourHttpServer.listen(8080);
+
+Using this http server, get NowJS and use it to get a reference to the `everyone` object, a group that contains every connected user.
+
+ var nowjs = require('now');
+ var everyone = nowjs.initialize(yourHttpServer);
+
+Setup on the client
+-------------------
+On pages that you would like to use NowJS on, simply include this script tag in your HTML head:
+`<script src="/nowjs/now.js"></script>`
+
+Using NowJS
+-------------------
+The secret to NowJS lies in two magic objects called `now` and `everyone.now`. In the **Setup on the server** section, we created the `everyone` object. Including the script tag in **Setup on the client** automatically added the `now` object to the browser document's global namespace.
+
+###The shared namespaces
+Each client has a `now` object, which is a namespace that is shared between the server and that particular client. Any variables or functions that are changed/added in this shared namespace get synced automatically to the server.
+
+The server has the `everyone.now` object, which is a namespace that is shared between the server and all clients. When the server adds/changes variables and functions in `everyone`, those changes are reflected in each client's `now` namespace. Variables added or changed in the `everyone` object will be reflected in all currently connected clients as well as all future clients.
+
+You can also create custom groups that behave just like everyone.now, but only include a subset of connected users.
+
+###Remote function calls
+Syncing variables is useful but the true power of NowJS lies in remote function calls. This means that the client can call functions that execute on the server, or vice-versa.
+
+Functions that are placed in a shared namespace can be called by either the server or the client. Functions are executed on the machine on which the function was created. When calling a remote function, pass in the arguments as usual; closures and callbacks work fine.
+
+Note that when making a remote function call, `return` values are ignored. Any type of value you need to `return` should be in a callback.
+Quick example:
+
+ now.sayHi = function() {
+ return "hi"
+ }
+Should be changed to
+
+ now.sayHi = function(callback) {
+ callback("hi")
+ }
+
+This change is because `return` is a synchronous operation while communication over the network with Node is asynchronous. Callbacks allow greater flexibility without blocking the main thread.
+
+When a remote machine invokes a function, the `now` namespace that is shared between it and the remote machine is in scope. This namespace can be accessed in the function body through the `this.now` object (i.e. `this` client's `now`). If the function is being executed on the server, the `everyone.now` namespace also remains available.
+
+###Special behavior of everyone.now
+When you call a function inside the `everyone.now` namespace, NowJS will attempt to call the corresponding function in each connected client's `now` namespace. If the corresponding function exists, a remote function call will be made to that client. If not, a call will not be made.
+
+Setting variables inside the `everyone.now` namespace will set the same value uniformly across all clients' `now` namespaces. It is possible to also get/read values from `everyone.now`, but since clients may change the value of the variable in their own `now` namespace, the returned value is indeterminate/meaningless.
+
+
+### The this.now and this.user object
+Each connected user in NowJS has a scope it shares with the server. The `everyone.now` object is used to control the now scopes across all clients, but they can also be manipulated individually. This is exposed via the `this.now` object
+
+For example
+
+ everyone.now.testFunc = function(){
+ // this.now.doSomething();
+ console.log(this.user.clientId);
+ }
+
+ everyone.now.testFunc();
+
+Would list the clientId of every user connected to the client. Note that when you call `everyone.now.testFunc()`, `testFunc` is actually called many times, once for each user, each time with that user's specific this.now and this.user.
+
+You can also add your own properties to `this.user` (for example, `this.user.loggedIn = true;`), this is **not** shared with the client but will be available wherever `this.user` is available.
+
+
+###Client connected/disconnected events on the server
+NowJS allows you to specify a callback to be fired when a client connects or disconnects on the server. To set a listener for the events, do the following:
+
+ everyone.on('connect', function(){});
+ everyone.on('disconnect', function(){});
+
+The callbacks are run in the context `this.now` and `this.user`. This makes it easy to access information about that client for setup or setdown procedures.
+
+###Client ready event on the client
+NowJS allows you to specify a callback to be fired when the client has successfully connected to the NowJS server. To set a listener for the events, do the following:
+
+ now.ready(function(){});
+
+
+###Client disconnect event on the client
+If the client loses communication with the server, a event is fired
+
+ now.core.on('disconnect', function(){})
+
+All remote functions are deleted at this time. The client will attempt to reconnect to the server using Socket.IO's built-in capabilities, which utilizes exponential backoff.
+
+###Accessing clientId on the client
+To access the clientId the server uses to identify client on the client side, simply access
+
+ now.core.clientId;
+
+##The NowJS module object
+
+Calling `require('now')` on the server returns a reference to the NowJS module object. You should store this in a variable for easy access like this:
+
+ var nowjs = require('now');
+
+In previous versions of NowJS, before 0.5.0, it was common practice to immediately chain an `initialize` call after requiring the module, rather than storing a reference to the module object. Such code would look like this:
+
+ var everyone = require('now').initialize(httpServer); // pre 0.5.0
+
+As of NowJS 0.5.0, it is strongly encouraged to break this up into two different calls, so that a reference to the NowJS module object can be stored, like this:
+
+ var nowjs = require('now');
+ var everyone = nowjs.initialize(httpServer);
+
+The module object exposes several methods that can be used:
+
+###.initialize(httpServer, [options])
+The initialize function takes a Node.js http server such as the one available in the `http` module or a module like Express.
+Returns a reference to the `everyone` object.
+
+You can also pass in an options object.
+Here are the currently available options and their defaults
+
+ {
+ "clientWrite" : true, // Enable syncing of changes to variables that originate from the client (browser)
+ "socketio" : {}, // This is the options object passed into io.listen(port, options)
+ "autoHost" : true, // This flag enables NowJS to serve the client-side libraries using the provided httpServer
+ "host" : undefined, // Overrides the autodetected host information when autoHost is enabled. You may need to set this if the server behind a reverse proxy or other complex network setup.
+ "port" : undefined // Overrides the autodetected port information when autoHost is enabled
+ }
+
+These options may also be stored in a configuration file which NowJS will search for. Simply save your options object to a file named nowjs.json . NowJS will search for this file in your shell's current working directory. The configuration file must contain only valid JSON.
+
+NowJS will only search for a configuration file if an options object is not provided. If neither are provided, the default options will be used. If your provided options are incomplete and only a subset of options are specified, the default values will be used for the unspecified options.
+
+###.getGroup(groupName)
+This method takes an arbitrary string `groupName` and returns an `ClientGroup` object whose name is `groupName`. If a group with that name was already created by a previous call to `getGroup`, that group will be returned. Otherwise, a new group will be created and returned.
+
+###.getClient(clientId, function(){})
+*Experimental. This method may change in future versions*
+
+Get client allows you to address a single client by passing its clientId as a parameter. The clientId is simply the `this.user.clientId` of the client.
+The second parameter is the callback you wish to be called with the client scope.
+Inside the callback you can access `this.user` and `this.now` for the clientId given.
+
+If the clientId given does not exist, the callback is called with an `err` parameter
+
+###.generateClientLibs(serverHost, serverPort, [exportPath])
+Takes the NowJS host and port information as strings and writes the generated client-side Javascript file to exportPath (where exportPath is a valid relative or absolute filesystem path). This is useful when autoHost is disabled and you would like to host the client-side now.js file yourself.
+
+This function is not intended to be used within your main NowJS application itself. Instead, it was meant to be used in a single-purpose script that you run every time you update NowJS. Such a script could look like this:
+
+ var nowjs = require('now');
+ nowjs.generateClientLibs('localhost', 8080, '/some/path/now.js');
+
+You may then take the generated file and minify/host it yourself.
+If no exportPath is provided, the generated source will be piped to standard output.
+
+
+<a name="groups"></a>
+##Groups in NowJS
+While the `everyone` object is used to perform actions on all connected clients, it is sometimes useful to be able to address a smaller subset of clients. For this reason, NowJS 0.5.0 and above exposes the groups API.
+
+A group is created or retrieved by passing a string to the `getGroup` method of the NowJS module object. Calling this method returns a group object. For example, to create a group called "foo," one would do this:
+
+ var fooGroup = nowjs.getGroup("foo");`
+
+Users can be added to a group by passing their `this.user.clientId` string to the `addUser` method of the group object. A similar call to `removeUser` will remove the user from the group. Continuing the example above, one could do this:
+
+ everyone.now.addToFooGroup = function(){
+ var fooGroup = nowjs.getGroup("foo");
+ fooGroup.addUser(this.user.clientId);
+ }
+
+ everyone.now.removeFromGroup = function(){
+ var fooGroup = nowjs.getGroup("foo");
+ fooGroup.removeUser(this.user.clientId);
+ }
+
+The groups behave similarly to the `everyone` object explained earlier. Each group has a `now` namespace that can be used to perform actions on all members of that group. For example,
+
+ everyone.now.sendToFooGroup = function(){
+ var fooGroup = nowjs.getGroup("foo");
+ fooGroup.now.receiveMessage("Hello, members of foo group");
+ }
+
+In the above function, `receiveMessage` would be called on only users who had previously added to the group named "foo."
+
+While the `everyone` object and group objects expose similar functionality, there are subtle yet crucial differences in how they work. It is highly discouraged to use groups to set variables for only a subset of users, like this: `fooGroup.now.x = 3`. A discussion of this topic can be found in the Best Practices document.
+
+###Group objects
+###.addUser(clientId)
+Takes a user's `this.user.clientId`, and adds that user to the group. Throws an error if `clientId` is not a valid sessionId.
+
+###.removeUser(clientId)
+Takes a user's `this.user.clientId` and removes that user to the group. Throws an error if `clientId` is not a valid sessionId.
+
+###.now
+A `now` namespace similar to `everyone.now`. Actions to this namespace affect all users that are members of the group. For example, actions on 'fooGroup.now' from the above example affects all users in the group 'foo'.
+
+###.on(connect/disconnect, function(){})
+Every group receives two events `connect` and `disconnect`. Connect is triggered when a user is added to the group. Disconnect is triggered when a user is removed from the group or is disconnected from the server. You can access that users `this.now` and `this.user` objects from the callback
+
+ everyone.on('connect', function(){
+ //this.now.setup();
+ });
+
+ everyone.on('disconnect', function(){
+ //this.now.destruct();
+ });
+
+###.hasClient(clientId)
+*Experimental. This method may change in future versions*
+
+Takes a clientId and returns a boolean `true` or `false` indicating whether the clientId is a member of the group
+
+###.count
+*Experimental. This method may change in future versions*
+
+This variable is the number of users in the group
+For example, to find the number of users in the everyone group
+
+ everyone.count;
+
+
+Further Reading
+----------------------
+Now that you've read the User Manual guide, try the NowJS [Quick Start](http://nowjs.com/guide) and [Best Practices](http://nowjs.com/bestpractices)
+
+Have more questions? You can reach us in #nowjs on freenode
View
47 node_modules/now/examples/express_example/app.js
@@ -0,0 +1,47 @@
+var express = require('express');
+
+var app = express.createServer();
+
+// Configuration
+
+app.set('views', __dirname + '/views');
+app.set('view engine', 'ejs');
+
+
+
+// Routes
+
+app.get('/', function(req, res){
+ res.render('index', {locals: {
+ title: 'NowJS + Express Example'
+ }});
+});
+
+app.get('/chat', function(req, res){
+ res.render('chat', {locals: {
+ title: 'NowJS + Express Example'
+ }});
+});
+
+app.listen(8080);
+console.log("Express server listening on port %d", app.address().port);
+
+
+// NowJS component
+
+var everyone = require("../../").initialize(app);
+
+
+everyone.connected(function(){
+ console.log("Joined: " + this.now.name);
+});
+
+
+everyone.disconnected(function(){
+ console.log("Left: " + this.now.name);
+});
+
+everyone.now.distributeMessage = function(message){
+ everyone.now.receiveMessage(this.now.name, message);
+};
+
View
24 node_modules/now/examples/express_example/views/chat.ejs
@@ -0,0 +1,24 @@
+<h2>Chat Window</h2>
+<div id="messages"></div>
+<div style="position: absolute; bottom: 25;">
+<input type="text" id="text-input">
+<input type="button" value="Send" id="send-button">
+</div>
+
+<script>
+ $(document).ready(function(){
+
+ now.receiveMessage = function(name, message){
+ $("#messages").append("<br>" + name + ": " + message);
+ }
+
+ $("#send-button").click(function(){
+ now.distributeMessage($("#text-input").val());
+ $("#text-input").val("");
+ $("#text-input").focus();
+ });
+
+ now.name = prompt("What's your name?", "");
+
+ });
+</script>
View
13 node_modules/now/examples/express_example/views/index.ejs
@@ -0,0 +1,13 @@
+<h1><%= title %></h1>
+<p>Welcome to <%= title %></p>
+<p>This is an example of an embedded chat window added to any site. <a href='#' id='chat'>Chat with us</a></p>
+<div id="floater" style="position: absolute; right: 0; top:0; width="25%" height="100%"></div>
+<script>
+ $(document).ready(function() {
+ $('#chat').click(function(e) {
+ e.preventDefault();
+ $('<iframe width="300px" height="100%" sandbox="allow-same-origin allow-forms allow-scripts" src="http://localhost:8080/chat"></iframe>').appendTo('#floater');
+ });
+
+ });
+</script>
View
11 node_modules/now/examples/express_example/views/layout.ejs
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title><%= title %></title>
+ <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
+ <script src="/nowjs/now.js"></script>
+ </head>
+ <body>
+ <%- body %>
+ </body>
+</html>
View
30 node_modules/now/examples/helloworld_example/helloworld.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<title>nowjs test</title>
+<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
+<script src="/nowjs/now.js"></script>
+
+<script>
+$(document).ready(function(){
+ now.receiveMessage = function(name, message){
+ $("#messages").append("<br>" + name + ": " + message);
+ }
+
+ $("#send-button").click(function(){
+ now.distributeMessage($("#text-input").val());
+ $("#text-input").val("");
+ });
+
+ now.name = prompt("What's your name?", "");
+
+});
+</script>
+</head>
+
+<body>
+<div id="messages"></div>
+<input type="text" id="text-input">
+<input type="button" value="Send" id="send-button">
+</body>
+</html>
View
23 node_modules/now/examples/helloworld_example/helloworld_server.js
@@ -0,0 +1,23 @@
+var fs = require('fs');
+var server = require('http').createServer(function(req, response){
+ fs.readFile(__dirname+'/helloworld.html', function(err, data){
+ response.writeHead(200, {'Content-Type':'text/html'});
+ response.write(data);
+ response.end();
+ });
+});
+server.listen(8080);
+var nowjs = require("../../");
+var everyone = nowjs.initialize(server);
+
+everyone.on("connect", function(){
+ console.log("Joined: " + this.now.name);
+});
+
+everyone.on("disconnect", function(){
+ console.log("Left: " + this.now.name);
+});
+
+everyone.now.distributeMessage = function(message){
+ everyone.now.receiveMessage(this.now.name, message);
+};
View
41 node_modules/now/examples/multiroomchat_example/multiroomchat.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<title>nowjs test</title>
+<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
+<script src="/nowjs/now.js"></script>
+
+<script>
+$(document).ready(function(){
+ now.receiveMessage = function(name, message){
+ $("#messages").append("<br>" + name + ": " + message);
+ }
+
+ $("#send-button").click(function(){
+ now.distributeMessage($("#text-input").val());
+ $("#text-input").val("");
+ });
+
+ $(".change").click(function(){
+ now.changeRoom($(this).text());
+ });
+
+ now.name = prompt("What's your name?", "");
+
+});
+</script>
+</head>
+
+<body>
+
+<div>
+ <a href="#" class="change selected">room 1</a> -
+ <a href="#" class="change">room 2</a> -
+ <a href="#" class="change">room 3</a>
+</div>
+<br>
+<div id="messages"><br>You're in room 1</div>
+<input type="text" id="text-input">
+<input type="button" value="Send" id="send-button">
+</body>
+</html>
View
36 node_modules/now/examples/multiroomchat_example/multiroomchat_server.js
@@ -0,0 +1,36 @@
+var fs = require('fs');
+var server = require('http').createServer(function(req, response){
+ fs.readFile(__dirname+'/multiroomchat.html', function(err, data){
+ response.writeHead(200, {'Content-Type':'text/html'});
+ response.write(data);
+ response.end();
+ });
+});
+server.listen(8080);
+
+
+var nowjs = require("../../");
+var everyone = nowjs.initialize(server);
+
+
+everyone.on('connect', function(){
+ this.now.room = "room 1";
+ nowjs.getGroup(this.now.room).addUser(this.user.clientId);
+ console.log("Joined: " + this.now.name);
+});
+
+
+everyone.on('disconnect', function(){
+ console.log("Left: " + this.now.name);
+});
+
+everyone.now.changeRoom = function(newRoom){
+ nowjs.getGroup(this.now.room).removeUser(this.user.clientId);
+ nowjs.getGroup(newRoom).addUser(this.user.clientId);
+ this.now.room = newRoom;
+ this.now.receiveMessage("SERVER", "You're now in " + this.now.room);
+}
+
+everyone.now.distributeMessage = function(message){
+ nowjs.getGroup(this.now.room).now.receiveMessage(this.now.name, message);
+};
View
200 node_modules/now/lib/clientGroup.js
@@ -0,0 +1,200 @@
+var proxy = require('./wrap.js');
+var nowUtil = require('./nowUtil.js').nowUtil;
+var EventEmitter = require('events').EventEmitter;
+
+function ClientGroup(nowCore, socket, groupName){
+
+ this.groupName = groupName;
+ this._socket = socket;
+ this._nowCore = nowCore;
+
+ // Contains references to scopes of clients that belong to group
+ this._groupScopes = {};
+
+ // The scope of the group itself
+ this.nowScope = {};
+
+ // The default scope. This is merged to all new users joining the group. Differs from nowScope because it stores original functions, not multicallers
+ this.defaultScope = {};
+
+ // Whether the group is `everyone`
+ this._isSuperGroup = false;
+
+ this.count = 0;
+ this.now = this._generateProxy();
+}
+
+
+ClientGroup.prototype.__proto__ = EventEmitter.prototype;
+
+// Set super group
+ClientGroup.prototype.setAsSuperGroup = function(){
+ this._isSuperGroup = true;
+}
+
+// Connected is alias for .on `connect`
+ClientGroup.prototype.connected = function(func) {
+ this.on('connect', func);
+};
+
+// Connected is alias for .on `disconnect`
+ClientGroup.prototype.disconnected = function(func) {
+ this.on('disconnect', func);
+};
+
+// Return boolean whether group contains a particular clientId
+ClientGroup.prototype.hasClient = function(clientId) {
+ return nowUtil.hasProperty(this._groupScopes, clientId);
+};
+
+
+// Generate the multicaller function, a special function that calls
+// functions at a particular fqn for some group of users
+ClientGroup.prototype.generateMultiCaller = function(fqn){
+ nowUtil.debug("generateMultiCaller", fqn);
+
+ var self = this;
+ // Return the actual function
+ return function multicall(){
+ for(var clientId in self._groupScopes){
+ nowUtil.debug("Multicaller", "Calling "+fqn+" on client " + clientId);
+ var clientScope = self._groupScopes[clientId];
+
+ // Retrieve the target function
+ var theFunction = nowUtil.getVarFromFqn(fqn, clientScope);
+
+ // Call the function with this.now and this.user
+ if(theFunction !== false) {
+ theFunction.apply({now: clientScope, user: self._nowCore.userObjects[clientId]}, arguments);
+ } else {
+ nowUtil.debug("Multicaller", "No function found for client " + clientId);
+ }
+ }
+ };
+
+};
+
+// Add a clientId to the group, if it isn't already there
+ClientGroup.prototype.addUser = function(clientId){
+ if (this.hasClient(clientId)) {
+ // User already in the group.
+ return;
+ }
+ if(nowUtil.hasProperty(this._nowCore.scopes, clientId)){
+
+ if(!this._isSuperGroup){
+
+ // If not a super group, merge functions in the new user's
+ // scope to the group scope
+ nowUtil.multiMergeFunctionsToMulticallers([this], this._nowCore.scopes[clientId]);
+
+ // Add the group to the user's list of groups
+ this._nowCore.clientGroups[clientId][this.groupName] = this;
+
+ // Merge the items in the group's default scope to the proxy,
+ // triggering a replaceVar to the client for any changes
+ nowUtil.mergeScopes(this._nowCore.proxies[clientId], this.defaultScope);
+ } else {
+
+ // Merge default scope to the user's scope, not triggering a
+ // replaceVar to the client. The user already gets the
+ // replaceVar in initalizeScope
+ nowUtil.mergeScopes(this._nowCore.scopes[clientId], this.defaultScope);
+
+ }
+
+ // Add user's scope reference to this users groupScopes
+ this._groupScopes[clientId] = this._nowCore.scopes[clientId];
+
+ this.count++;
+
+ nowUtil.debug(this.groupName+" addUser", "adding " + clientId);
+
+ // Emit the connect event, along with this.now and this.user
+ this.emit.apply({_events: this._events, now:this._nowCore.proxies[clientId], user:this._nowCore.userObjects[clientId]}, ['connect', clientId]);
+ } else {
+ throw new Error("Invalid client id");
+ }
+
+};
+
+ClientGroup.prototype.removeUser = function(clientId){
+ if(nowUtil.hasProperty(this._groupScopes, clientId)){
+ nowUtil.debug(this.groupName+" removeUser", "removing " + clientId);
+
+ this.count--;
+
+ // Emit disconnect event
+ this.emit.apply({_events: this._events, now: this._nowCore.proxies[clientId], user: this._nowCore.userObjects[clientId]}, ['disconnect', clientId]);
+
+ // Delete this clientId from clientGroups
+ delete this._nowCore.clientGroups[clientId][this.groupName];
+
+ // Delete the reference from groupScopes after disconnect event,
+ // so any changes can still be made in groupScopes event handler
+ delete this._groupScopes[clientId];
+ }
+};
+
+
+ClientGroup.prototype._generateProxy = function(){
+ // Store function is called by the proxy object upon variables changes.
+ // Key contains the top level key of the change (ex 'x' if now.x or
+ // a child of it was changed).
+ // Val contains the new value.
+ // Callback contains a callback for use in proxy internals.
+ // Changes contains a key value map of fqn's to new values.
+
+ var self = this;
+
+ var processChanges = function(key, val, changes){
+ var currScopes = [];
+
+ // Create multicallers for the current group
+ var data = nowUtil.decycle(val, "now."+key, [function(fqn, func){
+ var multiCaller = self.generateMultiCaller(fqn);
+ nowUtil.createVarAtFqn(fqn, self.nowScope, multiCaller);
+ return nowUtil.serializeFunction(fqn, func);
+ }]);
+
+ // Send the changes to everybody in the group
+ for(var clientId in self._groupScopes){
+ self._socket.clients[clientId].send({type: 'replaceVar', data: {key: key, value: data[0]}});
+ }
+
+ // Put all relevant nowCore.scopes in array so we traverse only once
+ for(var i in self._groupScopes) {
+ currScopes.push(self._groupScopes[i]);
+ }
+ // Don't forget the default scope of the server, which is merged
+ // into scopes of new users of group
+ currScopes.push(self.defaultScope);
+
+ nowUtil.mergeChanges(currScopes, changes);
+
+ // If is `everyone`, add multicallers to all groups for the change
+ if(self._isSuperGroup){
+ var obj = {};
+ obj[key] = val;
+ nowUtil.multiMergeFunctionsToMulticallers(self._nowCore.groups, obj);
+ }
+
+ return data;
+ };
+
+ var store = {
+ set: function(key, val, callback, changes){
+
+ nowUtil.debug(self.groupName+"Store", key + " => " + val);
+
+ var data = processChanges(key, val, changes);
+
+ callback();
+ },
+ remove: function(key){}
+ };
+
+ return proxy.wrap(store, this.nowScope)
+}
+
+exports.ClientGroup = ClientGroup;
View
109 node_modules/now/lib/fileServer.js
@@ -0,0 +1,109 @@
+var fs = require('fs');
+var nowUtil = require('./nowUtil').nowUtil;
+
+var fileCache = {};
+var nowFileCache = {};
+
+var defaultListeners;
+var server;
+var options;
+
+exports.generateClientLibs = generateClientLibs;
+
+exports.wrapServer = function(httpServer, serverOptions){
+ server = httpServer;
+ options = serverOptions;
+ defaultListeners = server.listeners('request');
+ if(serverOptions.autoHost) {
+ server.removeAllListeners('request');
+ server.on('request', handleResponse);
+ }
+}
+
+// Called upon http server request
+function handleResponse(request, response){
+ // Handle only GET requests for /nowjs/* files. Pass all other requests through
+ var i;
+ if(request.method === "GET"){
+
+ // Detect if request involves the now.js file
+ if(request.url.split('?')[0] === "/nowjs/now.js") {
+ serveFile(__dirname + '/now.js', request, response, options);
+ } else {
+ // Make sure default listeners are still handled
+ for(i in defaultListeners){
+ defaultListeners[i].call(server, request, response);
+ }
+ }
+ } else {
+ for(i in defaultListeners){
+ // Make sure default listeners are still handled
+ defaultListeners[i].call(server, request, response);
+ }
+ }
+};
+
+// Actually serve the file
+function serveFile(filename, request, response, options){
+ var options = options || {};
+
+ // Write file from cache if possible
+ if(nowUtil.hasProperty(fileCache, filename)) {
+ response.writeHead(200);
+ response.write(fileCache[filename]);
+ response.end();
+ } else {
+ if(filename.indexOf("/now.js") !== -1) {
+
+ // Write file from cache if possible
+ if(nowUtil.hasProperty(nowFileCache, request.headers.host)) {
+
+ // Write file from cache
+ response.writeHead(200, {'content-type': 'text/javascript'});
+ response.write(nowFileCache[request.headers.host].nowUtil);
+ response.write(nowFileCache[request.headers.host].now);
+ response.end();
+ } else {
+ // Determine hostname / port if not given in options
+ var host = request.headers.host.split(":");
+ var hostServer = options['host'] || host[0];
+ var hostPort = options['port'] || host[1] || '80';
+
+ // Call generate client libs, which takes the desired host/port and executes callback with two parts of now.js as parameters
+ generateClientLibs(hostServer, hostPort, function(nowText, utilText){
+
+ // Write to client
+ response.writeHead(200, {'content-type': 'text/javascript'});
+ response.write(utilText);
+ response.write(nowText);
+ response.end();
+
+ // Add to cache
+ nowFileCache[request.headers.host] = {now: nowText, nowUtil: utilText};
+ });
+ }
+ } else {
+ // For any other filename, read file and server (not cached)
+ fs.readFile(filename, function(err, data){
+ var text = data.toString();
+ response.writeHead(200);
+ response.write(text);
+ response.end();
+ fileCache[filename] = text;
+ });
+ }
+ }
+}
+
+// Takes host and port and call callback with now.js and nowUtil.js as parameters
+function generateClientLibs(hostServer, hostPort, callback){
+ fs.readFile(__dirname + "/now.js", function(err, data){
+ var nowText = data.toString();
+ nowText = nowText.replace(/\*\*SERVER\*\*/g, hostServer);
+ nowText = nowText.replace(/\*\*PORT\*\*/g, hostPort);
+ fs.readFile(__dirname + "/nowUtil.js", function(err, data){
+ var utilText = data.toString();
+ callback(nowText, utilText);
+ });
+ });
+}
View
465 node_modules/now/lib/now.js
@@ -0,0 +1,465 @@
+var SERVER_ID = 'server';
+var isIE = nowUtil.isLegacyIE();
+var socket;
+var noFunc = function () {
+ logging.log("Closure reference not defined.");
+};
+
+if (Array.prototype.indexOf === undefined) {
+ Array.prototype.indexOf = function (val) {
+ for (var i = this.length; i--;) {
+ if (this[i] == val) return i;
+ }
+ return -1;
+ };
+}
+
+var nowCore = {
+
+ // The client scope
+ scopes: {},
+
+ // Watcher objects for all variables in client
+ watchers: {},
+
+ // Blacklist of items to not trigger watcher callback for
+ watchersBlacklist: {},
+
+
+ // Contains references to closures passed in as pararmeters to remote calls
+ // (Generated closure id) => reference to closure function
+ closures: {},
+
+
+ // All of the different client messages we'll handle
+ messageHandlers: {
+
+ // A remote function call from client
+ remoteCall: function (client, data){
+ nowUtil.debug("handleRemoteCall", data.callId);
+ var clientScope = nowCore.scopes[client.sessionId];
+
+ var theFunction;
+
+ // Retrieve the function, either from closures hash or from the now scope
+ if(data.fqn.split('_')[0] === 'closure'){
+ theFunction = nowCore.closures[data.fqn];
+ } else {
+ theFunction = nowUtil.getVarFromFqn(data.fqn, clientScope);
+ }
+
+ var theArgs = data.args;
+
+ if(typeof theArgs === "object" && !nowUtil.isArray(theArgs)) {
+ var args = [];
+ // Enumeration order is not defined so this might be useless, but there will be cases when it works
+ for(var i in theArgs) {
+ args.push(theArgs[i]);
+ }
+ theArgs = args;
+ }
+
+ // Search (only at top level) of args for functions parameters, and replace with wrapper remote call function
+ for(var i = 0, ii = theArgs.length; i < ii; i++){
+ if(nowUtil.hasProperty(theArgs[i], 'type') && theArgs[i].type === 'function'){
+ theArgs[i] = nowCore.constructRemoteFunction(client, theArgs[i].fqn);
+ }
+ }
+
+ // Call the function with this.now and this.user
+ theFunction.apply({now: clientScope, clientId: client.sessionId}, theArgs);
+
+ nowUtil.debug("handleRemoteCall" , "completed " + data.callId);
+ },
+
+
+ // Called by initializeScope from the client side
+ createScope: function (client, data){
+
+ // Initialize blacklist object
+ nowCore.watchersBlacklist[client.sessionId] = {};
+
+ // This is the now object as populated by the client
+ // constructHandleFunctionForClientScope returns a function that will generate multicallers and remote call functions for this client
+ var scope = nowUtil.retrocycle(data.scope, nowCore.constructHandleFunctionForClientScope(client));
+
+ nowUtil.debug("handleCreateScope", "");
+ nowUtil.print(scope);
+
+ // Blacklist the entire scope so it is not sent back to the client
+ nowUtil.addChildrenToBlacklist(nowCore.watchersBlacklist[client.sessionId], scope, "now");
+
+
+ // Create the watcher object
+ nowCore.watchers[client.sessionId] = new nowLib.NowWatcher("now", scope, {}, function (prop, fqn, oldVal, newVal){
+
+ // Handle variable value changes in this callback
+
+ // If not on blacklist do changes
+ if(!nowUtil.hasProperty(nowCore.watchersBlacklist[client.sessionId], fqn)){
+ nowUtil.debug("clientScopeWatcherVariableChanged", fqn + " => " + newVal);
+ if(oldVal && typeof oldVal === "object") {
+ var oldFqns = nowUtil.getAllChildFqns(oldVal, fqn);
+
+ for(var i in oldFqns) {
+ delete nowCore.watchers[client.sessionId].data.watchedKeys[oldFqns[i]];
+ }
+ }
+
+
+ nowUtil.addChildrenToBlacklist(nowCore.watchersBlacklist[client.sessionId], newVal, fqn);
+
+ var key = fqn.split(".")[1];
+ var data = nowUtil.decycle(scope[key], "now."+key, [nowUtil.serializeFunction]);
+
+ client.send({type: 'replaceVar', data: {key: key, value: data[0]}});
+ } else {
+ // If on blacklist, remove from blacklist
+ nowUtil.debug("clientScopeWatcherVariableChanged", fqn + " change ignored");
+ delete nowCore.watchersBlacklist[client.sessionId][fqn];
+ }
+
+ // In case the object is an array, we delete from hashedArrays to prevent multiple watcher firing
+ delete nowCore.watchers[client.sessionId].data.hashedArrays[fqn];
+
+ });
+
+
+ nowCore.scopes[client.sessionId] = scope;
+ nowLib.nowJSReady();
+ },
+
+ replaceVar: function (client, data){
+ nowUtil.debug("handleReplaceVar", data.key + " => " + data.value);
+
+ var scope = nowCore.scopes[client.sessionId];
+ var newVal = nowUtil.retrocycle(data.value, nowCore.constructHandleFunctionForClientScope(client));
+
+ nowCore.watchersBlacklist[client.sessionId]["now."+data.key] = true;
+ nowUtil.addChildrenToBlacklist(nowCore.watchersBlacklist[client.sessionId], newVal, "now."+data.key);
+
+ for(var key in nowCore.watchers[client.sessionId].data.watchedKeys) {
+ if(key.indexOf("now."+data.key+".") === 0) {
+ delete nowCore.watchers[client.sessionId].data.watchedKeys[key];
+ }
+ }
+
+ if(nowUtil.hasProperty(data.value, "type") && data.value.type === 'function') {
+ data.value = nowCore.constructRemoteFunction(client, data.value.fqn);
+ newVal = data.value;
+ }
+
+ scope[data.key] = newVal;
+ }
+ },
+
+ constructHandleFunctionForClientScope: function (client) {
+ return function (funcObj) {
+ return nowCore.constructRemoteFunction(client, funcObj.fqn);
+ };
+ },
+
+ handleDisconnection: function (client) {
+ nowUtil.debug("disconnect", "server disconnected");
+ // y-combinator trick
+ (function (y) {
+ y(now, y, [now, now.core]);
+ })(function (obj, fn, seen) {
+ for (var i in obj) {
+ if (obj[i] && typeof obj[i] === 'object' &&
+ obj[i] != document && seen.indexOf(obj[i]) === -1) {
+ console.log(i);
+ seen[seen.length] = obj[i];
+ fn(obj[i], fn, seen);
+ }
+ else if (typeof obj[i] === 'function' && obj[i].remote) {
+ delete obj[i];
+ }
+ }
+ });
+ },
+
+ constructRemoteFunction: function (client, fqn){
+
+ nowUtil.debug("constructRemoteFunction", fqn);
+
+ var remoteFn = function (){
+ var callId = fqn+ "_"+ nowUtil.generateRandomString(10);
+
+ nowUtil.debug("executeRemoteFunction", fqn + ", " + callId);
+
+ var theArgs = Array.prototype.slice.call(arguments);
+
+ for(var i in theArgs){
+ if(typeof theArgs[i] === 'function' && nowUtil.hasProperty(theArgs, i)){
+ var closureId = "closure_" + theArgs[i].name + "_" + nowUtil.generateRandomString(10);
+ nowCore.closures[closureId] = theArgs[i];
+ theArgs[i] = {type: 'function', fqn: closureId};
+ }
+ }
+
+ client.send({type: 'remoteCall', data: {callId: callId, fqn: fqn, args: theArgs}});
+ };
+ remoteFn.remote = true;
+ return remoteFn;
+ },
+
+ _events: {},
+
+ // Event code from socket.io
+ on: function (name, fn){
+ if (!(name in nowCore._events)) {
+ nowCore._events[name] = [];
+ }
+ nowCore._events[name].push(fn);
+ return nowCore;
+ },
+
+ emit: function (name, args){
+ if (name in nowCore._events){
+ var events = nowCore._events[name].concat();
+ for (var i = 0, ii = events.length; i < ii; i++) {
+ events[i].apply(nowCore, args === undefined ? [] : args);
+ }
+ }
+ return nowCore;
+ },
+
+ removeEvent: function (name, fn){
+ if (name in nowCore._events){
+ for (var a = 0, l = nowCore._events[name].length; a < l; a++) {
+ if (nowCore._events[name][a] == fn) {
+ nowCore._events[name].splice(a, 1);
+ }
+ }
+ }
+ return nowCore;
+ }
+};
+
+var nowLib = {
+
+ nowJSReady: function (){
+ // client initialized
+ var nowOld = now;
+ now = nowCore.scopes[SERVER_ID];
+ var ready = nowOld.ready;
+ var core = nowOld.core;
+
+ delete nowOld.ready;
+ delete nowOld.core;
+ nowUtil.initializeScope(nowOld, socket);
+
+ nowUtil.addChildrenToBlacklist(nowCore.watchersBlacklist[SERVER_ID], nowOld, "now");
+
+ for(var key in nowOld) {
+ now[key] = nowOld[key];
+ }
+ now.core = core;
+ now.ready = function (func){
+ if(func && typeof func === "function") {
+ func();
+ } else {
+ nowCore.emit('ready');
+ }
+ };
+
+
+ setTimeout(function (){
+ nowCore.watchers[SERVER_ID].processScope();
+ }, 1000);
+
+ // Call the ready handlers
+ ready();
+ },
+
+ NowWatcher: function (fqnRoot, scopeObj, scopeClone, variableChanged) {
+ this.data = {watchedKeys: {}, hashedArrays: {}};
+
+ var badNames = {'now.ready': true, 'now.core': true };
+
+ this.traverseObject = function (path, obj, arrayBlacklist, objClone) {
+ // Prevent new array items from being double counted
+ for(var key in obj){
+ if(nowUtil.hasProperty(obj, key)){
+ var fqn = path+"."+key;
+ // Ignore ready function
+ if(nowUtil.hasProperty(badNames, fqn)) {
+ continue;
+ }
+ if(isIE && !nowUtil.isArray(obj) && typeof obj[key] !== "object" && nowUtil.hasProperty(objClone, key) && obj[key] !== objClone[key]) {
+ this.variableChanged(key, fqn, objClone[key], obj[key]);
+ objClone[key] = nowUtil.shallowCopy(obj[key]);
+ }
+ if(!nowUtil.hasProperty(this.data.watchedKeys, fqn)) {
+ if(!isIE){
+ nowUtil.watch(obj, key, fqn, this.variableChanged);
+ } else {
+ objClone[key] = nowUtil.shallowCopy(obj[key]);
+ }
+ if(!nowUtil.hasProperty(arrayBlacklist, fqn)) {
+ this.variableChanged(key, fqn, "", obj[key]);
+ }
+ this.data.watchedKeys[fqn] = true;
+ }
+
+ if(obj[key] && typeof obj[key] === 'object') {
+ if(nowUtil.isArray(obj[key])) {
+ if(nowUtil.hasProperty(this.data.hashedArrays, fqn)){
+ var diff = this.compareArray(this.data.hashedArrays[fqn], obj[key]);
+ if(diff === false) {
+ // Replace the whole array
+ this.variableChanged(key, fqn, this.data.hashedArrays[fqn], obj[key]);
+ } else if(diff !== true) {
+ for(var i in diff) {
+ if(nowUtil.hasProperty(diff, i)){
+ arrayBlacklist[fqn+"."+i] = true;
+ this.variableChanged(i, fqn+"."+i, this.data.hashedArrays[fqn][i], diff[i]);
+ }
+ }
+ }
+ }
+ this.data.hashedArrays[fqn] = obj[key].slice(0);
+ }
+ if(isIE && (!nowUtil.hasProperty(objClone, key) || !(typeof objClone[key] === "object"))) {
+ if(nowUtil.isArray(obj[key])) {
+ objClone[key] = [];
+ } else {
+ objClone[key] = {};
+ }
+ }
+ if(isIE){
+ this.traverseObject(fqn, obj[key], arrayBlacklist, objClone[key]);
+ } else {
+ this.traverseObject(fqn, obj[key], arrayBlacklist);
+ }
+ }
+ }
+ }
+ };
+
+ this.processScope = function (){
+ if(isIE) {
+ this.traverseObject(fqnRoot, scopeObj, {}, scopeClone);
+ } else {
+ this.traverseObject(fqnRoot, scopeObj, {});
+ }
+ setTimeout(function (){
+ nowCore.watchers[SERVER_ID].processScope();
+ }, 1000);
+ };
+
+ this.variableChanged = variableChanged;
+
+ /**
+ * Returns true if two the two arrays are identical.
+ * Returns an object of differences if keys have been added or the value at a key has changed
+ * Returns false if keys have been deleted
+ */
+ this.compareArray = function (oldArr, newArr) {
+ var result = {};
+ var modified = false;
+ if(newArr.length >= oldArr.length) {
+ for(var i in newArr) {
+ if(!nowUtil.hasProperty(oldArr, i) || newArr[i] !== oldArr[i]) {
+ result[i] = newArr[i];
+ modified = true;
+ }
+ }
+ return (modified) ? result : true;
+ } else {
+ return false;
+ }
+ };
+ },
+
+ handleNewConnection: function (client){
+ if (client.handled) return;
+ client.handled = true;
+ client.on('message', function (message){
+ if(nowUtil.hasProperty(message, "type") && nowUtil.hasProperty(nowCore.messageHandlers, message.type)) {
+ nowCore.messageHandlers[message.type](client, message.data);
+ }
+ });
+ client.on('disconnect', function (){
+ nowCore.handleDisconnection(client);
+ nowCore.emit('disconnect');
+ });
+ // Forward planning for socket io 0.7
+ client.on('error', function (){
+ nowCore.emit('error');
+ });
+ client.on('retry', function (){
+ nowCore.emit('retry');
+ });
+ client.on('reconnect', function (){
+ nowCore.emit('reconnect');
+ });
+ client.on('reconnect_failed', function (){
+ // Error to user.
+ });
+
+ }
+
+};
+
+var now = {
+ ready: function (func) {
+ if(arguments.length === 0) {
+ nowCore.emit('ready');
+ } else {
+ nowCore.on('ready', func);
+ }
+ },
+ core: {
+ on: nowCore.on,
+ removeEvent: nowCore.removeEvent,
+ clientId: undefined
+ }
+};
+
+(function (){
+ var dependencies = [
+ { key: 'io', path: '/socket.io/socket.io.js'}
+ ];
+ var dependenciesLoaded = 0;
+
+ var nowJSScriptLoaded = function (){
+ dependenciesLoaded++;
+ if(dependenciesLoaded !== dependencies.length) {
+ return;
+ }
+
+ nowUtil.debug("isIE", isIE);
+
+ socket = new io.Socket('**SERVER**', {port: **PORT**});
+ now.core.socketio = socket;
+ socket.connect();
+ socket.on('connect', function (){
+ var client = socket;
+ client.sessionId = SERVER_ID;
+ now.core.clientId = socket.transport.sessionid;
+ nowLib.handleNewConnection(client);
+ nowCore.emit('connect');
+ });
+ };
+
+ for(var i=0, ii=dependencies.length; i < ii; i++){
+ if (window[dependencies[i]['key']]) {
+ nowJSScriptLoaded();
+ return;
+ }
+ var fileref=document.createElement('script');
+ fileref.setAttribute("type","text/javascript");
+ fileref.setAttribute("src", "http://**SERVER**:**PORT**"+dependencies[i]['path']);
+ fileref.onload = nowJSScriptLoaded;
+ if(isIE) {
+ fileref.onreadystatechange = function () {
+ if(fileref.readyState === "loaded") {
+ nowJSScriptLoaded();
+ }
+ };
+ }
+ document.getElementsByTagName("head")[0].appendChild(fileref);
+ }
+}());
View
361 node_modules/now/lib/nowServerLib.js
@@ -0,0 +1,361 @@
+var proxy = require('./wrap.js');
+var io = require("socket.io");
+var http = require("http");
+var fs = require('fs');
+var nowUtil = require("./nowUtil.js").nowUtil;
+
+// The socket created by socket.io
+var socket;
+
+// Everyone group
+var everyone;
+var fileServer = require('./fileServer.js');
+var ClientGroup = require('./clientGroup.js').ClientGroup;
+var noFunc = function () {
+ logging.log("Closure reference not defined.");
+};
+
+var nowCore = {
+
+ // Scopes (now objects) of connected users
+ // clientId => now objects
+ scopes: {},
+
+ // Proxies, now objects are actually exposed as these. Modifications to proxy objects trigger the `store` callback which allows us to sync changes
+ // clientId => now proxies
+ proxies: {},
+
+ // Contains references to closures passed in as pararmeters to remote calls
+ // (Generated closure id) => reference to closure function
+ closures: {},
+
+ // Maps clientId to an object containing a map of groupNames to group object references
+ // clientId => {groupName => (group object references)}
+ clientGroups : {},
+
+ // Contains all groups that exist
+ // groupName => (group object references)
+ groups: {},
+
+ // Keeps track of all this.user objects, so they can be available anywhere this.now is available
+ userObjects : {},
+
+
+ // The defalt options. This is extended and overwritten by users options upon initialize
+ options: {
+ clientWrite: true,
+ autoHost: true,
+ socketio: {},
+ closureTimeout: 30000
+ },
+
+
+ // All of the different client messages we'll handle
+ messageHandlers: {
+
+ // A remote function call from client
+ remoteCall: function (client, data){
+ nowUtil.debug("handleRemoteCall", data.callId);
+ var clientScope = nowCore.proxies[client.sessionId];
+ var theFunction;
+
+ // Retrieve the function, either from closures hash or from the now scope
+ if (data.fqn.split('_')[0] === 'closure'){
+ theFunction = nowCore.closures[data.fqn];
+ } else {
+ theFunction = nowUtil.getVarFromFqn(data.fqn, clientScope);
+ }
+
+ var theArgs = data.args;
+
+ // Convert object to array if for some reason it was sent incorrectly
+ // This should rarely happen
+ if (typeof theArgs === "object" && !nowUtil.isArray(theArgs)) {
+ var args = [];
+ // Enumeration order is not defined so this might be useless, but there will be cases when it works
+ for(var i in theArgs) {
+ args.push(theArgs[i]);
+ }
+ theArgs = args;
+ }
+
+ if(typeof theArgs === "string") {
+ theArgs = eval(theArgs);
+ }
+
+ // Search (only at top level) of args for functions parameters, and replace with wrapper remote call function
+ for(var i = 0, ii = theArgs.length; i < ii; i++){
+ if(nowUtil.hasProperty(theArgs[i], 'type') && theArgs[i].type === 'function'){
+ theArgs[i] = nowCore.constructRemoteFunction(client, theArgs[i].fqn);
+ }
+ }
+ console.log('type of args: ' + typeof theArgs);
+ console.log('args: ' + theArgs);
+ for(var i in theArgs) {
+ console.log('the arg: ' + theArgs[i]);
+ }
+
+ // Call the function with this.now and this.user
+ theFunction.apply({now: clientScope, user: client.user }, theArgs);
+
+ nowUtil.debug("handleRemoteCall" , "completed " + data.callId);
+ },
+
+
+ // Called by initializeScope from the client side
+ createScope: function (client, data){
+
+ // This is the now object as populated by the client
+ // constructHandleFunctionForClientScope returns a function that will generate multicallers and remote call functions for this client
+ var scope = nowUtil.retrocycle(data.scope, nowCore.constructHandleFunctionForClientScope(client));
+
+ nowUtil.debug("handleCreateScope", "");
+ nowUtil.print(scope);
+
+ client.user = client.user ? client.user : {clientId: client.sessionId};
+
+ var tmp;
+ //Check if Socket.IO client object has a request, headers and cookie associated with it. Some transports (i.e. Flash socket) do not.
+ if((tmp = client.request) && (tmp = tmp.headers) && (tmp = tmp.cookie)){
+ client.user.cookie = tmp;
+ }
+
+ nowCore.userObjects[client.sessionId] = client.user;
+
+ // Create proxy object
+ nowCore.proxies[client.sessionId] = proxy.wrap(nowCore.constructClientScopeStore(client), scope, client.user);
+
+ // The now object, wrapped by the proxy
+ nowCore.scopes[client.sessionId] = scope;
+
+ // Initialize empty hash of groups this user belongs to
+ nowCore.clientGroups[client.sessionId] = {};
+
+ // Add to the everyone group!
+ everyone.addUser(client.sessionId);
+
+ },
+
+ // Handler for variable values changes
+ replaceVar: function (client, data){
+
+ // If clientWrite is false (not the default) then ignore writes
+ if(nowCore.options.clientWrite) {
+
+ // constructHandleFunctionForClientScope returns a function that will generate multicallers and remote call functions for this client
+ var newVal = nowUtil.retrocycle({key: data.value}, nowCore.constructHandleFunctionForClientScope(client));
+
+ nowUtil.debug("handleReplaceVar", data.key + " => " + data.value);
+ nowUtil.print(data.value);
+
+ var scope = nowCore.scopes[client.sessionId];
+
+ // If a new function was added, make sure those functions have multicallers in the scope of all groups that the client is a part of
+ var obj = {};
+ obj[data.key] = newVal.key;
+ nowUtil.multiMergeFunctionsToMulticallers(nowCore.clientGroups[client.sessionId], obj);
+
+ // Change the variable to the new value in the now scope of the client
+ scope[data.key] = newVal.key;
+ } else {
+ nowUtil.debug("handleReplaceVar", "preventing client write");
+ }
+ }
+ },
+
+
+
+ handleDisconnection: function (client) {
+ //Remove scope and other functions
+ if(!client.connected) {
+
+ everyone.removeUser(client.sessionId);
+
+ var groups = nowCore.clientGroups[client.sessionId];
+ for(var i in groups){
+ groups[i].removeUser(client.sessionId);
+ }
+
+ delete nowCore.scopes[client.sessionId];
+ delete nowCore.proxies[client.sessionId];
+ delete nowCore.closures[client.sessionId];
+ delete nowCore.clientGroups[client.sessionId];
+ }
+ },
+
+
+ // Returns a function for use in retrocycle when it encounters a functin. generates a multicaller and returns a remote function to replace the original
+ constructHandleFunctionForClientScope: function (client) {
+ return function (funcObj) {
+ // Generate multicaller
+ var multiCaller = everyone.generateMultiCaller(funcObj.fqn);
+ // Insert the multicaller
+ nowUtil.createVarAtFqn(funcObj.fqn, everyone.nowScope, multiCaller);
+ // Return a remote function for replacing the serialized function in the scope
+ return nowCore.constructRemoteFunction(client, funcObj.fqn);
+ };
+ },
+
+
+ // Constructs a remote function, given a fqn to the function on the originating side
+ constructRemoteFunction: function (client, fqn) {
+ nowUtil.debug("constructRemoteFunction", fqn);
+
+ // Create the function
+ var remoteFn = function () {
+
+ // Generate a random call id
+ var callId = fqn+ "_"+ nowUtil.generateRandomString();
+
+ nowUtil.debug("executeRemoteFunction", fqn + ", " + callId);
+
+ // Create a copy of the arguments
+ var theArgs = Array.prototype.slice.call(arguments);
+
+ // Find functions in the arguments, and store functions in closure table and serialize functions
+ for(var i in theArgs){
+ if(typeof theArgs[i] === 'function'){
+ var closureId = "closure_" + theArgs[i].name + "_" + nowUtil.generateRandomString();
+ nowCore.closures[closureId] = theArgs[i];
+ theArgs[i] = {type: 'function', fqn: closureId};
+ setTimeout(function () {
+ theArgs[i] = noFunc;
+ }, nowCore.options.closureTimeout);
+ }
+ }
+
+ // On the next tick, send the remoteCall request
+ process.nextTick(function (){
+ client.send({type: 'remoteCall', data: {callId: callId, fqn: fqn, args: theArgs}});
+ });
+
+ };
+ return remoteFn;
+ },
+
+
+ // THe store function to be used in the now object proxy for clients
+ constructClientScopeStore: function (client) {
+ return {
+ set: function (key, val, callback, changes){
+ nowUtil.debug("clientScopeStore", key + " => " + val);
+
+ // Decycle the object with one version that has serialized objects, the other with multicallers
+ var data = nowUtil.decycle(val, "now."+key, [nowUtil.serializeFunction, everyone.generateMultiCaller]);
+ // data[0] = For client
+ // data[1] = For Everyone
+
+ // Send serialized function version of data to client
+ client.send({type: 'replaceVar', data: {key: key, value: data[0]}});
+
+ // Send multicaller function version of data to grop
+ everyone.nowScope[key] = data[1];
+
+ // If a new function was added, make sure those functions have multicallers in the scope of all groups that the client is a part of
+ var obj = {};
+ obj[key] = val;
+ nowUtil.multiMergeFunctionsToMulticallers(nowCore.clientGroups[client.sessionId], obj);
+
+ callback();
+ },
+ remove: function (key){
+ // console.log("remove " + key);
+ }
+ };
+ }
+};
+
+
+// Returns existing group or creates a new group
+exports.getGroup = function (groupName){
+ if(!nowUtil.hasProperty(nowCore.groups, groupName)){
+ nowCore.groups[groupName] = new ClientGroup(nowCore, socket, groupName);
+ }
+ return nowCore.groups[groupName];
+}
+
+
+// Return a specific client
+exports.getClient = function (clientId, callback) {
+ if(nowUtil.hasProperty(nowCore.proxies, clientId)) {
+ callback.apply({now: nowCore.proxies[clientId], user: nowCore.userObjects[clientId] });
+ } else {
+ // throw "No such clientId" + clientId;
+ callback(new Error("No such clientId" + clientId));
+ return false;
+ }
+}
+
+
+// Handle new socket.io connection
+function handleNewConnection(client){
+ client.on('message', function (message){
+ var messageObj = message;
+
+ // Route to message handlers
+ if(nowUtil.hasProperty(messageObj, 'type') && nowUtil.hasProperty(nowCore.messageHandlers, messageObj.type)) {
+ nowCore.messageHandlers[messageObj.type](client, messageObj.data);
+ }
+ });
+ client.on('disconnect', function (){
+ nowCore.handleDisconnection(client);
+ });
+};
+
+exports.initialize = function (server, options){
+ options = options || readConfigFile();
+ // Merge user and default options
+ nowUtil.mergeScopes(nowCore.options, options);
+
+ // Override the default HTTP server listeners
+ fileServer.wrapServer(server, nowCore.options);
+
+ socket = io.listen(server, nowCore.options.socketio || {});
+
+ // Expose the underlying socket.io object
+ exports.socketio = socket;
+
+ // Initialize the everyone group
+ everyone = exports.getGroup("everyone");
+ everyone.setAsSuperGroup();
+
+
+ socket.on('connection', function (client){
+ nowUtil.initializeScope(everyone.defaultScope, client);
+ handleNewConnection(client);
+ });
+
+ return everyone;
+};
+
+function readConfigFile(){
+ var path = process.cwd()+"/nowjs.json";
+ try{
+ var conf = fs.readFileSync(path);
+ var parsedConf = JSON.parse(conf);
+ return parsedConf;
+ } catch(e) {
+ return undefined;
+ }
+}
+
+// Provide function for clients to control client lib generation
+exports.generateClientLibs = function (hostServer, hostPort, path){
+ fileServer.generateClientLibs(hostServer, hostPort, function (nowText, utilText){
+ if(path){
+ var stream = fs.createWriteStream(path);
+ stream.on('open', function (fd){
+ stream.write(utilText);
+ stream.end(nowText);
+ });
+ } else {
+ process.stdout.write(utilText);
+ process.stdout.write(nowText);
+ }
+ });
+};
+
+// Handle uncaught exceptions
+process.on('uncaughtException', function (err) {
+ nowUtil.error(err);
+});
View
650 node_modules/now/lib/nowUtil.js
@@ -0,0 +1,650 @@
+/**
+ * nowUtil.js
+ *
+ * Various utility functions used by both client and server side
+ *
+ */
+
+var nowUtil = {
+
+ hasProperty: function(obj, prop) {
+ return Object.prototype.hasOwnProperty.call(Object(obj), prop);
+ },
+
+ // Creates the serialized form of functions to be sent over the wire
+ serializeFunction: function(fqn, func) {
+ return {type: "function", fqn: fqn};
+ },
+
+
+ // Find all fqns of properties in parentObj and add them to the given blacklist, prepened by parentFqn
+ addChildrenToBlacklist: function(blacklist, parentObj, parentFqn){
+ for(var prop in parentObj){
+ if(nowUtil.hasProperty(parentObj, prop)){
+ blacklist[(parentFqn+"."+prop)] = true;
+ if(parentObj[prop] && typeof parentObj[prop] === 'object'){
+ nowUtil.addChildrenToBlacklist(blacklist, parentObj[prop], parentFqn+"."+prop);
+ }
+ }
+ }
+ },
+
+
+ // Remove all fqns contained in parentObj from given blacklist
+ removeChildrenFromBlacklist: function(blacklist, parentObj, parentFqn){
+ for(var prop in parentObj){
+ if(nowUtil.hasProperty(parentObj, prop)){
+ delete blacklist[(parentFqn+"."+prop)];
+ if(parentObj[prop] && typeof parentObj[prop] === 'object'){
+ nowUtil.removeChildrenFromBlacklist(blacklist, parentObj[prop], parentFqn+"."+prop);
+ }
+ }
+ }
+ },
+
+
+ // Return array of all fqns of parentObj, prepended by parentFqn, recursively
+ getAllChildFqns: function(parentObj, parentFqn){
+ var fqns = [];
+
+ function getAllChildFqnsHelper(parentObj, parentFqn){
+ for(var prop in parentObj){
+ if(nowUtil.hasProperty(parentObj, prop)) {
+ fqns.push(parentFqn+"."+prop);
+ if(parentObj[prop] && typeof parentObj[prop] === 'object'){
+ getAllChildFqnsHelper(parentObj[prop], parentFqn+"."+prop);
+ }
+ }
+ }
+ }
+ getAllChildFqnsHelper(parentObj, parentFqn);
+ return fqns;
+ },
+
+
+ // This is the client-side equivalent of the proxy object from wrap.js.
+ // Takes an object and the name of a property, calls the handler function when that property changes
+ watch: function (obj, prop, fqn, handler) {
+ var val = obj[prop];
+ var getter = function () {
+ return val;
+ };
+ var setter = function (newVal) {
+ var oldval = val;
+ val = newVal;
+ handler.call(obj, prop, fqn, oldval, newVal);
+ return newVal;
+ };
+ if (Object.defineProperty) {// ECMAScript 5
+ Object.defineProperty(obj, prop, {
+ get: getter,
+ set: setter
+ });
+ } else if (Object.prototype.__defineGetter__ && Object.prototype.__defineSetter__) { // legacy
+ Object.prototype.__defineGetter__.call(obj, prop, getter);
+ Object.prototype.__defineSetter__.call(obj, prop, setter);
+ }
+ },
+
+
+ // Used in initialization to serialize obj and send it over the given socket
+ initializeScope: function(obj, socket) {
+ var data = nowUtil.decycle(obj, 'now', [nowUtil.serializeFunction]);
+ var scope = data[0];
+ nowUtil.debug("initializeScope", JSON.stringify(data));
+ nowUtil.print(scope);
+ socket.send({type: 'createScope', data: {scope: scope}});
+ },
+
+
+ // Cross-browser isArray
+ isArray: Array.isArray || function (obj) {
+ return Object.prototype.toString.call(obj) === '[object Array]';
+ },
+
+
+ // Attempt to traverse the scope and return the property the fqn represents. Returns false if not found
+ getVarFromFqn: function(fqn, scope){
+ var path = fqn.split(".");
+ path.shift();
+ var currVar = scope;
+ while(path.length > 0){
+ var prop = path.shift();
+ if(nowUtil.hasProperty(currVar, prop)) {
+ currVar = currVar[prop];
+ } else {
+ return false;
+ }
+ }
+ return currVar;
+ },
+
+
+ // Traverse scope to get the parent object of the given fqn
+ getVarParentFromFqn: function(fqn, scope){
+ var path = fqn.split(".");
+ path.shift();
+
+ var currVar = scope;
+ while(path.length > 1){
+ var prop = path.shift();
+ currVar = currVar[prop];
+ }
+ return currVar;
+ },
+
+
+ // Traverse scope to get the parent object of the given fqn, or create and return it if it does't exist
+ forceGetParentVarAtFqn: function(fqn, scope){
+ var path = fqn.split(".");
+ path.shift();
+
+ var currVar = scope;
+ while(path.length > 1){
+ var prop = path.shift();
+ if(!nowUtil.hasProperty(currVar, prop)){
+ if(!isNaN(path[0])) {
+ currVar[prop] = [];
+ } else {
+ currVar[prop] = {};
+ }
+ }
+ currVar = currVar[prop];
+ }
+ return currVar;
+ },
+
+
+ // Check if is <IE9 by defineProperty feature detection
+ isLegacyIE: function(){
+ try {
+ Object.defineProperty({}, '', {});
+ return false;
+ } catch (err) {
+ return true;
+ }
+ return true;