├── public ├── explorer │ ├── res │ │ ├── Thumbs.db │ │ ├── add.png │ │ ├── down.gif │ │ ├── key.png │ │ ├── bodyBg.png │ │ ├── bodyImg.png │ │ ├── cancel.gif │ │ ├── delete.png │ │ ├── expand.gif │ │ ├── semi-bg.png │ │ ├── spinner.gif │ │ ├── subNavL.png │ │ ├── subNavR.png │ │ ├── arrow_down.png │ │ ├── arrow_up.png │ │ ├── arrowdown.gif │ │ ├── blueTriBig.gif │ │ ├── headerBg.png │ │ ├── lightning.png │ │ ├── lock_add.png │ │ ├── navPointer.gif │ │ ├── navPointer.png │ │ ├── page_copy.png │ │ ├── page_paste.png │ │ ├── persevere.jpg │ │ ├── persevere.png │ │ ├── selected.png │ │ ├── table_add.png │ │ ├── blueTriSmall.png │ │ ├── paste_plain.png │ │ ├── subContentBg.png │ │ ├── persevere-205.jpg │ │ ├── persevere-273.jpg │ │ ├── persevere-273.png │ │ ├── persevere-glow.png │ │ ├── invert-persevere.png │ │ ├── chart_organisation.png │ │ ├── invert-persevere-273.png │ │ ├── iframeHistory.html │ │ └── common.css │ ├── js │ │ └── dojo-persevere │ │ │ ├── README.txt │ │ │ ├── resources │ │ │ └── login │ │ │ │ ├── login.html │ │ │ │ └── register.html │ │ │ ├── LoginLink.js │ │ │ ├── persevere.js │ │ │ └── Login.js │ └── explorer.js └── explorer.html ├── README ├── package.json └── lib ├── persvr.js └── json-query.js /public/explorer/res/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/Thumbs.db -------------------------------------------------------------------------------- /public/explorer/res/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/add.png -------------------------------------------------------------------------------- /public/explorer/res/down.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/down.gif -------------------------------------------------------------------------------- /public/explorer/res/key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/key.png -------------------------------------------------------------------------------- /public/explorer/res/bodyBg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/bodyBg.png -------------------------------------------------------------------------------- /public/explorer/res/bodyImg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/bodyImg.png -------------------------------------------------------------------------------- /public/explorer/res/cancel.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/cancel.gif -------------------------------------------------------------------------------- /public/explorer/res/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/delete.png -------------------------------------------------------------------------------- /public/explorer/res/expand.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/expand.gif -------------------------------------------------------------------------------- /public/explorer/res/semi-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/semi-bg.png -------------------------------------------------------------------------------- /public/explorer/res/spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/spinner.gif -------------------------------------------------------------------------------- /public/explorer/res/subNavL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/subNavL.png -------------------------------------------------------------------------------- /public/explorer/res/subNavR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/subNavR.png -------------------------------------------------------------------------------- /public/explorer/res/arrow_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/arrow_down.png -------------------------------------------------------------------------------- /public/explorer/res/arrow_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/arrow_up.png -------------------------------------------------------------------------------- /public/explorer/res/arrowdown.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/arrowdown.gif -------------------------------------------------------------------------------- /public/explorer/res/blueTriBig.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/blueTriBig.gif -------------------------------------------------------------------------------- /public/explorer/res/headerBg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/headerBg.png -------------------------------------------------------------------------------- /public/explorer/res/lightning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/lightning.png -------------------------------------------------------------------------------- /public/explorer/res/lock_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/lock_add.png -------------------------------------------------------------------------------- /public/explorer/res/navPointer.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/navPointer.gif -------------------------------------------------------------------------------- /public/explorer/res/navPointer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/navPointer.png -------------------------------------------------------------------------------- /public/explorer/res/page_copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/page_copy.png -------------------------------------------------------------------------------- /public/explorer/res/page_paste.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/page_paste.png -------------------------------------------------------------------------------- /public/explorer/res/persevere.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/persevere.jpg -------------------------------------------------------------------------------- /public/explorer/res/persevere.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/persevere.png -------------------------------------------------------------------------------- /public/explorer/res/selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/selected.png -------------------------------------------------------------------------------- /public/explorer/res/table_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/table_add.png -------------------------------------------------------------------------------- /public/explorer/res/blueTriSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/blueTriSmall.png -------------------------------------------------------------------------------- /public/explorer/res/paste_plain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/paste_plain.png -------------------------------------------------------------------------------- /public/explorer/res/subContentBg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/subContentBg.png -------------------------------------------------------------------------------- /public/explorer/res/persevere-205.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/persevere-205.jpg -------------------------------------------------------------------------------- /public/explorer/res/persevere-273.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/persevere-273.jpg -------------------------------------------------------------------------------- /public/explorer/res/persevere-273.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/persevere-273.png -------------------------------------------------------------------------------- /public/explorer/res/persevere-glow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/persevere-glow.png -------------------------------------------------------------------------------- /public/explorer/res/invert-persevere.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/invert-persevere.png -------------------------------------------------------------------------------- /public/explorer/res/chart_organisation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/chart_organisation.png -------------------------------------------------------------------------------- /public/explorer/res/invert-persevere-273.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kriszyp/persevere/master/public/explorer/res/invert-persevere-273.png -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Currently this is just a placeholder for potential future Persevere work. Please see http://www.persvr.org/ for the main Persevere site, or see the http://github.com/kriszyp/pintura for the Persevere 2.0 project called Pintura for running as a JSGI application. -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "persevere", 3 | "author": "Kris Zyp", 4 | "dependencies": ["pintura"], 5 | "contributors": [], 6 | "keywords": [ 7 | "json", 8 | "database", 9 | "javascript", 10 | "persistence", 11 | "rest" 12 | ], 13 | "githubName": "persevere", 14 | "type": "zip", 15 | "location": "http://github.com/kriszyp/persevere/zipball/master" 16 | } -------------------------------------------------------------------------------- /public/explorer/res/iframeHistory.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /lib/persvr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Some backwards compatible functions for Persevere 3 | */ 4 | 5 | var modelModule = require("./model"), 6 | Model = modelModule.Model; 7 | Class = function(schema){ 8 | return global[schema.id] = Model(schema.id, schema); 9 | }; 10 | 11 | load = function(id){ 12 | var parts = id.split("/"); 13 | var model = modelModule; 14 | for(var i = 1; i < parts.length - 1; i++){ 15 | model = model.get(parts[i]); 16 | } 17 | return model.get(parts[i]); 18 | }; 19 | 20 | -------------------------------------------------------------------------------- /public/explorer/js/dojo-persevere/README.txt: -------------------------------------------------------------------------------- 1 | Persevere JavaScript Client 2 | 3 | The Persevere JavaScript Client provides an implementation of the Persistent JavaScript API through HTTP (RFC 2616) with JSON for data interaction with a server. 4 | 5 | This library is persevere.js and requires Dojo 1.2. To use the library: 6 | 7 | 8 | 9 | The documentation for the Persevere JavaScript Client can be found at: 10 | http://docs.persvr.org/persevere-javascript-client 11 | 12 | This package also includes a Login widget, implemented as a Dojo widget. The Login widget 13 | supports authenticating to Persevere and registering new users. -------------------------------------------------------------------------------- /public/explorer/js/dojo-persevere/resources/login/login.html: -------------------------------------------------------------------------------- 1 || 5 | 6 | | 7 |8 | 12 | | 13 |
| 16 | 17 | | 18 |19 | 23 | | 24 |
| 5 | 6 | | 7 |8 | 13 | | 14 |
| 17 | 18 | | 19 |20 | 25 | | 26 |
| 29 | 30 | | 31 |32 | 37 | | 38 |
New " + className;
205 | //dojo.byId("removeItem").innerHTML = "Delete " + className;
206 | //dojo.byId("query").value = "";
207 | activeClassName = className;
208 | explorer.setItemName(className);
209 | explorer.setStore(activeStore = persevereStores[className]);
210 | }
211 | dojo.addOnLoad(function(){
212 | storesDfd.addCallback(function(stores){
213 | persevereStores = stores;
214 | var classes = dojo.byId("classes");
215 | for(i in persevereStores){
216 | var classOption = classes.appendChild(document.createElement("option"));
217 | classOption.innerHTML = i;
218 | classOption.value = i;
219 | }
220 | classes.value = "Class";
221 | dojo.connect(classes,"change",function(){
222 | showTable(classes.value);
223 | });
224 | showTable("Class");
225 | });
226 | });
227 |
228 | }
229 |
230 |
231 |
232 |
--------------------------------------------------------------------------------
/public/explorer/res/common.css:
--------------------------------------------------------------------------------
1 | /* ---------- reset ----------*/
2 | html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp,
3 | small, strike, strong, sub, sup, tt, var, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {
4 | margin: 0;
5 | padding: 0;
6 | border: 0;
7 | outline: 0;
8 | font-weight: inherit;
9 | font-style: inherit;
10 | list-style: none;
11 | font-size: 100%;
12 | font-family: inherit;
13 | vertical-align: baseline;
14 | }
15 |
16 | html, body {
17 | height: 100%;
18 | width: 100%;
19 | margin: 0;
20 | padding: 0;
21 | font-family: "Trebuchet MS", Verdana, Helvetica, sans-serif;
22 | color: #111;
23 | background-color:#333333;
24 | }
25 | p{
26 | padding-top:5px;
27 | padding-bottom:5px;
28 | }
29 |
30 | h1 {
31 | font-weight:bold;
32 | font-size:1.2em;
33 | margin-bottom:1em;
34 | }
35 |
36 | /* ---------- header ----------*/
37 | #headerContainer {
38 | background: url("headerBg.png") repeat-x top left;
39 | width: 100%;
40 | height: 116px;
41 | border-top: 1px solid #CFCFCF;
42 | border-bottom: 1px solid #000;
43 | }
44 |
45 | #logo {
46 | position:absolute;
47 | background: url("persevere-glow.png") no-repeat top left;
48 | width: 470px;
49 | height: 55px;
50 | left:0px;
51 | margin-top:10px;
52 | margin-left:126px;
53 | }
54 |
55 | /* ---------- navigation ----------*/
56 | #mainNav {
57 | position: absolute;
58 | right: 0px;
59 | font-size: 14px;
60 | margin: 35px 126px 0 0;
61 | }
62 |
63 | #headerContainer #subNav {
64 | margin-top:76px;
65 | }
66 |
67 | #subNav {
68 | font-size: 14px;
69 | }
70 |
71 | #mainNav li,
72 | #subNav li {
73 | float: left;
74 | }
75 |
76 | #mainNav li a,
77 | #subNav li a {
78 | float:left;
79 | font-family: "Verdana","Arial","Helvetica",sans-serif;
80 | margin-left: 34px;
81 | padding-bottom: 23px;
82 | }
83 |
84 | .project{
85 | height:100%;
86 | width:100%;
87 | }
88 |
89 | .project #projectsLink, .contact #contactLink, .about #aboutLink {
90 | background: url("navPointer.png") no-repeat left bottom;
91 | }
92 |
93 | .project #projectsLink {
94 | background-position: 65% 24px;
95 | }
96 |
97 | .about #aboutLink {
98 | background-position: 80% 24px;
99 | }
100 |
101 | .contact #contactLink {
102 | background-position: 78% 24px;
103 | }
104 |
105 | .dj_ie6 .project #projectsLink, .dj_ie6 .contact #contactLink, .dj_ie6 .about #aboutLink {
106 | background: url("navPointer.gif") no-repeat bottom center;
107 | }
108 |
109 | #mainNav a,
110 | #subNav a {
111 | color: #EFEFEF;
112 | text-decoration: none;
113 | }
114 |
115 | #mainNav a:hover,
116 | #subNav a:hover {
117 | color: #FFF;
118 | }
119 |
120 | #subNav {
121 | margin: 0 0 0 126px;
122 | font-size: 12px;
123 | }
124 |
125 | #subNav li {
126 | margin: 8px 31px 0 0;
127 | }
128 |
129 | #subNav li a {
130 | margin: 0;
131 | }
132 |
133 | #subNav .active {
134 | background: url("subNavR.png") no-repeat right top;
135 | height: 25px;
136 | padding-right: 10px;
137 | }
138 |
139 | #subNav .active a {
140 | background: url("subNavL.png") no-repeat left top;
141 | color: #444;
142 | margin-left: 0;
143 | padding-left: 10px;
144 | height: 25px;
145 | }
146 |
147 | #subNav li a {
148 | padding: 4px 0 0 0;
149 | }
150 |
151 | /* ---------- content ----------*/
152 | #content {
153 | background: #BBCED4 url("bodyBg.png") repeat-x top left;
154 | width: 100%;
155 | height: auto;
156 | border-top: 1px solid #FFF;
157 | border-bottom: 1px solid #CECECE;
158 | font-size: 12px;
159 | }
160 |
161 | #contentOverlay {
162 | background: url("bodyImg.png") no-repeat top left;
163 | padding: 50px 0 50px 0;
164 | }
165 |
166 | /* ---------- sub content ----------*/
167 | #subContent {
168 | background: #eef2f3 url("bodyBg.png") repeat-x top left;
169 | width: 100%;
170 | min-height: 250px;
171 | height:auto !important;
172 | height: 250px;
173 | border-top: 1px solid #FFF;
174 | }
175 |
176 | #subContent #subContentOverlay {
177 | margin: 36px 20px 20px;
178 | padding-bottom: 50px;
179 | padding-left: 105px;
180 | font-size:80%;
181 | width:800px;
182 | }
183 |
184 | #subContent #subContentL h2 {
185 | margin-left: 141px;
186 | margin-right: 10px;
187 | }
188 |
189 | #subContent h2 {
190 | background: #E6E6FF;
191 | height: 16px;
192 | color: #7D3333;
193 | font-size: 16px;
194 | font-weight: normal;
195 | padding: 8px;
196 | font-family: "Myriad Pro", "Trebuchet MS", Verdana, Helvetica, sans-serif;
197 | -moz-border-radius: 7px;
198 | -webkit-border-radius: 7px;
199 | border: 1px solid #E1E1E1;
200 |
201 | margin: 10px;
202 | width:300px;
203 |
204 | }
205 |
206 | #subContent h3 {
207 | height: 16px;
208 | margin: 15px;
209 | color: #515152;
210 | font-size: 14px;
211 | font-weight: bold;
212 | font-family: Arial, Verdana, Helvetica, sans-serif;
213 | }
214 |
215 | #subContent li, #mainContent ul li {
216 | background: url("blueTriSmall.png") no-repeat 0px 7px;
217 | display: block;
218 | line-height: 20px;
219 | margin-left: 1em;
220 | padding-left: 1em;
221 | font-size: 12px;
222 | }
223 | #explorerSection {
224 | margin: 20px;
225 | font-size: 80%;
226 | }
227 |
228 | #mainContent ol li {
229 | list-style:decimal;
230 | margin-left: 2em;
231 | padding-left: 0.3em;
232 | }
233 |
234 |
235 | #mainContent {
236 | overflow:hidden;
237 | width:100%;
238 | }
239 |
240 | #mainScroller {
241 | width:900%;
242 | }
243 |
244 | .contentBox {
245 | margin-left:126px;
246 | margin-right:2%;
247 | width:11%;
248 | float:left;
249 | }
250 |
251 | .contentBoxLogo {
252 | float: left;
253 | padding-right: 50px;
254 | width: 170px;
255 | }
256 |
257 | .contentBoxContent {
258 | float: left;
259 | width: 60%;
260 | }
261 |
262 | #subContent #subContentL #contributorPager {
263 | float:right;
264 | padding-top:3px;
265 | }
266 |
267 | #subContent #subContentL #contributorPager li {
268 | background: url("dot.gif") no-repeat;
269 | width:10px;
270 | height:10px;
271 | float:left;
272 | padding:0px;
273 | margin:0px;
274 | cursor:pointer;
275 | }
276 |
277 | #subContent #subContentL #contributorPager li.active {
278 | background:url("dotActive.gif") no-repeat;
279 | }
280 |
281 | #contributors {
282 | position:relative;
283 | margin-left:150px;
284 | margin-top:40px;
285 | height:90px;
286 | }
287 |
288 | .contributorBox {
289 | position:absolute;
290 | top:0;
291 | vertical-align:top;
292 | }
293 |
294 | .contributorBox img {
295 | vertical-align:middle;
296 | margin:10px;
297 | }
298 |
299 | .contributorBoxSelected {
300 | z-index:1;
301 | }
302 |
303 | .moreLink {
304 | color:#0093C8;
305 | display:block;
306 | float:right;
307 | font-size:12px;
308 | margin-top: 10px;
309 | margin-right: 20px;
310 | text-decoration:none;
311 | background:url("blueTriBig.gif") no-repeat 100% 70%;
312 | padding-right: 14px;
313 | }
314 |
315 | .projectLink {
316 | display:block;
317 | width:143px;
318 | background:url("linkSite.png") no-repeat;
319 | height:25px;
320 | margin-top:10px;
321 | text-decoration:none;
322 | }
323 |
324 | #mainContent p {
325 | padding-top: 5px;
326 | padding-bottom: 5px;
327 | }
328 |
329 | #mainContent h2 {
330 | padding-top: 10px;
331 | padding-bottom: 10px;
332 | font-weight: bold;
333 | }
334 |
335 | #mainContent a,
336 | #subContent a {
337 | color:#0093C8;
338 | text-decoration:none;
339 | }
340 |
341 | .boardMember {
342 | width: 100%;
343 | float: left;
344 | margin-bottom: 30px;
345 | }
346 |
347 | .boardMember img {
348 | float: left;
349 | padding: 7px;
350 | background: #FFF;
351 | border: 1px solid #ABABAB;
352 | }
353 |
354 | #mainContent .boardMember h2 {
355 | padding-top: 0;
356 | }
357 |
358 | .boardMember h2,
359 | .boardMember p {
360 | float: left;
361 | margin-left: 15px;
362 | width: 60%;
363 | }
364 | p {
365 | line-height:1.2em;
366 | }
367 | pre {
368 | border: 1px solid #ddd;
369 | padding: 1em;
370 | font-family: Courier;
371 | background-color:#eed;
372 | }
373 | #table-of-contents{
374 | overflow: auto;
375 | width:200px;
376 | top:120px;
377 | left:840px;
378 | position:fixed;
379 | bottom:1px;
380 | background-color:#E6E6FF;
381 | border: 1px solid #555;
382 | }
383 | #table-of-contents ul{
384 | padding-left:10px;
385 | margin-left:1px;
386 | }
387 | #aboutSection, #gettingStartedSection {
388 | padding-left:105px;
389 | }
390 | .details{
391 | width:100px;
392 | height:40px;
393 | background: url("../jsclient/dijit/themes/tundra/images/spriteArrows.gif") no-repeat top left;
394 | }
395 | .dojoxGridCell{
396 | font-size: 1.19em;
397 | }
398 | .expandable {padding-left: 20px;background: url('expand.gif') no-repeat 3px 3px;cursor: pointer;}
399 | .expanded {background: url('down.gif') no-repeat 3px 3px;padding-bottom:1px;padding-right: 1px;}
400 | .simple {padding-left: 20px;}
401 | textarea {}
402 | .pngImg {width:16px;height:16px;}
403 | .dropDownOptions {width: 19px;height: 21px;background: url('arrowdown.gif'); background-repeat: no-repeat;}
404 | .selected, .selected .tree {border: 1px solid blue;} // background: url('selected.png') repeat-x
405 | .field {width: 30%;display: block;float: left;}
406 | .objecttab {padding-left: 5px;padding-right: 5px;background-color: #ccc;padding-bottom: 1px;}
407 | .children {border: 1px solid #ccc;}
408 | .tree{overflow:auto; border: 1px solid #aaa}
409 | #status {
410 | position:absolute;
411 | top:0px;
412 | left:0px;
413 | z-index:10;
414 | background:url('spinner.gif') white no-repeat;
415 | border:1px solid black;
416 | padding:5px;
417 | padding-left:25px;
418 | font-family:arial;
419 | font-size: 80%;
420 | }
421 |
422 |
--------------------------------------------------------------------------------
/public/explorer/js/dojo-persevere/Login.js:
--------------------------------------------------------------------------------
1 | dojo.provide("persevere.Login");
2 |
3 | dojo.require("dijit.form.ValidationTextBox");
4 | dojo.require("dijit.form.Button");
5 | dojo.require("dijit.ProgressBar");
6 | dojo.require("dijit.Dialog");
7 |
8 | dojo.declare("persevere.Login", dijit.Dialog,
9 | {
10 | // summary: A login/register Dialog for a persevere server
11 | //
12 | // description:
13 | // Displays a dialog for logging into a persevere server and also allows new users
14 | // to register. You can provide your own login and register forms via 'loginHref'
15 | // and 'registerHref'. 'Login' and 'Register' buttons will be automatically added
16 | // to the login dialog and 'Register' and 'Cancel' buttons will be automatically
17 | // added to the register dialog.
18 | //
19 | // example:
20 | // |
21 | //
22 | // example:
23 | // | var foo = new dojox.data.persevere.Login({userUrl: "/User/"});
24 | // | dojo.body().appendChild(foo.domNode);
25 | // | foo.startup();
26 |
27 | // TODO: need to try to make this so that you can only have one instance per page.
28 | // consider disabling the close (x) button on the dialog.
29 |
30 | // currentUser: Object
31 | // The last user to be logged in via this widget.
32 | currentUser: null,
33 |
34 | // userUrl: String
35 | // The url to the 'User' class. This url is used to authenticate
36 | // and create users.
37 | userUrl: 'User/',
38 |
39 | // loginHref: String
40 | // The url to be used as the href to the login form.
41 | loginHref: dojo.moduleUrl("persevere", 'resources/login/login.html'),
42 |
43 | // loginMethod: String
44 | // The name of the method belonging to the Class at 'userUrl' that authenticates a user
45 | loginMethod: "authenticate",
46 |
47 | // registerHref: String
48 | // The url to be used as the href to the form used to register a new user.
49 | registerHref: dojo.moduleUrl("persevere", 'resources/login/register.html'),
50 |
51 | // registerMethod: String
52 | // The name of the method belonging to the Class at 'userUrl' that creates a new user
53 | registerMethod: "createUser",
54 |
55 | // userField: String
56 | // The name of the username field in the form at 'loginHref'.
57 | userField: 'username',
58 |
59 | // passField: String
60 | // The name of the password field in the form at 'loginHref'.
61 | passField: 'password',
62 |
63 | // newUserField: String
64 | // The name of the new username field in the form at 'registerHref'.
65 | newUserField: 'newUsername',
66 |
67 | // newPassField: String
68 | // The name of the new password field in the form at 'registerHref'.
69 | newPassField: 'newPassword',
70 |
71 | // confirmPassField: String
72 | // The name of the confirm password field in the form at 'registerHref'.
73 | confirmPassField: 'confirmPassword',
74 |
75 | _loginTitle: 'Login',
76 | _registerTitle: 'Add a new User',
77 |
78 | // how long the cookie should last, set to null for session-only authentication,
79 | // defaults to 10 days
80 | cookieLength: 864000000,
81 |
82 | constructor: function(options){
83 | dojo.mixin(this, options);
84 | // a progress bar to show that we're waiting on a response from the server
85 | this._busy = new dijit.ProgressBar({style:"display:none", indeterminate:true});
86 | // a place to put messages such as the error response from the server
87 | this._message = dojo.doc.createElement("div");
88 | dojo.query(this._message).style({color:"red", wordWrap:"break-word", width:"220px", margin:"auto"});
89 | // connect the ENTER key to the _onSubmit
90 | dojo.connect(this.domNode, "onkeypress", this, function(e){
91 | if(e.charOrCode == dojo.keys.ENTER){
92 | this._onSubmit();
93 | }
94 | });
95 | },
96 |
97 | startup: function(){
98 | this._showLogin();
99 | },
100 |
101 | _showLogin: function(){
102 | // summary: shows the login dialog
103 | this._message.innerHTML = '';
104 | var footer = dojo.doc.createElement('div');
105 | var buttons = dojo.doc.createElement('div');
106 | // need to find a better way to right-align the buttons - using dir:rtl and tabindex is not ideal
107 | buttons.setAttribute("dir", "rtl");
108 | var registerButton = new dijit.form.Button({type: "reset", label: "Register", tabIndex: "-1"}).placeAt(buttons);
109 | registerButton.onClick = dojo.hitch(this, "_showRegister");
110 | var loginButton = new dijit.form.Button({type: "submit", label: "Login"}).placeAt(buttons);
111 | footer.appendChild(buttons);
112 | footer.appendChild(this._message);
113 | this._busy.placeAt(footer);
114 | this.onDownloadEnd = function(){
115 | this.containerNode.appendChild(footer);
116 | };
117 | this.execute = this._login;
118 | this.attr("href", this.loginHref);
119 | this.attr("title", this._loginTitle);
120 | this.show();
121 | },
122 |
123 | _showRegister: function(){
124 | // summary: shows the register dialog
125 | this._message.innerHTML = '';
126 | var footer = dojo.doc.createElement('div');
127 | var buttons = dojo.doc.createElement('div');
128 | buttons.setAttribute("dir", "rtl");
129 | var cancelButton = new dijit.form.Button({type: "reset", label: "Cancel", tabIndex: "-1"}).placeAt(buttons);
130 | cancelButton.onClick = dojo.hitch(this, "_showLogin");
131 | var submitButton = new dijit.form.Button({type: "submit", label: "Register"}).placeAt(buttons);
132 | footer.appendChild(buttons);
133 | footer.appendChild(this._message);
134 | this._busy.placeAt(footer);
135 | this.onDownloadEnd = function(){
136 | this.containerNode.appendChild(footer);
137 | };
138 | this.execute = this._register;
139 | this.attr("href", this.registerHref);
140 | this.attr("title", this._registerTitle);
141 | this.show();
142 | },
143 |
144 | _login: function(form){
145 | // summary: this is the login action - it attempts to authenticate the user
146 | // using the "authenticate" method of the Class at 'userUrl' using the form params
147 | if (this.validate()){
148 | this._busy.attr("style", "display:block");
149 | dojo.xhrPost({
150 | url: this.userUrl,
151 | postData: dojo.toJson({method: this.loginMethod, id:"login", user: form[this.userField], password: form[this.passField], expires: this.cookieLength && new Date(new Date().getTime() + this.cookieLength).toGMTString()}),
152 | handleAs: "json",
153 | headers: {Accept:"application/javascript, application/json"},
154 | load: dojo.hitch(this, "_loginLoad"),
155 | error: dojo.hitch(this, "_loginError")
156 | });
157 | } else {
158 | this._message.innerHTML = 'Input is not valid';
159 | this.show();
160 | }
161 | },
162 |
163 | _loginLoad: function(response, request){
164 | // summary: handles the response to the authentication attempt
165 | this._busy.attr("style", "display:none");
166 | if (response.error != null){
167 | this._message.innerHTML = response.error;
168 | this.onLoginFail(response, request);
169 | } else {
170 | this.currentUser = response.result;
171 | this.onLoginSuccess(response, request);
172 | }
173 | return response;
174 | },
175 |
176 | _loginError: function(response, request){
177 | // summary: handles login errors
178 | this._busy.attr("style", "display:none");
179 | this.onLoginError(response, request);
180 | return response;
181 | },
182 |
183 | _register: function(form){
184 | // summary: this is the register action - it attempts to register a new user
185 | // using the 'registerMethod' of the Class at the 'userUrl'
186 | if (this.validate() && (form[this.newPassField] == form[this.confirmPassField])){
187 | this._busy.attr("style", "display:block");
188 | dojo.xhrPost({
189 | url: this.userUrl,
190 | postData: dojo.toJson({method: this.registerMethod,id:"register", params:[form[this.newUserField], form[this.newPassField]]}),
191 | handleAs: "json",
192 | load: dojo.hitch(this, "_registerLoad"),
193 | error: dojo.hitch(this, "_registerError")
194 | })
195 | } else {
196 | this._message.innerHTML = 'Input is not valid';
197 | this.show();
198 | }
199 | },
200 |
201 | _registerLoad: function(response, request){
202 | this._busy.attr("style", "display:none");
203 | if (response.error != null){
204 | this._message.innerHTML = response.error;
205 | this.onRegisterFail(response, request);
206 | } else {
207 | this.onRegisterSuccess(response, request);
208 | }
209 | return response;
210 | },
211 |
212 | _registerError: function(response, request){
213 | this._busy.attr("style", "display:none");
214 | this.onRegisterError(response, request);
215 | return response;
216 | },
217 |
218 | login: function(){
219 | this._showLogin();
220 | },
221 |
222 | logout: function(callBack){
223 | if (confirm("Are you sure you want to sign out?")) {
224 | dojo.xhrPost({
225 | url: this.userUrl,
226 | postData: dojo.toJson({
227 | method: this.loginMethod,
228 | id: "logout",
229 | user: null,
230 | password: null
231 | }),
232 | handleAs: "json",
233 | handle: function(response, request){
234 | this.currentUser = null;
235 | }
236 | }).addCallback(callBack);
237 | }
238 | },
239 |
240 | onLoginSuccess: function(response, request){
241 | },
242 |
243 | onLoginFail: function(response, request){
244 | this.show();
245 | },
246 |
247 | onLoginError: function(response, request){
248 | console.error("HTTP status code: ", request.xhr.status);
249 | },
250 |
251 | onRegisterSuccess: function(response, request){
252 | // change this to authenticate the user and add the rest of the
253 | // register params to the new user object
254 | /* var form = this.attr("value");
255 | var user = response.result;
256 | for (var attr in form){
257 | if (!user[attr] && (attr != this.newUserField) && (attr != this.newPassField) && (attr != this.confirmPassField)){
258 | user[attr] = form[attr];
259 | }
260 | }
261 | var login = dojo.xhrPost({
262 | url: this.userUrl,
263 | postData: dojo.toJson({method: this.loginMethod, id:"login", params:[form[this.newUserField], form[this.newPassField]]}),
264 | handleAs: "json",
265 | handle: dojo.hitch(this, "_loginHandle"),
266 | error: dojo.hitch(this, "_loginError")
267 | });
268 | var call = {
269 | url: this.userUrl + response.result.id
270 | // pick up from here... - need to add the other fields to the user object.
271 | }
272 | login.addCallback(dojo.hitch(this, function(){
273 | dojo.xhrPut({
274 | url: this.userUrl + response.result.id
275 | })
276 | }));*/
277 | this._showLogin();
278 | this._message.innerHTML = 'Registration successful. Please login.'
279 | },
280 |
281 | onRegisterFail: function(response, request){
282 | this.show();
283 | },
284 |
285 | onRegisterError: function(response, request){
286 | console.error("HTTP status code: ", request.xhr.status);
287 | }
288 | });
289 |
--------------------------------------------------------------------------------
/lib/json-query.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This module provides querying functionality, with a JSONQuery implementation
3 | * and a helper class for parsing JSONQueries
4 | */
5 |
6 | // The main function for executing JSONQueries
7 | exports.jsonQuery = jsonQuery;
8 |
9 | // its easier to write (and read) these as regular expressions (since that is how they are used)
10 | var $prop = /(?:@?\.?([a-zA-Z_$][\w_$]*))/.source;
11 | var $value = /("(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\/[\w_$]+\/[\w]+|\-?[0-9]+(?:\.[0-9]+)?(?:[eE]\-?[0-9]+)?|true(?![\w])|false(?![\w])|null(?![\w]))/.source;
12 | var $comparator = /(===|!==|==|!=|>=|<=|=|<|>)/.source;
13 | var $operator = /([\+\-\*\/\&\|\?\:])/.source;
14 | var $logic = /([\&\|])/.source;
15 | var $expression = /((?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\[(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|[^\]])*\]|[^\]])*)/.source;
16 | var $filter = "(?:\\[?\\?" + $expression + "\\]?)";
17 | var $sort = "(?:\\[[\\\\\\/]" + $expression + "\\])";
18 | exports.QueryRegExp = QueryRegExp;
19 | function QueryRegExp(regexp){
20 | return new RegExp((regexp.source || regexp).replace(/\$[a-z]+/g, function(t){
21 | switch(t){
22 | case "$prop" : return $prop;
23 | case "$value" : return $value;
24 | case "$comparator" : return $comparator;
25 | case "$operator" : return $operator;
26 | case "$logic" : return $logic;
27 | case "$expression" : return $expression;
28 | case "$filter" : return $filter;
29 | case "$sort" : return $sort;
30 | }
31 | return t;
32 | }), (regexp.global ? "g" : "") + (regexp.ignoreCase ? "m" : ""));
33 | }
34 | function throwMaxIterations(){
35 | throw new Error("Query has taken too much computation, and the user is not allowed to execute resource-intense queries. Increase maxIterations in your config file to allow longer running non-indexed queries to be processed.");
36 | }
37 | exports.maxIterations = 10000;
38 | function stringToValue(string){
39 | switch(string){
40 | case "true": return true;
41 | case "false": return false;
42 | case "null": return null;
43 | default:
44 | var number = parseFloat(string, 10);
45 | if(isNaN(number)){
46 | if(exports.compatible){
47 | if(string.charAt(0) == "'" && string.charAt(string.length-1) == "'"){
48 | return JSON.parse('"' + string.substring(1,string.length-1) + '"');
49 | }
50 | }
51 | return string;
52 | }
53 | return number;
54 | }
55 |
56 | };
57 | function convertComparator(comparator){
58 | switch(comparator){
59 | case "-+" : return "<";
60 | case "+-" : return ">";
61 | case "+=-" : return "=>";
62 | case "-=+" : return "=<";
63 | }
64 | return comparator;
65 | }
66 | exports.compatible = true;
67 | exports.parseQuery = function(/*String*/query){
68 | if(exports.compatible){
69 | query = query.replace(/%3C=/g,"-=+").replace(/%3E=/g,"+=-").replace(/%3C/g,"-+").replace(/%3E/g,"+-");
70 | }
71 | var ast = {children:[], type:"group"};
72 | var originalAst = ast;
73 | query.replace(/(([\w%\._]+)([\-=\+!]+)([\+\-\w%\._]+))|([&\|,\)])|(([\+\-\w%\._]*)(\(?))/g,
74 | function(t, expression, name, comparator, value, token, callOrGroup, methodOrValue, openParan){
75 | if(expression){
76 | comparison = {
77 | type:"comparison",
78 | comparator: convertComparator(comparator),
79 | name: decodeURIComponent(name),
80 | value: stringToValue(decodeURIComponent(value))
81 | };
82 | ast.children.push(comparison);
83 | }
84 | else if(callOrGroup){
85 | if(openParan){
86 | var newAst = {type:"group", children:[]};
87 | ast.children.push(newAst);
88 | newAst.parent = ast;
89 | ast = newAst;
90 | if(methodOrValue){
91 | ast.type = "call";
92 | ast.method = methodOrValue;
93 | }
94 | }
95 | else{
96 | ast.children.push(stringToValue(methodOrValue));
97 | }
98 | }
99 | else if(token){
100 | switch(token){
101 | case ')' :
102 | ast = ast.parent;
103 | break;
104 | case '&' : case '|':
105 | if(!ast.logic){
106 | ast.logic = token;
107 | }
108 | else if(ast.logic != token){
109 | var newAst = {type:"group", children:[]};
110 | newAst.children.push(ast);
111 | if(ast.parent){
112 | ast.parent.children[ast.parent.length-1] = newAst;
113 | }
114 | // set the parent to that because a real paran should go up to the real parent
115 | newAst.parent = ast.parent;
116 | ast = newAst;
117 | ast.logic = token;
118 | }
119 | }
120 | }
121 | });
122 | ast.logic = ast.logic || "&";
123 | return ast;
124 | /*
125 | var TOKEN = /\(|[\w%\._]+/g;
126 | var OPERATOR = /[-=+!]+|\(/g;
127 | var NEXT = /[&\|\)]/g;
128 |
129 | TOKEN.lastIndex = 0;
130 | function group(){
131 | var ast = [];
132 | var match = TOKEN.exec(query);
133 | if(match === '('){
134 | ast.push(group());
135 | }
136 | else{
137 | OPERATOR.lastIndex = TOKEN.lastIndex;
138 | var operator = OPERATOR.exec(query);
139 | var comparison = {};
140 | ast.push(comparison);
141 | if(operator == '('){
142 | comparison.type = "call";
143 | comparison.parameters =
144 | }
145 | comparison.type = operator;
146 |
147 | }
148 | return ast;
149 | }
150 | return group();*/
151 | }
152 | function executeQuery(query, options, target){
153 | if(typeof query === "string"){
154 | query = parseQuery(query);
155 | }
156 | var methods = options.methods || {};
157 | if(!methods.sort){
158 | methods.sort = function(sortAttribute){
159 | var firstChar = sortAttribute.charAt(0);
160 | var ascending = true;
161 | if(firstChar == "-" || firstChar == "+"){
162 | if(firstChar == "-"){
163 | ascending = false;
164 | }
165 | sortAttribute = sortAttribute.substring(1);
166 | }
167 | this.sort(function(a, b){
168 | return ascending == a[sortAttribute] > b[sortAttribute] ? 1 : -1;
169 | });
170 | return this;
171 | }
172 | }
173 | var first = true;
174 | var js = "";
175 | query.children.forEach(function(child){
176 | if(child.type == "comparison"){
177 | if(!options){
178 | throw new Error("Values must be set as parameters on the options argument, which was not provided");
179 | }
180 | if(first){
181 | js += "target = target.filter(function(item){return ";
182 | first = false;
183 | }
184 | else{
185 | js += query.logic + query.logic;
186 | }
187 | var index = (options.parameters = options.parameters || []).push(child.value);
188 | if(child.comparator == "="){
189 | child.comparator = "==";
190 | }
191 | js += "item." + child.name + child.comparator + "options.parameters[" + (index -1) + "]";
192 |
193 | }
194 | if(!first){
195 | js += "});";
196 | }
197 | else if(child.type == "call"){
198 | if(methods[child.method]){
199 | var index = (options.parameters = options.parameters || []).push(child.children);
200 | js += "target = methods." + child.method + ".apply(target,options.parameters[" + (index -1) + "]);";
201 | }
202 | else{
203 | throw new URIError("Invalid JSON Query syntax, " + child.method + " not implemented");
204 | }
205 | }
206 | else{
207 | throw new URIError("Invalid JSON Query syntax, unknown type");
208 | }
209 | });
210 | return eval(js + "target;");
211 |
212 | }
213 |
214 | function jsonQuery(/*String*/query, obj, args){
215 | // summary:
216 | // Performs a JSONQuery on the provided object and returns the results.
217 | // If no object is provided (just a query), it returns a function that evaluates objects
218 | // according to the provided query.
219 | // query:
220 | // Query string
221 | // obj:
222 | // Target of the JSONQuery
223 | // description:
224 | // | dojox.json.query("foo",{foo:"bar"}) - > "bar"
225 | // | evaluator = dojox.json.query("?foo='bar'&rating>3");
226 | query = query.toString();
227 | var iterations = 0;
228 | // setup JSONQuery library
229 | function slice(obj,start,end,step){
230 | var i, results = [];
231 | if(step < 5){
232 | // do an iterator friendly
233 | i = 0;
234 | obj.forEach(function(item){
235 | if(i >= end){
236 | return results;
237 | }
238 | if(i >= start && i % step == 0){
239 | results.push(item);
240 | }
241 | i++;
242 | if(i > exports.maxIterations){
243 | throwMaxIterations();
244 | }
245 | });
246 | return results;
247 | }
248 | var len=obj.length;
249 | end = end || len;
250 |
251 | start = (start < 0) ? Math.max(0,start+len) : Math.min(len,start);
252 | end = (end < 0) ? Math.max(0,end+len) : Math.min(len,end);
253 | iterations += end - start;
254 | if(iterations > exports.maxIterations){
255 | throwMaxIterations();
256 | }
257 | for(i=start; i