├── .gitignore ├── .gitmodules ├── README.md ├── client ├── .DS_Store ├── 404.html ├── crossdomain.xml ├── css │ ├── base.css │ ├── handheld.css │ ├── jquery-ui-1.8.4.custom.css │ └── style.css ├── demo │ └── elements.html ├── img │ ├── add.png │ ├── delete-icon.png │ ├── delete.png │ ├── editbg.png │ ├── export.png │ ├── features.png │ ├── footer.png │ ├── footerInverse.png │ ├── logo.png │ ├── settings.png │ ├── splash.png │ ├── ui-bg_flat_0_aaaaaa_40x100.png │ ├── ui-bg_flat_75_ffffff_40x100.png │ ├── ui-bg_glass_55_fbf9ee_1x400.png │ ├── ui-bg_glass_65_ffffff_1x400.png │ ├── ui-bg_glass_75_dadada_1x400.png │ ├── ui-bg_highlight-soft_75_cccccc_1x100.png │ ├── ui-bg_highlight-soft_75_e6e6e6_1x100.png │ ├── ui-bg_inset-soft_95_fef1ec_1x100.png │ ├── ui-icons_222222_256x240.png │ ├── ui-icons_2e83ff_256x240.png │ ├── ui-icons_454545_256x240.png │ ├── ui-icons_888888_256x240.png │ └── ui-icons_cd0a0a_256x240.png ├── index.html ├── js │ ├── app-lib.js │ ├── app.js │ ├── dd_belatedpng.js │ ├── gerk.js │ ├── hi.js │ ├── jquery-1.4.2.min.js │ ├── jquery-ui-1.8.custom.min.js │ ├── jquery.hotKeys.js │ ├── modernizr-1.5.min.js │ ├── onhashchange.js │ ├── plugins.js │ ├── profiling │ │ ├── charts.swf │ │ ├── config.js │ │ ├── yahoo-profiling.css │ │ └── yahoo-profiling.min.js │ └── underscore.js ├── nginx.conf ├── robots.txt └── test │ ├── index.html │ ├── qunit │ ├── qunit.css │ └── qunit.js │ └── tests.js ├── server.js └── vendor └── node-static ├── LICENSE ├── README.md ├── benchmark └── node-static-0.3.0.txt ├── examples └── file-server.js ├── lib ├── node-static.js └── node-static │ ├── mime.js │ └── util.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/.gitmodules -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | # a collaborative bdd project planning tool for node 6 | 7 | 8 | prenup allows you to meaningfully engage your clients and convert their domain knowledge into tangible milestones, features, scenarios, and unit tests. 9 | 10 | 11 | ## features 12 | 13 | - Scenarios are created using [kyuri][1], a custom dialect of [Gherkin][12] geared towards asynchronous programming 14 | - Intuitive and friendly user interface that takes the frustration out of Behavior Driven Development 15 | - Generates [VowsJS][3] testing stubs (Vows is a well established node.js testing framework) 16 | - Milestones, Features, Scenarios, Points 17 | - Support for 160+ languages 18 | - Heavily influenced by Cucumber. If you know [Cuke][10], you know prenup. 19 | 20 | 21 | ## things that would be implemented if we didn't build this in 48 hours 22 | 23 | - real-time project management collaboration using [socket.io][9] 24 | - user accounts using [roles.js][7] 25 | - automated billing using [paynode][8] 26 | - native mobile app (iPhone / iPad / BlackBerry) using [Titanium AppCelerator][6] 27 | 28 | ##Usage 29 | 30 | ### using prenup locally 31 |
32 |   git clone git@github.com:nodejitsu/prenup.git
33 |   cd prenup
34 |   node server.js
35 | 
36 | 37 | ### using prenup online 38 | 39 | visit [http://prenup.nodejitsu.com][5] 40 | 41 | ## Vows 42 | 43 | [VowsJS][3] is a popular [Behavior Driven Development][4] framework for node.js. Vows was built from the ground up to test asynchronous code. It executes your tests in parallel when it makes sense, and sequentially when there are dependencies. 44 | 45 | Instead of crafting your VowsJS code from hand (using JavaScript), kyuri allows you to auto-generate Vows stubs. 46 | 47 | ## kyuri 48 | 49 | [kyuri][1] comes pre-bundled with prenup. [kyuri][1] is the language used to describe your Features and Scenarios. [kyuri][1] is a dialect of Gherkin, a well establish BDD language made popular by [Cucumber][10]. 50 | 51 | 52 | ## authors 53 | ### created for node knockout 2010 by The NYC Nodejitsu Ninjas 54 | #### [indexzero][15], [hij1nx][14], [FotoVerite][16] & [Marak][13] 55 | 56 | ### acknowledgments 57 | Heavily inspired by Sean Cribbs' [Lowdownapp][4], an entry in the 2009 Rails Rumble 58 | 59 | 60 | [1]: http://github.com/nodejitsu/kyuri "kyuri" 61 | [2]: http://cukes.info/ "Cucumber" 62 | [3]: http://vowsjs.org/ "Vowjs" 63 | [4]: http://lowdownapp.com/ "Lowdownapp" 64 | [5]: http://prenup.nodejitsu.com/ "prenup" 65 | [6]: http://www.appcelerator.com/ "Titanium AppCelerator" 66 | [7]: http://github.com/marak/roles.js/ "roles.js" 67 | [8]: http://github.com/jamescarr/paynode "paynode" 68 | [9]: http://socket.io/ "socket.io" 69 | [10]: http://cukes.info "Cucumber" 70 | [11]: http://nodejs.org "node.js" 71 | [12]: http://wiki.github.com/aslakhellesoy/cucumber/gherkin "gherkin" 72 | [13]: http://github.com/Marak "Marak" 73 | [14]: http://github.com/hij1nx "hij1nx" 74 | [15]: http://github.com/indexzero "indexzero" 75 | [16]: http://github.com/FotoVerite "FotoVerite" 76 | -------------------------------------------------------------------------------- /client/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/client/.DS_Store -------------------------------------------------------------------------------- /client/404.html: -------------------------------------------------------------------------------- 1 | 2 | not found 3 | 4 | 12 | 13 | 14 | 15 | 16 |
17 |

Not found

18 |

