]> gitweb @ CieloNegro.org - Rakka.git/commitdiff
implemented login/out interface
authorpho <pho@cielonegro.org>
Tue, 15 Jan 2008 03:46:40 +0000 (12:46 +0900)
committerpho <pho@cielonegro.org>
Tue, 15 Jan 2008 03:46:40 +0000 (12:46 +0900)
darcs-hash:20080115034640-62b54-9d72c1034c7265fc53139892829834f14db736b2.gz

Rakka.cabal
Rakka/Wiki/Interpreter/Base.hs
defaultPages/SideBar/Right.xml
defaultPages/StyleSheet/Default.xml
js/Makefile
js/base64.js
js/editPage.js
js/login.js [new file with mode: 0644]

index da9c403d07375ad74d946c64f3088df6f3f496a0..228f1a0a6c8dedf99a11c2d315a36a7433c8a86b 100644 (file)
@@ -34,6 +34,7 @@ Extra-Source-Files:
     js/jquery-1.2.1.js
     js/jquery-dom.js
     js/localFile.js
+    js/login.js
     js/screen.js
 
 Flag build-test-suite
index 6b883c376c270d68a2ecfaa00b112706bb358b66..bb4c4ad1ba24ad184c5ca3cc910c81a2d0371e0e 100644 (file)
@@ -24,12 +24,13 @@ interpreters = [ lineBreakInterp
                , otherLangsInterp
                , newPageInterp
                , editPageInterp
+               , loginInterp
                ]
 
 
 lineBreakInterp :: Interpreter
 lineBreakInterp = InlineCommandInterpreter {
-                    iciName      = "br"
+                    iciName = "br"
                   , iciInterpret
                       = \ _ (InlineCommand _ attrs _) -> return $ LineBreak attrs
                   }
