]> gitweb @ CieloNegro.org - Rakka.git/blob - js/editPage.js
improvements of page locking
[Rakka.git] / js / editPage.js
1 (function () {
2
3     var $previewHeader = null;
4     var $previewArea   = null;
5
6     var isDirty = null;
7
8     Rakka.editPage = function (pageName) {
9         var $area = Rakka.switchScreen();
10
11         Rakka.displayWaitingMessage("Loading... please wait.");
12     
13         // XML 版のページを取得する。
14         $.ajax({
15             url    : Rakka.baseURI + pageName + ".xml",
16             success: function (pageXml) {
17                 Rakka.hideWaitingMessage();
18             
19                 var $page       = $(pageXml).find("page");
20                 var oldRevision = $page.attr("revision");
21                 var defaultType
22                     = $page.attr("isBinary") == "yes"          ? "binary"
23                     : $page.attr("type")     == "text/x-rakka" ? "rakka"
24                     : $page.attr("type")     == "text/css"     ? "css"
25                     : $page.attr("redirect") != null           ? "redirect"
26                     :                                            "unknown"
27                     ;
28                 var isLocked    = $page.attr("isLocked") == "yes";
29                 var source
30                     = $page.attr("redirect") != null ? $page.attr("redirect")
31                     : $page.find("textData").text()
32                     ;
33                 var summary     = $page.find("summary").text();
34                 
35                 displayPageEditor(pageName, oldRevision, defaultType, isLocked, source, summary);
36             },
37             error  : function (req) {
38                 Rakka.hideWaitingMessage();
39                 
40                 if (req.status == 404) {
41                     displayPageEditor(pageName, null, "rakka", false, null, "");
42                 }
43                 else {
44                     $area.text("Error: " + req.status + " " + req.statusText);
45                 }
46             }
47         });
48     };
49
50     Rakka.newPage = function () {
51         displayPageEditor("", null, "rakka", false, null, "");
52     };
53
54     var displayPageEditor = function (pageName, oldRevision, defaultType, isLocked, source, summary) {
55         var $area = Rakka.switchScreen();
56
57         $previewHeader = $( $.H1({}, "Preview") );
58         $area.append($previewHeader);
59         $previewHeader.hide();
60
61         $previewArea = $( $.DIV({className: "preview"}) );
62         $area.append($previewArea);
63         $previewArea.hide();
64
65         $area.append($.H1({}, pageName == "" ? "Create page" : "Edit page"));
66
67         var makeDirty = function () {
68             isDirty = true;
69         };
70     
71         var fldPageName
72             = $.INPUT({type : "text", value: pageName});
73
74         $(fldPageName).change(makeDirty);
75
76         var chkIsLocked
77             = $.INPUT({type   : "checkbox",
78                        checked: (isLocked ? "checked" : "")});
79
80         $(chkIsLocked).change(makeDirty);
81
82         var trIsLocked
83             = $.TR({},
84                    $.TH({}, "Page lock"),
85                    $.TD({},
86                         $.LABEL({},
87                                 chkIsLocked,
88                                 "Disallow anonymous users to edit or delete this page")));
89         
90         var btnTypeRakka
91             = $.INPUT({type   : "radio",
92                        name   : "type",
93                        checked: (defaultType == "rakka"    ? "checked" : "")});
94
95         $(btnTypeRakka).change(makeDirty);
96
97         var btnTypeCSS
98             = $.INPUT({type   : "radio",
99                        name   : "type",
100                        checked: (defaultType == "css"      ? "checked" : "")});
101
102         $(btnTypeCSS).change(makeDirty);
103
104         var btnTypeBinary
105             = $.INPUT({type   : "radio",
106                        name   : "type",
107                        checked: (defaultType == "binary"   ? "checked" : "")});
108
109         $(btnTypeBinary).change(makeDirty);
110
111         var btnTypeRedirect
112             = $.INPUT({type   : "radio",
113                        name   : "type",
114                        checked: (defaultType == "redirect" ? "checked" : "")});
115
116         $(btnTypeRedirect).change(makeDirty);
117
118         var fldSummary
119             = $.TEXTAREA({className: "summary"}, summary);
120
121         $(fldSummary).change(makeDirty);
122
123         var trSummary
124             = $.TR({},
125                    $.TH({}, "Summary"),
126                    $.TD({}, fldSummary));
127
128         var fldRakkaSource
129             = $.TEXTAREA({className: "source"},
130                          (defaultType == "rakka" && source != null ? source : ""));
131
132         $(fldRakkaSource).change(makeDirty);
133
134         var fldCSSSource
135             = $.TEXTAREA({className: "source"},
136                          (defaultType == "css"   && source != null ? source : ""));
137
138         $(fldCSSSource).change(makeDirty);
139
140         var fldUploadFile
141             = $.INPUT({type: "file"});
142
143         $(fldUploadFile).change(makeDirty);
144
145         var fldRedirect
146             = $.INPUT({type: "text", value: (defaultType == "redirect" ? source : "")});
147
148         $(fldRedirect).change(makeDirty);
149
150         var trContent
151             = $.TR({}, 
152                    $.TH({}),
153                    $.TD({})
154                   );
155
156         var btnPreview
157             = $.INPUT({type: "button", value: "Preview page"});
158         
159         $(btnPreview).click(function () {
160             if (btnTypeRakka.checked) {
161                 previewRakkaPage(
162                     fldPageName.value, fldRakkaSource.value);
163             }
164             else if (btnTypeBinary.checked) {
165                 previewBinaryPage(
166                     fldPageName.value, fldUploadFile.value);
167             }
168         });
169
170         var btnSubmit
171             = $.INPUT({type: "button", value: "Submit page"});
172         
173         $(btnSubmit).click(function () {
174             if (btnTypeRakka.checked) {
175                 submitTextPage(
176                     pageName,
177                     oldRevision,
178                     fldPageName.value,
179                     chkIsLocked.checked,
180                     "text/x-rakka",
181                     fldSummary.value,
182                     fldRakkaSource.value);
183             }
184             else if (btnTypeCSS.checked) {
185                 submitTextPage(
186                     pageName,
187                     oldRevision,
188                     fldPageName.value,
189                     chkIsLocked.checked,
190                     "text/css",
191                     fldSummary.value,
192                     fldCSSSource.value);
193             }
194             else if (btnTypeBinary.checked) {
195                 submitBinaryPage(
196                     pageName,
197                     oldRevision,
198                     fldPageName.value,
199                     chkIsLocked.checked,
200                     fldSummary.value,
201                     fldUploadFile.value);
202             }
203             else if (btnTypeRedirect.checked) {
204                 submitRedirection(
205                     pageName,
206                     oldRevision,
207                     fldPageName.value,
208                     chkIsLocked.checked,
209                     fldRedirect.value);
210             }
211         });
212
213         var btnDelete
214             = $.INPUT({type: "button", value: "Delete this page"});
215         
216         $(btnDelete).click(function () {
217             if (window.confirm("Do you really want to delete this page?")) {
218                 deletePage(pageName);
219             }
220         });
221
222         var btnCancel
223             = $.INPUT({type: "button", value: "Cancel editing"});
224
225         $(btnCancel).click(function () {
226             if (isDirty) {
227                 if (window.confirm("Do you really want to discard changes?")) {
228                     Rakka.restoreScreen();
229                 }
230             }
231             else {
232                 Rakka.restoreScreen();
233             }
234         });
235
236         var updateTRContent = function () {
237             if (btnTypeRakka.checked) {
238                 $(trSummary).show();
239                 $(trContent).find("th").text("Wiki source");
240                 $(trContent).find("td").empty().append(fldRakkaSource);
241                 $(btnPreview).show();
242             }
243             else if (btnTypeCSS.checked) {
244                 $(trSummary).show();
245                 $(trContent).find("th").text("CSS source");
246                 $(trContent).find("td").empty().append(fldCSSSource);
247                 $(btnPreview).hide();
248             }
249             else if (btnTypeBinary.checked) {
250                 $(trSummary).show();
251                 $(trContent).find("th").text("File");
252                 $(trContent).find("td").empty().append(fldUploadFile);
253                 $(btnPreview).show();
254             }
255             else if (btnTypeRedirect.checked) {
256                 $(trSummary).hide();
257                 $(trContent).find("th").text("Destination Page");
258                 $(trContent).find("td").empty().append(fldRedirect);
259                 $(btnPreview).hide();
260             }
261         };
262         $(btnTypeRakka   ).change(updateTRContent);
263         $(btnTypeCSS     ).change(updateTRContent);
264         $(btnTypeBinary  ).change(updateTRContent);
265         $(btnTypeRedirect).change(updateTRContent);
266         updateTRContent();
267
268         var pageEditor
269             = $.TABLE({className: "pageEditor"},
270                       $.TBODY({},
271                               $.TR({},
272                                    $.TH({}, "Page name"),
273                                    $.TD({}, fldPageName)
274                                   ),
275                               trIsLocked,
276                               $.TR({},
277                                    $.TH({}, "Page type"),
278                                    $.TD({},
279                                         $.UL({},
280                                              $.LI({},
281                                                   $.LABEL({},
282                                                           btnTypeRakka,
283                                                           "Wiki page"
284                                                          )
285                                                  ),
286                                              $.LI({},
287                                                   $.LABEL({},
288                                                           btnTypeCSS,
289                                                           "Style sheet"
290                                                          )
291                                                  ),
292                                              $.LI({},
293                                                   $.LABEL({},
294                                                           btnTypeBinary,
295                                                           "Binary file"
296                                                          )
297                                                  ),
298                                              $.LI({},
299                                                   $.LABEL({},
300                                                           btnTypeRedirect,
301                                                           "Redirection"
302                                                          )
303                                                  )
304                                             )
305                                        )
306                                   ),
307                               trSummary,
308                               trContent,
309                               $.TR({},
310                                    $.TH({}),
311                                    $.TD({}, btnPreview, btnSubmit, btnDelete, btnCancel)
312                                   )
313                              )
314                      );
315
316         if (oldRevision == null || oldRevision == 0) {
317             // 削除不可
318             $(btnDelete).hide();
319         }
320
321         $area.append(pageEditor);
322
323         isDirty = false;
324     };
325
326     var previewRakkaPage = function (pageName, source) {
327         Rakka.displayWaitingMessage("Loading... please wait.");
328         
329         var url = Rakka.baseURI + "render/" + encodeURI(pageName);
330         $.ajax({
331             type       : "POST",
332             url        : url,
333             contentType: "text/x-rakka",
334             data       : source,
335             processData: false,
336             success    : function (resultDoc) {
337                 Rakka.hideWaitingMessage();
338                 showPreview(resultDoc);
339             },
340             error      : function (req) {
341                 Rakka.hideWaitingMessage();
342                 alert("Error: " + req.status + " " + req.statusText);
343             }
344         });
345     };
346
347     var previewBinaryPage = function (pageName, path) {
348         Rakka.displayWaitingMessage("Loading... please wait.");
349
350         /* Firefox でバイナリを送らうとすると 0x00 の位置で切れてしまふ。*/
351         var bin = Rakka.loadLocalBinaryFile(path);
352         var url = Rakka.baseURI + "render/" + encodeURI(pageName);
353         $.ajax({
354             type       : "POST",
355             url        : url,
356             contentType: "application/x-rakka-base64-stream",
357             data       : Rakka.encodeBase64(bin),
358             processData: false,
359             success    : function (resultDoc) {
360                 Rakka.hideWaitingMessage();
361                 showPreview(resultDoc);
362             },
363             error      : function (req) {
364                 Rakka.hideWaitingMessage();
365                 alert("Error: " + req.status + " " + req.statusText);
366             }
367         });
368     };
369
370     var showPreview = function (doc) {
371         $previewArea.empty();
372         
373         $previewHeader.show();
374         $previewArea.show();
375         
376         var root  = doc.documentElement;
377         var child = root.firstChild;
378         do {
379             if (child.nodeType == 1) {
380                 // 要素だったので複製
381                 $previewArea.append(child.cloneNode(true));
382             }
383         } while (child = child.nextSibling);
384
385         Rakka.scrollToTopLeft();
386     };
387
388     var submitTextPage = function (pageName, oldRevision, givenPageName, isLocked, mimeType, summary, text) {
389         var doc = document.implementation.createDocument(
390             "http://cielonegro.org/schema/Rakka/Page/1.0", "page", null);
391
392         var page = doc.documentElement;
393
394         if (oldRevision != null) {
395             // ページ書換時
396             var updateInfo = doc.createElement("updateInfo");
397             updateInfo.setAttribute("oldRevision", oldRevision);
398
399             if (pageName != givenPageName) {
400                 var move = doc.createElement("move");
401                 move.setAttribute("from", pageName);
402                 updateInfo.appendChild(move);
403             }
404
405             page.appendChild(updateInfo);
406         }
407
408         page.setAttribute("isLocked", isLocked ? "yes" : "no");
409         page.setAttribute("type", mimeType);
410
411         if (summary != null) {
412             var s = doc.createElement("summary");
413             s.appendChild(
414                 doc.createTextNode(summary));
415             page.appendChild(s);
416         }
417
418         var textData = doc.createElement("textData");
419         textData.appendChild(
420             doc.createTextNode(text));
421
422         page.appendChild(textData);
423
424         Rakka.displayWaitingMessage("Submitting... please wait.");
425
426         var url = Rakka.baseURI + encodeURI(givenPageName);
427         $.ajax({
428             type       : "PUT",
429             url        : url,
430             contentType: "text/xml",
431             data       : doc,
432             processData: false,
433             beforeSend : function (req) {
434                 Rakka.setAuthorization(req);
435             },
436             success    : function () {
437                 window.location.replace(url);
438             },
439             error      : function (req) {
440                 Rakka.hideWaitingMessage();
441                 
442                 var $area = Rakka.switchScreen();
443                 $area.text("Error: " + req.status + " " + req.statusText);
444             }
445         });
446     };
447
448     var submitBinaryPage = function (pageName, oldRevision, givenPageName, isLocked, summary, path) {
449         var doc = document.implementation.createDocument(
450             "http://cielonegro.org/schema/Rakka/Page/1.0", "page", null);
451
452         var page = doc.documentElement;
453
454         if (oldRevision != null) {
455             // ページ書換時
456             var updateInfo = doc.createElement("updateInfo");
457             updateInfo.setAttribute("oldRevision", oldRevision);
458
459             if (pageName != givenPageName) {
460                 var move = doc.createElement("move");
461                 move.setAttribute("from", pageName);
462                 updateInfo.appendChild(move);
463             }
464
465             page.appendChild(updateInfo);
466         }
467
468         page.setAttribute("isLocked", isLocked ? "yes" : "no");
469         page.setAttribute("type", "");
470
471         if (summary != null) {
472             var s = doc.createElement("summary");
473             s.appendChild(
474                 doc.createTextNode(summary));
475             page.appendChild(s);
476         }
477
478         var bin = Rakka.loadLocalBinaryFile(path);
479         var b64 = Rakka.encodeBase64(bin);
480
481         var binaryData = doc.createElement("binaryData");
482         binaryData.appendChild(
483             doc.createTextNode(b64));
484
485         page.appendChild(binaryData);
486
487         Rakka.displayWaitingMessage("Submitting... please wait.");
488
489         var url = Rakka.baseURI + encodeURI(givenPageName);
490         $.ajax({
491             type       : "PUT",
492             url        : url,
493             contentType: "text/xml",
494             data       : doc,
495             processData: false,
496             beforeSend : function (req) {
497                 Rakka.setAuthorization(req);
498             },
499             success    : function () {
500                 window.location.replace(url);
501             },
502             error      : function (req) {
503                 Rakka.hideWaitingMessage();
504                 
505                 var $area = Rakka.switchScreen();
506                 $area.text("Error: " + req.status + " " + req.statusText);
507             }
508         });
509     };
510
511     var submitRedirection = function (pageName, oldRevision, givenPageName, isLocked, destination) {
512         var doc = document.implementation.createDocument(
513             "http://cielonegro.org/schema/Rakka/Page/1.0", "page", null);
514
515         var page = doc.documentElement;
516
517         if (oldRevision != null) {
518             // ページ書換時
519             var updateInfo = doc.createElement("updateInfo");
520             updateInfo.setAttribute("oldRevision", oldRevision);
521
522             if (pageName != givenPageName) {
523                 var move = doc.createElement("move");
524                 move.setAttribute("from", pageName);
525                 updateInfo.appendChild(move);
526             }
527
528             page.appendChild(updateInfo);
529         }
530
531         page.setAttribute("isLocked", isLocked ? "yes" : "no");
532         page.setAttribute("redirect", destination);
533
534         Rakka.displayWaitingMessage("Submitting... please wait.");
535
536         var url = Rakka.baseURI + encodeURI(givenPageName);
537         $.ajax({
538             type       : "PUT",
539             url        : url,
540             contentType: "text/xml",
541             data       : doc,
542             processData: false,
543             beforeSend : function (req) {
544                 Rakka.setAuthorization(req);
545             },
546             success    : function () {
547                 window.location.replace(url);
548             },
549             error      : function (req) {
550                 Rakka.hideWaitingMessage();
551                 
552                 var $area = Rakka.switchScreen();
553                 $area.text("Error: " + req.status + " " + req.statusText);
554             }
555         });
556     };
557
558     var deletePage = function (pageName) {
559         var url = Rakka.baseURI + encodeURI(pageName);
560         $.ajax({
561             type       : "DELETE",
562             url        : url,
563             beforeSend : function (req) {
564                 Rakka.setAuthorization(req);
565             },
566             success    : function () {
567                 window.location.replace(url);
568             },
569             error      : function (req) {
570                 Rakka.hideWaitingMessage();
571                 
572                 var $area = Rakka.switchScreen();
573                 $area.text("Error: " + req.status + " " + req.statusText);
574             }
575         });
576     };
577
578 })();