>>>
formatter
>>>
- writeDocumentToString [ (a_indent, v_1) ]
+ writeDocumentToString [ (a_indent , v_1 )
+ , (a_output_encoding, utf8)
+ , (a_no_xml_pi , v_0 ) ]
)
- output $ UTF8.encodeString resultStr
+ output resultStr
outputXmlPage' :: XmlTree -> IOSArrow XmlTree XmlTree -> Resource ()
>>>
constA tree
>>>
- writeDocumentToString [ (a_indent, v_1) ]
+ writeDocumentToString [ (a_indent , v_1 )
+ , (a_output_encoding, utf8)
+ , (a_no_xml_pi , v_0 ) ]
)
- output $ UTF8.encodeString xmlStr
+ output xmlStr
getUserID :: Environment -> Resource (Maybe String)
>>>
xmlizePage
>>>
- writeDocumentToString [ (a_indent, v_1) ]
+ writeDocumentToString [ (a_indent , v_1 )
+ , (a_output_encoding, utf8)
+ , (a_no_xml_pi , v_0 ) ]
)
- output $ UTF8.encodeString resultStr
+ output resultStr
_ -> do BaseURI baseURI <- getSysConf (envSysConf env)
let uri = mkPageFragmentURI
)
where
-import qualified Codec.Binary.UTF8.String as UTF8
import Control.Arrow
import Control.Arrow.ArrowIO
import Control.Arrow.ArrowList
>>>
render env
>>>
- writeDocumentToString [ (a_indent, v_1) ]
+ writeDocumentToString [ (a_indent , v_1)
+ , (a_output_encoding, utf8)
+ , (a_no_xml_pi , v_0) ]
)
- output $ UTF8.encodeString xmlStr
+ output xmlStr
render :: (ArrowXml a, ArrowChoice a, ArrowIO a) =>
>>>
mkResponseTree
>>>
- writeDocumentToString [ (a_indent, v_1) ]
+ writeDocumentToString [ (a_indent , v_1 )
+ , (a_output_encoding, utf8)
+ , (a_no_xml_pi , v_0 ) ]
)
- output $ UTF8.encodeString xmlStr
+ output xmlStr
where
mkResponseTree :: ArrowXml a => a b XmlTree
mkResponseTree
-- <input type="button"
-- value="Create new page"
-- onclick="Rakka.newPage()"
--- class="newButton" />
+-- class="newButton controls" />
newPageInterp :: Interpreter
newPageInterp
= InlineCommandInterpreter {
attrs = [ ("type" , "button")
, ("value" , label)
, ("onclick", "Rakka.newPage()")
- , ("class" , "newButton")
+ , ("class" , "newButton controls")
]
in
return (Input attrs)
-- <input type="button"
-- value="Edit"
-- onclick="Rakka.editPage(\"Foo\")"
--- class="editButton" />
+-- class="editButton controls" />
editPageInterp :: Interpreter
editPageInterp
= InlineCommandInterpreter {
attrs = [ ("type" , "button")
, ("value" , label)
, ("onclick", "Rakka.editPage(\"" ++ name ++ "\")")
- , ("class" , "editButton")
+ , ("class" , "editButton controls")
]
in
return (Input attrs)
-- <input type="button"
-- value="Login"
--- class="loginButton" />
+-- class="loginButton controls" />
loginInterp :: Interpreter
loginInterp
= InlineCommandInterpreter {
= \ _ _ ->
let attrs = [ ("type" , "button")
, ("value", "Login")
- , ("class", "loginButton")
+ , ("class", "loginButton controls")
]
in
return (Input attrs)
-- <input type="button"
-- value="Configuration"
--- class="configButton" />
+-- class="configButton controls" />
configurationInterp :: Interpreter
configurationInterp
= InlineCommandInterpreter {
= \ _ _ ->
let attrs = [ ("type" , "button")
, ("value", "Configuration")
- , ("class", "configButton")
+ , ("class", "configButton controls")
]
in
return (Input attrs)
content: "Error: "
}
+/* sidebar mask ***************************************************************/
+.sideBarMask {
+ position: fixed;
+
+ background-color: black;
+ color: white;
+ opacity: 0.7;
+
+ z-index: 1;
+}
+
+.sideBarMask .content {
+ padding: 40px 0;
+}
+
+.sideBarMask .content input[type="button"] {
+ font-size: 120%;
+ font-weight: bold;
+
+ background-color: #f5f5f5;
+ color: #000055;
+
+ border-color: #dddddd;
+ border-width: 2px;
+ border-style: solid;
+
+ border-radius: 10px;
+ -moz-border-radius: 10px;
+}
+
/* waiting message ************************************************************/
.waitingMessageBoard {
position: fixed;
left: 0;
top: 0;
- width: 100%;
- height: 100%;
+ right: 0;
+ bottom: 0;
background-color: black;
color: white;
content: "Error: "
}
+/* sidebar mask ***************************************************************/
+.sideBarMask {
+ position: fixed;
+
+ background-color: black;
+ color: white;
+ opacity: 0.7;
+
+ z-index: 1;
+}
+
+.sideBarMask .content {
+ padding: 40px 0;
+}
+
+.sideBarMask .content input[type="button"] {
+ font-size: 120%;
+ font-weight: bold;
+}
+
/* waiting message ************************************************************/
.waitingMessageBoard {
position: fixed;
left: 0;
top: 0;
- width: 100%;
- height: 100%;
+ right: 0;
+ bottom: 0;
background-color: white;
color: black;
/* Namespace Rakka */
var Rakka = {};
+/* These are constants that may be overwritten by HTML itself. */
Rakka.baseURI = null;
Rakka.isLocked = false;
Rakka.isGlobalLocked = false;
Rakka.isSpecialPage = false;
+/* Common regular expressions */
Rakka.rePageName = /^[^ a-z.|#\[\]][^ .|#\[\]]*$/;
return obj;
})();
var source
- = $page.attr("redirect") != null ? $page.attr("redirect")
- : $page.attr("isBinary") != null ? Rakka.decodeBase64($page.find("binaryData").text())
- : $page.find("textData").text()
+ = $page.attr("redirect") != null ? $page.attr("redirect")
+ : $page.attr("isBinary") == "yes" ? Rakka.decodeBase64($page.find("binaryData").text())
+ : $page.find("textData").text()
;
var summary = $page.find("summary").text();
}
});
- var btnCancel
- = $.INPUT({type: "button", value: "Cancel editing"});
-
- $(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) {
$(trPageLang).show();
trContent,
$.TR({},
$.TH({}),
- $.TD({}, btnPreview, btnSubmit, btnDelete, btnCancel)
+ $.TD({}, btnPreview, btnSubmit, btnDelete)
)
)
);
var cached_rawHash;
var cached_map;
- Rakka.getRawHash = function () {
- // Don't use window.location.hash as it isn't portable.
- var r = window.location.hash;
+ /*
+ var re_key = /^[^:|]+$/;
+ var re_value = /^[^|]*$/;
+ */
+
+ var getRawHash = function () {
+ /* Don't use window.location.hash as it isn't portable due to
+ * an ambiguous specification.
+ */
+ var r = window.location.href;
var i = r.indexOf("#");
return (i >= 0
? r.substr(i + 1)
: "");
};
- Rakka.getHashedParamMap = function () {
- var raw = Rakka.getRawHash();
+ /*
+ var setRawHash = function (hash) {
+ var r = window.location.href;
+ var i = r.indexOf("#");
+ var b = (i >= 0
+ ? r.substr(0, i)
+ : r);
+ window.location.href = b + "#" + hash;
+ };
+ */
+
+ var getHashedParamMap = function () {
+ var raw = getRawHash();
if (cached_rawHash != raw) {
var src = decodeURIComponent(raw);
cached_map = {};
$.each(src.split("|"), function () {
// tuple ::= key ':' value
- // | key (value is empty)
+ // | key (value is the same as key)
var i = this.indexOf(":");
if (i >= 0) {
- cached_map[this.substr(0, i)] = this.substr(i + 1);
+ var key = this.substr(0, i);
+ var val = this.substr(i + 1);
+ cached_map[key] = val;
}
else {
- cached_map[this.substr(0, i)] = "";
+ var key = this;
+ cached_map[key] = key;
}
});
};
Rakka.getHashedParam = function (key) {
- return Rakka.getHashedParamMap()[key];
+ return getHashedParamMap()[key];
+ };
+
+ /*
+ var setHashedParamMap = function (map) {
+ var tuples = "";
+
+ $.each(map, function(key, val) {
+ var tuple = (key == val
+ ? key
+ : key + ":" + val);
+
+ tuples = (tuples == ""
+ ? tuple
+ : tuples + "|" + tuple);
+ });
+
+ cached_map = map;
+ cached_raw = encodeURIComponent(tuples);
+
+ setRawHash(cached_raw);
};
- Rakka.setHashedParamMap = function (map) {
- //////////
+ Rakka.setHashedParam = function (key, value) {
+ var diff = {};
+ diff[key] = value;
+ Rakka.setHashedParams(diff);
+ };
+
+ Rakka.setHashedParams = function (diff) {
+ var orig = getHashedParamMap();
+ var next = {};
+
+ // Copy 'orig' to 'next'.
+ $.each(orig, function (key, val) {
+ next[key] = val;
+ });
+
+ // Overwrite the content of 'next' with 'diff'.
+ $.each(diff, function (key, val) {
+
+ if (!key.match(re_key)) {
+ throw new Error("Invalid key: " + key);
+ }
+ if (!val.match(re_value)) {
+ throw new Error("Invalid value: " + val);
+ }
+
+ if (diff[key] == null) {
+ delete next[key];
+ }
+ else {
+ next[key] = val;
+ }
+ });
+
+ setHashedParamMap(next);
};
+ */
});
\ No newline at end of file
(function () {
-
+
var switchedArea = null;
Rakka.switchScreen = function () {
if (switchedArea == null) {
switchedArea = $.DIV({});
-
+
$("div.sideBar div.outline").hide();
$("p.redirection").hide();
.hide()
.end()
.append(switchedArea);
+
+ $("body").append(
+ $.DIV({className: "left sideBarMask"}));
+
+ var btnClose
+ = $.INPUT({type : "button",
+ className: "closeButton",
+ value : "Close"});
+ $("body").append(
+ $.DIV({className: "right sideBarMask"},
+ $.DIV({className: "content"},
+ btnClose)));
+
+ $(btnClose).click(function () {
+ Rakka.restoreScreen();
+ });
}
else {
$(switchedArea).empty();
}
-
+
return $(switchedArea);
};
$(switchedArea).remove();
switchedArea = null;
+ $("div.sideBarMask").remove();
+
$("div.body").children().show();
}
return null;
waitingMessageBoard
= $.P({className: "waitingMessageBoard"},
$.P({}, msg));
-
+
$("body").append(waitingMessageBoard);
};
waitingMessageBoard = null;
}
};
-
+
})();
var lines = src.split(/\n/);
$.each(lines, function () {
- var m = this.match(/^(\S+)\s+(\S+)$/);
+ var m = this.match(/^(\S+)\s+(\S+)$/);
- map[ m[1] ] = m[2];
- });
+ if (m) {
+ map[ m[1] ] = m[2];
+ }
+ });
return map;
};
};
var appendConfigPanel = function ($area) {
- var conf = Rakka.getSystemConfig();
$area.append($.H1({}, "Configuration"));
var fldSiteName
- = $.INPUT({type: "text", value: conf.siteName});
+ = $.INPUT({type: "text"});
var fldBaseURI
- = $.INPUT({type: "text", value: conf.baseURI});
+ = $.INPUT({type: "text"});
var fldDefaultPage
- = $.INPUT({type: "text", value: conf.defaultPage});
+ = $.INPUT({type: "text"});
var fldStyleSheet
- = $.INPUT({type: "text", value: conf.styleSheet});
+ = $.INPUT({type: "text"});
var fldLanguages
- = $.TEXTAREA({value: encoder_of.languages(conf.languages)});
+ = $.TEXTAREA({});
var chkGlobalLock
- = $.INPUT({type: "checkbox", checked: conf.globalLock});
+ = $.INPUT({type: "checkbox"});
var btnSave
- = $.INPUT({type: "button", value: "Save changes", disabled: "disabled"});
+ = $.INPUT({type: "button", value: "Save changes"});
+
+ var btnRevert
+ = $.INPUT({type: "button", value: "Revert changes"});
+
+ var makeClean = function () {
+ $(btnSave).attr({disabled: "disabled"});
+ $(btnRevert).attr({disabled: "disabled"});
+ };
+
+ var updateConfig = function () {
+ var conf = Rakka.getSystemConfig();
+
+ fldSiteName.value = conf.siteName;
+ fldBaseURI.value = conf.baseURI;
+ fldDefaultPage.value = conf.defaultPage;
+ fldStyleSheet.value = conf.styleSheet;
+ fldLanguages.value = encoder_of.languages(conf.languages);
+ chkGlobalLock.checked = conf.globalLock;
+
+ makeClean();
+ };
+ updateConfig();
+
+ var validate = function () {
+ var isValid = (function () {
+ if (!isValidBaseURI(fldBaseURI.value)) {
+ return false;
+ }
+
+ if (fldDefaultPage.value.match(Rakka.rePageName) == null) {
+ return false;
+ }
+
+ if (fldStyleSheet.value.match(Rakka.rePageName) == null) {
+ return false;
+ }
+
+ if (!isValidMap(fldLanguages.value)) {
+ return false;
+ }
+
+ return true;
+ })();
+
+ $(btnSave).attr({disabled: (isValid ? "" : "disabled")});
+ };
+
+ var makeDirty = function () {
+ $(btnRevert).attr({disabled: ""});
+ validate();
+ };
$(btnSave).click(function () {
var NS = "http://cielonegro.org/schema/Rakka/Config/1.0";
success : function () {
cachedConf = null;
Rakka.hideWaitingMessage();
- Rakka.restoreScreen();
+ makeClean();
},
error : function (req) {
Rakka.hideWaitingMessage();
+ // FIXME: better error handling
var $area = Rakka.switchScreen();
$area.text("Error: " + req.status + " " + req.statusText);
}
});
});
- var btnRevert
- = $.INPUT({type: "button", value: "Revert changes", disabled: "disabled"});
-
$(btnRevert).click(function () {
if (window.confirm("Do you really want to discard changes?")) {
- // FIXME: implement this
+ updateConfig();
}
});
$.TH({}),
$.TD({}, btnSave, btnRevert))));
- var validate = function () {
- var isValid = (function () {
- if (!isValidBaseURI(fldBaseURI.value)) {
- return false;
- }
-
- if (fldDefaultPage.value.match(Rakka.rePageName) == null) {
- return false;
- }
-
- if (fldStyleSheet.value.match(Rakka.rePageName) == null) {
- return false;
- }
-
- if (!isValidMap(fldLanguages.value)) {
- return false;
- }
-
- return true;
- })();
-
- $(btnSave).attr({disabled: (isValid ? "" : "disabled")});
- };
-
- var isDirty = null;
- var makeDirty = function () {
- if (!isDirty) {
- $(btnRevert).attr({disabled: ""});
- isDirty = true;
- }
- validate();
- };
-
$(fldSiteName)
.add(fldBaseURI)
.add(fldDefaultPage)