@@ -37,7 +38,7 @@ lineBreakInterp = InlineCommandInterpreter {
 
 spanInterp :: Interpreter
 spanInterp = InlineCommandInterpreter {
-               iciName      = "span"
+               iciName = "span"
              , iciInterpret
                  = \ _ (InlineCommand _ attrs contents) -> return $ Span attrs contents
              }
@@ -45,7 +46,7 @@ spanInterp = InlineCommandInterpreter {
 
 divInterp :: Interpreter
 divInterp = BlockCommandInterpreter {
-              bciName      = "div"
+              bciName = "div"
             , bciInterpret
                 = \ _ (BlockCommand _ attrs contents)
                 -> return $ Div attrs (map Block contents)
@@ -54,7 +55,7 @@ divInterp = BlockCommandInterpreter {
 
 pageNameInterp :: Interpreter
 pageNameInterp = InlineCommandInterpreter {
-                   iciName      = "pageName"
+                   iciName = "pageName"
                  , iciInterpret
                      = \ ctx _ -> return $ Text (ctxPageName ctx)
                  }
@@ -63,7 +64,7 @@ pageNameInterp = InlineCommandInterpreter {
 otherLangsInterp :: Interpreter
 otherLangsInterp
     = BlockCommandInterpreter {
-        bciName      = "inOtherLanguages"
+        bciName = "inOtherLanguages"
       , bciInterpret
           = \ ctx _ ->
             let linkTable = case ctxMainPage ctx of
@@ -107,7 +108,7 @@ otherLangsInterp
 newPageInterp :: Interpreter
 newPageInterp 
     = InlineCommandInterpreter {
-        iciName      = "newPage"
+        iciName = "newPage"
       , iciInterpret
           = \ _ (InlineCommand _ args _) ->
             let label = fromMaybe "Create new page" (lookup "label" args)
@@ -128,7 +129,7 @@ newPageInterp
 editPageInterp :: Interpreter
 editPageInterp 
     = InlineCommandInterpreter {
-        iciName      = "editPage"
+        iciName = "editPage"
       , iciInterpret
           = \ ctx (InlineCommand _ args _) ->
             let name  = fromMaybe (ctxPageName ctx) (lookup "page" args)
@@ -141,3 +142,21 @@ editPageInterp
             in
               return (Input attrs)
       }
+
+
+-- <input type="button"
+--        value="Login"
+--        class="loginButton" />
+loginInterp :: Interpreter
+loginInterp 
+    = InlineCommandInterpreter {
+        iciName = "login"
+      , iciInterpret
+          = \ _ _ ->
+            let attrs = [ ("type"   , "button")
+                        , ("value"  , "Login")
+                        , ("class"  , "loginButton")
+                        ]
+            in
+              return (Input attrs)
+      }
\ No newline at end of file
index ea9531a4d81e2661acf48908e08c38208101d4d4..79612f2b41c37ddbc82bf833e87fdfd87f1a5ac1 100644 (file)
@@ -3,6 +3,7 @@
       type="text/x-rakka">
   <textData><![CDATA[
 = Control =
+* <login />
 * <newPage />
 * <editPage />
 
index d4f7fe5b50b7d196d0360437f52919502a0e069f..d23597501d5ba339b91e5f65483df70e297b25b9 100644 (file)
@@ -61,6 +61,10 @@ input[type="button"] {
     padding: 0px;
 }
 
+td, th {
+    padding: 3px;
+}
+
 .title {
     padding: 5px 20px;
 }
@@ -157,9 +161,6 @@ input[type="button"] {
 table.pageEditor {
     width: 100%;
 }
-.pageEditor td, .pageEditor th {
-    padding: 3px;
-}
 .pageEditor th {
     width: 6em;
 }
index a399e6f2fe63a2ecaf33292c430a0cd71c8b516b..63477dd7bab4bae8ac88cde27c5a886f1b06a6ff 100644 (file)
@@ -8,6 +8,7 @@ SOURCES = \
        base64.js \
        editPage.js \
        localFile.js \
+       login.js \
        redirection.js \
        screen.js \
        $(NULL)
@@ -19,8 +20,8 @@ build: ../Rakka/Resource/JavaScript.hs
 
 
 packed.js: $(SOURCES) $(COMPRESSOR)
-#      cat $(SOURCES) > $@
-       cat $(SOURCES) | $(COMPRESS) --warn -o $@
+       cat $(SOURCES) > $@
+#      cat $(SOURCES) | $(COMPRESS) --warn -o $@
 
 
 ../Rakka/Resource/JavaScript.hs: packed.js
index f4775ae59ecce21947f7c918e401225ee974b9e1..3fdc256ddb68dd778e6056f27feee79aeb850949 100644 (file)
@@ -1,6 +1,16 @@
 (function () {
 
-    var b64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+    var encTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+    var decTable = new Array(
+        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
+        52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
+        -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
+        15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
+        -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+        41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);
 
     Rakka.encodeBase64 = function (src) {
         var len = src.length;
             var c1 = src.charCodeAt(i++);
             
             if (i == len) {
-                ret += b64Chars.charAt(c1 >> 2);
-                ret += b64Chars.charAt((c1 & 0x03) << 4);
+                ret += encTable.charAt(c1 >> 2);
+                ret += encTable.charAt((c1 & 0x03) << 4);
                 ret += "==";
             }
             else {
                 var c2 = src.charCodeAt(i++);
 
                 if (i == len) {
-                    ret += b64Chars.charAt(c1 >> 2);
-                    ret += b64Chars.charAt(((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4));
-                    ret += b64Chars.charAt((c2 & 0x0F) << 2);
+                    ret += encTable.charAt(c1 >> 2);
+                    ret += encTable.charAt(((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4));
+                    ret += encTable.charAt((c2 & 0x0F) << 2);
                     ret += "=";
                 }
                 else {
                     var c3 = src.charCodeAt(i++);
 
-                    ret += b64Chars.charAt(c1 >> 2);
-                    ret += b64Chars.charAt(((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4));
-                    ret += b64Chars.charAt(((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6));
-                    ret += b64Chars.charAt(c3 & 0x3F);
+                    ret += encTable.charAt(c1 >> 2);
+                    ret += encTable.charAt(((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4));
+                    ret += encTable.charAt(((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6));
+                    ret += encTable.charAt(c3 & 0x3F);
+                }
+            }
+        }
+
+        return ret;
+    };
+
+    Rakka.decodeBase64 = function (src) {
+        var len = src.length;
+        var i   = 0;
+        var ret = "";
+
+        while (i < len) {
+            var c1;
+            do {
+                c1 = decTable[src.charCodeAt(i++)];
+            } while (i < len && c1 == -1);
+            
+            if (c1 != -1) {
+                var c2;
+                do {
+                    c2 = decTable[src.charCodeAt(i++)];
+                } while (i < len && c2 == -1);
+                
+                if (c2 != -1) {
+
+                    ret += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));
+
+                    var c3;
+                    do {
+                        c3 = src.charCodeAt(i++);
+                        if (c3 == 61) {
+                            return ret;
+                        }
+                        c3 = decTable[c3];
+                    } while (i < len && c3 == -1);
+
+                    if (c3 != -1) {
+                        ret += String.fromCharCode(((c2 & 0x0F) << 4) | ((c3 & 0x3C) >> 2));
+
+                        var c4;
+                        do {
+                            c4 = src.charCodeAt(i++);
+                            if (c4 == 61) {
+                                return ret;
+                            }
+                            c4 = decTable[c4];
+                        } while (i < len && c4 == -1);
+
+                        if (c4 != -1) {
+                            ret += String.fromCharCode(((c3 & 0x03) << 6) | c4);
+                        }
+                    }
                 }
             }
         }
index 960ce4eb5f6f8fdba41b9c9837d0c1fc0a732a02..fb887352f85a5b80bac5092b146ea6ed68ad03bd 100644 (file)
-Rakka.$previewHeader = null;
-Rakka.$previewArea   = null;
+(function () {
 
-Rakka.isDirty = null;
+    var $previewHeader = null;
+    var $previewArea   = null;
 
-Rakka.editPage = function (pageName) {
-    var $area = Rakka.switchScreen();
+    var isDirty = null;
 
-    Rakka.displayWaitingMessage("Loading... please wait.");
+    Rakka.editPage = function (pageName) {
+        var $area = Rakka.switchScreen();
+
+        Rakka.displayWaitingMessage("Loading... please wait.");
     
-    // XML 版のページを取得する。
-    $.ajax({
-        url    : Rakka.baseURI + pageName + ".xml",
-        success: function (pageXml) {
-            Rakka.hideWaitingMessage();
+        // XML 版のページを取得する。
+        $.ajax({
+            url    : Rakka.baseURI + pageName + ".xml",
+            success: function (pageXml) {
+                Rakka.hideWaitingMessage();
             
-            var $page       = $(pageXml).find("page");
-            var oldRevision = $page.attr("revision");
-            var defaultType
-                = $page.attr("isBinary") == "yes"          ? "binary"
-                : $page.attr("type")     == "text/x-rakka" ? "rakka"
-                : $page.attr("type")     == "text/css"     ? "css"
-                : $page.attr("redirect") != null           ? "redirect"
-                :                                            "unknown"
-                ;
-            var source
-                = $page.attr("redirect") != null ? $page.attr("redirect")
-                : $page.find("textData").text()
-                ;
-            var summary     = $page.find("summary").text();
+                var $page       = $(pageXml).find("page");
+                var oldRevision = $page.attr("revision");
+                var defaultType
+                    = $page.attr("isBinary") == "yes"          ? "binary"
+                    : $page.attr("type")     == "text/x-rakka" ? "rakka"
+                    : $page.attr("type")     == "text/css"     ? "css"
+                    : $page.attr("redirect") != null           ? "redirect"
+                    :                                            "unknown"
+                    ;
+                var source
+                    = $page.attr("redirect") != null ? $page.attr("redirect")
+                    : $page.find("textData").text()
+                    ;
+                var summary     = $page.find("summary").text();
                 
-            Rakka.displayPageEditor(pageName, oldRevision, defaultType, source, summary);
-        },
-        error  : function (req) {
-            Rakka.hideWaitingMessage();
-            
-            if (req.status == 404) {
-                Rakka.displayPageEditor(pageName, null, "rakka", null, "");
-            }
-            else {
-                $area.text("Error: " + req.status + " " + req.statusText);
+                displayPageEditor(pageName, oldRevision, defaultType, source, summary);
+            },
+            error  : function (req) {
+                Rakka.hideWaitingMessage();
+                
+                if (req.status == 404) {
+                    displayPageEditor(pageName, null, "rakka", null, "");
+                }
+                else {
+                    $area.text("Error: " + req.status + " " + req.statusText);
+                }
             }
-        }
-    });
-};
+        });
+    };
 
-Rakka.newPage = function () {
-    Rakka.displayPageEditor("", null, "rakka", null, "");
-};
+    Rakka.newPage = function () {
+        displayPageEditor("", null, "rakka", null, "");
+    };
 
-Rakka.displayPageEditor = function (pageName, oldRevision, defaultType, source, summary) {
-    var $area = Rakka.switchScreen();
-    $area.empty();
+    var displayPageEditor = function (pageName, oldRevision, defaultType, source, summary) {
+        var $area = Rakka.switchScreen();
 
-    Rakka.$previewHeader = $( $.H1({}, "Preview") );
-    $area.append(Rakka.$previewHeader);
-    Rakka.$previewHeader.hide();
+        $previewHeader = $( $.H1({}, "Preview") );
+        $area.append($previewHeader);
+        $previewHeader.hide();
 
-    Rakka.$previewArea = $( $.DIV({className: "preview"}) );
-    $area.append(Rakka.$previewArea);
-    Rakka.$previewArea.hide();
+        $previewArea = $( $.DIV({className: "preview"}) );
+        $area.append($previewArea);
+        $previewArea.hide();
 
-    $area.append($.H1({}, pageName == "" ? "Create page" : "Edit page"));
+        $area.append($.H1({}, pageName == "" ? "Create page" : "Edit page"));
 
-    var makeDirty = function () {
-        Rakka.isDirty = true;
-    };
+        var makeDirty = function () {
+            isDirty = true;
+        };
     
-    var fldPageName
-        = $.INPUT({type : "text", value: pageName});
+        var fldPageName
+            = $.INPUT({type : "text", value: pageName});
 
-    $(fldPageName).change(makeDirty);
+        $(fldPageName).change(makeDirty);
 
-    var btnTypeRakka
-        = $.INPUT({type   : "radio",
-                   name   : "type",
-                   checked: (defaultType == "rakka"    ? "checked" : "")});
+        var btnTypeRakka
+            = $.INPUT({type   : "radio",
+                       name   : "type",
+                       checked: (defaultType == "rakka"    ? "checked" : "")});
 
-    $(btnTypeRakka).change(makeDirty);
+        $(btnTypeRakka).change(makeDirty);
 
-    var btnTypeCSS
-        = $.INPUT({type   : "radio",
-                   name   : "type",
-                   checked: (defaultType == "css"      ? "checked" : "")});
+        var btnTypeCSS
+            = $.INPUT({type   : "radio",
+                       name   : "type",
+                       checked: (defaultType == "css"      ? "checked" : "")});
 
-    $(btnTypeCSS).change(makeDirty);
+        $(btnTypeCSS).change(makeDirty);
 
-    var btnTypeBinary
-        = $.INPUT({type   : "radio",
-                   name   : "type",
-                   checked: (defaultType == "binary"   ? "checked" : "")});
+        var btnTypeBinary
+            = $.INPUT({type   : "radio",
+                       name   : "type",
+                       checked: (defaultType == "binary"   ? "checked" : "")});
 
-    $(btnTypeBinary).change(makeDirty);
+        $(btnTypeBinary).change(makeDirty);
 
-    var btnTypeRedirect
-        = $.INPUT({type   : "radio",
-                   name   : "type",
-                   checked: (defaultType == "redirect" ? "checked" : "")});
+        var btnTypeRedirect
+            = $.INPUT({type   : "radio",
+                       name   : "type",
+                       checked: (defaultType == "redirect" ? "checked" : "")});
 
-    $(btnTypeRedirect).change(makeDirty);
+        $(btnTypeRedirect).change(makeDirty);
 
-    var fldSummary
-        = $.TEXTAREA({className: "summary"}, summary);
+        var fldSummary
+            = $.TEXTAREA({className: "summary"}, summary);
 
-    $(fldSummary).change(makeDirty);
+        $(fldSummary).change(makeDirty);
 
-    var trSummary
-        = $.TR({},
-               $.TH({}, "Summary"),
-               $.TD({}, fldSummary));
+        var trSummary
+            = $.TR({},
+                   $.TH({}, "Summary"),
+                   $.TD({}, fldSummary));
 
-    var fldRakkaSource
-        = $.TEXTAREA({className: "source"},
-                     (defaultType == "rakka" && source != null ? source : ""));
+        var fldRakkaSource
+            = $.TEXTAREA({className: "source"},
+                         (defaultType == "rakka" && source != null ? source : ""));
 
-    $(fldRakkaSource).change(makeDirty);
+        $(fldRakkaSource).change(makeDirty);
 
-    var fldCSSSource
-        = $.TEXTAREA({className: "source"},
-                     (defaultType == "css"   && source != null ? source : ""));
+        var fldCSSSource
+            = $.TEXTAREA({className: "source"},
+                         (defaultType == "css"   && source != null ? source : ""));
 
-    $(fldCSSSource).change(makeDirty);
+        $(fldCSSSource).change(makeDirty);
 
-    var fldUploadFile
-        = $.INPUT({type: "file"});
+        var fldUploadFile
+            = $.INPUT({type: "file"});
 
-    $(fldUploadFile).change(makeDirty);
+        $(fldUploadFile).change(makeDirty);
 
-    var fldRedirect
-        = $.INPUT({type: "text", value: (defaultType == "redirect" ? source : "")});
+        var fldRedirect
+            = $.INPUT({type: "text", value: (defaultType == "redirect" ? source : "")});
 
-    $(fldRedirect).change(makeDirty);
+        $(fldRedirect).change(makeDirty);
 
-    var trContent
-        = $.TR({}, 
-               $.TH({}),
-               $.TD({})
-              );
+        var trContent
+            = $.TR({}, 
+                   $.TH({}),
+                   $.TD({})
+                  );
 
-    var btnPreview
-        = $.INPUT({type: "button", value: "Preview page"});
-    
-    $(btnPreview).click(function () {
-        if (btnTypeRakka.checked) {
-            Rakka.previewRakkaPage(
-                fldPageName.value, fldRakkaSource.value);
-        }
-        else if (btnTypeBinary.checked) {
-            Rakka.previewBinaryPage(
-                fldPageName.value, fldUploadFile.value);
-        }
-    });
+        var btnPreview
+            = $.INPUT({type: "button", value: "Preview page"});
+        
+        $(btnPreview).click(function () {
+            if (btnTypeRakka.checked) {
+                previewRakkaPage(
+                    fldPageName.value, fldRakkaSource.value);
+            }
+            else if (btnTypeBinary.checked) {
+                previewBinaryPage(
+                    fldPageName.value, fldUploadFile.value);
+            }
+        });
+
+        var btnSubmit
+            = $.INPUT({type: "button", value: "Submit page"});
+        
+        $(btnSubmit).click(function () {
+            if (btnTypeRakka.checked) {
+                submitTextPage(
+                    pageName,
+                    oldRevision,
+                    fldPageName.value,
+                    "text/x-rakka",
+                    fldSummary.value,
+                    fldRakkaSource.value);
+            }
+            else if (btnTypeCSS.checked) {
+                submitTextPage(
+                    pageName,
+                    oldRevision,
+                    fldPageName.value,
+                    "text/css",
+                    fldSummary.value,
+                    fldCSSSource.value);
+            }
+            else if (btnTypeBinary.checked) {
+                submitBinaryPage(
+                    pageName,
+                    oldRevision,
+                    fldPageName.value,
+                    fldSummary.value,
+                    fldUploadFile.value);
+            }
+            else if (btnTypeRedirect.checked) {
+                submitRedirection(
+                    pageName,
+                    oldRevision,
+                    fldPageName.value,
+                    fldRedirect.value);
+            }
+        });
+
+        var btnDelete
+            = $.INPUT({type: "button", value: "Delete this page"});
+        
+        $(btnDelete).click(function () {
+            if (window.confirm("Do you really want to delete this page?")) {
+                deletePage(pageName);
+            }
+        });
 
-    var btnSubmit
-        = $.INPUT({type: "button", value: "Submit page"});
-    
-    $(btnSubmit).click(function () {
-        if (btnTypeRakka.checked) {
-            Rakka.submitTextPage(
-                pageName,
-                oldRevision,
-                fldPageName.value,
-                "text/x-rakka",
-                fldSummary.value,
-                fldRakkaSource.value);
-        }
-        else if (btnTypeCSS.checked) {
-            Rakka.submitTextPage(
-                pageName,
-                oldRevision,
-                fldPageName.value,
-                "text/css",
-                fldSummary.value,
-                fldCSSSource.value);
-        }
-        else if (btnTypeBinary.checked) {
-            Rakka.submitBinaryPage(
-                pageName,
-                oldRevision,
-                fldPageName.value,
-                fldSummary.value,
-                fldUploadFile.value);
-        }
-        else if (btnTypeRedirect.checked) {
-            Rakka.submitRedirection(
-                pageName,
-                oldRevision,
-                fldPageName.value,
-                fldRedirect.value);
-        }
-    });
+        var btnCancel
+            = $.INPUT({type: "button", value: "Cancel editing"});
 
-    var btnDelete
-        = $.INPUT({type: "button", value: "Delete this page"});
-    
-    $(btnDelete).click(function () {
-        if (window.confirm("Do you really want to delete this page?")) {
-            Rakka.deletePage(pageName);
+        $(btnCancel).click(function () {
+            if (isDirty) {
+                if (window.confirm("Do you really want to discard changes?")) {
+                    Rakka.restoreScreen();
+                }
+            }
+            else {
+                Rakka.restoreScreen();
+            }
+        });
+
+        var updateTRContent = function () {
+            if (btnTypeRakka.checked) {
+                $(trSummary).show();
+                $(trContent).find("th").text("Wiki source");
+                $(trContent).find("td").empty().append(fldRakkaSource);
+                $(btnPreview).show();
+            }
+            else if (btnTypeCSS.checked) {
+                $(trSummary).show();
+                $(trContent).find("th").text("CSS source");
+                $(trContent).find("td").empty().append(fldCSSSource);
+                $(btnPreview).hide();
+            }
+            else if (btnTypeBinary.checked) {
+                $(trSummary).show();
+                $(trContent).find("th").text("File");
+                $(trContent).find("td").empty().append(fldUploadFile);
+                $(btnPreview).show();
+            }
+            else if (btnTypeRedirect.checked) {
+                $(trSummary).hide();
+                $(trContent).find("th").text("Destination Page");
+                $(trContent).find("td").empty().append(fldRedirect);
+                $(btnPreview).hide();
+            }
+        };
+        $(btnTypeRakka   ).change(updateTRContent);
+        $(btnTypeCSS     ).change(updateTRContent);
+        $(btnTypeBinary  ).change(updateTRContent);
+        $(btnTypeRedirect).change(updateTRContent);
+        updateTRContent();
+
+        var pageEditor
+            = $.TABLE({className: "pageEditor"},
+                      $.TBODY({},
+                              $.TR({},
+                                   $.TH({}, "Page name"),
+                                   $.TD({}, fldPageName)
+                                  ),
+                              $.TR({},
+                                   $.TH({}, "Page type"),
+                                   $.TD({},
+                                        $.UL({},
+                                             $.LI({},
+                                                  $.LABEL({},
+                                                          btnTypeRakka,
+                                                          "Wiki page"
+                                                         )
+                                                 ),
+                                             $.LI({},
+                                                  $.LABEL({},
+                                                          btnTypeCSS,
+                                                          "Style sheet"
+                                                         )
+                                                 ),
+                                             $.LI({},
+                                                  $.LABEL({},
+                                                          btnTypeBinary,
+                                                          "Binary file"
+                                                         )
+                                                 ),
+                                             $.LI({},
+                                                  $.LABEL({},
+                                                          btnTypeRedirect,
+                                                          "Redirection"
+                                                         )
+                                                 )
+                                            )
+                                       )
+                                  ),
+                              trSummary,
+                              trContent,
+                              $.TR({},
+                                   $.TH({}),
+                                   $.TD({}, btnPreview, btnSubmit, btnDelete, btnCancel)
+                                  )
+                             )
+                     );
+
+        if (oldRevision == null || oldRevision == 0) {
+            // 削除不可
+            $(btnDelete).hide();
         }
-    });
 
-    var btnCancel
-        = $.INPUT({type: "button", value: "Cancel editing"});
+        $area.append(pageEditor);
 
-    $(btnCancel).click(function () {
-        if (Rakka.isDirty) {
-            if (window.confirm("Do you really want to discard changes?")) {
-                Rakka.restoreScreen();
+        isDirty = false;
+    };
+
+    var previewRakkaPage = function (pageName, source) {
+        Rakka.displayWaitingMessage("Loading... please wait.");
+        
+        var url = Rakka.baseURI + "render/" + encodeURI(pageName);
+        $.ajax({
+            type       : "POST",
+            url        : url,
+            contentType: "text/x-rakka",
+            data       : source,
+            processData: false,
+            success    : function (resultDoc) {
+                Rakka.hideWaitingMessage();
+                showPreview(resultDoc);
+            },
+            error      : function (req) {
+                Rakka.hideWaitingMessage();
+                alert("Error: " + req.status + " " + req.statusText);
             }
-        }
-        else {
-            Rakka.restoreScreen();
-        }
-    });
-
-    var updateTRContent = function () {
-        if (btnTypeRakka.checked) {
-            $(trSummary).show();
-            $(trContent).find("th").text("Wiki source");
-            $(trContent).find("td").empty().append(fldRakkaSource);
-            $(btnPreview).show();
-        }
-        else if (btnTypeCSS.checked) {
-            $(trSummary).show();
-            $(trContent).find("th").text("CSS source");
-            $(trContent).find("td").empty().append(fldCSSSource);
-            $(btnPreview).hide();
-        }
-        else if (btnTypeBinary.checked) {
-            $(trSummary).show();
-            $(trContent).find("th").text("File");
-            $(trContent).find("td").empty().append(fldUploadFile);
-            $(btnPreview).show();
-        }
-        else if (btnTypeRedirect.checked) {
-            $(trSummary).hide();
-            $(trContent).find("th").text("Destination Page");
-            $(trContent).find("td").empty().append(fldRedirect);
-            $(btnPreview).hide();
-        }
+        });
     };
-    $(btnTypeRakka   ).change(updateTRContent);
-    $(btnTypeCSS     ).change(updateTRContent);
-    $(btnTypeBinary  ).change(updateTRContent);
-    $(btnTypeRedirect).change(updateTRContent);
-    updateTRContent();
-
-    var pageEditor
-        = $.TABLE({className: "pageEditor"},
-                  $.TBODY({},
-                          $.TR({},
-                               $.TH({}, "Page name"),
-                               $.TD({}, fldPageName)
-                              ),
-                          $.TR({},
-                               $.TH({}, "Page type"),
-                               $.TD({},
-                                    $.UL({},
-                                         $.LI({},
-                                              $.LABEL({},
-                                                      btnTypeRakka,
-                                                      "Wiki page"
-                                                     )
-                                             ),
-                                         $.LI({},
-                                              $.LABEL({},
-                                                      btnTypeCSS,
-                                                      "Style sheet"
-                                                     )
-                                             ),
-                                         $.LI({},
-                                              $.LABEL({},
-                                                      btnTypeBinary,
-                                                      "Binary file"
-                                                     )
-                                             ),
-                                         $.LI({},
-                                              $.LABEL({},
-                                                      btnTypeRedirect,
-                                                      "Redirection"
-                                                     )
-                                             )
-                                        )
-                                   )
-                              ),
-                          trSummary,
-                          trContent,
-                          $.TR({},
-                               $.TH({}),
-                               $.TD({}, btnPreview, btnSubmit, btnDelete, btnCancel)
-                              )
-                         )
-                 );
-
-    if (oldRevision == null || oldRevision == 0) {
-        // 削除不可
-        $(btnDelete).hide();
-    }
-
-    $area.append(pageEditor);
-
-    Rakka.isDirty = false;
-};
-
-Rakka.previewRakkaPage = function (pageName, source) {
-    Rakka.displayWaitingMessage("Loading... please wait.");
-    
-    var url = Rakka.baseURI + "render/" + encodeURI(pageName);
-    $.ajax({
-        type       : "POST",
-        url        : url,
-        contentType: "text/x-rakka",
-        data       : source,
-        processData: false,
-        success    : function (resultDoc) {
-            Rakka.hideWaitingMessage();
-            Rakka.showPreview(resultDoc);
-        },
-        error      : function (req) {
-            Rakka.hideWaitingMessage();
-            alert("Error: " + req.status + " " + req.statusText);
-        }
-    });
-};
-
-Rakka.previewBinaryPage = function (pageName, path) {
-    Rakka.displayWaitingMessage("Loading... please wait.");
-
-    /* Firefox でバイナリを送らうとすると 0x00 の位置で切れてしまふ。*/
-    var bin = Rakka.loadLocalBinaryFile(path);
-    var url = Rakka.baseURI + "render/" + encodeURI(pageName);
-    $.ajax({
-        type       : "POST",
-        url        : url,
-        contentType: "application/x-rakka-base64-stream",
-        data       : Rakka.encodeBase64(bin),
-        processData: false,
-        success    : function (resultDoc) {
-            Rakka.hideWaitingMessage();
-            Rakka.showPreview(resultDoc);
-        },
-        error      : function (req) {
-            Rakka.hideWaitingMessage();
-            alert("Error: " + req.status + " " + req.statusText);
-        }
-    });
-};
 
-Rakka.showPreview = function (doc) {
-    Rakka.$previewArea.empty();
-    
-    Rakka.$previewHeader.show();
-    Rakka.$previewArea.show();
-    
-    var root  = doc.documentElement;
-    var child = root.firstChild;
-    do {
-        if (child.nodeType == 1) {
-            // 要素だったので複製
-            Rakka.$previewArea.append(child.cloneNode(true));
-        }
-    } while (child = child.nextSibling);
+    var previewBinaryPage = function (pageName, path) {
+        Rakka.displayWaitingMessage("Loading... please wait.");
+
+        /* Firefox でバイナリを送らうとすると 0x00 の位置で切れてしまふ。*/
+        var bin = Rakka.loadLocalBinaryFile(path);
+        var url = Rakka.baseURI + "render/" + encodeURI(pageName);
+        $.ajax({
+            type       : "POST",
+            url        : url,
+            contentType: "application/x-rakka-base64-stream",
+            data       : Rakka.encodeBase64(bin),
+            processData: false,
+            success    : function (resultDoc) {
+                Rakka.hideWaitingMessage();
+                showPreview(resultDoc);
+            },
+            error      : function (req) {
+                Rakka.hideWaitingMessage();
+                alert("Error: " + req.status + " " + req.statusText);
+            }
+        });
+    };
+
+    var showPreview = function (doc) {
+        $previewArea.empty();
+        
+        $previewHeader.show();
+        $previewArea.show();
+        
+        var root  = doc.documentElement;
+        var child = root.firstChild;
+        do {
+            if (child.nodeType == 1) {
+                // 要素だったので複製
+                $previewArea.append(child.cloneNode(true));
+            }
+        } while (child = child.nextSibling);
+
+        Rakka.scrollToTopLeft();
+    };
 
-    Rakka.scrollToTopLeft();
-};
+    var submitTextPage = function (pageName, oldRevision, givenPageName, mimeType, summary, text) {
+        var doc = document.implementation.createDocument(
+            "http://cielonegro.org/schema/Rakka/Page/1.0", "page", null);
 
-Rakka.submitTextPage = function (pageName, oldRevision, givenPageName, mimeType, summary, text) {
-    var doc = document.implementation.createDocument(
-        "http://cielonegro.org/schema/Rakka/Page/1.0", "page", null);
+        var page = doc.documentElement;
 
-    var page = doc.documentElement;
+        if (oldRevision != null) {
+            // ページ書換時
+            var updateInfo = doc.createElement("updateInfo");
+            updateInfo.setAttribute("oldRevision", oldRevision);
 
-    if (oldRevision != null) {
-        // ページ書換時
-        var updateInfo = doc.createElement("updateInfo");
-        updateInfo.setAttribute("oldRevision", oldRevision);
+            if (pageName != givenPageName) {
+                var move = doc.createElement("move");
+                move.setAttribute("from", pageName);
+                updateInfo.appendChild(move);
+            }
 
-        if (pageName != givenPageName) {
-            var move = doc.createElement("move");
-            move.setAttribute("from", pageName);
-            updateInfo.appendChild(move);
+            page.appendChild(updateInfo);
         }
 
-        page.appendChild(updateInfo);
-    }
-
-    page.setAttribute("type", mimeType);
-
-    if (summary != null) {
-        var s = doc.createElement("summary");
-        s.appendChild(
-            doc.createTextNode(summary));
-        page.appendChild(s);
-    }
-
-    var textData = doc.createElement("textData");
-    textData.appendChild(
-        doc.createTextNode(text));
-
-    page.appendChild(textData);
-
-    Rakka.displayWaitingMessage("Submitting... please wait.");
-
-    var url = Rakka.baseURI + encodeURI(givenPageName);
-    $.ajax({
-        type       : "PUT",
-        url        : url,
-        contentType: "text/xml",
-        data       : doc,
-        processData: false,
-        success    : function () {
-            window.location.replace(url);
-        },
-        error      : function (req) {
-            Rakka.hideWaitingMessage();
-            
-            var $area = Rakka.switchScreen();
-            $area.text("Error: " + req.status + " " + req.statusText);
+        page.setAttribute("type", mimeType);
+
+        if (summary != null) {
+            var s = doc.createElement("summary");
+            s.appendChild(
+                doc.createTextNode(summary));
+            page.appendChild(s);
         }
-    });
-};
 
-Rakka.submitBinaryPage = function (pageName, oldRevision, givenPageName, summary, path) {
-    var doc = document.implementation.createDocument(
-        "http://cielonegro.org/schema/Rakka/Page/1.0", "page", null);
+        var textData = doc.createElement("textData");
+        textData.appendChild(
+            doc.createTextNode(text));
+
+        page.appendChild(textData);
+
+        Rakka.displayWaitingMessage("Submitting... please wait.");
+
+        var url = Rakka.baseURI + encodeURI(givenPageName);
+        $.ajax({
+            type       : "PUT",
+            url        : url,
+            contentType: "text/xml",
+            data       : doc,
+            processData: false,
+            success    : function () {
+                window.location.replace(url);
+            },
+            error      : function (req) {
+                Rakka.hideWaitingMessage();
+                
+                var $area = Rakka.switchScreen();
+                $area.text("Error: " + req.status + " " + req.statusText);
+            }
+        });
+    };
+
+    var submitBinaryPage = function (pageName, oldRevision, givenPageName, summary, path) {
+        var doc = document.implementation.createDocument(
+            "http://cielonegro.org/schema/Rakka/Page/1.0", "page", null);
 
-    var page = doc.documentElement;
+        var page = doc.documentElement;
 
-    if (oldRevision != null) {
-        // ページ書換時
-        var updateInfo = doc.createElement("updateInfo");
-        updateInfo.setAttribute("oldRevision", oldRevision);
+        if (oldRevision != null) {
+            // ページ書換時
+            var updateInfo = doc.createElement("updateInfo");
+            updateInfo.setAttribute("oldRevision", oldRevision);
 
-        if (pageName != givenPageName) {
-            var move = doc.createElement("move");
-            move.setAttribute("from", pageName);
-            updateInfo.appendChild(move);
+            if (pageName != givenPageName) {
+                var move = doc.createElement("move");
+                move.setAttribute("from", pageName);
+                updateInfo.appendChild(move);
+            }
+
+            page.appendChild(updateInfo);
         }
 
-        page.appendChild(updateInfo);
-    }
-
-    page.setAttribute("type", "");
-
-    if (summary != null) {
-        var s = doc.createElement("summary");
-        s.appendChild(
-            doc.createTextNode(summary));
-        page.appendChild(s);
-    }
-
-    var bin = Rakka.loadLocalBinaryFile(path);
-    var b64 = Rakka.encodeBase64(bin);
-
-    var binaryData = doc.createElement("binaryData");
-    binaryData.appendChild(
-        doc.createTextNode(b64));
-
-    page.appendChild(binaryData);
-
-    Rakka.displayWaitingMessage("Submitting... please wait.");
-
-    var url = Rakka.baseURI + encodeURI(givenPageName);
-    $.ajax({
-        type       : "PUT",
-        url        : url,
-        contentType: "text/xml",
-        data       : doc,
-        processData: false,
-        success    : function () {
-            window.location.replace(url);
-        },
-        error      : function (req) {
-            Rakka.hideWaitingMessage();
-            
-            var $area = Rakka.switchScreen();
-            $area.text("Error: " + req.status + " " + req.statusText);
+        page.setAttribute("type", "");
+
+        if (summary != null) {
+            var s = doc.createElement("summary");
+            s.appendChild(
+                doc.createTextNode(summary));
+            page.appendChild(s);
         }
-    });
-};
 
-Rakka.submitRedirection = function (pageName, oldRevision, givenPageName, destination) {
-    var doc = document.implementation.createDocument(
-        "http://cielonegro.org/schema/Rakka/Page/1.0", "page", null);
+        var bin = Rakka.loadLocalBinaryFile(path);
+        var b64 = Rakka.encodeBase64(bin);
+
+        var binaryData = doc.createElement("binaryData");
+        binaryData.appendChild(
+            doc.createTextNode(b64));
+
+        page.appendChild(binaryData);
+
+        Rakka.displayWaitingMessage("Submitting... please wait.");
+
+        var url = Rakka.baseURI + encodeURI(givenPageName);
+        $.ajax({
+            type       : "PUT",
+            url        : url,
+            contentType: "text/xml",
+            data       : doc,
+            processData: false,
+            success    : function () {
+                window.location.replace(url);
+            },
+            error      : function (req) {
+                Rakka.hideWaitingMessage();
+                
+                var $area = Rakka.switchScreen();
+                $area.text("Error: " + req.status + " " + req.statusText);
+            }
+        });
+    };
 
-    var page = doc.documentElement;
+    var submitRedirection = function (pageName, oldRevision, givenPageName, destination) {
+        var doc = document.implementation.createDocument(
+            "http://cielonegro.org/schema/Rakka/Page/1.0", "page", null);
 
-    if (oldRevision != null) {
-        // ページ書換時
-        var updateInfo = doc.createElement("updateInfo");
-        updateInfo.setAttribute("oldRevision", oldRevision);
+        var page = doc.documentElement;
 
-        if (pageName != givenPageName) {
-            var move = doc.createElement("move");
-            move.setAttribute("from", pageName);
-            updateInfo.appendChild(move);
-        }
+        if (oldRevision != null) {
+            // ページ書換時
+            var updateInfo = doc.createElement("updateInfo");
+            updateInfo.setAttribute("oldRevision", oldRevision);
 
-        page.appendChild(updateInfo);
-    }
-
-    page.setAttribute("redirect", destination);
-
-    Rakka.displayWaitingMessage("Submitting... please wait.");
-
-    var url = Rakka.baseURI + encodeURI(givenPageName);
-    $.ajax({
-        type       : "PUT",
-        url        : url,
-        contentType: "text/xml",
-        data       : doc,
-        processData: false,
-        success    : function () {
-            window.location.replace(url);
-        },
-        error      : function (req) {
-            Rakka.hideWaitingMessage();
-            
-            var $area = Rakka.switchScreen();
-            $area.text("Error: " + req.status + " " + req.statusText);
-        }
-    });
-};
-
-Rakka.deletePage = function (pageName) {
-    var url = Rakka.baseURI + encodeURI(pageName);
-    $.ajax({
-        type       : "DELETE",
-        url        : url,
-        success    : function () {
-            window.location.replace(url);
-        },
-        error      : function (req) {
-            Rakka.hideWaitingMessage();
-            
-            var $area = Rakka.switchScreen();
-            $area.text("Error: " + req.status + " " + req.statusText);
+            if (pageName != givenPageName) {
+                var move = doc.createElement("move");
+                move.setAttribute("from", pageName);
+                updateInfo.appendChild(move);
+            }
+
+            page.appendChild(updateInfo);
         }
-    });
-};
+
+        page.setAttribute("redirect", destination);
+
+        Rakka.displayWaitingMessage("Submitting... please wait.");
+
+        var url = Rakka.baseURI + encodeURI(givenPageName);
+        $.ajax({
+            type       : "PUT",
+            url        : url,
+            contentType: "text/xml",
+            data       : doc,
+            processData: false,
+            success    : function () {
+                window.location.replace(url);
+            },
+            error      : function (req) {
+                Rakka.hideWaitingMessage();
+                
+                var $area = Rakka.switchScreen();
+                $area.text("Error: " + req.status + " " + req.statusText);
+            }
+        });
+    };
+
+    var deletePage = function (pageName) {
+        var url = Rakka.baseURI + encodeURI(pageName);
+        $.ajax({
+            type       : "DELETE",
+            url        : url,
+            success    : function () {
+                window.location.replace(url);
+            },
+            error      : function (req) {
+                Rakka.hideWaitingMessage();
+                
+                var $area = Rakka.switchScreen();
+                $area.text("Error: " + req.status + " " + req.statusText);
+            }
+        });
+    };
+
+})();
\ No newline at end of file
diff --git a/js/login.js b/js/login.js
new file mode 100644 (file)
index 0000000..95b1f00
--- /dev/null
@@ -0,0 +1,128 @@
+(function () {
+    
+    Rakka.showLoginPanel = function () {
+        var $area = Rakka.switchScreen();
+
+        $area.append($.H1({}, "Login"));
+
+        var fldUserID
+            = $.INPUT({type: "text"});
+
+        var fldPassword
+            = $.INPUT({type: "password"});
+
+        var btnLogin
+            = $.INPUT({type: "button", value: "Login"});
+
+        $(btnLogin).click(function () {
+            login(fldUserID.value, fldPassword.value);
+        });
+
+        var btnCancel
+            = $.INPUT({type: "button", value: "Cancel"});
+
+        $(btnCancel).click(function () {
+            Rakka.restoreScreen();
+        });
+
+        var loginPanel
+            = $.TABLE({className: "loginPanel"},
+                      $.TBODY({},
+                              $.TR({},
+                                   $.TH({}, "User ID"),
+                                   $.TD({}, fldUserID)
+                                  ),
+                              $.TR({},
+                                   $.TH({}, "Password"),
+                                   $.TD({}, fldPassword)
+                                  ),
+                              $.TR({},
+                                   $.TH({}),
+                                   $.TD({}, btnLogin, btnCancel)
+                                  )
+                             )
+                     );
+
+        $area.append(loginPanel);
+    };
+
+    var login = function (userID, password) {
+        $.ajax({
+            type      : "GET",
+            url       : Rakka.baseURI + "checkAuth",
+            beforeSend: function (req) {
+                req.setRequestHeader(
+                    "Authorization",
+                    "Basic " + Rakka.encodeBase64(userID + ":" + password));
+            },
+            success   : function () {
+                document.cookie
+                    = "rakkaLoginInfo="
+                    + Rakka.encodeBase64(userID + ":" + password)
+                    + ";max-age=31536000";
+                updateLoginState();
+                Rakka.restoreScreen();
+            },
+            error     : function (req) {
+                if (req.status == 403) {
+                    alert("Login failed: wrong ID or password");
+                }
+                else {
+                    alert("Error: " + req.status + " " + req.statusText);
+                }
+            }
+        });
+    };
+
+    var logout = function () {
+        document.cookie = "rakkaLoginInfo=;max-age=0";
+        updateLoginState();
+    };
+
+    var currentUserID;
+    var currentPassword;
+
+    var updateLoginState = function () {
+        currentUserID   = null;
+        currentPassword = null;
+        
+        var cookies = document.cookie.split(/;\s*/);
+        $.each(cookies, function () {
+            var m = this.match(/^([^=]*)=(.*)$/);
+            if (m) {
+                var key   = m[1];
+                var value = m[2];
+
+                if (key == "rakkaLoginInfo") {
+                    m = Rakka.decodeBase64(value).match(/^([^:]*):(.*)$/);
+                    if (m) {
+                        currentUserID   = m[1];
+                        currentPassword = m[2];
+                    }
+                }
+            }
+        });
+
+        if (currentUserID != null) {
+            /* ログイン中 */
+            $("input.loginButton")
+                .val("Logout [" + currentUserID + "]")
+                .unbind("click")
+                .click(function () {
+                    logout();
+                });
+        }
+        else {
+            /* ログインしてゐない */
+            $("input.loginButton")
+                .val("Login")
+                .unbind("click")
+                .click(Rakka.showLoginPanel);
+        }
+    };
+
+    $(document).ready(function () {
+        updateLoginState();
+    });
+
+})();