:(

19 |
-------------------------------------------------------------------------------- /client/crossdomain.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /client/css/base.css: -------------------------------------------------------------------------------- 1 | 2 | .feature-container { 3 | opacity: 0.5; 4 | } 5 | 6 | .feature-container, .scenario-container { 7 | border: 1px solid #515151; 8 | margin-top: 8px; 9 | margin-top: 8px; 10 | position: relative; 11 | } 12 | 13 | .feature-container .header, .scenario-container .header { 14 | padding: 4px; 15 | background: #555 url('../img/footer.png') repeat-x 0px 0px; 16 | color: #eee; 17 | height: 20px; 18 | position: relative; 19 | cursor:pointer; 20 | } 21 | 22 | .feature-container .header input, .scenario-container .header input { 23 | height: 15px; 24 | border: none; 25 | background-color: transparent; 26 | color: #eee; 27 | margin: 1px; 28 | margin-left: 31px; 29 | width: 500px; 30 | } 31 | 32 | .feature-container .header input:hover, .scenario-container .header input:hover { 33 | border: 1px solid #aaa; 34 | margin: 0px; 35 | margin-left: 30px; 36 | background-color: #fff; 37 | color: #515151; 38 | } 39 | 40 | 41 | .header .delete { 42 | position: absolute; 43 | cursor: pointer; 44 | padding: 3px; 45 | right: 3px; 46 | top: 3px; 47 | height: 14px; 48 | width: 14px; 49 | } 50 | 51 | .scenario-container { 52 | margin: 8px 40px 8px 8px; 53 | } 54 | 55 | .scenario ul { 56 | padding-bottom: 20px; 57 | } 58 | 59 | .step-container { 60 | position: relative; 61 | border: 1px solid #ccc; 62 | margin: 8px 35px 8px 8px; 63 | padding: 5px; 64 | height: 25px; 65 | 66 | list-style-type: none; 67 | cursor: move; 68 | } 69 | 70 | .step-container.active { 71 | background: #555 url('../img/footer.png') repeat-x 0px 0px; 72 | 73 | -moz-box-shadow: none; 74 | -webkit-box-shadow: none; 75 | box-shadow: none; 76 | } 77 | 78 | .step-container .delete { 79 | margin: 3px; 80 | cursor: pointer; 81 | color: #fff; 82 | display: none; 83 | } 84 | 85 | .step-container.active .delete { 86 | display: block; 87 | } 88 | 89 | .step-container.active input { 90 | border: 1px solid #aaa; 91 | background-color: #fff; 92 | 93 | -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; 94 | } 95 | 96 | .step select { 97 | height: 26px; 98 | padding-top: 4px; 99 | } 100 | 101 | .add-step, .add-scenario, .add-feature { 102 | display: none; 103 | position: absolute; 104 | right: -40px; 105 | bottom: -22px; 106 | background: url('../img/add.png') no-repeat scroll top left; 107 | width: 37px; 108 | height: 40px; 109 | outline: none; 110 | } 111 | 112 | .add-scenario { 113 | right: -42px; 114 | } 115 | 116 | .step input { 117 | border: none; 118 | height: 20px; 119 | padding-left: 4px; 120 | border: 1px solid #fff; 121 | } 122 | 123 | .active { 124 | opacity: 1; 125 | -moz-box-shadow: 0px 3px 3px #666; 126 | -webkit-box-shadow: 0px 3px 3px #666; 127 | box-shadow: 0px 3px 3px #666; 128 | 129 | } 130 | 131 | .hover{ 132 | /* border:1px solid purple !important; */ 133 | } 134 | 135 | /* utility */ 136 | 137 | .margin-small { 138 | } 139 | 140 | .round { 141 | -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; 142 | } 143 | 144 | .round-small { 145 | -moz-border-radius: 2px; -webkit-border-radius: 2px; border-radius: 2px; 146 | } 147 | 148 | 149 | code .keyword { font-weight: bold } 150 | code .string, code .regexp { color: green } 151 | code .class, code .special { color: blue } 152 | code .number { color: pink } 153 | code .comment { color: grey } 154 | 155 | .ui-icon { 156 | 157 | display: block; 158 | text-indent: -99999px; 159 | overflow: hidden; 160 | background-repeat: no-repeat; 161 | 162 | width: 16px; 163 | height: 16px; 164 | background-image: url(../img/ui-icons_222222_256x240.png); 165 | 166 | } 167 | 168 | .ui-icon-carat-1-n { background-position: 0 0; } 169 | .ui-icon-carat-1-ne { background-position: -16px 0; } 170 | .ui-icon-carat-1-e { background-position: -32px 0; } 171 | .ui-icon-carat-1-se { background-position: -48px 0; } 172 | .ui-icon-carat-1-s { background-position: -64px 0; } 173 | .ui-icon-carat-1-sw { background-position: -80px 0; } 174 | .ui-icon-carat-1-w { background-position: -96px 0; } 175 | .ui-icon-carat-1-nw { background-position: -112px 0; } 176 | .ui-icon-carat-2-n-s { background-position: -128px 0; } 177 | .ui-icon-carat-2-e-w { background-position: -144px 0; } 178 | .ui-icon-triangle-1-n { background-position: 0 -16px; } 179 | .ui-icon-triangle-1-ne { background-position: -16px -16px; } 180 | .ui-icon-triangle-1-e { background-position: -32px -16px; } 181 | .ui-icon-triangle-1-se { background-position: -48px -16px; } 182 | .ui-icon-triangle-1-s { background-position: -64px -16px; } 183 | .ui-icon-triangle-1-sw { background-position: -80px -16px; } 184 | .ui-icon-triangle-1-w { background-position: -96px -16px; } 185 | .ui-icon-triangle-1-nw { background-position: -112px -16px; } 186 | .ui-icon-triangle-2-n-s { background-position: -128px -16px; } 187 | .ui-icon-triangle-2-e-w { background-position: -144px -16px; } 188 | .ui-icon-arrow-1-n { background-position: 0 -32px; } 189 | .ui-icon-arrow-1-ne { background-position: -16px -32px; } 190 | .ui-icon-arrow-1-e { background-position: -32px -32px; } 191 | .ui-icon-arrow-1-se { background-position: -48px -32px; } 192 | .ui-icon-arrow-1-s { background-position: -64px -32px; } 193 | .ui-icon-arrow-1-sw { background-position: -80px -32px; } 194 | .ui-icon-arrow-1-w { background-position: -96px -32px; } 195 | .ui-icon-arrow-1-nw { background-position: -112px -32px; } 196 | .ui-icon-arrow-2-n-s { background-position: -128px -32px; } 197 | .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } 198 | .ui-icon-arrow-2-e-w { background-position: -160px -32px; } 199 | .ui-icon-arrow-2-se-nw { background-position: -176px -32px; } 200 | .ui-icon-arrowstop-1-n { background-position: -192px -32px; } 201 | .ui-icon-arrowstop-1-e { background-position: -208px -32px; } 202 | .ui-icon-arrowstop-1-s { background-position: -224px -32px; } 203 | .ui-icon-arrowstop-1-w { background-position: -240px -32px; } 204 | .ui-icon-arrowthick-1-n { background-position: 0 -48px; } 205 | .ui-icon-arrowthick-1-ne { background-position: -16px -48px; } 206 | .ui-icon-arrowthick-1-e { background-position: -32px -48px; } 207 | .ui-icon-arrowthick-1-se { background-position: -48px -48px; } 208 | .ui-icon-arrowthick-1-s { background-position: -64px -48px; } 209 | .ui-icon-arrowthick-1-sw { background-position: -80px -48px; } 210 | .ui-icon-arrowthick-1-w { background-position: -96px -48px; } 211 | .ui-icon-arrowthick-1-nw { background-position: -112px -48px; } 212 | .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } 213 | .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } 214 | .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } 215 | .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } 216 | .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } 217 | .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } 218 | .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } 219 | .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } 220 | .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } 221 | .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } 222 | .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } 223 | .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } 224 | .ui-icon-arrowreturn-1-w { background-position: -64px -64px; } 225 | .ui-icon-arrowreturn-1-n { background-position: -80px -64px; } 226 | .ui-icon-arrowreturn-1-e { background-position: -96px -64px; } 227 | .ui-icon-arrowreturn-1-s { background-position: -112px -64px; } 228 | .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } 229 | .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } 230 | .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } 231 | .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } 232 | .ui-icon-arrow-4 { background-position: 0 -80px; } 233 | .ui-icon-arrow-4-diag { background-position: -16px -80px; } 234 | .ui-icon-extlink { background-position: -32px -80px; } 235 | .ui-icon-newwin { background-position: -48px -80px; } 236 | .ui-icon-refresh { background-position: -64px -80px; } 237 | .ui-icon-shuffle { background-position: -80px -80px; } 238 | .ui-icon-transfer-e-w { background-position: -96px -80px; } 239 | .ui-icon-transferthick-e-w { background-position: -112px -80px; } 240 | .ui-icon-folder-collapsed { background-position: 0 -96px; } 241 | .ui-icon-folder-open { background-position: -16px -96px; } 242 | .ui-icon-document { background-position: -32px -96px; } 243 | .ui-icon-document-b { background-position: -48px -96px; } 244 | .ui-icon-note { background-position: -64px -96px; } 245 | .ui-icon-mail-closed { background-position: -80px -96px; } 246 | .ui-icon-mail-open { background-position: -96px -96px; } 247 | .ui-icon-suitcase { background-position: -112px -96px; } 248 | .ui-icon-comment { background-position: -128px -96px; } 249 | .ui-icon-person { background-position: -144px -96px; } 250 | .ui-icon-print { background-position: -160px -96px; } 251 | .ui-icon-trash { background-position: -176px -96px; } 252 | .ui-icon-locked { background-position: -192px -96px; } 253 | .ui-icon-unlocked { background-position: -208px -96px; } 254 | .ui-icon-bookmark { background-position: -224px -96px; } 255 | .ui-icon-tag { background-position: -240px -96px; } 256 | .ui-icon-home { background-position: 0 -112px; } 257 | .ui-icon-flag { background-position: -16px -112px; } 258 | .ui-icon-calendar { background-position: -32px -112px; } 259 | .ui-icon-cart { background-position: -48px -112px; } 260 | .ui-icon-pencil { background-position: -64px -112px; } 261 | .ui-icon-clock { background-position: -80px -112px; } 262 | .ui-icon-disk { background-position: -96px -112px; } 263 | .ui-icon-calculator { background-position: -112px -112px; } 264 | .ui-icon-zoomin { background-position: -128px -112px; } 265 | .ui-icon-zoomout { background-position: -144px -112px; } 266 | .ui-icon-search { background-position: -160px -112px; } 267 | .ui-icon-wrench { background-position: -176px -112px; } 268 | .ui-icon-gear { background-position: -192px -112px; } 269 | .ui-icon-heart { background-position: -208px -112px; } 270 | .ui-icon-star { background-position: -224px -112px; } 271 | .ui-icon-link { background-position: -240px -112px; } 272 | .ui-icon-cancel { background-position: 0 -128px; } 273 | .ui-icon-plus { background-position: -16px -128px; } 274 | .ui-icon-plusthick { background-position: -32px -128px; } 275 | .ui-icon-minus { background-position: -48px -128px; } 276 | .ui-icon-minusthick { background-position: -64px -128px; } 277 | .ui-icon-close { background-position: -80px -128px; } 278 | .ui-icon-closethick { background-position: -96px -128px; } 279 | .ui-icon-key { background-position: -112px -128px; } 280 | .ui-icon-lightbulb { background-position: -128px -128px; } 281 | .ui-icon-scissors { background-position: -144px -128px; } 282 | .ui-icon-clipboard { background-position: -160px -128px; } 283 | .ui-icon-copy { background-position: -176px -128px; } 284 | .ui-icon-contact { background-position: -192px -128px; } 285 | .ui-icon-image { background-position: -208px -128px; } 286 | .ui-icon-video { background-position: -224px -128px; } 287 | .ui-icon-script { background-position: -240px -128px; } 288 | .ui-icon-alert { background-position: 0 -144px; } 289 | .ui-icon-info { background-position: -16px -144px; } 290 | .ui-icon-notice { background-position: -32px -144px; } 291 | .ui-icon-help { background-position: -48px -144px; } 292 | .ui-icon-check { background-position: -64px -144px; } 293 | .ui-icon-bullet { background-position: -80px -144px; } 294 | .ui-icon-radio-off { background-position: -96px -144px; } 295 | .ui-icon-radio-on { background-position: -112px -144px; } 296 | .ui-icon-pin-w { background-position: -128px -144px; } 297 | .ui-icon-pin-s { background-position: -144px -144px; } 298 | .ui-icon-play { background-position: 0 -160px; } 299 | .ui-icon-pause { background-position: -16px -160px; } 300 | .ui-icon-seek-next { background-position: -32px -160px; } 301 | .ui-icon-seek-prev { background-position: -48px -160px; } 302 | .ui-icon-seek-end { background-position: -64px -160px; } 303 | .ui-icon-seek-start { background-position: -80px -160px; } 304 | /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ 305 | .ui-icon-seek-first { background-position: -80px -160px; } 306 | .ui-icon-stop { background-position: -96px -160px; } 307 | .ui-icon-eject { background-position: -112px -160px; } 308 | .ui-icon-volume-off { background-position: -128px -160px; } 309 | .ui-icon-volume-on { background-position: -144px -160px; } 310 | .ui-icon-power { background-position: 0 -176px; } 311 | .ui-icon-signal-diag { background-position: -16px -176px; } 312 | .ui-icon-signal { background-position: -32px -176px; } 313 | .ui-icon-battery-0 { background-position: -48px -176px; } 314 | .ui-icon-battery-1 { background-position: -64px -176px; } 315 | .ui-icon-battery-2 { background-position: -80px -176px; } 316 | .ui-icon-battery-3 { background-position: -96px -176px; } 317 | .ui-icon-circle-plus { background-position: 0 -192px; } 318 | .ui-icon-circle-minus { background-position: -16px -192px; } 319 | .ui-icon-circle-close { background-position: -32px -192px; } 320 | .ui-icon-circle-triangle-e { background-position: -48px -192px; } 321 | .ui-icon-circle-triangle-s { background-position: -64px -192px; } 322 | .ui-icon-circle-triangle-w { background-position: -80px -192px; } 323 | .ui-icon-circle-triangle-n { background-position: -96px -192px; } 324 | .ui-icon-circle-arrow-e { background-position: -112px -192px; } 325 | .ui-icon-circle-arrow-s { background-position: -128px -192px; } 326 | .ui-icon-circle-arrow-w { background-position: -144px -192px; } 327 | .ui-icon-circle-arrow-n { background-position: -160px -192px; } 328 | .ui-icon-circle-zoomin { background-position: -176px -192px; } 329 | .ui-icon-circle-zoomout { background-position: -192px -192px; } 330 | .ui-icon-circle-check { background-position: -208px -192px; } 331 | .ui-icon-circlesmall-plus { background-position: 0 -208px; } 332 | .ui-icon-circlesmall-minus { background-position: -16px -208px; } 333 | .ui-icon-circlesmall-close { background-position: -32px -208px; } 334 | .ui-icon-squaresmall-plus { background-position: -48px -208px; } 335 | .ui-icon-squaresmall-minus { background-position: -64px -208px; } 336 | .ui-icon-squaresmall-close { background-position: -80px -208px; } 337 | .ui-icon-grip-dotted-vertical { background-position: 0 -224px; } 338 | .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } 339 | .ui-icon-grip-solid-vertical { background-position: -32px -224px; } 340 | .ui-icon-grip-solid-horizontal { background-position: -48px -224px; } 341 | .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } 342 | .ui-icon-grip-diagonal-se { background-position: -80px -224px; } 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | /* LEGACY */ 367 | 368 | .action-button { 369 | background:#D4D5C9; 370 | padding:5px; 371 | border-radius: 5px; 372 | display:inline; 373 | margin:10px 5px 10px 0; 374 | } 375 | 376 | a {cursor:pointer;} 377 | 378 | .shadow { 379 | -moz-box-shadow: 0px 3px 3px #666; 380 | -webkit-box-shadow: 0px 3px 3px #666; 381 | box-shadow: 0px 3px 3px #666; 382 | } 383 | 384 | #splash { 385 | padding-top: 240px; 386 | height: auto !important; 387 | background: url('../img/splash.png') no-repeat scroll top left; 388 | text-align: 'center'; 389 | } 390 | 391 | 392 | #projectTitle { 393 | font-size:20px; 394 | -moz-border-radius:4px 4px 4px 4px; 395 | background-color:transparent; 396 | border:1px solid transparent; 397 | height:18px; 398 | width:80% !important; 399 | padding-left:42px; 400 | padding-top:30px; 401 | } 402 | 403 | #instructions { 404 | margin-top: 1px; 405 | border:1px solid #AAAAAA; 406 | position: relative; 407 | padding: 10px; 408 | height: 200px; 409 | display: none; 410 | } 411 | 412 | .remove { 413 | cursor: pointer; 414 | position: absolute; 415 | right: 2px; 416 | top: 2px; 417 | width: 16px; 418 | height: 16px; 419 | padding: 2px; 420 | } 421 | 422 | .remove span, .remove-milestone { 423 | background-image:url("../img/ui-icons_888888_256x240.png"); 424 | background-position:-80px -128px; 425 | background-repeat:no-repeat; 426 | display:block; 427 | overflow:hidden; 428 | text-indent:-99999px; 429 | } 430 | 431 | #main { 432 | position: absolute; 433 | top: 60px; 434 | right: 0px; 435 | left: 0px; 436 | bottom: 95px; 437 | padding-left: 30px; 438 | padding-right: 30px; 439 | overflow: auto; 440 | min-width: 700px; 441 | padding-bottom: 20px; 442 | } 443 | 444 | 445 | #toolbar { 446 | padding: 10px; 447 | } 448 | 449 | #milestones { 450 | height:50px; 451 | margin:10px; 452 | } 453 | 454 | label img { 455 | margin-left: 8px; 456 | vertical-align: middle; 457 | } 458 | 459 | #milestones ul li{ 460 | display:inline; 461 | list-style: none; 462 | width:150px; 463 | font-size:16px; 464 | background:#D4D58F; 465 | padding:5px; 466 | border-radius: 5px; 467 | } 468 | 469 | 470 | input, .inlineEdit { 471 | height: 20px; 472 | } 473 | 474 | .add-milestone { 475 | position: absolute; 476 | right: 40px; 477 | top: 10px; 478 | } 479 | 480 | .toggle-view { 481 | position: absolute; 482 | right: 190px; 483 | top: 10px; 484 | } 485 | 486 | .learn-shortcuts { 487 | position: absolute; 488 | right: 380px; 489 | top: 10px; 490 | 491 | } 492 | 493 | 494 | .scenario .step input[type="text"] { 495 | margin-left:0px; 496 | width:96%; 497 | } 498 | 499 | .scenario, .feature { 500 | overflow: hidden; 501 | } 502 | 503 | .feature { 504 | padding-bottom: 20px; 505 | } 506 | 507 | .add-scenario, .add-feature { 508 | margin-top: 4px; 509 | } 510 | 511 | .steps { 512 | 513 | } 514 | 515 | .step { 516 | width: 100%; 517 | } 518 | 519 | .step .grip-col { 520 | width: 20px; 521 | } 522 | 523 | .step .operator-col { 524 | padding-right:10px; 525 | } 526 | 527 | .step .content-col { 528 | width: 100%; 529 | } 530 | 531 | .step .delete-col { 532 | width: 20px; 533 | } 534 | 535 | .step .delete-col div { 536 | position: relative; 537 | top:0px; 538 | left:0px; 539 | padding: 2px; 540 | margin-left: 10px; 541 | } 542 | 543 | .grip {float:left; margin:2px 5px; } 544 | .step-close {float:left; margin-left:10px; margin-top:5px;} 545 | .grip {float:left; margin:2px 5px; } 546 | 547 | .ui-accordion-content{ 548 | overflow:hidden !important;} 549 | 550 | .textPad{ 551 | display:none; 552 | } 553 | .textPad textarea{ 554 | width:100%; 555 | height:1000px; 556 | } 557 | 558 | footer { 559 | background: #555 url('../img/footer.png') repeat-x 0px 0px; 560 | position: absolute; 561 | bottom: 35px; 562 | right: 0px; 563 | left: 0px; 564 | height: 60px; 565 | border-top: 1px solid #999; 566 | color: #fff; 567 | cursor: pointer; 568 | } 569 | 570 | footer table { 571 | width: 100%; 572 | } 573 | 574 | footer table td{ 575 | padding: 20px; 576 | text-align: center; 577 | vertical-align: middle; 578 | font-size: 1.2em; 579 | } 580 | 581 | footer div { 582 | cursor: pointer; 583 | } 584 | 585 | #logo { 586 | position: absolute; 587 | top: 10px; 588 | right: 0px; 589 | background: url('../img/logo.png') no-repeat scroll top left; 590 | width: 233px; 591 | height: 40px; 592 | } 593 | 594 | #settings { 595 | background: url('../img/settings.png') no-repeat scroll top left; 596 | width: 61px; 597 | height: 53px; 598 | } 599 | 600 | #export { 601 | float: right; 602 | background: url('../img/export.png') no-repeat scroll top left; 603 | width: 61px; 604 | height: 53px; 605 | } 606 | 607 | #features { 608 | background: url('../img/features.png') no-repeat scroll top left; 609 | width: 61px; 610 | height: 53px; 611 | } 612 | 613 | #feature-add { 614 | display: none; 615 | } 616 | 617 | ul { 618 | margin: 2px; 619 | } 620 | 621 | .ui-dialog .ui-dialog-titlebar { 622 | display: none; 623 | } 624 | 625 | #toolbar .ui-button-text-only .ui-button-text { 626 | padding:2px 2px 2px 8px; 627 | } 628 | 629 | #toolbar { 630 | height: 35px; 631 | } 632 | 633 | #toolbar ul { 634 | list-style: none; 635 | } 636 | 637 | #toolbar ul li { 638 | float: left; 639 | } 640 | 641 | #export-stubs { 642 | display:none; 643 | } 644 | 645 | #export-stubs code{ 646 | width:200px; 647 | } 648 | 649 | button { 650 | cursor: pointer; 651 | border: 0; 652 | } 653 | 654 | #container{ display:none; } 655 | #progressBar{ 656 | border:1px solid #D3D3D3; 657 | float:left; 658 | height:29px; 659 | position:relative; 660 | width:555px; 661 | } 662 | 663 | #progressBar .ui-slider-handle { 664 | display: none; 665 | } 666 | 667 | #progressBar .ui-slider-horizontal { 668 | 669 | } 670 | 671 | #progressBar .ui-slider-range-min { 672 | background: url("../img/ui-bg_highlight-soft_75_e6e6e6_1x100.png") repeat-x scroll 50% 50% #E6E6E6; 673 | } 674 | 675 | #okay { 676 | bottom:2px; 677 | left:15px; 678 | } 679 | -------------------------------------------------------------------------------- /client/css/handheld.css: -------------------------------------------------------------------------------- 1 | 2 | * { 3 | float: none; 4 | font-size: 80%; 5 | background: #fff; 6 | color: #000; 7 | } -------------------------------------------------------------------------------- /client/css/jquery-ui-1.8.4.custom.css: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery UI CSS Framework @VERSION 3 | * 4 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) 5 | * Dual licensed under the MIT or GPL Version 2 licenses. 6 | * http://jquery.org/license 7 | * 8 | * http://docs.jquery.com/UI/Theming/API 9 | */ 10 | 11 | /* Layout helpers 12 | ----------------------------------*/ 13 | .ui-helper-hidden { display: none; } 14 | .ui-helper-hidden-accessible { position: absolute; left: -99999999px; } 15 | .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } 16 | .ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } 17 | .ui-helper-clearfix { display: inline-block; } 18 | /* required comment for clearfix to work in Opera \*/ 19 | * html .ui-helper-clearfix { height:1%; } 20 | .ui-helper-clearfix { display:block; } 21 | /* end clearfix */ 22 | .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } 23 | 24 | 25 | /* Interaction Cues 26 | ----------------------------------*/ 27 | .ui-state-disabled { cursor: default !important; } 28 | 29 | 30 | /* Icons 31 | ----------------------------------*/ 32 | 33 | /* states and images */ 34 | .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } 35 | 36 | 37 | /* Misc visuals 38 | ----------------------------------*/ 39 | 40 | /* Overlays */ 41 | .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } 42 | 43 | 44 | /* 45 | * jQuery UI CSS Framework @VERSION 46 | * 47 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) 48 | * Dual licensed under the MIT or GPL Version 2 licenses. 49 | * http://jquery.org/license 50 | * 51 | * http://docs.jquery.com/UI/Theming/API 52 | * 53 | * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=03_highlight_soft.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=05_inset_soft.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px 54 | */ 55 | 56 | 57 | /* Component containers 58 | ----------------------------------*/ 59 | .ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; } 60 | .ui-widget .ui-widget { font-size: 1em; } 61 | .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; } 62 | .ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(../img/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; } 63 | .ui-widget-content a { color: #222222; } 64 | .ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(../img/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; } 65 | .ui-widget-header a { color: #222222; } 66 | 67 | /* Interaction states 68 | ----------------------------------*/ 69 | .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(../img/ui-bg_highlight-soft_75_e6e6e6_1x100.png) 50% 50% repeat-x; font-weight: normal; color: #555555; } 70 | .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; } 71 | .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(../img/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } 72 | .ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; } 73 | .ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(../img/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } 74 | .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; } 75 | .ui-widget :active { outline: none; } 76 | 77 | /* Interaction Cues 78 | ----------------------------------*/ 79 | .ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(../img/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; } 80 | .ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } 81 | .ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(../img/ui-bg_inset-soft_95_fef1ec_1x100.png) 50% bottom repeat-x; color: #cd0a0a; } 82 | .ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; } 83 | .ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; } 84 | .ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } 85 | .ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } 86 | .ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } 87 | 88 | /* Icons 89 | ----------------------------------*/ 90 | 91 | /* states and images */ 92 | .ui-icon { width: 16px; height: 16px; background-image: url(../img/ui-icons_222222_256x240.png); } 93 | .ui-widget-content .ui-icon {background-image: url(../img/ui-icons_222222_256x240.png); } 94 | .ui-widget-header .ui-icon {background-image: url(../img/ui-icons_222222_256x240.png); } 95 | .ui-state-default .ui-icon { background-image: url(../img/ui-icons_888888_256x240.png); } 96 | .ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(../img/ui-icons_454545_256x240.png); } 97 | .ui-state-active .ui-icon {background-image: url(../img/ui-icons_454545_256x240.png); } 98 | .ui-state-highlight .ui-icon {background-image: url(../img/ui-icons_2e83ff_256x240.png); } 99 | .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(../img/ui-icons_cd0a0a_256x240.png); } 100 | 101 | /* positioning */ 102 | .ui-icon-carat-1-n { background-position: 0 0; } 103 | .ui-icon-carat-1-ne { background-position: -16px 0; } 104 | .ui-icon-carat-1-e { background-position: -32px 0; } 105 | .ui-icon-carat-1-se { background-position: -48px 0; } 106 | .ui-icon-carat-1-s { background-position: -64px 0; } 107 | .ui-icon-carat-1-sw { background-position: -80px 0; } 108 | .ui-icon-carat-1-w { background-position: -96px 0; } 109 | .ui-icon-carat-1-nw { background-position: -112px 0; } 110 | .ui-icon-carat-2-n-s { background-position: -128px 0; } 111 | .ui-icon-carat-2-e-w { background-position: -144px 0; } 112 | .ui-icon-triangle-1-n { background-position: 0 -16px; } 113 | .ui-icon-triangle-1-ne { background-position: -16px -16px; } 114 | .ui-icon-triangle-1-e { background-position: -32px -16px; } 115 | .ui-icon-triangle-1-se { background-position: -48px -16px; } 116 | .ui-icon-triangle-1-s { background-position: -64px -16px; } 117 | .ui-icon-triangle-1-sw { background-position: -80px -16px; } 118 | .ui-icon-triangle-1-w { background-position: -96px -16px; } 119 | .ui-icon-triangle-1-nw { background-position: -112px -16px; } 120 | .ui-icon-triangle-2-n-s { background-position: -128px -16px; } 121 | .ui-icon-triangle-2-e-w { background-position: -144px -16px; } 122 | .ui-icon-arrow-1-n { background-position: 0 -32px; } 123 | .ui-icon-arrow-1-ne { background-position: -16px -32px; } 124 | .ui-icon-arrow-1-e { background-position: -32px -32px; } 125 | .ui-icon-arrow-1-se { background-position: -48px -32px; } 126 | .ui-icon-arrow-1-s { background-position: -64px -32px; } 127 | .ui-icon-arrow-1-sw { background-position: -80px -32px; } 128 | .ui-icon-arrow-1-w { background-position: -96px -32px; } 129 | .ui-icon-arrow-1-nw { background-position: -112px -32px; } 130 | .ui-icon-arrow-2-n-s { background-position: -128px -32px; } 131 | .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } 132 | .ui-icon-arrow-2-e-w { background-position: -160px -32px; } 133 | .ui-icon-arrow-2-se-nw { background-position: -176px -32px; } 134 | .ui-icon-arrowstop-1-n { background-position: -192px -32px; } 135 | .ui-icon-arrowstop-1-e { background-position: -208px -32px; } 136 | .ui-icon-arrowstop-1-s { background-position: -224px -32px; } 137 | .ui-icon-arrowstop-1-w { background-position: -240px -32px; } 138 | .ui-icon-arrowthick-1-n { background-position: 0 -48px; } 139 | .ui-icon-arrowthick-1-ne { background-position: -16px -48px; } 140 | .ui-icon-arrowthick-1-e { background-position: -32px -48px; } 141 | .ui-icon-arrowthick-1-se { background-position: -48px -48px; } 142 | .ui-icon-arrowthick-1-s { background-position: -64px -48px; } 143 | .ui-icon-arrowthick-1-sw { background-position: -80px -48px; } 144 | .ui-icon-arrowthick-1-w { background-position: -96px -48px; } 145 | .ui-icon-arrowthick-1-nw { background-position: -112px -48px; } 146 | .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } 147 | .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } 148 | .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } 149 | .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } 150 | .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } 151 | .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } 152 | .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } 153 | .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } 154 | .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } 155 | .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } 156 | .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } 157 | .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } 158 | .ui-icon-arrowreturn-1-w { background-position: -64px -64px; } 159 | .ui-icon-arrowreturn-1-n { background-position: -80px -64px; } 160 | .ui-icon-arrowreturn-1-e { background-position: -96px -64px; } 161 | .ui-icon-arrowreturn-1-s { background-position: -112px -64px; } 162 | .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } 163 | .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } 164 | .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } 165 | .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } 166 | .ui-icon-arrow-4 { background-position: 0 -80px; } 167 | .ui-icon-arrow-4-diag { background-position: -16px -80px; } 168 | .ui-icon-extlink { background-position: -32px -80px; } 169 | .ui-icon-newwin { background-position: -48px -80px; } 170 | .ui-icon-refresh { background-position: -64px -80px; } 171 | .ui-icon-shuffle { background-position: -80px -80px; } 172 | .ui-icon-transfer-e-w { background-position: -96px -80px; } 173 | .ui-icon-transferthick-e-w { background-position: -112px -80px; } 174 | .ui-icon-folder-collapsed { background-position: 0 -96px; } 175 | .ui-icon-folder-open { background-position: -16px -96px; } 176 | .ui-icon-document { background-position: -32px -96px; } 177 | .ui-icon-document-b { background-position: -48px -96px; } 178 | .ui-icon-note { background-position: -64px -96px; } 179 | .ui-icon-mail-closed { background-position: -80px -96px; } 180 | .ui-icon-mail-open { background-position: -96px -96px; } 181 | .ui-icon-suitcase { background-position: -112px -96px; } 182 | .ui-icon-comment { background-position: -128px -96px; } 183 | .ui-icon-person { background-position: -144px -96px; } 184 | .ui-icon-print { background-position: -160px -96px; } 185 | .ui-icon-trash { background-position: -176px -96px; } 186 | .ui-icon-locked { background-position: -192px -96px; } 187 | .ui-icon-unlocked { background-position: -208px -96px; } 188 | .ui-icon-bookmark { background-position: -224px -96px; } 189 | .ui-icon-tag { background-position: -240px -96px; } 190 | .ui-icon-home { background-position: 0 -112px; } 191 | .ui-icon-flag { background-position: -16px -112px; } 192 | .ui-icon-calendar { background-position: -32px -112px; } 193 | .ui-icon-cart { background-position: -48px -112px; } 194 | .ui-icon-pencil { background-position: -64px -112px; } 195 | .ui-icon-clock { background-position: -80px -112px; } 196 | .ui-icon-disk { background-position: -96px -112px; } 197 | .ui-icon-calculator { background-position: -112px -112px; } 198 | .ui-icon-zoomin { background-position: -128px -112px; } 199 | .ui-icon-zoomout { background-position: -144px -112px; } 200 | .ui-icon-search { background-position: -160px -112px; } 201 | .ui-icon-wrench { background-position: -176px -112px; } 202 | .ui-icon-gear { background-position: -192px -112px; } 203 | .ui-icon-heart { background-position: -208px -112px; } 204 | .ui-icon-star { background-position: -224px -112px; } 205 | .ui-icon-link { background-position: -240px -112px; } 206 | .ui-icon-cancel { background-position: 0 -128px; } 207 | .ui-icon-plus { background-position: -16px -128px; } 208 | .ui-icon-plusthick { background-position: -32px -128px; } 209 | .ui-icon-minus { background-position: -48px -128px; } 210 | .ui-icon-minusthick { background-position: -64px -128px; } 211 | .ui-icon-close { background-position: -80px -128px; } 212 | .ui-icon-closethick { background-position: -96px -128px; } 213 | .ui-icon-key { background-position: -112px -128px; } 214 | .ui-icon-lightbulb { background-position: -128px -128px; } 215 | .ui-icon-scissors { background-position: -144px -128px; } 216 | .ui-icon-clipboard { background-position: -160px -128px; } 217 | .ui-icon-copy { background-position: -176px -128px; } 218 | .ui-icon-contact { background-position: -192px -128px; } 219 | .ui-icon-image { background-position: -208px -128px; } 220 | .ui-icon-video { background-position: -224px -128px; } 221 | .ui-icon-script { background-position: -240px -128px; } 222 | .ui-icon-alert { background-position: 0 -144px; } 223 | .ui-icon-info { background-position: -16px -144px; } 224 | .ui-icon-notice { background-position: -32px -144px; } 225 | .ui-icon-help { background-position: -48px -144px; } 226 | .ui-icon-check { background-position: -64px -144px; } 227 | .ui-icon-bullet { background-position: -80px -144px; } 228 | .ui-icon-radio-off { background-position: -96px -144px; } 229 | .ui-icon-radio-on { background-position: -112px -144px; } 230 | .ui-icon-pin-w { background-position: -128px -144px; } 231 | .ui-icon-pin-s { background-position: -144px -144px; } 232 | .ui-icon-play { background-position: 0 -160px; } 233 | .ui-icon-pause { background-position: -16px -160px; } 234 | .ui-icon-seek-next { background-position: -32px -160px; } 235 | .ui-icon-seek-prev { background-position: -48px -160px; } 236 | .ui-icon-seek-end { background-position: -64px -160px; } 237 | .ui-icon-seek-start { background-position: -80px -160px; } 238 | /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ 239 | .ui-icon-seek-first { background-position: -80px -160px; } 240 | .ui-icon-stop { background-position: -96px -160px; } 241 | .ui-icon-eject { background-position: -112px -160px; } 242 | .ui-icon-volume-off { background-position: -128px -160px; } 243 | .ui-icon-volume-on { background-position: -144px -160px; } 244 | .ui-icon-power { background-position: 0 -176px; } 245 | .ui-icon-signal-diag { background-position: -16px -176px; } 246 | .ui-icon-signal { background-position: -32px -176px; } 247 | .ui-icon-battery-0 { background-position: -48px -176px; } 248 | .ui-icon-battery-1 { background-position: -64px -176px; } 249 | .ui-icon-battery-2 { background-position: -80px -176px; } 250 | .ui-icon-battery-3 { background-position: -96px -176px; } 251 | .ui-icon-circle-plus { background-position: 0 -192px; } 252 | .ui-icon-circle-minus { background-position: -16px -192px; } 253 | .ui-icon-circle-close { background-position: -32px -192px; } 254 | .ui-icon-circle-triangle-e { background-position: -48px -192px; } 255 | .ui-icon-circle-triangle-s { background-position: -64px -192px; } 256 | .ui-icon-circle-triangle-w { background-position: -80px -192px; } 257 | .ui-icon-circle-triangle-n { background-position: -96px -192px; } 258 | .ui-icon-circle-arrow-e { background-position: -112px -192px; } 259 | .ui-icon-circle-arrow-s { background-position: -128px -192px; } 260 | .ui-icon-circle-arrow-w { background-position: -144px -192px; } 261 | .ui-icon-circle-arrow-n { background-position: -160px -192px; } 262 | .ui-icon-circle-zoomin { background-position: -176px -192px; } 263 | .ui-icon-circle-zoomout { background-position: -192px -192px; } 264 | .ui-icon-circle-check { background-position: -208px -192px; } 265 | .ui-icon-circlesmall-plus { background-position: 0 -208px; } 266 | .ui-icon-circlesmall-minus { background-position: -16px -208px; } 267 | .ui-icon-circlesmall-close { background-position: -32px -208px; } 268 | .ui-icon-squaresmall-plus { background-position: -48px -208px; } 269 | .ui-icon-squaresmall-minus { background-position: -64px -208px; } 270 | .ui-icon-squaresmall-close { background-position: -80px -208px; } 271 | .ui-icon-grip-dotted-vertical { background-position: 0 -224px; } 272 | .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } 273 | .ui-icon-grip-solid-vertical { background-position: -32px -224px; } 274 | .ui-icon-grip-solid-horizontal { background-position: -48px -224px; } 275 | .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } 276 | .ui-icon-grip-diagonal-se { background-position: -80px -224px; } 277 | 278 | 279 | /* Misc visuals 280 | ----------------------------------*/ 281 | 282 | /* Corner radius */ 283 | .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; } 284 | .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; } 285 | .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } 286 | .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } 287 | .ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; } 288 | .ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } 289 | .ui-corner-right { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } 290 | .ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } 291 | .ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; } 292 | 293 | /* Overlays */ 294 | .ui-widget-overlay { background: #aaaaaa url(../img/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } 295 | .ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(../img/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/* 296 | * jQuery UI Resizable @VERSION 297 | * 298 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) 299 | * Dual licensed under the MIT or GPL Version 2 licenses. 300 | * http://jquery.org/license 301 | * 302 | * http://docs.jquery.com/UI/Resizable#theming 303 | */ 304 | .ui-resizable { position: relative;} 305 | .ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;} 306 | .ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } 307 | .ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; } 308 | .ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } 309 | .ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } 310 | .ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; } 311 | .ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } 312 | .ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } 313 | .ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } 314 | .ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* 315 | * jQuery UI Selectable @VERSION 316 | * 317 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) 318 | * Dual licensed under the MIT or GPL Version 2 licenses. 319 | * http://jquery.org/license 320 | * 321 | * http://docs.jquery.com/UI/Selectable#theming 322 | */ 323 | .ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; } 324 | /* 325 | * jQuery UI Accordion @VERSION 326 | * 327 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) 328 | * Dual licensed under the MIT or GPL Version 2 licenses. 329 | * http://jquery.org/license 330 | * 331 | * http://docs.jquery.com/UI/Accordion#theming 332 | */ 333 | /* IE/Win - Fix animation bug - #4615 */ 334 | .ui-accordion { width: 100%; } 335 | .ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; height: 26px; } 336 | .ui-accordion .ui-accordion-li-fix { display: inline; } 337 | .ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } 338 | .ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: 4px; } 339 | .ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; } 340 | .ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } 341 | .ui-accordion .ui-accordion-content { padding: 10px; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; } 342 | .ui-accordion .ui-accordion-content-active { display: block; }/* 343 | * jQuery UI Autocomplete @VERSION 344 | * 345 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) 346 | * Dual licensed under the MIT or GPL Version 2 licenses. 347 | * http://jquery.org/license 348 | * 349 | * http://docs.jquery.com/UI/Autocomplete#theming 350 | */ 351 | .ui-autocomplete { position: absolute; cursor: default; } 352 | 353 | /* workarounds */ 354 | * html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ 355 | 356 | /* 357 | * jQuery UI Menu @VERSION 358 | * 359 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) 360 | * Dual licensed under the MIT or GPL Version 2 licenses. 361 | * http://jquery.org/license 362 | * 363 | * http://docs.jquery.com/UI/Menu#theming 364 | */ 365 | .ui-menu { 366 | list-style:none; 367 | padding: 2px; 368 | margin: 0; 369 | display:block; 370 | float: left; 371 | } 372 | .ui-menu .ui-menu { 373 | margin-top: -3px; 374 | } 375 | .ui-menu .ui-menu-item { 376 | margin:0; 377 | padding: 0; 378 | zoom: 1; 379 | float: left; 380 | clear: left; 381 | width: 100%; 382 | } 383 | .ui-menu .ui-menu-item a { 384 | text-decoration:none; 385 | display:block; 386 | padding:.2em .4em; 387 | line-height:1.5; 388 | zoom:1; 389 | } 390 | .ui-menu .ui-menu-item a.ui-state-hover, 391 | .ui-menu .ui-menu-item a.ui-state-active { 392 | font-weight: normal; 393 | margin: -1px; 394 | } 395 | /* 396 | * jQuery UI Button @VERSION 397 | * 398 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) 399 | * Dual licensed under the MIT or GPL Version 2 licenses. 400 | * http://jquery.org/license 401 | * 402 | * http://docs.jquery.com/UI/Button#theming 403 | */ 404 | .ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */ 405 | .ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */ 406 | button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */ 407 | .ui-button-icons-only { width: 3.4em; } 408 | button.ui-button-icons-only { width: 3.7em; } 409 | 410 | /*button text element */ 411 | .ui-button .ui-button-text { display: block; line-height: 1.4; } 412 | .ui-button-text-only .ui-button-text { padding: .4em 1em; } 413 | .ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; } 414 | .ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; } 415 | .ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; } 416 | .ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; } 417 | /* no icon support for input elements, provide padding by default */ 418 | input.ui-button { padding: .4em 1em; } 419 | 420 | /*button icon element(s) */ 421 | .ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; } 422 | .ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; } 423 | .ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; } 424 | .ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } 425 | .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } 426 | 427 | /*button sets*/ 428 | .ui-buttonset { margin-right: 7px; } 429 | .ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; } 430 | 431 | /* workarounds */ 432 | button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */ 433 | /* 434 | * jQuery UI Dialog @VERSION 435 | * 436 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) 437 | * Dual licensed under the MIT or GPL Version 2 licenses. 438 | * http://jquery.org/license 439 | * 440 | * http://docs.jquery.com/UI/Dialog#theming 441 | */ 442 | .ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; } 443 | .ui-dialog .ui-dialog-titlebar { padding: .5em 1em .3em; position: relative; } 444 | .ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .2em 0; } 445 | .ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } 446 | .ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } 447 | .ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } 448 | .ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } 449 | .ui-dialog .ui-dialog-buttonpane { text-align: right; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } 450 | .ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; } 451 | .ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; } 452 | .ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } 453 | .ui-draggable .ui-dialog-titlebar { cursor: move; } 454 | /* 455 | * jQuery UI Slider @VERSION 456 | * 457 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) 458 | * Dual licensed under the MIT or GPL Version 2 licenses. 459 | * http://jquery.org/license 460 | * 461 | * http://docs.jquery.com/UI/Slider#theming 462 | */ 463 | .ui-slider { position: relative; text-align: left; } 464 | .ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } 465 | .ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; } 466 | 467 | .ui-slider-horizontal { height: .8em; } 468 | .ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } 469 | .ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } 470 | .ui-slider-horizontal .ui-slider-range-min { left: 0; } 471 | .ui-slider-horizontal .ui-slider-range-max { right: 0; } 472 | 473 | .ui-slider-vertical { width: .8em; height: 100px; } 474 | .ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } 475 | .ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } 476 | .ui-slider-vertical .ui-slider-range-min { bottom: 0; } 477 | .ui-slider-vertical .ui-slider-range-max { top: 0; }/* 478 | * jQuery UI Tabs @VERSION 479 | * 480 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) 481 | * Dual licensed under the MIT or GPL Version 2 licenses. 482 | * http://jquery.org/license 483 | * 484 | * http://docs.jquery.com/UI/Tabs#theming 485 | */ 486 | .ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ 487 | .ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; } 488 | .ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; } 489 | .ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; } 490 | .ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; } 491 | .ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } 492 | .ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ 493 | .ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; } 494 | .ui-tabs .ui-tabs-hide { display: none !important; } 495 | /* 496 | * jQuery UI Datepicker @VERSION 497 | * 498 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) 499 | * Dual licensed under the MIT or GPL Version 2 licenses. 500 | * http://jquery.org/license 501 | * 502 | * http://docs.jquery.com/UI/Datepicker#theming 503 | */ 504 | .ui-datepicker { width: 17em; padding: .2em .2em 0; } 505 | .ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } 506 | .ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } 507 | .ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } 508 | .ui-datepicker .ui-datepicker-prev { left:2px; } 509 | .ui-datepicker .ui-datepicker-next { right:2px; } 510 | .ui-datepicker .ui-datepicker-prev-hover { left:1px; } 511 | .ui-datepicker .ui-datepicker-next-hover { right:1px; } 512 | .ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } 513 | .ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } 514 | .ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; } 515 | .ui-datepicker select.ui-datepicker-month-year {width: 100%;} 516 | .ui-datepicker select.ui-datepicker-month, 517 | .ui-datepicker select.ui-datepicker-year { width: 49%;} 518 | .ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } 519 | .ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } 520 | .ui-datepicker td { border: 0; padding: 1px; } 521 | .ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } 522 | .ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } 523 | .ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } 524 | .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } 525 | 526 | /* with multiple calendars */ 527 | .ui-datepicker.ui-datepicker-multi { width:auto; } 528 | .ui-datepicker-multi .ui-datepicker-group { float:left; } 529 | .ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } 530 | .ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } 531 | .ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } 532 | .ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } 533 | .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } 534 | .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } 535 | .ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } 536 | .ui-datepicker-row-break { clear:both; width:100%; } 537 | 538 | /* RTL support */ 539 | .ui-datepicker-rtl { direction: rtl; } 540 | .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } 541 | .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } 542 | .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } 543 | .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } 544 | .ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } 545 | .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } 546 | .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } 547 | .ui-datepicker-rtl .ui-datepicker-group { float:right; } 548 | .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } 549 | .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } 550 | 551 | /* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ 552 | .ui-datepicker-cover { 553 | display: none; /*sorry for IE5*/ 554 | display/**/: block; /*sorry for IE5*/ 555 | position: absolute; /*must have*/ 556 | z-index: -1; /*must have*/ 557 | filter: mask(); /*must have*/ 558 | top: -4px; /*must have*/ 559 | left: -4px; /*must have*/ 560 | width: 200px; /*must have*/ 561 | height: 200px; /*must have*/ 562 | }/* 563 | * jQuery UI Progressbar @VERSION 564 | * 565 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) 566 | * Dual licensed under the MIT or GPL Version 2 licenses. 567 | * http://jquery.org/license 568 | * 569 | * http://docs.jquery.com/UI/Progressbar#theming 570 | */ 571 | .ui-progressbar { height:2em; text-align: left; } 572 | .ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; } -------------------------------------------------------------------------------- /client/css/style.css: -------------------------------------------------------------------------------- 1 | html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, 2 | abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, 3 | small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, 4 | fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, 5 | article, aside, figure, footer, header, hgroup, menu, nav, section, menu, 6 | time, mark, audio, video { 7 | margin:0; 8 | padding:0; 9 | border:0; 10 | outline:0; 11 | font-size:100%; 12 | vertical-align:baseline; 13 | background:transparent; 14 | } 15 | article, aside, figure, footer, header, hgroup, nav, section { display:block; } 16 | nav ul { list-style:none; } 17 | blockquote, q { quotes:none; } 18 | blockquote:before, blockquote:after, q:before, q:after { content:''; content:none; } 19 | a { margin:0; padding:0; font-size:100%; vertical-align:baseline; background:transparent; } 20 | ins { background-color:#ff9; color:#000; text-decoration:none; } 21 | mark { background-color:#ff9; color:#000; font-style:italic; font-weight:bold; } 22 | del { text-decoration: line-through; } 23 | abbr[title], dfn[title] { border-bottom:1px dotted #000; cursor:help; } 24 | table { border-collapse:collapse; border-spacing:0; } 25 | hr { display:block; height:1px; border:0; border-top:1px solid #ccc; margin:1em 0; padding:0; } 26 | input, select { vertical-align:middle; } 27 | 28 | 29 | body { font:13px sans-serif; *font-size:small; *font:x-small; line-height:1.22; } 30 | table { font-size:inherit; font:100%; } 31 | select, input, textarea { font:99% sans-serif; } 32 | pre, code, kbd, samp { font-family: monospace, sans-serif; } 33 | 34 | body, select, input, textarea { color:#444; } 35 | h1,h2,h3,h4,h5,h6 { font-weight: bold; text-rendering: optimizeLegibility; } 36 | html { -webkit-font-smoothing: antialiased; } 37 | a:hover, a:active { outline: none; } 38 | a, a:active, a:visited { color:#607890; } 39 | a:hover { color:#036; } 40 | ul { margin-left:30px; } 41 | ol { margin-left:30px; list-style-type: decimal; } 42 | small { font-size:85%; } 43 | strong, th { font-weight: bold; } 44 | td, td img { vertical-align:top; } 45 | sub { vertical-align: sub; font-size: smaller; } 46 | sup { vertical-align: super; font-size: smaller; } 47 | 48 | pre { padding: 15px; white-space: pre; white-space: pre-wrap; white-space: pre-line; word-wrap: break-word; } 49 | 50 | input[type="radio"] { vertical-align: text-bottom; } 51 | input[type="checkbox"] { vertical-align: bottom; *vertical-align: baseline; } 52 | .ie6 input { vertical-align: text-bottom; } 53 | label, input[type=button], input[type=submit], button { cursor: pointer; } 54 | 55 | ::-moz-selection{ background: #FF5E99; color:#fff; text-shadow: none; } 56 | ::selection { background:#FF5E99; color:#fff; text-shadow: none; } 57 | 58 | a:link { -webkit-tap-highlight-color: #FF5E99; } 59 | 60 | 61 | html { overflow-y: scroll; } 62 | button { width: auto; overflow: visible; } 63 | .ie7 img { -ms-interpolation-mode: bicubic; } 64 | 65 | .ir { display:block; text-indent:-999em; overflow:hidden; background-repeat: no-repeat; } 66 | .hidden { display:none; visibility:hidden; } 67 | .visuallyhidden { position:absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px, 1px, 1px, 1px); } 68 | .invisible { visibility: hidden; } 69 | .clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } 70 | .clearfix { display: inline-block; } 71 | * html .clearfix { height: 1%; } 72 | .clearfix { display: block; } 73 | 74 | /* Primary Styles 75 | Author: 76 | */ 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | /* 89 | * print styles 90 | */ 91 | @media print { 92 | * { background: transparent !important; color: #444 !important; text-shadow: none; } 93 | a, a:visited { color: #444 !important; text-decoration: underline; } 94 | a:after { content: " (" attr(href) ")"; } 95 | abbr:after { content: " (" attr(title) ")"; } 96 | .ir a:after { content: ""; } /* Don't show links for images */ 97 | pre, blockquote { border: 1px solid #999; page-break-inside: avoid; } 98 | img { page-break-inside: avoid; } 99 | @page { margin: 0.5cm; } 100 | p, h2, h3 { orphans: 3; widows: 3; } 101 | h2, h3{ page-break-after: avoid; } 102 | } 103 | 104 | 105 | 106 | @media all and (orientation:portrait) { 107 | 108 | } 109 | 110 | @media all and (orientation:landscape) { 111 | 112 | } 113 | 114 | /* Grade-A Mobile Browsers */ 115 | @media screen and (max-device-width: 480px) { 116 | html { -webkit-text-size-adjust:none; -ms-text-size-adjust:none; } 117 | 118 | } 119 | 120 | -------------------------------------------------------------------------------- /client/demo/elements.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 20 | 21 | 22 | 23 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 |
58 | 61 |
62 | 63 | 69 | 70 | 71 | 72 |

Title 01 Heading

73 |
74 |

Level 03 Heading

75 |

Lorem ipsum emphasised text dolor sit amet, strong text 76 | consectetur adipisicing elit, abbreviated text sed do eiusmod tempor 77 | incididunt ut labore et dolore magna aliqua. Ut 78 | quoted text enim ad minim veniam, quis nostrud exercitation link text 79 | ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute 80 | inserted text irure dolor in reprehenderit in voluptate velit esse cillum 81 | dolore eu fugiat nulla pariatur. Excepteur sint occaecat code text cupidatat 82 | non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

83 | 84 |

85 | Suspendisse rhoncus, est ac sollicitudin viverra, leo orci sagittis massa, sed condimentum acronym text est tortor a lectus. Curabitur porta feugiat ullamcorper. Integer lacinia mi id odio faucibus eget tincidunt nisl iaculis. Nam adipiscing hendrerit turpis, et porttitor felis sollicitudin et. Donec dictum massa ac neque accumsan tempor. Cras aliquam, ipsum sit amet laoreet hendrerit, purus deleted text sapien convallis dui, et porta leo ipsum ac nunc. Nullam ornare porta dui ac semper. Cras aliquam laoreet hendrerit. Quisque vulputate dolor eget mi porta vel porta nisl pretium. Vivamus non leo magna, quis imperdiet risus. Morbi tempor risus placerat tellus imperdiet fringilla. 86 |

87 | 88 |
89 |

I am not one who was born in the possession of knowledge; I am one who is fond of antiquity, and earnest in seeking it there.

90 |
91 | 92 |

Confucius, The Confucian Analects, (551 BC - 479 BC)

93 | 94 |

Level 03 Heading

95 | 96 |

Extended paragraph. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod 97 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud 98 | exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in 99 | reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint 100 | occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

101 | 102 |
    103 |
  1. Unus
  2. 104 |
  3. Duo
  4. 105 |
  5. Tres
  6. 106 |
  7. Quattuor
  8. 107 |
108 | 109 |

Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla 110 | pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit 111 | anim id est laborum.

112 | 113 |

Header 3

114 | 115 |

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt 116 | ut labore et dolore magna aliqua.

117 | 118 |

Unordered lists

119 | 125 |

Lorem ipsum dolor sit amet,consectetur adipisicing elit, sed do eiusmod tempor incididunt 126 | ut labore et dolore magna aliqua.

127 | 128 |
body { font:0.8125em/1.618 Arial, sans-serif; 
129 |       background-color:#fff;  
130 |       color:#111;
131 |       }
132 | 133 |

Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla 134 | pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit 135 | anim id est laborum.

136 | 137 |

Header 4

138 | 139 |

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt 140 | ut labore et dolore magna aliqua.

141 | 142 |
143 |
Definition list
144 |
Consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna 145 | aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea 146 | commodo consequat.
147 |
Lorem ipsum dolor sit amet
148 |
Consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna 149 | aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea 150 | commodo consequat.
151 | 152 |
153 | 154 |

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt 155 | ut labore et dolore magna aliqua.

156 |

Ordered list

157 |
    158 |
  1. List item
  2. 159 |
  3. List item
  4. 160 |
  5. List item 161 |
      162 |
    1. List item level 2
    2. 163 |
    3. List item level 2 164 |
        165 |
      1. List item level 3
      2. 166 |
      3. List item level 3
      4. 167 |
      168 |
    4. 169 |
    170 |
  6. 171 |
172 |

Unordered list

173 | 189 | 190 |

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt 191 | ut labore et dolore magna aliqua.

192 | 193 | 194 |

Tables

195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 |
Jimi Hendrix - albums
AlbumYearPrice
AlbumYearPrice
Are You Experienced 1967$10.00
Axis: Bold as Love1967$12.00
Electric Ladyland1968$10.00
Band of Gypsys1970$12.00
234 |

235 | I am the a tag example
236 | 237 | I am the abbr tag example
238 | 239 | I am the acronym tag example
240 | I am the b tag example
241 | I am the big tag example
242 | 243 | I am the cite tag example
244 | 245 | I am the code tag example
246 | I am the del tag example
247 | I am the dfn tag example
248 | 249 | I am the em tag example
250 | 251 | I am the font tag example
252 | I am the i tag example
253 | I am the ins tag example
254 | 255 | I am the kbd tag example
256 | 257 | I am the q tag inside a q tag example
258 | I am the s tag example
259 | I am the samp tag example
260 | 261 | I am the small tag example
262 | I am the span tag example
263 | I am the strike tag example
264 | I am the strong tag example
265 | 266 | I am the sub tag example
267 | I am the sup tag example
268 | I am the tt tag example
269 | I am the var tag example
270 | 271 | I am the u tag example 272 |

273 | 274 |

This is a <p> with some code inside.

275 | 276 |

What is Lorem Ipsum?

277 |

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

278 | 279 |

This Lorem Ipsum HTML example is created from the parts of Placeholder Markup with Lorem Ipsum - Jon Tan, 280 | Emastic CSS Framework, 281 | Tripoli CSS Framework and 282 | Baseline CSS Framework .

283 | 284 |
Address: somewhere, World
285 | 286 | 287 | 288 |

289 | Link
290 | <strong>
291 | <del> deleted
292 | <dfn> dfn
293 | <em> emphasis 294 |

295 |
296 | <html>
297 | 	<head>
298 | 	</head>
299 | 	<body>
300 | 	<div class = "main"> <div>
301 | 	</body>
302 | </html> 
303 | 
304 | 305 | <tt> 306 | Pellentesque tempor, dui ut ultrices viverra, neque urna blandit nisi, id accumsan dolor est vitae risus. 307 | 308 | 309 |
310 | 311 | 312 | 313 | 314 |
315 |
Description list title 01
316 | 317 |
Description list description 01
318 |
Description list title 02
319 |
Description list description 02
320 |
Description list description 03
321 | 322 |
323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 |
Table Caption
Table head thTable head td
Table foot thTable foot td
Table body thTable body td
Table body tdTable body td
355 | 356 |
357 | 358 |
359 |
360 | Form legend 361 | 362 |
363 |
364 |
365 | 366 |
367 |
368 | 369 |
370 |
371 | 372 |
373 | 374 |
375 | 376 | 377 | 378 |
379 | 382 |
383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | -------------------------------------------------------------------------------- /client/img/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/client/img/add.png -------------------------------------------------------------------------------- /client/img/delete-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/client/img/delete-icon.png -------------------------------------------------------------------------------- /client/img/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/client/img/delete.png -------------------------------------------------------------------------------- /client/img/editbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/client/img/editbg.png -------------------------------------------------------------------------------- /client/img/export.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/client/img/export.png -------------------------------------------------------------------------------- /client/img/features.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/client/img/features.png -------------------------------------------------------------------------------- /client/img/footer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/client/img/footer.png -------------------------------------------------------------------------------- /client/img/footerInverse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/client/img/footerInverse.png -------------------------------------------------------------------------------- /client/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/client/img/logo.png -------------------------------------------------------------------------------- /client/img/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/client/img/settings.png -------------------------------------------------------------------------------- /client/img/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/client/img/splash.png -------------------------------------------------------------------------------- /client/img/ui-bg_flat_0_aaaaaa_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/client/img/ui-bg_flat_0_aaaaaa_40x100.png -------------------------------------------------------------------------------- /client/img/ui-bg_flat_75_ffffff_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/client/img/ui-bg_flat_75_ffffff_40x100.png -------------------------------------------------------------------------------- /client/img/ui-bg_glass_55_fbf9ee_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/client/img/ui-bg_glass_55_fbf9ee_1x400.png -------------------------------------------------------------------------------- /client/img/ui-bg_glass_65_ffffff_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/client/img/ui-bg_glass_65_ffffff_1x400.png -------------------------------------------------------------------------------- /client/img/ui-bg_glass_75_dadada_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/client/img/ui-bg_glass_75_dadada_1x400.png -------------------------------------------------------------------------------- /client/img/ui-bg_highlight-soft_75_cccccc_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/client/img/ui-bg_highlight-soft_75_cccccc_1x100.png -------------------------------------------------------------------------------- /client/img/ui-bg_highlight-soft_75_e6e6e6_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/client/img/ui-bg_highlight-soft_75_e6e6e6_1x100.png -------------------------------------------------------------------------------- /client/img/ui-bg_inset-soft_95_fef1ec_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/client/img/ui-bg_inset-soft_95_fef1ec_1x100.png -------------------------------------------------------------------------------- /client/img/ui-icons_222222_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/client/img/ui-icons_222222_256x240.png -------------------------------------------------------------------------------- /client/img/ui-icons_2e83ff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/client/img/ui-icons_2e83ff_256x240.png -------------------------------------------------------------------------------- /client/img/ui-icons_454545_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/client/img/ui-icons_454545_256x240.png -------------------------------------------------------------------------------- /client/img/ui-icons_888888_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/client/img/ui-icons_888888_256x240.png -------------------------------------------------------------------------------- /client/img/ui-icons_cd0a0a_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/client/img/ui-icons_cd0a0a_256x240.png -------------------------------------------------------------------------------- /client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 | 31 | 32 | 33 |
34 | 35 | 36 |
37 | 38 |
39 | prenup is an open-source node.js project planning tool that allows you to meaningfully engage your clients and convert their domain knowledge into tangible milestones, features, scenarios, and unit tests. 40 |
41 |
42 | 43 |
44 | 45 |
    46 | 47 | 48 | 49 |
    50 | 51 |
    52 |
    53 |
    54 | 55 |
    56 |
    57 | 58 | 76 |
    77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /client/js/app-lib.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var STR_MAPS = { 4 | HTML_DECODE: { 5 | '<': '<' 6 | ,'>': '>' 7 | ,'&': '&' 8 | ,'"': '"' 9 | }, 10 | HTML_ENCODE: { 11 | '<': '<' 12 | ,'>': '>' 13 | ,'&': '&' 14 | ,'"': '"' 15 | }, 16 | ESCAPE_CHARSS: { 17 | '\\': '\\\\', 18 | '\'': '\\\'', 19 | '"': '\\"', 20 | '\r': '\\r', 21 | '\n': '\\n', 22 | '\t': '\\t', 23 | '\f': '\\f', 24 | '\b': '\\b' 25 | } 26 | }; 27 | 28 | var jExtras = { 29 | 30 | jup: (function() { 31 | 32 | var Util = { 33 | 34 | isArray: (function() { return Array.isArray || function(obj) { 35 | // isArray function adapted from underscore.js 36 | return !!(obj && obj.concat && obj.unshift && !obj.callee); 37 | }})(), 38 | 39 | sup: function(target, data) { 40 | 41 | return data ? target.replace(/\{\{([^\{\}]*)\}\}/g, function(str, r) { 42 | try { return data[r]; } catch(ex) {} 43 | }) : target; 44 | }, 45 | 46 | translate: function (o, data) { 47 | 48 | var c = [], atts = [], count = 1, selfClosing = false; 49 | 50 | for (var i in o) { 51 | if (o.hasOwnProperty(i) ) { 52 | 53 | count++; 54 | selfClosing = false; 55 | 56 | if(typeof c[0] == "string") { 57 | switch(o[0].toLowerCase()) { 58 | case "area": 59 | case "base": 60 | case "basefont": 61 | case "br": 62 | case "hr": 63 | case "input": 64 | case "img": 65 | case "link": 66 | case "meta": 67 | selfClosing = true; 68 | break; 69 | } 70 | } 71 | 72 | if (o[i] && typeof o[i] == "object") { 73 | 74 | if(!Util.isArray(o[i])) { 75 | for(var attribute in o[i]) { 76 | if (o[i].hasOwnProperty(attribute)) { 77 | atts.push([" ", Util.sup(attribute, data).replace(/ /g, "-"), "=\"", Util.sup(o[i][attribute], data), "\""].join("")); 78 | } 79 | } 80 | c[i] = ""; 81 | c[0] = [c[0], atts.join("")].join(""); 82 | } 83 | else { 84 | c[i] = this.translate(o[i], data); 85 | } 86 | } 87 | else { 88 | c[i] = Util.sup(o[i], data); 89 | } 90 | 91 | if(typeof c[0] == "string") { 92 | 93 | c[0] = ["<", o[0], atts.join(""), (selfClosing ? "/>" : ">")].join(""); 94 | 95 | if(selfClosing == false) { 96 | c.push(""); 97 | } 98 | } 99 | } 100 | } 101 | if(count-1 == o.length) { 102 | return [c.join("")]; 103 | } 104 | } 105 | }; 106 | 107 | return { 108 | version: "0.2", 109 | data: function(str) { 110 | return ["{{", str, "}}"].join(""); 111 | }, 112 | html: function() { 113 | 114 | var args = Array.prototype.slice.call(arguments), structure = [], data = {}; 115 | 116 | if(args.length == 2) { 117 | structure = args[1]; 118 | data = args[0]; 119 | } 120 | else { 121 | if(Util.isArray(args[0])) { 122 | structure = args[0]; 123 | } 124 | else { 125 | data = args[0].data || null; 126 | structure = args[0].structure; 127 | } 128 | } 129 | if(Util.isArray(data)) { 130 | 131 | var copystack = []; 132 | 133 | for(var c=0; c < data.length; c++) { 134 | copystack.push(Util.translate(structure, data[c])[0]); 135 | } 136 | return copystack.join(""); 137 | } 138 | else if(data) { 139 | for(var d=0; d < data.length; d++) { 140 | return Util.translate(args[2] ? structure : Util.translate(structure)[0], data[d]); 141 | } 142 | } 143 | return Util.translate(structure)[0]; 144 | } 145 | }; 146 | })(), 147 | 148 | hash: { 149 | 150 | path: function(hash) { 151 | 152 | var hash = window.location.hash; 153 | return hash.substr(1, hash.length).split("/"); 154 | } 155 | }, 156 | 157 | querystring: { 158 | 159 | toJSON: function(query) { 160 | /* Special thanks to @bga_ for this bit of code, 161 | a big improvement on my crummy RegEx version */ 162 | 163 | query = query || window.location.search; 164 | 165 | var p = 0, 166 | ret = {}, 167 | _unescape = unescape, 168 | key, 169 | value, 170 | queryLen; 171 | 172 | if(query.charAt(p) == '?') { 173 | ++p; 174 | } 175 | 176 | if(query.charAt(p) == '&') { 177 | ++p; 178 | } 179 | 180 | if(query.charAt(query.length - 1) != '&') { 181 | query += '&'; 182 | } 183 | 184 | queryLen = query.length - 1; 185 | 186 | --p; 187 | while(++p < queryLen) { 188 | 189 | key = _unescape(query.slice(p, (p = query.indexOf('=', p)))); 190 | value = _unescape(query.slice(++p, (p = query.indexOf('&', p)))); 191 | 192 | ret[key] = value; 193 | } 194 | 195 | return ret; 196 | } 197 | }, 198 | 199 | array: { 200 | 201 | group: function(a, callback) { 202 | 203 | var len = a.length, groups = [], keys = {}; 204 | for (var i = 0; i < length; i++) { 205 | var key = callback(a[i], i); 206 | if (! key || !key.length) { 207 | continue; 208 | } 209 | var items = keys[key]; 210 | if (!items) { 211 | items = []; 212 | items.key = key; 213 | keys[key] = items; 214 | groups.add(items); 215 | } 216 | items.add(a[i]); 217 | } 218 | return groups; 219 | }, 220 | 221 | aggregate: function(a, seed, callback) { 222 | var len = a.length; 223 | for (var i = 0; i < length; i++) { 224 | seed = callback(seed, a[i], i, a); 225 | } 226 | return seed; 227 | }, 228 | 229 | removeRange: function(a, index, count) { 230 | return a.splice(index, count); 231 | } 232 | }, 233 | 234 | string: { 235 | 236 | html: { 237 | 238 | decode: function(s) { 239 | s = s.replace(/(&|<|>|")/gi, 240 | function(_s, r) { 241 | return STR_MAPS.HTML_DECODE[r]; 242 | }); 243 | return s; 244 | }, 245 | 246 | encode: function(s) { 247 | if (/([&<>"])/g.test(s)) { 248 | s = s.replace(/([&<>"])/g, 249 | function(_s, r) { 250 | return STR_MAPS.HTML_ENCODE[r]; 251 | }); 252 | } 253 | return s; 254 | } 255 | }, 256 | 257 | quote: function(s) { 258 | s.replace(new RegExp("([\'\"\\\\\x00-\x1F\x7F-\uFFFF])", "g"), 259 | function(str, r) { 260 | return STR_MAPS.ESCAPE_CHARS[r] || 261 | '\\u' + r.charCodeAt(0).toString(16).toUpperCase().padLeft(4, '0'); 262 | }); 263 | }, 264 | 265 | subst: function(s, o) { 266 | var count = -1; 267 | return s.replace(/{{([^{}]*)}}/g, 268 | function(str, r) { 269 | if(!isNaN(r)) { 270 | return o[r]; 271 | } 272 | count++; 273 | return o[(o instanceof Array) ? count : r]; 274 | } 275 | ); 276 | } 277 | 278 | } 279 | }; 280 | 281 | // put everything under one roof. (assumption that $ is a library that has an extend method (most likely jQuery)) 282 | window.$ = (typeof window.$ != "undefined") ? $.extend($, jExtras) : jExtras; 283 | 284 | 285 | 286 | })(); 287 | -------------------------------------------------------------------------------- /client/js/dd_belatedpng.js: -------------------------------------------------------------------------------- 1 | /** 2 | * DD_belatedPNG: Adds IE6 support: PNG images for CSS background-image and HTML . 3 | * Author: Drew Diller 4 | * Email: drew.diller@gmail.com 5 | * URL: http://www.dillerdesign.com/experiment/DD_belatedPNG/ 6 | * Version: 0.0.8a 7 | * Licensed under the MIT License: http://dillerdesign.com/experiment/DD_belatedPNG/#license 8 | * 9 | * Example usage: 10 | * DD_belatedPNG.fix('.png_bg'); // argument is a CSS selector 11 | * DD_belatedPNG.fixPng( someNode ); // argument is an HTMLDomElement 12 | **/ 13 | 14 | /* 15 | PLEASE READ: 16 | Absolutely everything in this script is SILLY. I know this. IE's rendering of certain pixels doesn't make sense, so neither does this code! 17 | */ 18 | 19 | var DD_belatedPNG = { 20 | ns: 'DD_belatedPNG', 21 | imgSize: {}, 22 | delay: 10, 23 | nodesFixed: 0, 24 | createVmlNameSpace: function () { /* enable VML */ 25 | if (document.namespaces && !document.namespaces[this.ns]) { 26 | document.namespaces.add(this.ns, 'urn:schemas-microsoft-com:vml'); 27 | } 28 | }, 29 | createVmlStyleSheet: function () { /* style VML, enable behaviors */ 30 | /* 31 | Just in case lots of other developers have added 32 | lots of other stylesheets using document.createStyleSheet 33 | and hit the 31-limit mark, let's not use that method! 34 | further reading: http://msdn.microsoft.com/en-us/library/ms531194(VS.85).aspx 35 | */ 36 | var screenStyleSheet, printStyleSheet; 37 | screenStyleSheet = document.createElement('style'); 38 | screenStyleSheet.setAttribute('media', 'screen'); 39 | document.documentElement.firstChild.insertBefore(screenStyleSheet, document.documentElement.firstChild.firstChild); 40 | if (screenStyleSheet.styleSheet) { 41 | screenStyleSheet = screenStyleSheet.styleSheet; 42 | screenStyleSheet.addRule(this.ns + '\\:*', '{behavior:url(#default#VML)}'); 43 | screenStyleSheet.addRule(this.ns + '\\:shape', 'position:absolute;'); 44 | screenStyleSheet.addRule('img.' + this.ns + '_sizeFinder', 'behavior:none; border:none; position:absolute; z-index:-1; top:-10000px; visibility:hidden;'); /* large negative top value for avoiding vertical scrollbars for large images, suggested by James O'Brien, http://www.thanatopsic.org/hendrik/ */ 45 | this.screenStyleSheet = screenStyleSheet; 46 | 47 | /* Add a print-media stylesheet, for preventing VML artifacts from showing up in print (including preview). */ 48 | /* Thanks to Rémi Prévost for automating this! */ 49 | printStyleSheet = document.createElement('style'); 50 | printStyleSheet.setAttribute('media', 'print'); 51 | document.documentElement.firstChild.insertBefore(printStyleSheet, document.documentElement.firstChild.firstChild); 52 | printStyleSheet = printStyleSheet.styleSheet; 53 | printStyleSheet.addRule(this.ns + '\\:*', '{display: none !important;}'); 54 | printStyleSheet.addRule('img.' + this.ns + '_sizeFinder', '{display: none !important;}'); 55 | } 56 | }, 57 | readPropertyChange: function () { 58 | var el, display, v; 59 | el = event.srcElement; 60 | if (!el.vmlInitiated) { 61 | return; 62 | } 63 | if (event.propertyName.search('background') != -1 || event.propertyName.search('border') != -1) { 64 | DD_belatedPNG.applyVML(el); 65 | } 66 | if (event.propertyName == 'style.display') { 67 | display = (el.currentStyle.display == 'none') ? 'none' : 'block'; 68 | for (v in el.vml) { 69 | if (el.vml.hasOwnProperty(v)) { 70 | el.vml[v].shape.style.display = display; 71 | } 72 | } 73 | } 74 | if (event.propertyName.search('filter') != -1) { 75 | DD_belatedPNG.vmlOpacity(el); 76 | } 77 | }, 78 | vmlOpacity: function (el) { 79 | if (el.currentStyle.filter.search('lpha') != -1) { 80 | var trans = el.currentStyle.filter; 81 | trans = parseInt(trans.substring(trans.lastIndexOf('=')+1, trans.lastIndexOf(')')), 10)/100; 82 | el.vml.color.shape.style.filter = el.currentStyle.filter; /* complete guesswork */ 83 | el.vml.image.fill.opacity = trans; /* complete guesswork */ 84 | } 85 | }, 86 | handlePseudoHover: function (el) { 87 | setTimeout(function () { /* wouldn't work as intended without setTimeout */ 88 | DD_belatedPNG.applyVML(el); 89 | }, 1); 90 | }, 91 | /** 92 | * This is the method to use in a document. 93 | * @param {String} selector - REQUIRED - a CSS selector, such as '#doc .container' 94 | **/ 95 | fix: function (selector) { 96 | if (this.screenStyleSheet) { 97 | var selectors, i; 98 | selectors = selector.split(','); /* multiple selectors supported, no need for multiple calls to this anymore */ 99 | for (i=0; i size.H) { 241 | c.B = size.H; 242 | } 243 | el.vml.image.shape.style.clip = 'rect('+c.T+'px '+(c.R+fudge)+'px '+c.B+'px '+(c.L+fudge)+'px)'; 244 | } 245 | else { 246 | el.vml.image.shape.style.clip = 'rect('+dC.T+'px '+dC.R+'px '+dC.B+'px '+dC.L+'px)'; 247 | } 248 | }, 249 | figurePercentage: function (bg, size, axis, position) { 250 | var horizontal, fraction; 251 | fraction = true; 252 | horizontal = (axis == 'X'); 253 | switch(position) { 254 | case 'left': 255 | case 'top': 256 | bg[axis] = 0; 257 | break; 258 | case 'center': 259 | bg[axis] = 0.5; 260 | break; 261 | case 'right': 262 | case 'bottom': 263 | bg[axis] = 1; 264 | break; 265 | default: 266 | if (position.search('%') != -1) { 267 | bg[axis] = parseInt(position, 10) / 100; 268 | } 269 | else { 270 | fraction = false; 271 | } 272 | } 273 | bg[axis] = Math.ceil( fraction ? ( (size[horizontal?'W': 'H'] * bg[axis]) - (size[horizontal?'w': 'h'] * bg[axis]) ) : parseInt(position, 10) ); 274 | if (bg[axis] % 2 === 0) { 275 | bg[axis]++; 276 | } 277 | return bg[axis]; 278 | }, 279 | fixPng: function (el) { 280 | el.style.behavior = 'none'; 281 | var lib, els, nodeStr, v, e; 282 | if (el.nodeName == 'BODY' || el.nodeName == 'TD' || el.nodeName == 'TR') { /* elements not supported yet */ 283 | return; 284 | } 285 | el.isImg = false; 286 | if (el.nodeName == 'IMG') { 287 | if(el.src.toLowerCase().search(/\.png$/) != -1) { 288 | el.isImg = true; 289 | el.style.visibility = 'hidden'; 290 | } 291 | else { 292 | return; 293 | } 294 | } 295 | else if (el.currentStyle.backgroundImage.toLowerCase().search('.png') == -1) { 296 | return; 297 | } 298 | lib = DD_belatedPNG; 299 | el.vml = {color: {}, image: {}}; 300 | els = {shape: {}, fill: {}}; 301 | for (v in el.vml) { 302 | if (el.vml.hasOwnProperty(v)) { 303 | for (e in els) { 304 | if (els.hasOwnProperty(e)) { 305 | nodeStr = lib.ns + ':' + e; 306 | el.vml[v][e] = document.createElement(nodeStr); 307 | } 308 | } 309 | el.vml[v].shape.stroked = false; 310 | el.vml[v].shape.appendChild(el.vml[v].fill); 311 | el.parentNode.insertBefore(el.vml[v].shape, el); 312 | } 313 | } 314 | el.vml.image.shape.fillcolor = 'none'; /* Don't show blank white shapeangle when waiting for image to load. */ 315 | el.vml.image.fill.type = 'tile'; /* Makes image show up. */ 316 | el.vml.color.fill.on = false; /* Actually going to apply vml element's style.backgroundColor, so hide the whiteness. */ 317 | lib.attachHandlers(el); 318 | lib.giveLayout(el); 319 | lib.giveLayout(el.offsetParent); 320 | el.vmlInitiated = true; 321 | lib.applyVML(el); /* Render! */ 322 | } 323 | }; 324 | try { 325 | document.execCommand("BackgroundImageCache", false, true); /* TredoSoft Multiple IE doesn't like this, so try{} it */ 326 | } catch(r) {} 327 | DD_belatedPNG.createVmlNameSpace(); 328 | DD_belatedPNG.createVmlStyleSheet(); -------------------------------------------------------------------------------- /client/js/gerk.js: -------------------------------------------------------------------------------- 1 | var GERK = {}; 2 | 3 | GERK.i18n = { 4 | "uk": { 5 | "examples": "Приклади", 6 | "feature": "Функціонал", 7 | "name": "Ukrainian", 8 | "but": "Але", 9 | "and": "І|А також|Та", 10 | "scenario_outline": "Структура сценарію", 11 | "background": "Передумова", 12 | "native": "Українська", 13 | "when": "Якщо|Коли", 14 | "then": "То|Тоді", 15 | "given": "Припустимо|Припустимо, що|Нехай|Дано", 16 | "scenario": "Сценарій" 17 | }, 18 | "it": { 19 | "examples": "Esempi", 20 | "feature": "Funzionalità", 21 | "name": "Italian", 22 | "but": "Ma", 23 | "and": "E", 24 | "scenario_outline": "Schema dello scenario", 25 | "background": "Contesto", 26 | "native": "italiano", 27 | "when": "Quando", 28 | "then": "Allora", 29 | "given": "Dato", 30 | "scenario": "Scenario" 31 | }, 32 | "zh-CN": { 33 | "examples": "例子", 34 | "feature": "功能", 35 | "name": "Chinese simplified", 36 | "but": "但是<", 37 | "and": "而且<", 38 | "scenario_outline": "场景大纲", 39 | "background": "背景", 40 | "native": "简体中文", 41 | "when": "当<", 42 | "then": "那么<", 43 | "given": "假如<", 44 | "scenario": "场景" 45 | }, 46 | "no": { 47 | "examples": "Eksempler", 48 | "feature": "Egenskap", 49 | "name": "Norwegian", 50 | "but": "Men", 51 | "and": "Og", 52 | "scenario_outline": "Abstrakt Scenario", 53 | "background": "Bakgrunn", 54 | "native": "norsk", 55 | "when": "Når", 56 | "then": "Så", 57 | "given": "Gitt", 58 | "scenario": "Scenario" 59 | }, 60 | "ja": { 61 | "examples": "例|サンプル", 62 | "feature": "フィーチャ|機能", 63 | "name": "Japanese", 64 | "but": "しかし<|但し<|ただし<", 65 | "and": "かつ<", 66 | "scenario_outline": "シナリオアウトライン|シナリオテンプレート|テンプレ|シナリオテンプレ", 67 | "background": "背景", 68 | "native": "日本語", 69 | "when": "もし<", 70 | "then": "ならば<", 71 | "given": "前提<", 72 | "scenario": "シナリオ" 73 | }, 74 | "fr": { 75 | "examples": "Exemples", 76 | "feature": "Fonctionnalité", 77 | "name": "French", 78 | "but": "Mais", 79 | "and": "Et", 80 | "scenario_outline": "Plan du scénario|Plan du Scénario", 81 | "background": "Contexte", 82 | "native": "français", 83 | "when": "Quand|Lorsque|Lorsqu'<", 84 | "then": "Alors", 85 | "given": "Soit|Etant donné", 86 | "scenario": "Scénario" 87 | }, 88 | "en-tx": { 89 | "examples": "Examples", 90 | "feature": "Feature", 91 | "name": "Texan", 92 | "but": "But y'all", 93 | "and": "And y'all", 94 | "scenario_outline": "All y'all", 95 | "background": "Background", 96 | "native": "Texan", 97 | "when": "When y'all", 98 | "then": "Then y'all", 99 | "given": "Given y'all", 100 | "scenario": "Scenario" 101 | }, 102 | "de": { 103 | "examples": "Beispiele", 104 | "feature": "Funktionalität", 105 | "name": "German", 106 | "but": "Aber", 107 | "and": "Und", 108 | "scenario_outline": "Szenariogrundriss", 109 | "background": "Grundlage", 110 | "native": "Deutsch", 111 | "when": "Wenn", 112 | "then": "Dann", 113 | "given": "Angenommen|Gegeben sei", 114 | "scenario": "Szenario" 115 | }, 116 | "sk": { 117 | "examples": "Príklady", 118 | "feature": "Požiadavka", 119 | "name": "Slovak", 120 | "but": "Ale", 121 | "and": "A", 122 | "scenario_outline": "Náčrt Scenáru", 123 | "background": "Pozadie", 124 | "native": "Slovensky", 125 | "when": "Keď", 126 | "then": "Tak", 127 | "given": "Pokiaľ", 128 | "scenario": "Scenár" 129 | }, 130 | "hu": { 131 | "examples": "Példák", 132 | "feature": "Jellemző", 133 | "name": "Hungarian", 134 | "but": "De", 135 | "and": "És", 136 | "scenario_outline": "Forgatókönyv vázlat", 137 | "background": "Háttér", 138 | "native": "magyar", 139 | "when": "Majd|Ha|Amikor", 140 | "then": "Akkor", 141 | "given": "Amennyiben|Adott", 142 | "scenario": "Forgatókönyv" 143 | }, 144 | "sv": { 145 | "examples": "Exempel", 146 | "feature": "Egenskap", 147 | "name": "Swedish", 148 | "but": "Men", 149 | "and": "Och", 150 | "scenario_outline": "Abstrakt Scenario", 151 | "background": "Bakgrund", 152 | "native": "Svenska", 153 | "when": "När", 154 | "then": "Så", 155 | "given": "Givet", 156 | "scenario": "Scenario" 157 | }, 158 | "ru": { 159 | "examples": "Значения", 160 | "feature": "Функционал|Фича", 161 | "name": "Russian", 162 | "but": "Но|А", 163 | "and": "И|К тому же", 164 | "scenario_outline": "Структура сценария", 165 | "background": "Предыстория", 166 | "native": "русский", 167 | "when": "Если|Когда", 168 | "then": "То|Тогда", 169 | "given": "Допустим|Дано|Пусть", 170 | "scenario": "Сценарий" 171 | }, 172 | "fi": { 173 | "examples": "Tapaukset", 174 | "feature": "Ominaisuus", 175 | "name": "Finnish", 176 | "but": "Mutta", 177 | "and": "Ja", 178 | "scenario_outline": "Tapausaihio", 179 | "background": "Tausta", 180 | "native": "suomi", 181 | "when": "Kun", 182 | "then": "Niin", 183 | "given": "Oletetaan", 184 | "scenario": "Tapaus" 185 | }, 186 | "es": { 187 | "examples": "Ejemplos", 188 | "feature": "Característica", 189 | "name": "Spanish", 190 | "but": "Pero", 191 | "and": "Y", 192 | "scenario_outline": "Esquema del escenario", 193 | "background": "Antecedentes", 194 | "native": "español", 195 | "when": "Cuando", 196 | "then": "Entonces", 197 | "given": "Dado", 198 | "scenario": "Escenario" 199 | }, 200 | "zh-TW": { 201 | "examples": "例子", 202 | "feature": "功能", 203 | "name": "Chinese traditional", 204 | "but": "但是<", 205 | "and": "而且<|並且<", 206 | "scenario_outline": "場景大綱|劇本大綱", 207 | "background": "背景", 208 | "native": "繁體中文", 209 | "when": "當<", 210 | "then": "那麼<", 211 | "given": "假設<", 212 | "scenario": "場景|劇本" 213 | }, 214 | "pt": { 215 | "examples": "Exemplos", 216 | "feature": "Funcionalidade", 217 | "name": "Portuguese", 218 | "but": "Mas", 219 | "and": "E", 220 | "scenario_outline": "Esquema do Cenário|Esquema do Cenario", 221 | "background": "Contexto", 222 | "native": "português", 223 | "when": "Quando", 224 | "then": "Então|Entao", 225 | "given": "Dado", 226 | "scenario": "Cenário|Cenario" 227 | }, 228 | "ko": { 229 | "examples": "예", 230 | "feature": "기능", 231 | "name": "Korean", 232 | "but": "하지만<|단<", 233 | "and": "그리고<", 234 | "scenario_outline": "시나리오 개요", 235 | "background": "배경", 236 | "native": "한국어", 237 | "when": "만일<|만약<", 238 | "then": "그러면<", 239 | "given": "조건<|먼저<", 240 | "scenario": "시나리오" 241 | }, 242 | "et": { 243 | "examples": "Juhtumid", 244 | "feature": "Omadus", 245 | "name": "Estonian", 246 | "but": "Kuid", 247 | "and": "Ja", 248 | "scenario_outline": "Raamstsenaarium", 249 | "background": "Taust", 250 | "native": "eesti keel", 251 | "when": "Kui", 252 | "then": "Siis", 253 | "given": "Eeldades", 254 | "scenario": "Stsenaarium" 255 | }, 256 | "uz": { 257 | "examples": "Мисоллар", 258 | "feature": "Функционал", 259 | "name": "Uzbek", 260 | "but": "Лекин|Бирок|Аммо", 261 | "and": "Ва", 262 | "scenario_outline": "Сценарий структураси", 263 | "background": "Тарих", 264 | "native": "Узбекча", 265 | "when": "Агар", 266 | "then": "Унда", 267 | "given": "Агар", 268 | "scenario": "Сценарий" 269 | }, 270 | "id": { 271 | "examples": "Contoh", 272 | "feature": "Fitur", 273 | "name": "Indonesian", 274 | "but": "Tapi", 275 | "and": "Dan", 276 | "scenario_outline": "Skenario konsep", 277 | "background": "Dasar", 278 | "native": "Bahasa Indonesia", 279 | "when": "Ketika", 280 | "then": "Maka", 281 | "given": "Dengan", 282 | "scenario": "Skenario" 283 | }, 284 | "en-Scouse": { 285 | "examples": "Examples", 286 | "feature": "Feature", 287 | "name": "Scouse", 288 | "but": "Buh", 289 | "and": "An", 290 | "scenario_outline": "Wharrimean is", 291 | "background": "Dis is what went down", 292 | "native": "Scouse", 293 | "when": "Wun|Youse know like when", 294 | "then": "Dun|Den youse gotta", 295 | "given": "Givun|Youse know when youse got", 296 | "scenario": "The thing of it is" 297 | }, 298 | "cs": { 299 | "examples": "Příklady", 300 | "feature": "Požadavek", 301 | "name": "Czech", 302 | "but": "Ale", 303 | "and": "A|A také", 304 | "scenario_outline": "Náčrt Scénáře|Osnova scénáře", 305 | "background": "Pozadí|Kontext", 306 | "native": "Česky", 307 | "when": "Když", 308 | "then": "Pak", 309 | "given": "Pokud", 310 | "scenario": "Scénář" 311 | }, 312 | "bg": { 313 | "examples": "Примери", 314 | "feature": "Функционалност", 315 | "name": "Bulgarian", 316 | "but": "Но", 317 | "and": "И", 318 | "scenario_outline": "Рамка на сценарий", 319 | "background": "Предистория", 320 | "native": "български", 321 | "when": "Когато", 322 | "then": "То", 323 | "given": "Дадено", 324 | "scenario": "Сценарий" 325 | }, 326 | "pl": { 327 | "examples": "Przykłady", 328 | "feature": "Właściwość", 329 | "name": "Polish", 330 | "but": "Ale", 331 | "and": "Oraz", 332 | "scenario_outline": "Szablon scenariusza", 333 | "background": "Założenia", 334 | "native": "polski", 335 | "when": "Jeżeli", 336 | "then": "Wtedy", 337 | "given": "Zakładając", 338 | "scenario": "Scenariusz" 339 | }, 340 | "en-au": { 341 | "examples": "Cobber", 342 | "feature": "Crikey", 343 | "name": "Australian", 344 | "but": "Cept", 345 | "and": "N", 346 | "scenario_outline": "Blokes", 347 | "background": "Background", 348 | "native": "Australian", 349 | "when": "When", 350 | "then": "Ya gotta", 351 | "given": "Ya know how", 352 | "scenario": "Mate" 353 | }, 354 | "ar": { 355 | "examples": "امثلة", 356 | "feature": "خاصية", 357 | "name": "Arabic", 358 | "but": "لكن", 359 | "and": "و", 360 | "scenario_outline": "سيناريو مخطط", 361 | "background": "الخلفية", 362 | "native": "العربية", 363 | "when": "متى|عندما", 364 | "then": "اذاً|ثم", 365 | "given": "بفرض", 366 | "scenario": "سيناريو" 367 | }, 368 | "sr-Latn": { 369 | "examples": "Primeri|Scenariji", 370 | "feature": "Funkcionalnost|Mogućnost|Mogucnost|Osobina", 371 | "name": "Serbian (Latin)", 372 | "but": "Ali", 373 | "and": "I", 374 | "scenario_outline": "Struktura scenarija|Skica|Koncept", 375 | "background": "Kontekst|Osnova|Pozadina", 376 | "native": "Srpski (Latinica)", 377 | "when": "Kada|Kad", 378 | "then": "Onda", 379 | "given": "Zadato|Zadate|Zatati", 380 | "scenario": "Scenario|Primer" 381 | }, 382 | "ro": { 383 | "examples": "Exemplele", 384 | "feature": "Functionalitate", 385 | "name": "Romanian", 386 | "but": "Dar", 387 | "and": "Si", 388 | "scenario_outline": "Scenariul de sablon", 389 | "background": "Conditii", 390 | "native": "română", 391 | "when": "Cand", 392 | "then": "Atunci", 393 | "given": "Daca", 394 | "scenario": "Scenariu" 395 | }, 396 | "he": { 397 | "examples": "דוגמאות", 398 | "feature": "תכונה", 399 | "name": "Hebrew", 400 | "but": "אבל", 401 | "and": "וגם", 402 | "scenario_outline": "תבנית תרחיש", 403 | "background": "רקע", 404 | "native": "עברית", 405 | "when": "כאשר", 406 | "then": "אז|אזי", 407 | "given": "בהינתן", 408 | "scenario": "תרחיש" 409 | }, 410 | "en-lol": { 411 | "examples": "EXAMPLZ", 412 | "feature": "OH HAI", 413 | "name": "LOLCAT", 414 | "but": "BUT", 415 | "and": "AN", 416 | "scenario_outline": "MISHUN SRSLY", 417 | "background": "B4", 418 | "native": "LOLCAT", 419 | "when": "WEN", 420 | "then": "DEN", 421 | "given": "I CAN HAZ", 422 | "scenario": "MISHUN" 423 | }, 424 | "da": { 425 | "examples": "Eksempler", 426 | "feature": "Egenskab", 427 | "name": "Danish", 428 | "but": "Men", 429 | "and": "Og", 430 | "scenario_outline": "Abstrakt Scenario", 431 | "background": "Baggrund", 432 | "native": "dansk", 433 | "when": "Når", 434 | "then": "Så", 435 | "given": "Givet", 436 | "scenario": "Scenarie" 437 | }, 438 | "vi": { 439 | "examples": "Dữ liệu", 440 | "feature": "Tính năng", 441 | "name": "Vietnamese", 442 | "but": "Nhưng", 443 | "and": "Và", 444 | "scenario_outline": "Khung tình huống|Khung kịch bản", 445 | "background": "Bối cảnh", 446 | "native": "Tiếng Việt", 447 | "when": "Khi", 448 | "then": "Thì", 449 | "given": "Biết|Cho", 450 | "scenario": "Tình huống|Kịch bản" 451 | }, 452 | "tr": { 453 | "examples": "Örnekler", 454 | "feature": "Özellik", 455 | "name": "Turkish", 456 | "but": "Fakat|Ama", 457 | "and": "Ve", 458 | "scenario_outline": "Senaryo taslağı", 459 | "background": "Geçmiş", 460 | "native": "Türkçe", 461 | "when": "Eğer ki", 462 | "then": "O zaman", 463 | "given": "Diyelim ki", 464 | "scenario": "Senaryo" 465 | }, 466 | "ro-RO": { 467 | "examples": "Exemplele", 468 | "feature": "Funcționalitate", 469 | "name": "Romanian (diacritical)", 470 | "but": "Dar", 471 | "and": "Și", 472 | "scenario_outline": "Scenariul de şablon", 473 | "background": "Condiţii", 474 | "native": "română (diacritical)", 475 | "when": "Când", 476 | "then": "Atunci", 477 | "given": "Dacă", 478 | "scenario": "Scenariu" 479 | }, 480 | "nl": { 481 | "examples": "Voorbeelden", 482 | "feature": "Functionaliteit", 483 | "name": "Dutch", 484 | "but": "Maar", 485 | "and": "En", 486 | "scenario_outline": "Abstract Scenario", 487 | "background": "Achtergrond", 488 | "native": "Nederlands", 489 | "when": "Als", 490 | "then": "Dan", 491 | "given": "Gegeven|Stel", 492 | "scenario": "Scenario" 493 | }, 494 | "lt": { 495 | "examples": "Pavyzdžiai|Scenarijai|Variantai", 496 | "feature": "Savybė", 497 | "name": "Lithuanian", 498 | "but": "Bet", 499 | "and": "Ir", 500 | "scenario_outline": "Scenarijaus šablonas", 501 | "background": "Kontekstas", 502 | "native": "lietuvių kalba", 503 | "when": "Kai", 504 | "then": "Tada", 505 | "given": "Duota", 506 | "scenario": "Scenarijus" 507 | }, 508 | "ca": { 509 | "examples": "Exemples", 510 | "feature": "Característica|Funcionalitat", 511 | "name": "Catalan", 512 | "but": "Però", 513 | "and": "I", 514 | "scenario_outline": "Esquema de l'escenari", 515 | "background": "Rerefons|Antecedents", 516 | "native": "català", 517 | "when": "Quan", 518 | "then": "Aleshores|Cal", 519 | "given": "Donat|Donada|Atès|Atesa", 520 | "scenario": "Escenari" 521 | }, 522 | "lu": { 523 | "examples": "Beispiller", 524 | "feature": "Funktionalitéit", 525 | "name": "Luxemburgish", 526 | "but": "awer|mä", 527 | "and": "an|a", 528 | "scenario_outline": "Plang vum Szenario", 529 | "background": "Hannergrond", 530 | "native": "Lëtzebuergesch", 531 | "when": "wann", 532 | "then": "dann", 533 | "given": "ugeholl", 534 | "scenario": "Szenario" 535 | }, 536 | "en-pirate": { 537 | "examples": "Dead men tell no tales", 538 | "feature": "Ahoy matey!", 539 | "name": "Pirate", 540 | "but": "Avast!", 541 | "and": "Aye", 542 | "scenario_outline": "Shiver me timbers", 543 | "background": "Yo-ho-ho", 544 | "native": "Pirate", 545 | "when": "Blimey!", 546 | "then": "Let go and haul", 547 | "given": "Gangway!", 548 | "scenario": "Heave to" 549 | }, 550 | "cy-GB": { 551 | "examples": "Enghreifftiau", 552 | "feature": "Arwedd", 553 | "name": "Welsh", 554 | "but": "Ond", 555 | "and": "A", 556 | "scenario_outline": "Scenario Amlinellol", 557 | "background": "Cefndir", 558 | "native": "Cymraeg", 559 | "when": "Pryd", 560 | "then": "Yna", 561 | "given": "Anrhegedig a", 562 | "scenario": "Scenario" 563 | }, 564 | "en": { 565 | "examples": "Examples|Scenarios", 566 | "feature": "Feature", 567 | "name": "English", 568 | "but": "But", 569 | "and": "And", 570 | "scenario_outline": "Scenario Outline", 571 | "background": "Background", 572 | "native": "English", 573 | "when": "When", 574 | "then": "Then", 575 | "given": "Given", 576 | "scenario": "Scenario" 577 | }, 578 | "sr-Cyrl": { 579 | "examples": "Примери|Сценарији", 580 | "feature": "Функционалност|Могућност|Особина", 581 | "name": "Serbian", 582 | "but": "Али", 583 | "and": "И", 584 | "scenario_outline": "Структура сценарија|Скица|Концепт", 585 | "background": "Контекст|Основа|Позадина", 586 | "native": "Српски", 587 | "when": "Када|Кад", 588 | "then": "Онда", 589 | "given": "Задато|Задате|Задати", 590 | "scenario": "Сценарио|Пример" 591 | }, 592 | "lv": { 593 | "examples": "Piemēri|Paraugs", 594 | "feature": "Funkcionalitāte|Fīča", 595 | "name": "Latvian", 596 | "but": "Bet", 597 | "and": "Un", 598 | "scenario_outline": "Scenārijs pēc parauga", 599 | "background": "Konteksts|Situācija", 600 | "native": "latviešu", 601 | "when": "Ja", 602 | "then": "Tad", 603 | "given": "Kad", 604 | "scenario": "Scenārijs" 605 | }, 606 | "hr": { 607 | "examples": "Primjeri|Scenariji", 608 | "feature": "Osobina|Mogućnost|Mogucnost", 609 | "name": "Croatian", 610 | "but": "Ali", 611 | "and": "I", 612 | "scenario_outline": "Skica|Koncept", 613 | "background": "Pozadina", 614 | "native": "hrvatski", 615 | "when": "Kada|Kad", 616 | "then": "Onda", 617 | "given": "Zadan|Zadani|Zadano", 618 | "scenario": "Scenarij" 619 | }, 620 | "eo": { 621 | "examples": "Ekzemploj", 622 | "feature": "Trajto", 623 | "name": "Esperanto", 624 | "but": "Sed", 625 | "and": "Kaj", 626 | "scenario_outline": "Konturo de la scenaro", 627 | "background": "Fono", 628 | "native": "Esperanto", 629 | "when": "Se", 630 | "then": "Do", 631 | "given": "Donitaĵo", 632 | "scenario": "Scenaro" 633 | } 634 | }; 635 | -------------------------------------------------------------------------------- /client/js/hi.js: -------------------------------------------------------------------------------- 1 | var hijs = function (hijs) { 2 | // 3 | // hijs - JavaScript Syntax Highlighter 4 | // 5 | // Copyright (c) 2010 Alexis Sellier 6 | // 7 | 8 | // All elements which match this will be syntax highlighted. 9 | var selector = hijs || 'code'; 10 | 11 | var keywords = ('var function if else for while break switch case do new null in with void ' 12 | +'continue delete return this true false throw catch typeof with instanceof').split(' '), 13 | special = ('eval window document undefined NaN Infinity parseInt parseFloat ' 14 | +'encodeURI decodeURI encodeURIComponent decodeURIComponent').split(' '); 15 | 16 | // Syntax definition 17 | // The key becomes the class name of the 18 | // around the matched block of code. 19 | var syntax = [ 20 | ['comment', /(\/\*(?:[^*\n]|\*+[^\/*])*\*+\/)/g], 21 | ['comment', /(\/\/[^\n]*)/g], 22 | ['string' , /("(?:(?!")[^\\\n]|\\.)*"|'(?:(?!')[^\\\n]|\\.)*')/g], 23 | ['regexp' , /(\/.+\/[mgi]*)(?!\s*\w)/g], 24 | ['class' , /\b([A-Z][a-zA-Z]+)\b/g], 25 | ['number' , /\b([0-9]+(?:\.[0-9]+)?)\b/g], 26 | ['keyword', new(RegExp)('\\b(' + keywords.join('|') + ')\\b', 'g')], 27 | ['special', new(RegExp)('\\b(' + special.join('|') + ')\\b', 'g')] 28 | ]; 29 | var nodes, table = {}; 30 | 31 | if (/^[a-z]+$/.test(selector)) { 32 | nodes = document.getElementsByTagName(selector); 33 | } else if (/^\.[\w-]+$/.test(selector)) { 34 | nodes = document.getElementsByClassName(selector.slice(1)); 35 | } else if (document.querySelectorAll) { 36 | nodes = document.querySelectorAll(selector); 37 | } else { 38 | nodes = []; 39 | } 40 | 41 | for (var i = 0, children; i < nodes.length; i++) { 42 | children = nodes[i].childNodes; 43 | 44 | for (var j = 0, str; j < children.length; j++) { 45 | code = children[j]; 46 | 47 | if (code.length >= 0) { // It's a text node 48 | // Don't highlight command-line snippets 49 | if (! /^\$/.test(code.nodeValue.trim())) { 50 | syntax.forEach(function (s) { 51 | var k = s[0], v = s[1]; 52 | code.nodeValue = code.nodeValue.replace(v, function (_, m) { 53 | return '\u00ab' + encode(k) + '\u00b7' 54 | + encode(m) + 55 | '\u00b7' + encode(k) + '\u00bb'; 56 | }); 57 | }); 58 | } 59 | } 60 | } 61 | } 62 | for (var i = 0; i < nodes.length; i++) { 63 | nodes[i].innerHTML = 64 | nodes[i].innerHTML.replace(/\u00ab(.+?)\u00b7(.+?)\u00b7\1\u00bb/g, function (_, name, value) { 65 | value = value.replace(/\u00ab[^\u00b7]+\u00b7/g, '').replace(/\u00b7[^\u00bb]+\u00bb/g, ''); 66 | return '' + escape(decode(value)) + ''; 67 | }); 68 | } 69 | 70 | function escape(str) { 71 | return str.replace(//g, '>'); 72 | } 73 | 74 | // Encode ASCII characters to, and from Braille 75 | function encode (str, encoded) { 76 | table[encoded = str.split('').map(function (s) { 77 | if (s.charCodeAt(0) > 127) { return s } 78 | return String.fromCharCode(s.charCodeAt(0) + 0x2800); 79 | }).join('')] = str; 80 | return encoded; 81 | } 82 | function decode (str) { 83 | if (str in table) { 84 | return table[str]; 85 | } else { 86 | return str.trim().split('').map(function (s) { 87 | if (s.charCodeAt(0) - 0x2800 > 127) { return s } 88 | return String.fromCharCode(s.charCodeAt(0) - 0x2800); 89 | }).join(''); 90 | } 91 | } 92 | 93 | }; -------------------------------------------------------------------------------- /client/js/jquery.hotKeys.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery Hotkeys Plugin 3 | * Copyright 2010, John Resig 4 | * Dual licensed under the MIT or GPL Version 2 licenses. 5 | * 6 | * Based upon the plugin by Tzury Bar Yochay: 7 | * http://github.com/tzuryby/hotkeys 8 | * 9 | * Original idea by: 10 | * Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/ 11 | */ 12 | 13 | (function(jQuery){ 14 | 15 | jQuery.hotkeys = { 16 | version: "0.8", 17 | 18 | specialKeys: { 19 | 8: "backspace", 9: "tab", 13: "return", 16: "shift", 17: "ctrl", 18: "alt", 19: "pause", 20 | 20: "capslock", 27: "esc", 32: "space", 33: "pageup", 34: "pagedown", 35: "end", 36: "home", 21 | 37: "left", 38: "up", 39: "right", 40: "down", 45: "insert", 46: "del", 22 | 96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7", 23 | 104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".", 111 : "/", 24 | 112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", 117: "f6", 118: "f7", 119: "f8", 25 | 120: "f9", 121: "f10", 122: "f11", 123: "f12", 144: "numlock", 145: "scroll", 191: "/", 224: "meta" 26 | }, 27 | 28 | shiftNums: { 29 | "`": "~", "1": "!", "2": "@", "3": "#", "4": "$", "5": "%", "6": "^", "7": "&", 30 | "8": "*", "9": "(", "0": ")", "-": "_", "=": "+", ";": ": ", "'": "\"", ",": "<", 31 | ".": ">", "/": "?", "\\": "|" 32 | } 33 | }; 34 | 35 | function keyHandler( handleObj ) { 36 | // Only care when a possible input has been specified 37 | if ( typeof handleObj.data !== "string" ) { 38 | return; 39 | } 40 | 41 | var origHandler = handleObj.handler, 42 | keys = handleObj.data.toLowerCase().split(" "); 43 | 44 | handleObj.handler = function( event ) { 45 | // Don't fire in text-accepting inputs that we didn't directly bind to 46 | if ( this !== event.target && (/textarea|select/i.test( event.target.nodeName ) || 47 | event.target.type === "text") ) { 48 | return; 49 | } 50 | 51 | // Keypress represents characters, not special keys 52 | var special = event.type !== "keypress" && jQuery.hotkeys.specialKeys[ event.which ], 53 | character = String.fromCharCode( event.which ).toLowerCase(), 54 | key, modif = "", possible = {}; 55 | 56 | // check combinations (alt|ctrl|shift+anything) 57 | if ( event.altKey && special !== "alt" ) { 58 | modif += "alt+"; 59 | } 60 | 61 | if ( event.ctrlKey && special !== "ctrl" ) { 62 | modif += "ctrl+"; 63 | } 64 | 65 | // TODO: Need to make sure this works consistently across platforms 66 | if ( event.metaKey && !event.ctrlKey && special !== "meta" ) { 67 | modif += "meta+"; 68 | } 69 | 70 | if ( event.shiftKey && special !== "shift" ) { 71 | modif += "shift+"; 72 | } 73 | 74 | if ( special ) { 75 | possible[ modif + special ] = true; 76 | 77 | } else { 78 | possible[ modif + character ] = true; 79 | possible[ modif + jQuery.hotkeys.shiftNums[ character ] ] = true; 80 | 81 | // "$" can be triggered as "Shift+4" or "Shift+$" or just "$" 82 | if ( modif === "shift+" ) { 83 | possible[ jQuery.hotkeys.shiftNums[ character ] ] = true; 84 | } 85 | } 86 | 87 | for ( var i = 0, l = keys.length; i < l; i++ ) { 88 | if ( possible[ keys[i] ] ) { 89 | return origHandler.apply( this, arguments ); 90 | } 91 | } 92 | }; 93 | } 94 | 95 | jQuery.each([ "keydown", "keyup", "keypress" ], function() { 96 | jQuery.event.special[ this ] = { add: keyHandler }; 97 | }); 98 | 99 | })( jQuery ); -------------------------------------------------------------------------------- /client/js/modernizr-1.5.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Modernizr JavaScript library 1.5 3 | * http://www.modernizr.com/ 4 | * 5 | * Copyright (c) 2009-2010 Faruk Ates - http://farukat.es/ 6 | * Dual-licensed under the BSD and MIT licenses. 7 | * http://www.modernizr.com/license/ 8 | * 9 | * Featuring major contributions by 10 | * Paul Irish - http://paulirish.com 11 | */ 12 | window.Modernizr=function(i,e,I){function C(a,b){for(var c in a)if(m[a[c]]!==I&&(!b||b(a[c],D)))return true}function r(a,b){var c=a.charAt(0).toUpperCase()+a.substr(1);return!!C([a,"Webkit"+c,"Moz"+c,"O"+c,"ms"+c,"Khtml"+c],b)}function P(){j[E]=function(a){for(var b=0,c=a.length;b7)};d.historymanagement=function(){return!!(i.history&&history.pushState)};d.draganddrop=function(){return u("drag")&&u("dragstart")&&u("dragenter")&&u("dragover")&&u("dragleave")&&u("dragend")&&u("drop")};d.websockets=function(){return"WebSocket"in i};d.rgba=function(){m.cssText="background-color:rgba(150,255,150,.5)";return(""+m.backgroundColor).indexOf("rgba")!==-1};d.hsla=function(){m.cssText="background-color:hsla(120,40%,100%,.5)";return(""+ 17 | m.backgroundColor).indexOf("rgba")!==-1};d.multiplebgs=function(){m.cssText="background:url(//:),url(//:),red url(//:)";return/(url\s*\(.*?){3}/.test(m.background)};d.backgroundsize=function(){return r("backgroundSize")};d.borderimage=function(){return r("borderImage")};d.borderradius=function(){return r("borderRadius","",function(a){return(""+a).indexOf("orderRadius")!==-1})};d.boxshadow=function(){return r("boxShadow")};d.opacity=function(){var a=y.join("opacity:.5;")+"";m.cssText=a;return(""+m.opacity).indexOf("0.5")!== 18 | -1};d.cssanimations=function(){return r("animationName")};d.csscolumns=function(){return r("columnCount")};d.cssgradients=function(){var a=("background-image:"+y.join("gradient(linear,left top,right bottom,from(#9f9),to(white));background-image:")+y.join("linear-gradient(left top,#9f9, white);background-image:")).slice(0,-17);m.cssText=a;return(""+m.backgroundImage).indexOf("gradient")!==-1};d.cssreflections=function(){return r("boxReflect")};d.csstransforms=function(){return!!C(["transformProperty", 19 | "WebkitTransform","MozTransform","OTransform","msTransform"])};d.csstransforms3d=function(){var a=!!C(["perspectiveProperty","WebkitPerspective","MozPerspective","OPerspective","msPerspective"]);if(a){var b=document.createElement("style"),c=e.createElement("div");b.textContent="@media ("+y.join("transform-3d),(")+"modernizr){#modernizr{height:3px}}";e.getElementsByTagName("head")[0].appendChild(b);c.id="modernizr";s.appendChild(c);a=c.offsetHeight===3;b.parentNode.removeChild(b);c.parentNode.removeChild(c)}return a}; 20 | d.csstransitions=function(){return r("transitionProperty")};d.fontface=function(){var a;if(/*@cc_on@if(@_jscript_version>=5)!@end@*/0)a=true;else{var b=e.createElement("style"),c=e.createElement("span"),h,t=false,g=e.body,o,w;b.textContent="@font-face{font-family:testfont;src:url('data:font/ttf;base64,AAEAAAAMAIAAAwBAT1MvMliohmwAAADMAAAAVmNtYXCp5qrBAAABJAAAANhjdnQgACICiAAAAfwAAAAEZ2FzcP//AAMAAAIAAAAACGdseWYv5OZoAAACCAAAANxoZWFk69bnvwAAAuQAAAA2aGhlYQUJAt8AAAMcAAAAJGhtdHgGDgC4AAADQAAAABRsb2NhAIQAwgAAA1QAAAAMbWF4cABVANgAAANgAAAAIG5hbWUgXduAAAADgAAABPVwb3N03NkzmgAACHgAAAA4AAECBAEsAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAACAAMDAAAAAAAAgAACbwAAAAoAAAAAAAAAAFBmRWQAAAAgqS8DM/8zAFwDMwDNAAAABQAAAAAAAAAAAAMAAAADAAAAHAABAAAAAABGAAMAAQAAAK4ABAAqAAAABgAEAAEAAgAuqQD//wAAAC6pAP///9ZXAwAAAAAAAAACAAAABgBoAAAAAAAvAAEAAAAAAAAAAAAAAAAAAAABAAIAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEACoAAAAGAAQAAQACAC6pAP//AAAALqkA////1lcDAAAAAAAAAAIAAAAiAogAAAAB//8AAgACACIAAAEyAqoAAwAHAC6xAQAvPLIHBADtMrEGBdw8sgMCAO0yALEDAC88sgUEAO0ysgcGAfw8sgECAO0yMxEhESczESMiARDuzMwCqv1WIgJmAAACAFUAAAIRAc0ADwAfAAATFRQWOwEyNj0BNCYrASIGARQGKwEiJj0BNDY7ATIWFX8aIvAiGhoi8CIaAZIoN/43KCg3/jcoAWD0JB4eJPQkHh7++EY2NkbVRjY2RgAAAAABAEH/+QCdAEEACQAANjQ2MzIWFAYjIkEeEA8fHw8QDxwWFhwWAAAAAQAAAAIAAIuYbWpfDzz1AAsEAAAAAADFn9IuAAAAAMWf0i797/8zA4gDMwAAAAgAAgAAAAAAAAABAAADM/8zAFwDx/3v/98DiAABAAAAAAAAAAAAAAAAAAAABQF2ACIAAAAAAVUAAAJmAFUA3QBBAAAAKgAqACoAWgBuAAEAAAAFAFAABwBUAAQAAgAAAAEAAQAAAEAALgADAAMAAAAQAMYAAQAAAAAAAACLAAAAAQAAAAAAAQAhAIsAAQAAAAAAAgAFAKwAAQAAAAAAAwBDALEAAQAAAAAABAAnAPQAAQAAAAAABQAKARsAAQAAAAAABgAmASUAAQAAAAAADgAaAUsAAwABBAkAAAEWAWUAAwABBAkAAQBCAnsAAwABBAkAAgAKAr0AAwABBAkAAwCGAscAAwABBAkABABOA00AAwABBAkABQAUA5sAAwABBAkABgBMA68AAwABBAkADgA0A/tDb3B5cmlnaHQgMjAwOSBieSBEYW5pZWwgSm9obnNvbi4gIFJlbGVhc2VkIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgT3BlbiBGb250IExpY2Vuc2UuIEtheWFoIExpIGdseXBocyBhcmUgcmVsZWFzZWQgdW5kZXIgdGhlIEdQTCB2ZXJzaW9uIDMuYmFlYzJhOTJiZmZlNTAzMiAtIHN1YnNldCBvZiBKdXJhTGlnaHRiYWVjMmE5MmJmZmU1MDMyIC0gc3Vic2V0IG9mIEZvbnRGb3JnZSAyLjAgOiBKdXJhIExpZ2h0IDogMjMtMS0yMDA5YmFlYzJhOTJiZmZlNTAzMiAtIHN1YnNldCBvZiBKdXJhIExpZ2h0VmVyc2lvbiAyIGJhZWMyYTkyYmZmZTUwMzIgLSBzdWJzZXQgb2YgSnVyYUxpZ2h0aHR0cDovL3NjcmlwdHMuc2lsLm9yZy9PRkwAQwBvAHAAeQByAGkAZwBoAHQAIAAyADAAMAA5ACAAYgB5ACAARABhAG4AaQBlAGwAIABKAG8AaABuAHMAbwBuAC4AIAAgAFIAZQBsAGUAYQBzAGUAZAAgAHUAbgBkAGUAcgAgAHQAaABlACAAdABlAHIAbQBzACAAbwBmACAAdABoAGUAIABPAHAAZQBuACAARgBvAG4AdAAgAEwAaQBjAGUAbgBzAGUALgAgAEsAYQB5AGEAaAAgAEwAaQAgAGcAbAB5AHAAaABzACAAYQByAGUAIAByAGUAbABlAGEAcwBlAGQAIAB1AG4AZABlAHIAIAB0AGgAZQAgAEcAUABMACAAdgBlAHIAcwBpAG8AbgAgADMALgBiAGEAZQBjADIAYQA5ADIAYgBmAGYAZQA1ADAAMwAyACAALQAgAHMAdQBiAHMAZQB0ACAAbwBmACAASgB1AHIAYQBMAGkAZwBoAHQAYgBhAGUAYwAyAGEAOQAyAGIAZgBmAGUANQAwADMAMgAgAC0AIABzAHUAYgBzAGUAdAAgAG8AZgAgAEYAbwBuAHQARgBvAHIAZwBlACAAMgAuADAAIAA6ACAASgB1AHIAYQAgAEwAaQBnAGgAdAAgADoAIAAyADMALQAxAC0AMgAwADAAOQBiAGEAZQBjADIAYQA5ADIAYgBmAGYAZQA1ADAAMwAyACAALQAgAHMAdQBiAHMAZQB0ACAAbwBmACAASgB1AHIAYQAgAEwAaQBnAGgAdABWAGUAcgBzAGkAbwBuACAAMgAgAGIAYQBlAGMAMgBhADkAMgBiAGYAZgBlADUAMAAzADIAIAAtACAAcwB1AGIAcwBlAHQAIABvAGYAIABKAHUAcgBhAEwAaQBnAGgAdABoAHQAdABwADoALwAvAHMAYwByAGkAcAB0AHMALgBzAGkAbAAuAG8AcgBnAC8ATwBGAEwAAAAAAgAAAAAAAP+BADMAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAQACAQIAEQt6ZXJva2F5YWhsaQ==')}"; 21 | e.getElementsByTagName("head")[0].appendChild(b);c.setAttribute("style","font:99px _,arial,helvetica;position:absolute;visibility:hidden");if(!g){g=s.appendChild(e.createElement("fontface"));t=true}c.innerHTML="........";c.id="fonttest";g.appendChild(c);h=c.offsetWidth*c.offsetHeight;c.style.font="99px testfont,_,arial,helvetica";a=h!==c.offsetWidth*c.offsetHeight;var v=function(){if(g.parentNode){a=j.fontface=h!==c.offsetWidth*c.offsetHeight;s.className=s.className.replace(/(no-)?fontface\b/,"")+ 22 | (a?" ":" no-")+"fontface"}};setTimeout(v,75);setTimeout(v,150);addEventListener("load",function(){v();(w=true)&&o&&o(a);setTimeout(function(){t||(g=c);g.parentNode.removeChild(g);b.parentNode.removeChild(b)},50)},false)}j._fontfaceready=function(p){w||a?p(a):(o=p)};return a||h!==c.offsetWidth};d.video=function(){var a=e.createElement("video"),b=!!a.canPlayType;if(b){b=new Boolean(b);b.ogg=a.canPlayType('video/ogg; codecs="theora"');b.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"');b.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"')}return b}; 23 | d.audio=function(){var a=e.createElement("audio"),b=!!a.canPlayType;if(b){b=new Boolean(b);b.ogg=a.canPlayType('audio/ogg; codecs="vorbis"');b.mp3=a.canPlayType("audio/mpeg;");b.wav=a.canPlayType('audio/wav; codecs="1"');b.m4a=a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")}return b};d.localStorage=function(){return"localStorage"in i&&i.localStorage!==null};d.sessionStorage=function(){try{return"sessionStorage"in i&&i.sessionStorage!==null}catch(a){return false}};d.webworkers=function(){return!!i.Worker}; 24 | d.applicationCache=function(){var a=i.applicationCache;return!!(a&&typeof a.status!="undefined"&&typeof a.update=="function"&&typeof a.swapCache=="function")};d.svg=function(){return!!e.createElementNS&&!!e.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect};d.smil=function(){return!!e.createElementNS&&/SVG/.test(M.call(e.createElementNS("http://www.w3.org/2000/svg","animate")))};d.svgclippaths=function(){return!!e.createElementNS&&/SVG/.test(M.call(e.createElementNS("http://www.w3.org/2000/svg", 25 | "clipPath")))};for(var z in d)if(O(d,z))N.push(((j[z.toLowerCase()]=d[z]())?"":"no-")+z.toLowerCase());j[E]||P();j.addTest=function(a,b){a=a.toLowerCase();if(!j[a]){b=!!b();s.className+=" "+(b?"":"no-")+a;j[a]=b;return j}};m.cssText="";D=n=null;(function(){var a=e.createElement("div");a.innerHTML="";return a.childNodes.length!==1})()&&function(a,b){function c(f,k){if(o[f])o[f].styleSheet.cssText+=k;else{var l=t[G],q=b[A]("style");q.media=f;l.insertBefore(q,l[G]);o[f]=q;c(f,k)}}function h(f, 26 | k){for(var l=new RegExp("\\b("+w+")\\b(?!.*[;}])","gi"),q=function(B){return".iepp_"+B},x=-1;++x\\s*$","i");g.innerHTML=f.outerHTML.replace(/\r|\n/g," ").replace(l,f.currentStyle.display=="block"?"":"");l=g.childNodes[0];l.className+=" iepp_"+q;l=p[p.length]=[f,l];f.parentNode.replaceChild(l[1],l[0])}h(b.styleSheets,"all")});a.attachEvent("onafterprint", 28 | function(){for(var f=-1,k;++fwindow._hash = '" + s + "'; window.onload = parent.hash.syncHash;<\/script>"); 58 | d.close(); 59 | }, 60 | 61 | syncHash: function () { 62 | var s = this._hash; 63 | if (s != document.location.hash) { 64 | document.location.hash = s; 65 | } 66 | }, 67 | 68 | onHashChanged: function () {} 69 | }; 70 | 71 | window.APP = (typeof window.APP != "undefined") ? window.APP : { 72 | 73 | overrides: {}, 74 | 75 | override: function(ns, plan) { 76 | overrides[ns] = plan; 77 | }, 78 | 79 | exec: function(params) { 80 | 81 | var strNS = params.ns 82 | ,self = this 83 | ,ns = {} 84 | ,sectors = strNS.split('.') 85 | ,methods 86 | ,isArray = (function() { return Array.isArray || function(obj) { 87 | return !!(obj && obj.concat && obj.unshift && !obj.callee); 88 | }})(); 89 | 90 | var i = 0 91 | ,len = sectors.length; 92 | 93 | for (i; i < sectors.length; i++) { 94 | var sector = sectors[i]; 95 | 96 | if (i == 0 && !window[sector]) { 97 | window[sector] = {}; 98 | ns = window[sector]; 99 | } 100 | else { 101 | ns = ns[sector] = (ns[sector] ? ns[sector] : {}); 102 | } 103 | } 104 | 105 | delete this.Main; 106 | eval(params.ns + " = this;"); // TODO: there may be a better way to do this assignment. 107 | 108 | methods = (typeof APP.overrides[ns] == "undefined") ? 109 | params.plan : APP.overrides[ns]; 110 | 111 | for(method in methods) { 112 | 113 | if(isArray(methods[method])) { 114 | 115 | var params = methods[method].slice(1, methods[method].length) 116 | ,i=params.length 117 | ,sync = false; 118 | 119 | for(; i>0; i--) { 120 | if(params[i] === "sync") { 121 | sync = true; 122 | } 123 | } 124 | 125 | sync ? self[methods[method][0]].call(self, params) : 126 | (function(method) { 127 | setTimeout(function() { 128 | self[method[0]].call(self, method.slice(1, method.length)); 129 | }, 1); 130 | })(methods[method]); 131 | } 132 | else { 133 | 134 | (function(method) { 135 | setTimeout(function() { 136 | self[method].call(self); 137 | }, 1); 138 | })(methods[method]) 139 | } 140 | } 141 | } 142 | }; 143 | -------------------------------------------------------------------------------- /client/js/plugins.js: -------------------------------------------------------------------------------- 1 | 2 | window.log = function(){ 3 | log.history = log.history || []; 4 | log.history.push(arguments); 5 | if(this.console){ 6 | console.log( Array.prototype.slice.call(arguments) ); 7 | } 8 | }; 9 | 10 | if(typeof console == 'undefined'){ 11 | var console = {}; 12 | console.log = function(){return false;} 13 | } 14 | 15 | (function(doc){ 16 | var write = doc.write; 17 | doc.write = function(q){ 18 | log('document.write(): ',arguments); 19 | if (/docwriteregexwhitelist/.test(q)) write.apply(doc,arguments); 20 | }; 21 | })(document); 22 | 23 | 24 | 25 | /* 26 | * jQuery Caret Range plugin 27 | * Copyright (c) 2009 Matt Zabriskie 28 | * Released under the MIT and GPL licenses. 29 | */ 30 | (function($) { 31 | $.extend($.fn, { 32 | caret: function (start, end) { 33 | var elem = this[0]; 34 | 35 | if (elem) { 36 | // get caret range 37 | if (typeof start == "undefined") { 38 | if (elem.selectionStart) { 39 | start = elem.selectionStart; 40 | end = elem.selectionEnd; 41 | } 42 | else if (document.selection) { 43 | var val = this.val(); 44 | var range = document.selection.createRange().duplicate(); 45 | range.moveEnd("character", val.length) 46 | start = (range.text == "" ? val.length : val.lastIndexOf(range.text)); 47 | 48 | range = document.selection.createRange().duplicate(); 49 | range.moveStart("character", -val.length); 50 | end = range.text.length; 51 | } 52 | } 53 | // set caret range 54 | else { 55 | var val = this.val(); 56 | 57 | if (typeof start != "number") start = -1; 58 | if (typeof end != "number") end = -1; 59 | if (start < 0) start = 0; 60 | if (end > val.length) end = val.length; 61 | if (end < start) end = start; 62 | if (start > end) start = end; 63 | 64 | elem.focus(); 65 | 66 | if (elem.selectionStart) { 67 | elem.selectionStart = start; 68 | elem.selectionEnd = end; 69 | } 70 | else if (document.selection) { 71 | var range = elem.createTextRange(); 72 | range.collapse(true); 73 | range.moveStart("character", start); 74 | range.moveEnd("character", end - start); 75 | range.select(); 76 | } 77 | } 78 | 79 | return {start:start, end:end}; 80 | } 81 | } 82 | }); 83 | })(jQuery); -------------------------------------------------------------------------------- /client/js/profiling/charts.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodejitsu/prenup/3667ae5d103461caaebc4967376df833ed12beac/client/js/profiling/charts.swf -------------------------------------------------------------------------------- /client/js/profiling/config.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | // call PROFILE.show() to show the profileViewer 4 | 5 | var PROFILE = { 6 | 7 | init : function(bool) { 8 | 9 | // define what objects, constructors and functions you want to profile 10 | // documentation here: http://developer.yahoo.com/yui/profiler/ 11 | 12 | YAHOO.tool.Profiler.registerObject("jQuery", jQuery, true); 13 | 14 | // the following would profile all methods within constructor's prototype 15 | // YAHOO.tool.Profiler.registerConstructor("Person"); 16 | 17 | // the following would profile the global function sayHi 18 | // YAHOO.tool.Profiler.registerFunction("sayHi", window); 19 | 20 | // if true is passed into init(), F9 will bring up the profiler 21 | if (bool){ 22 | $(document).keyup(function(e){ 23 | if (e.keyCode === 120){ 24 | PROFILE.show(); 25 | $(document).unbind('keyup',arguments.callee); 26 | } 27 | }) 28 | } 29 | }, 30 | 31 | //When the showProfile button is clicked, use YUI Loader to get all required 32 | //dependencies and then show the profile: 33 | show : function() { 34 | 35 | 36 | 37 | var s = document.createElement('link'); 38 | s.setAttribute('rel','stylesheet'); 39 | s.setAttribute('type','text/css'); 40 | s.setAttribute('href','js/profiling/yahoo-profiling.css'); 41 | document.body.appendChild(s); 42 | 43 | YAHOO.util.Dom.addClass(document.body, 'yui-skin-sam'); 44 | 45 | //instantiate ProfilerViewer with desired options: 46 | var pv = new YAHOO.widget.ProfilerViewer("", { 47 | visible: true, //expand the viewer mmediately after instantiation 48 | showChart: true, 49 | // base:"../../build/", 50 | swfUrl: "js/profiling/charts.swf" 51 | }); 52 | 53 | } 54 | 55 | }; 56 | 57 | // check some global debug variable to see if we should be profiling.. 58 | if (true) { PROFILE.init(true) } 59 | 60 | -------------------------------------------------------------------------------- /client/js/profiling/yahoo-profiling.css: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009, Yahoo! Inc. All rights reserved. 3 | Code licensed under the BSD License: 4 | http://developer.yahoo.net/yui/license.txt 5 | version: 2.7.0 6 | */ 7 | .yui-skin-sam .yui-pv{background-color:#4a4a4a;font:arial;position:relative;width:99%;z-index:1000;margin-bottom:1em;overflow:hidden;}.yui-skin-sam .yui-pv .hd{background:url(http://yui.yahooapis.com/2.7.0/build/profilerviewer/assets/skins/sam/header_background.png) repeat-x;min-height:30px;overflow:hidden;zoom:1;padding:2px 0;}.yui-skin-sam .yui-pv .hd h4{padding:8px 10px;margin:0;font:bold 14px arial;color:#fff;}.yui-skin-sam .yui-pv .hd a{background:#3f6bc3;font:bold 11px arial;color:#fff;padding:4px;margin:3px 10px 0 0;border:1px solid #3f567d;cursor:pointer;display:block;float:right;}.yui-skin-sam .yui-pv .hd span{display:none;}.yui-skin-sam .yui-pv .hd span.yui-pv-busy{height:18px;width:18px;background:url(http://yui.yahooapis.com/2.7.0/build/profilerviewer/assets/skins/sam/wait.gif) no-repeat;overflow:hidden;display:block;float:right;margin:4px 10px 0 0;}.yui-skin-sam .yui-pv .hd:after,.yui-pv .bd:after,.yui-skin-sam .yui-pv-chartlegend dl:after{content:'.';visibility:hidden;clear:left;height:0;display:block;}.yui-skin-sam .yui-pv .bd{position:relative;zoom:1;overflow-x:auto;overflow-y:hidden;}.yui-skin-sam .yui-pv .yui-pv-table{padding:0 10px;margin:5px 0 10px 0;}.yui-skin-sam .yui-pv .yui-pv-table .yui-dt-bd td{color:#eeee5c;font:12px arial;}.yui-skin-sam .yui-pv .yui-pv-table tr.yui-dt-odd{background:#929292;}.yui-skin-sam .yui-pv .yui-pv-table tr.yui-dt-even{background:#58637a;}.yui-skin-sam .yui-pv .yui-pv-table tr.yui-dt-even td.yui-dt-asc,.yui-skin-sam .yui-pv .yui-pv-table tr.yui-dt-even td.yui-dt-desc{background:#384970;}.yui-skin-sam .yui-pv .yui-pv-table tr.yui-dt-odd td.yui-dt-asc,.yui-skin-sam .yui-pv .yui-pv-table tr.yui-dt-odd td.yui-dt-desc{background:#6F6E6E;}.yui-skin-sam .yui-pv .yui-pv-table .yui-dt-hd th{background-image:none;background:#2E2D2D;}.yui-skin-sam .yui-pv th.yui-dt-asc .yui-dt-liner{background:transparent url(http://yui.yahooapis.com/2.7.0/build/profilerviewer/assets/skins/sam/asc.gif) no-repeat scroll right center;}.yui-skin-sam .yui-pv th.yui-dt-desc .yui-dt-liner{background:transparent url(http://yui.yahooapis.com/2.7.0/build/profilerviewer/assets/skins/sam/desc.gif) no-repeat scroll right center;}.yui-skin-sam .yui-pv .yui-pv-table .yui-dt-hd th a{color:#fff;font:bold 12px arial;}.yui-skin-sam .yui-pv .yui-pv-table .yui-dt-hd th.yui-dt-asc,.yui-skin-sam .yui-pv .yui-pv-table .yui-dt-hd th.yui-dt-desc{background:#333;}.yui-skin-sam .yui-pv-chartcontainer{padding:0 10px;}.yui-skin-sam .yui-pv-chart{height:250px;clear:right;margin:5px 0 0 0;color:#fff;}.yui-skin-sam .yui-pv-chartlegend div{float:right;margin:0 0 0 10px;_width:250px;}.yui-skin-sam .yui-pv-chartlegend dl{border:1px solid #999;padding:.2em 0 .2em .5em;zoom:1;margin:5px 0;}.yui-skin-sam .yui-pv-chartlegend dt{float:left;display:block;height:.7em;width:.7em;padding:0;}.yui-skin-sam .yui-pv-chartlegend dd{float:left;display:block;color:#fff;margin:0 1em 0 .5em;padding:0;font:11px arial;}.yui-skin-sam .yui-pv-minimized{height:35px;}.yui-skin-sam .yui-pv-minimized .bd{top:-3000px;}.yui-skin-sam .yui-pv-minimized .hd a.yui-pv-refresh{display:none;} -------------------------------------------------------------------------------- /client/js/underscore.js: -------------------------------------------------------------------------------- 1 | (function(){var n=this,A=n._,r=typeof StopIteration!=="undefined"?StopIteration:"__break__",j=Array.prototype,l=Object.prototype,o=j.slice,B=j.unshift,C=l.toString,p=l.hasOwnProperty,s=j.forEach,t=j.map,u=j.reduce,v=j.reduceRight,w=j.filter,x=j.every,y=j.some,m=j.indexOf,z=j.lastIndexOf;l=Array.isArray;var D=Object.keys,b=function(a){return new k(a)};if(typeof exports!=="undefined")exports._=b;n._=b;b.VERSION="1.1.0";var i=b.forEach=function(a,c,d){try{if(s&&a.forEach===s)a.forEach(c,d);else if(b.isNumber(a.length))for(var e= 2 | 0,f=a.length;e=e.computed&&(e={value:f,computed:g})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);var e={computed:Infinity};i(a,function(f,g,h){g=c?c.call(d,f,g,h):f;gh? 6 | 1:0}),"value")};b.sortedIndex=function(a,c,d){d=d||b.identity;for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.zip=function(){for(var a=b.toArray(arguments),c=b.max(b.pluck(a,"length")),d=new Array(c),e=0;e0?f-c:c-f)>=0)return e;e[g++]=f}};b.bind=function(a,c){var d=b.rest(arguments,2);return function(){return a.apply(c||{},d.concat(b.toArray(arguments)))}};b.bindAll=function(a){var c=b.rest(arguments);if(c.length==0)c=b.functions(a);i(c,function(d){a[d]=b.bind(a[d],a)});return a};b.memoize=function(a,c){var d={};c=c||b.identity;return function(){var e=c.apply(this,arguments);return e in 10 | d?d[e]:(d[e]=a.apply(this,arguments))}};b.delay=function(a,c){var d=b.rest(arguments,2);return setTimeout(function(){return a.apply(a,d)},c)};b.defer=function(a){return b.delay.apply(b,[a,1].concat(b.rest(arguments)))};b.wrap=function(a,c){return function(){var d=[a].concat(b.toArray(arguments));return c.apply(c,d)}};b.compose=function(){var a=b.toArray(arguments);return function(){for(var c=b.toArray(arguments),d=a.length-1;d>=0;d--)c=[a[d].apply(this,c)];return c[0]}};b.keys=D||function(a){if(b.isArray(a))return b.range(0, 11 | a.length);var c=[];for(var d in a)p.call(a,d)&&c.push(d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=function(a){return b.filter(b.keys(a),function(c){return b.isFunction(a[c])}).sort()};b.extend=function(a){i(b.rest(arguments),function(c){for(var d in c)a[d]=c[d]});return a};b.clone=function(a){if(b.isArray(a))return a.slice(0);return b.extend({},a)};b.tap=function(a,c){c(a);return a};b.isEqual=function(a,c){if(a===c)return true;var d=typeof a;if(d!=typeof c)return false; 12 | if(a==c)return true;if(!a&&c||a&&!c)return false;if(a.isEqual)return a.isEqual(c);if(b.isDate(a)&&b.isDate(c))return a.getTime()===c.getTime();if(b.isNaN(a)&&b.isNaN(c))return false;if(b.isRegExp(a)&&b.isRegExp(c))return a.source===c.source&&a.global===c.global&&a.ignoreCase===c.ignoreCase&&a.multiline===c.multiline;if(d!=="object")return false;if(a.length&&a.length!==c.length)return false;d=b.keys(a);var e=b.keys(c);if(d.length!=e.length)return false;for(var f in a)if(!(f in c)||!b.isEqual(a[f], 13 | c[f]))return false;return true};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(p.call(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=l||function(a){return!!(a&&a.concat&&a.unshift&&!a.callee)};b.isArguments=function(a){return a&&a.callee};b.isFunction=function(a){return!!(a&&a.constructor&&a.call&&a.apply)};b.isString=function(a){return!!(a===""||a&&a.charCodeAt&&a.substr)};b.isNumber=function(a){return a=== 14 | +a||C.call(a)==="[object Number]"};b.isBoolean=function(a){return a===true||a===false};b.isDate=function(a){return!!(a&&a.getTimezoneOffset&&a.setUTCFullYear)};b.isRegExp=function(a){return!!(a&&a.test&&a.exec&&(a.ignoreCase||a.ignoreCase===false))};b.isNaN=function(a){return b.isNumber(a)&&isNaN(a)};b.isNull=function(a){return a===null};b.isUndefined=function(a){return typeof a=="undefined"};b.noConflict=function(){n._=A;return this};b.identity=function(a){return a};b.times=function(a,c,d){for(var e= 15 | 0;e",interpolate:/<%=(.+?)%>/g};b.template=function(a,c){var d=b.templateSettings,e=new RegExp("'(?=[^"+d.end.substr(0,1)+"]*"+d.end.replace(/([.*+?^${}()|[\]\/\\])/g,"\\$1")+")","g");d=new Function("obj","var p=[],print=function(){p.push.apply(p,arguments);};with(obj||{}){p.push('"+a.replace(/\r/g, 16 | "\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t").replace(e,"\u2704").split("'").join("\\'").split("\u2704").join("'").replace(d.interpolate,"',$1,'").split(d.start).join("');").split(d.end).join("p.push('")+"');}return p.join('');");return c?d(c):d};b.each=b.forEach;b.foldl=b.inject=b.reduce;b.foldr=b.reduceRight;b.select=b.filter;b.all=b.every;b.any=b.some;b.contains=b.include;b.head=b.first;b.tail=b.rest;b.methods=b.functions;var k=function(a){this._wrapped=a},q=function(a,c){return c?b(a).chain(): 17 | a},E=function(a,c){k.prototype[a]=function(){var d=b.toArray(arguments);B.call(d,this._wrapped);return q(c.apply(b,d),this._chain)}};b.mixin(b);i(["pop","push","reverse","shift","sort","splice","unshift"],function(a){var c=j[a];k.prototype[a]=function(){c.apply(this._wrapped,arguments);return q(this._wrapped,this._chain)}});i(["concat","join","slice"],function(a){var c=j[a];k.prototype[a]=function(){return q(c.apply(this._wrapped,arguments),this._chain)}});k.prototype.chain=function(){this._chain= 18 | true;return this};k.prototype.value=function(){return this._wrapped}})(); 19 | -------------------------------------------------------------------------------- /client/nginx.conf: -------------------------------------------------------------------------------- 1 | user www www; 2 | worker_processes 5; 3 | error_log logs/error.log; 4 | pid logs/nginx.pid; 5 | worker_rlimit_nofile 8192; 6 | 7 | events { 8 | worker_connections 4096; 9 | } 10 | 11 | http { 12 | include mime.types; 13 | default_type application/octet-stream; 14 | log_format main '$remote_addr - $remote_user [$time_local] $status ' 15 | '"$request" $body_bytes_sent "$http_referer" ' 16 | '"$http_user_agent" "$http_x_forwarded_for"'; 17 | access_log logs/access.log main; 18 | 19 | keepalive_timeout 65; 20 | 21 | sendfile on; 22 | tcp_nopush on; 23 | tcp_nodelay off; 24 | 25 | gzip on; 26 | gzip_http_version 1.0; 27 | gzip_comp_level 2; 28 | gzip_min_length 1100; 29 | gzip_buffers 4 8k; 30 | gzip_proxied any; 31 | gzip_types text/html text/plain text/xml application/xml application/xml+rss text/css application/x-javascript text/javascript application/javascript application/json; 32 | 33 | gzip_static on; 34 | 35 | gzip_proxied expired no-cache no-store private auth; 36 | gzip_disable "MSIE [1-6]\."; 37 | gzip_vary on; 38 | 39 | server { 40 | listen 80 default deferred; 41 | server_name example.com; 42 | expires 1M; 43 | 44 | root /sites/example.com/public; 45 | 46 | #static assets 47 | location ~* ^.+\.(manifest)$ { 48 | expires 0S; 49 | root /sites/example.com/public; 50 | access_log logs/static.log; 51 | } 52 | location ~* ^.+\.(ico|ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ { 53 | # only set expires max IFF the file is a static file and exists 54 | if (-f $request_filename) { 55 | expires max; 56 | root /sites/example.com/public; 57 | access_log logs/static.log; 58 | } 59 | } 60 | 61 | } 62 | server { 63 | server_name www.example.com; 64 | rewrite ^(.*) http://example.com$1 permanent; 65 | } 66 | 67 | } 68 | 69 | -------------------------------------------------------------------------------- /client/robots.txt: -------------------------------------------------------------------------------- 1 | # www.robotstxt.org/ 2 | # www.google.com/support/webmasters/bin/answer.py?hl=en&answer=156449 3 | 4 | User-agent: * 5 | 6 | -------------------------------------------------------------------------------- /client/test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | QUnit Tests 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |

    QUnit Test Suite

    25 |

    26 |
    27 |

    28 |
      29 |
      test markup
      30 | 31 | -------------------------------------------------------------------------------- /client/test/qunit/qunit.css: -------------------------------------------------------------------------------- 1 | /** Font Family and Sizes */ 2 | 3 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { 4 | font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial; 5 | } 6 | 7 | #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } 8 | #qunit-tests { font-size: smaller; } 9 | 10 | 11 | /** Resets */ 12 | 13 | #qunit-tests, #qunit-tests li ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult { 14 | margin: 0; 15 | padding: 0; 16 | } 17 | 18 | 19 | /** Header */ 20 | 21 | #qunit-header { 22 | padding: 0.5em 0 0.5em 1em; 23 | 24 | color: #fff; 25 | text-shadow: rgba(0, 0, 0, 0.5) 4px 4px 1px; 26 | background-color: #0d3349; 27 | 28 | border-radius: 15px 15px 0 0; 29 | -moz-border-radius: 15px 15px 0 0; 30 | -webkit-border-top-right-radius: 15px; 31 | -webkit-border-top-left-radius: 15px; 32 | } 33 | 34 | #qunit-banner { 35 | height: 5px; 36 | } 37 | 38 | #qunit-testrunner-toolbar { 39 | padding: 0em 0 0.5em 2em; 40 | } 41 | 42 | #qunit-userAgent { 43 | padding: 0.5em 0 0.5em 2.5em; 44 | background-color: #2b81af; 45 | color: #fff; 46 | text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; 47 | } 48 | 49 | 50 | /** Tests: Pass/Fail */ 51 | 52 | #qunit-tests { 53 | list-style-position: inside; 54 | } 55 | 56 | #qunit-tests li { 57 | padding: 0.4em 0.5em 0.4em 2.5em; 58 | border-bottom: 1px solid #fff; 59 | list-style-position: inside; 60 | } 61 | 62 | #qunit-tests li strong { 63 | cursor: pointer; 64 | } 65 | 66 | #qunit-tests li ol { 67 | margin-top: 0.5em; 68 | padding: 0.5em; 69 | 70 | background-color: #fff; 71 | 72 | border-radius: 15px; 73 | -moz-border-radius: 15px; 74 | -webkit-border-radius: 15px; 75 | 76 | box-shadow: inset 0px 2px 13px #999; 77 | -moz-box-shadow: inset 0px 2px 13px #999; 78 | -webkit-box-shadow: inset 0px 2px 13px #999; 79 | } 80 | 81 | #qunit-tests li li { 82 | margin: 0.5em; 83 | padding: 0.4em 0.5em 0.4em 0.5em; 84 | background-color: #fff; 85 | border-bottom: none; 86 | list-style-position: inside; 87 | } 88 | 89 | /*** Passing Styles */ 90 | 91 | #qunit-tests li li.pass { 92 | color: #5E740B; 93 | background-color: #fff; 94 | border-left: 26px solid #C6E746; 95 | } 96 | 97 | #qunit-tests li.pass { color: #528CE0; background-color: #D2E0E6; } 98 | #qunit-tests li.pass span.test-name { color: #366097; } 99 | 100 | #qunit-tests li li.pass span.test-actual, 101 | #qunit-tests li li.pass span.test-expected { color: #999999; } 102 | 103 | strong b.pass { color: #5E740B; } 104 | 105 | #qunit-banner.qunit-pass { background-color: #C6E746; } 106 | 107 | /*** Failing Styles */ 108 | 109 | #qunit-tests li li.fail { 110 | color: #710909; 111 | background-color: #fff; 112 | border-left: 26px solid #EE5757; 113 | } 114 | 115 | #qunit-tests li.fail { color: #000000; background-color: #EE5757; } 116 | #qunit-tests li.fail span.test-name, 117 | #qunit-tests li.fail span.module-name { color: #000000; } 118 | 119 | #qunit-tests li li.fail span.test-actual { color: #EE5757; } 120 | #qunit-tests li li.fail span.test-expected { color: green; } 121 | 122 | strong b.fail { color: #710909; } 123 | 124 | #qunit-banner.qunit-fail, 125 | #qunit-testrunner-toolbar { background-color: #EE5757; } 126 | 127 | 128 | /** Footer */ 129 | 130 | #qunit-testresult { 131 | padding: 0.5em 0.5em 0.5em 2.5em; 132 | 133 | color: #2b81af; 134 | background-color: #D2E0E6; 135 | 136 | border-radius: 0 0 15px 15px; 137 | -moz-border-radius: 0 0 15px 15px; 138 | -webkit-border-bottom-right-radius: 15px; 139 | -webkit-border-bottom-left-radius: 15px; 140 | } 141 | 142 | /** Fixture */ 143 | 144 | #qunit-fixture { 145 | position: absolute; 146 | top: -10000px; 147 | left: -10000px; 148 | } 149 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | var sys = require('sys'), querystring = require('querystring'), url = require('url'); 2 | var static = require('./vendor/node-static/lib/node-static'); 3 | var kyuri = require('./vendor/kyuri/lib/kyuri'); 4 | 5 | 6 | // 7 | // Create a node-static server to serve the current directory 8 | // 9 | var file = new(static.Server)('./client', { cache: 7200, headers: {'X-Hello':'World!'} }); 10 | 11 | require('http').createServer(function (req, resp) { 12 | 13 | req.body = ''; 14 | 15 | req.addListener('data',function(chunk){ 16 | req.body += chunk 17 | }) 18 | 19 | req.addListener('end', function () { 20 | // Remark: here is an example of a simple router with node-static fallback 21 | if(req.url == '/'){ 22 | req.url = "index.html"; 23 | } 24 | if(req.url == '/export'){ 25 | var httpParams = {}; 26 | req.uri = url.parse(req.url); 27 | if(typeof req.uri.query == 'undefined'){req.uri.query = '';} 28 | req.uri.params = querystring.parse(req.uri.query); 29 | // request.uri.params 30 | var jsonAST = JSON.parse(req.body.toString()); 31 | // request processing logic goes here 32 | resp.writeHead(200, {'Content-Type': 'application/json'}); 33 | resp.write(JSON.stringify(kyuri.compile(jsonAST))); 34 | resp.end(); 35 | } 36 | else{ 37 | file.serve(req, resp, function (err, res) { 38 | if (err) { // An error as occured 39 | sys.error("> Error serving " + req.url + " - " + err.message); 40 | resp.writeHead(err.status, err.headers); 41 | resp.end(); 42 | } else { // The file was served successfully 43 | sys.puts("> " + req.url + " - " + res.message); 44 | } 45 | }); 46 | } 47 | }); 48 | }).listen(process.ENV.port || 8080); 49 | 50 | sys.puts("> prenup is listening on http://127.0.0.1:8080"); 51 | -------------------------------------------------------------------------------- /vendor/node-static/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 Alexis Sellier 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /vendor/node-static/README.md: -------------------------------------------------------------------------------- 1 | node-static 2 | =========== 3 | 4 | > a simple, *rfc 2616 compliant* file streaming module for [node](http://nodejs.org) 5 | 6 | node-static has an in-memory file cache, making it highly efficient. 7 | node-static understands and supports *conditional GET* and *HEAD* requests. 8 | node-static was inspired by some of the other static-file serving modules out there, 9 | such as node-paperboy and antinode. 10 | 11 | synopsis 12 | -------- 13 | 14 | var static = require('node-static'); 15 | 16 | // 17 | // Create a node-static server instance to serve the './public' folder 18 | // 19 | var file = new(static.Server)('./public'); 20 | 21 | require('http').createServer(function (request, response) { 22 | request.addListener('end', function () { 23 | // 24 | // Serve files! 25 | // 26 | file.serve(request, response); 27 | }); 28 | }).listen(8080); 29 | 30 | API 31 | --- 32 | 33 | ### Creating a node-static Server # 34 | 35 | Creating a file server instance is as simple as: 36 | 37 | new static.Server(); 38 | 39 | This will serve files in the current directory. If you want to serve files in a specific 40 | directory, pass it as the first argument: 41 | 42 | new static.Server('./public'); 43 | 44 | You can also specify how long the client is supposed to cache the files node-static serves: 45 | 46 | new static.Server('./public', { cache: 3600 }); 47 | 48 | This will set the `Cache-Control` header, telling clients to cache the file for an hour. 49 | This is the default setting. 50 | 51 | ### Serving files under a directory # 52 | 53 | To serve files under a directory, simply call the `serve` method on a `Server` instance, passing it 54 | the HTTP request and response object: 55 | 56 | var fileServer = new static.Server('./public'); 57 | 58 | require('http').createServer(function (request, response) { 59 | request.addListener('end', function () { 60 | fileServer.serve(request, response); 61 | }); 62 | }).listen(8080); 63 | 64 | ### Serving specific files # 65 | 66 | If you want to serve a specific file, like an error page for example, use the `serveFile` method: 67 | 68 | fileServer.serveFile('/error.html', 500, {}, request, response); 69 | 70 | This will serve the `error.html` file, from under the file root directory, with a `500` status code. 71 | For example, you could serve an error page, when the initial request wasn't found: 72 | 73 | require('http').createServer(function (request, response) { 74 | request.addListener('end', function () { 75 | fileServer.serve(request, response, function (e, res) { 76 | if (e && (e.status === 404)) { // If the file wasn't found 77 | fileServer.serveFile('/not-found.html', request, response); 78 | } 79 | }); 80 | }); 81 | }).listen(8080); 82 | 83 | More on intercepting errors bellow. 84 | 85 | ### Intercepting errors & Listening # 86 | 87 | An optional callback can be passed as last argument, it will be called every time a file 88 | has been served successfully, or if there was an error serving the file: 89 | 90 | var fileServer = new static.Server('./public'); 91 | 92 | require('http').createServer(function (request, response) { 93 | request.addListener('end', function () { 94 | fileServer.serve(request, response, function (err, result) { 95 | if (err) { // There was an error serving the file 96 | sys.error("Error serving " + request.url + " - " + err.message); 97 | 98 | // Respond to the client 99 | response.writeHead(err.status, err.headers); 100 | response.end(); 101 | } 102 | }); 103 | }); 104 | }).listen(8080); 105 | 106 | Note that if you pass a callback, and there is an error serving the file, node-static 107 | *will not* respond to the client. This gives you the opportunity to re-route the request, 108 | or handle it differently. 109 | 110 | For example, you may want to interpret a request as a static request, but if the file isn't found, 111 | send it to an application. 112 | 113 | If you only want to *listen* for errors, you can use *event listeners*: 114 | 115 | fileServer.serve(request, response).addListener('error', function (err) { 116 | sys.error("Error serving " + request.url + " - " + err.message); 117 | }); 118 | 119 | With this method, you don't have to explicitly send the response back, in case of an error. 120 | 121 | ### Options when creating an instance of `Server` # 122 | 123 | #### `cache` # 124 | 125 | Sets the `Cache-Control` header. 126 | 127 | example: `{ cache: 7200 }` 128 | 129 | Passing a number will set the cache duration to that number of seconds. 130 | Passing `false` will disable the `Cache-Control` header. 131 | 132 | > Defaults to `3600` 133 | 134 | #### `headers` # 135 | 136 | Sets response headers. 137 | 138 | example: `{ 'X-Hello': 'World!' }` 139 | 140 | > defaults to `{}` 141 | 142 | -------------------------------------------------------------------------------- /vendor/node-static/benchmark/node-static-0.3.0.txt: -------------------------------------------------------------------------------- 1 | This is ApacheBench, Version 2.3 <$Revision: 655654 $> 2 | Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ 3 | Licensed to The Apache Software Foundation, http://www.apache.org/ 4 | 5 | Benchmarking 127.0.0.1 (be patient) 6 | 7 | 8 | Server Software: node-static/0.3.0 9 | Server Hostname: 127.0.0.1 10 | Server Port: 8080 11 | 12 | Document Path: /lib/node-static.js 13 | Document Length: 6038 bytes 14 | 15 | Concurrency Level: 20 16 | Time taken for tests: 2.323 seconds 17 | Complete requests: 10000 18 | Failed requests: 0 19 | Write errors: 0 20 | Total transferred: 63190000 bytes 21 | HTML transferred: 60380000 bytes 22 | Requests per second: 4304.67 [#/sec] (mean) 23 | Time per request: 4.646 [ms] (mean) 24 | Time per request: 0.232 [ms] (mean, across all concurrent requests) 25 | Transfer rate: 26563.66 [Kbytes/sec] received 26 | 27 | Connection Times (ms) 28 | min mean[+/-sd] median max 29 | Connect: 0 0 0.2 0 3 30 | Processing: 1 4 1.4 4 28 31 | Waiting: 1 4 1.3 4 18 32 | Total: 2 5 1.5 4 28 33 | 34 | Percentage of the requests served within a certain time (ms) 35 | 50% 4 36 | 66% 5 37 | 75% 5 38 | 80% 5 39 | 90% 5 40 | 95% 6 41 | 98% 8 42 | 99% 9 43 | 100% 28 (longest request) 44 | -------------------------------------------------------------------------------- /vendor/node-static/examples/file-server.js: -------------------------------------------------------------------------------- 1 | var sys = require('sys'); 2 | var static = require('../lib/node-static'); 3 | 4 | // 5 | // Create a node-static server to serve the current directory 6 | // 7 | var file = new(static.Server)('.', { cache: 7200, headers: {'X-Hello':'World!'} }); 8 | 9 | require('http').createServer(function (request, response) { 10 | request.addListener('end', function () { 11 | // 12 | // Serve files! 13 | // 14 | file.serve(request, response, function (err, res) { 15 | if (err) { // An error as occured 16 | sys.error("> Error serving " + request.url + " - " + err.message); 17 | response.writeHead(err.status, err.headers); 18 | response.end(); 19 | } else { // The file was served successfully 20 | sys.puts("> " + request.url + " - " + res.message); 21 | } 22 | }); 23 | }); 24 | }).listen(8080); 25 | 26 | sys.puts("> node-static is listening on http://127.0.0.1:8080"); 27 | -------------------------------------------------------------------------------- /vendor/node-static/lib/node-static.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'), 2 | sys = require('sys'), 3 | events = require('events'), 4 | buffer = require('buffer'), 5 | http = require('http'), 6 | url = require('url'), 7 | path = require('path'); 8 | 9 | this.version = [0, 5, 1]; 10 | 11 | var mime = require('./node-static/mime'); 12 | var util = require('./node-static/util'); 13 | 14 | var serverInfo = 'node-static/' + this.version.join('.'); 15 | 16 | // In-memory file store 17 | this.store = {}; 18 | this.indexStore = {}; 19 | 20 | this.Server = function (root, options) { 21 | if (root && (typeof(root) === 'object')) { options = root, root = null } 22 | 23 | this.root = path.normalize(root || '.'); 24 | this.options = options || {}; 25 | this.cache = 3600; 26 | 27 | this.defaultHeaders = {}; 28 | this.options.headers = this.options.headers || {}; 29 | 30 | if ('cache' in this.options) { 31 | if (typeof(this.options.cache) === 'number') { 32 | this.cache = this.options.cache; 33 | } else if (! this.options.cache) { 34 | this.cache = false; 35 | } 36 | } 37 | 38 | if (this.cache !== false) { 39 | this.defaultHeaders['Cache-Control'] = 'max-age=' + this.cache; 40 | } 41 | this.defaultHeaders['Server'] = serverInfo; 42 | 43 | for (var k in this.defaultHeaders) { 44 | this.options.headers[k] = this.options.headers[k] || 45 | this.defaultHeaders[k]; 46 | } 47 | }; 48 | 49 | this.Server.prototype.serveDir = function (pathname, req, res, finish) { 50 | var htmlIndex = path.join(pathname, 'index.html'), 51 | that = this; 52 | 53 | fs.stat(htmlIndex, function (e, stat) { 54 | if (!e) { 55 | that.respond(null, 200, {}, [htmlIndex], stat, req, res, finish); 56 | } else { 57 | if (pathname in exports.store) { 58 | streamFiles(exports.indexStore[pathname].files); 59 | } else { 60 | // Stream a directory of files as a single file. 61 | fs.readFile(path.join(pathname, 'index.json'), function (e, contents) { 62 | if (e) { return finish(404, {}) } 63 | var index = JSON.parse(contents); 64 | exports.indexStore[pathname] = index; 65 | streamFiles(index.files); 66 | }); 67 | } 68 | } 69 | }); 70 | function streamFiles(files) { 71 | util.mstat(pathname, files, function (e, stat) { 72 | that.respond(pathname, 200, {}, files, stat, req, res, finish); 73 | }); 74 | } 75 | }; 76 | this.Server.prototype.serveFile = function (pathname, status, headers, req, res) { 77 | var that = this; 78 | var promise = new(events.EventEmitter); 79 | 80 | pathname = this.normalize(pathname); 81 | 82 | fs.stat(pathname, function (e, stat) { 83 | if (e) { 84 | return promise.emit('error', e); 85 | } 86 | that.respond(null, status, headers, [pathname], stat, req, res, function (status, headers) { 87 | that.finish(status, headers, req, res, promise); 88 | }); 89 | }); 90 | return promise; 91 | }; 92 | this.Server.prototype.finish = function (status, headers, req, res, promise, callback) { 93 | var result = { 94 | status: status, 95 | headers: headers, 96 | message: http.STATUS_CODES[status] 97 | }; 98 | 99 | headers['Server'] = serverInfo; 100 | 101 | if (!status || status >= 400) { 102 | if (callback) { 103 | callback(result); 104 | } else { 105 | if (promise.listeners('error').length > 0) { 106 | promise.emit('error', result); 107 | } 108 | res.writeHead(status, headers); 109 | res.end(); 110 | } 111 | } else { 112 | // Don't end the request here, if we're streaming; 113 | // it's taken care of in `prototype.stream`. 114 | if (status !== 200 || req.method !== 'GET') { 115 | res.writeHead(status, headers); 116 | res.end(); 117 | } 118 | callback && callback(null, result); 119 | promise.emit('success', result); 120 | } 121 | }; 122 | 123 | this.Server.prototype.servePath = function (pathname, status, headers, req, res, finish) { 124 | var that = this, 125 | promise = new(events.EventEmitter); 126 | 127 | pathname = this.normalize(pathname); 128 | 129 | // Only allow GET and HEAD requests 130 | if (req.method !== 'GET' && req.method !== 'HEAD') { 131 | finish(405, { 'Allow': 'GET, HEAD' }); 132 | return promise; 133 | } 134 | 135 | // Make sure we're not trying to access a 136 | // file outside of the root. 137 | if (new(RegExp)('^' + that.root).test(pathname)) { 138 | fs.stat(pathname, function (e, stat) { 139 | if (e) { 140 | finish(404, {}); 141 | } else if (stat.isFile()) { // Stream a single file. 142 | that.respond(null, status, headers, [pathname], stat, req, res, finish); 143 | } else if (stat.isDirectory()) { // Stream a directory of files. 144 | that.serveDir(pathname, req, res, finish); 145 | } else { 146 | finish(400, {}); 147 | } 148 | }); 149 | } else { 150 | // Forbidden 151 | finish(403, {}); 152 | } 153 | return promise; 154 | }; 155 | this.Server.prototype.normalize = function (pathname) { 156 | return path.normalize(path.join(this.root, pathname)); 157 | }; 158 | this.Server.prototype.serve = function (req, res, callback) { 159 | var that = this, 160 | promise = new(events.EventEmitter); 161 | 162 | var pathname = url.parse(req.url).pathname; 163 | 164 | var finish = function (status, headers) { 165 | that.finish(status, headers, req, res, promise, callback); 166 | }; 167 | 168 | process.nextTick(function () { 169 | that.servePath(pathname, 200, {}, req, res, finish).on('success', function (result) { 170 | promise.emit('success', result); 171 | }).on('error', function (err) { 172 | promise.emit('error'); 173 | }); 174 | }); 175 | if (! callback) { return promise } 176 | }; 177 | 178 | this.Server.prototype.respond = function (pathname, status, _headers, files, stat, req, res, finish) { 179 | var mtime = Date.parse(stat.mtime), 180 | key = pathname || files[0], 181 | headers = {}; 182 | 183 | // Copy default headers 184 | for (var k in this.options.headers) { headers[k] = this.options.headers[k] } 185 | 186 | headers['Etag'] = JSON.stringify([stat.ino, stat.size, mtime].join('-')); 187 | headers['Date'] = new(Date)().toUTCString(); 188 | headers['Last-Modified'] = new(Date)(stat.mtime).toUTCString(); 189 | 190 | // Conditional GET 191 | // If both the "If-Modified-Since" and "If-None-Match" headers 192 | // match the conditions, send a 304 Not Modified. 193 | if (req.headers['if-none-match'] === headers['Etag'] && 194 | Date.parse(req.headers['if-modified-since']) >= mtime) { 195 | finish(304, headers); 196 | } else if (req.method === 'HEAD') { 197 | finish(200, headers); 198 | } else { 199 | headers['Content-Length'] = stat.size; 200 | headers['Content-Type'] = mime.contentTypes[path.extname(files[0]).slice(1)] || 201 | 'application/octet-stream'; 202 | 203 | for (var k in headers) { _headers[k] = headers[k] } 204 | 205 | res.writeHead(status, _headers); 206 | 207 | // If the file was cached and it's not older 208 | // than what's on disk, serve the cached version. 209 | if (this.cache && (key in exports.store) && 210 | exports.store[key].stat.mtime >= stat.mtime) { 211 | res.end(exports.store[key].buffer); 212 | finish(status, _headers); 213 | } else { 214 | this.stream(pathname, files, new(buffer.Buffer)(stat.size), res, function (e, buffer) { 215 | if (e) { return finish(null, {}) } 216 | exports.store[key] = { 217 | stat: stat, 218 | buffer: buffer, 219 | timestamp: Date.now() 220 | }; 221 | finish(status, _headers); 222 | }); 223 | } 224 | } 225 | }; 226 | 227 | this.Server.prototype.stream = function (pathname, files, buffer, res, callback) { 228 | (function streamFile(files, offset) { 229 | var file = files.shift(); 230 | 231 | if (file) { 232 | // Stream the file to the client 233 | fs.createReadStream(path.join(pathname || '.', file), { 234 | flags: 'r', 235 | encoding: 'binary', 236 | mode: 0666, 237 | bufferSize: 4096 238 | }).addListener('data', function (chunk) { 239 | chunk.copy (buffer, offset, 0); 240 | res.write (chunk, 'binary'); 241 | offset += chunk.length; 242 | }).addListener('close', function () { 243 | streamFile(files, offset); 244 | }).addListener('error', function (err) { 245 | callback(err); 246 | sys.error(err); 247 | }); 248 | } else { 249 | res.end(); 250 | callback(null, buffer, offset); 251 | } 252 | })(files.slice(0), 0); 253 | }; 254 | -------------------------------------------------------------------------------- /vendor/node-static/lib/node-static/mime.js: -------------------------------------------------------------------------------- 1 | this.contentTypes = { 2 | "aiff": "audio/x-aiff", 3 | "arj": "application/x-arj-compressed", 4 | "asf": "video/x-ms-asf", 5 | "asx": "video/x-ms-asx", 6 | "au": "audio/ulaw", 7 | "avi": "video/x-msvideo", 8 | "bcpio": "application/x-bcpio", 9 | "ccad": "application/clariscad", 10 | "cod": "application/vnd.rim.cod", 11 | "com": "application/x-msdos-program", 12 | "cpio": "application/x-cpio", 13 | "cpt": "application/mac-compactpro", 14 | "csh": "application/x-csh", 15 | "css": "text/css", 16 | "deb": "application/x-debian-package", 17 | "dl": "video/dl", 18 | "doc": "application/msword", 19 | "drw": "application/drafting", 20 | "dvi": "application/x-dvi", 21 | "dwg": "application/acad", 22 | "dxf": "application/dxf", 23 | "dxr": "application/x-director", 24 | "etx": "text/x-setext", 25 | "ez": "application/andrew-inset", 26 | "fli": "video/x-fli", 27 | "flv": "video/x-flv", 28 | "gif": "image/gif", 29 | "gl": "video/gl", 30 | "gtar": "application/x-gtar", 31 | "gz": "application/x-gzip", 32 | "hdf": "application/x-hdf", 33 | "hqx": "application/mac-binhex40", 34 | "html": "text/html", 35 | "ice": "x-conference/x-cooltalk", 36 | "ief": "image/ief", 37 | "igs": "model/iges", 38 | "ips": "application/x-ipscript", 39 | "ipx": "application/x-ipix", 40 | "jad": "text/vnd.sun.j2me.app-descriptor", 41 | "jar": "application/java-archive", 42 | "jpeg": "image/jpeg", 43 | "jpg": "image/jpeg", 44 | "js": "text/javascript", 45 | "json": "application/json", 46 | "latex": "application/x-latex", 47 | "less": "text/css", 48 | "lsp": "application/x-lisp", 49 | "lzh": "application/octet-stream", 50 | "m": "text/plain", 51 | "m3u": "audio/x-mpegurl", 52 | "man": "application/x-troff-man", 53 | "me": "application/x-troff-me", 54 | "midi": "audio/midi", 55 | "mif": "application/x-mif", 56 | "mime": "www/mime", 57 | "movie": "video/x-sgi-movie", 58 | "mp4": "video/mp4", 59 | "mpg": "video/mpeg", 60 | "mpga": "audio/mpeg", 61 | "ms": "application/x-troff-ms", 62 | "nc": "application/x-netcdf", 63 | "oda": "application/oda", 64 | "ogm": "application/ogg", 65 | "pbm": "image/x-portable-bitmap", 66 | "pdf": "application/pdf", 67 | "pgm": "image/x-portable-graymap", 68 | "pgn": "application/x-chess-pgn", 69 | "pgp": "application/pgp", 70 | "pm": "application/x-perl", 71 | "png": "image/png", 72 | "pnm": "image/x-portable-anymap", 73 | "ppm": "image/x-portable-pixmap", 74 | "ppz": "application/vnd.ms-powerpoint", 75 | "pre": "application/x-freelance", 76 | "prt": "application/pro_eng", 77 | "ps": "application/postscript", 78 | "qt": "video/quicktime", 79 | "ra": "audio/x-realaudio", 80 | "rar": "application/x-rar-compressed", 81 | "ras": "image/x-cmu-raster", 82 | "rgb": "image/x-rgb", 83 | "rm": "audio/x-pn-realaudio", 84 | "rpm": "audio/x-pn-realaudio-plugin", 85 | "rtf": "text/rtf", 86 | "rtx": "text/richtext", 87 | "scm": "application/x-lotusscreencam", 88 | "set": "application/set", 89 | "sgml": "text/sgml", 90 | "sh": "application/x-sh", 91 | "shar": "application/x-shar", 92 | "silo": "model/mesh", 93 | "sit": "application/x-stuffit", 94 | "skt": "application/x-koan", 95 | "smil": "application/smil", 96 | "snd": "audio/basic", 97 | "sol": "application/solids", 98 | "spl": "application/x-futuresplash", 99 | "src": "application/x-wais-source", 100 | "stl": "application/SLA", 101 | "stp": "application/STEP", 102 | "sv4cpio": "application/x-sv4cpio", 103 | "sv4crc": "application/x-sv4crc", 104 | "swf": "application/x-shockwave-flash", 105 | "tar": "application/x-tar", 106 | "tcl": "application/x-tcl", 107 | "tex": "application/x-tex", 108 | "texinfo": "application/x-texinfo", 109 | "tgz": "application/x-tar-gz", 110 | "tiff": "image/tiff", 111 | "tr": "application/x-troff", 112 | "tsi": "audio/TSP-audio", 113 | "tsp": "application/dsptype", 114 | "tsv": "text/tab-separated-values", 115 | "txt": "text/plain", 116 | "unv": "application/i-deas", 117 | "ustar": "application/x-ustar", 118 | "vcd": "application/x-cdlink", 119 | "vda": "application/vda", 120 | "vivo": "video/vnd.vivo", 121 | "vrm": "x-world/x-vrml", 122 | "wav": "audio/x-wav", 123 | "wax": "audio/x-ms-wax", 124 | "wma": "audio/x-ms-wma", 125 | "wmv": "video/x-ms-wmv", 126 | "wmx": "video/x-ms-wmx", 127 | "wrl": "model/vrml", 128 | "wvx": "video/x-ms-wvx", 129 | "xbm": "image/x-xbitmap", 130 | "xlw": "application/vnd.ms-excel", 131 | "xml": "text/xml", 132 | "xpm": "image/x-xpixmap", 133 | "xwd": "image/x-xwindowdump", 134 | "xyz": "chemical/x-pdb", 135 | "zip": "application/zip" 136 | }; 137 | -------------------------------------------------------------------------------- /vendor/node-static/lib/node-static/util.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'), 2 | path = require('path'); 3 | 4 | this.mstat = function (dir, files, callback) { 5 | (function mstat(files, stats) { 6 | var file = files.shift(); 7 | 8 | if (file) { 9 | fs.stat(path.join(dir, file), function (e, stat) { 10 | if (e) { 11 | callback(e); 12 | } else { 13 | mstat(files, stats.concat([stat])); 14 | } 15 | }); 16 | } else { 17 | callback(null, { 18 | size: stats.reduce(function (total, stat) { 19 | return total + stat.size; 20 | }, 0), 21 | mtime: stats.reduce(function (latest, stat) { 22 | return latest > stat.mtime ? latest : stat.mtime; 23 | }, 0), 24 | ino: stats.reduce(function (total, stat) { 25 | return total + stat.ino; 26 | }, 0) 27 | }); 28 | } 29 | })(files.slice(0), []); 30 | }; 31 | -------------------------------------------------------------------------------- /vendor/node-static/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "node-static", 3 | "description" : "simple, compliant file streaming module for node", 4 | "url" : "http://github.com/cloudhead/node-static", 5 | "keywords" : ["http", "static", "file", "server"], 6 | "author" : "Alexis Sellier ", 7 | "contributors" : [], 8 | "licenses" : ["MIT"], 9 | "dependencies" : [], 10 | "lib" : "lib", 11 | "main" : "./lib/node-static", 12 | "version" : "0.5.1", 13 | "directories" : { "test": "./test" }, 14 | "engines" : { "node": ">= 0.1.100" } 15 | } 16 | --------------------------------------------------------------------------------