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