Added: incubator/ivy/ivyde/trunk/doc/xooki/xooki.js
URL: 
http://svn.apache.org/viewvc/incubator/ivy/ivyde/trunk/doc/xooki/xooki.js?view=auto&rev=501128
==============================================================================
--- incubator/ivy/ivyde/trunk/doc/xooki/xooki.js (added)
+++ incubator/ivy/ivyde/trunk/doc/xooki/xooki.js Mon Jan 29 09:50:00 2007
@@ -0,0 +1,901 @@
+/*
+       Copyright (c) 2006-2007, The Xooki project
+       http://xooki.sourceforge.net/
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+       
+       Some code is largely inspired by code found in the dojo toolkit, 
+       see http://dojotoolkit.org/ for more information.
+*/
+var xooki = {};
+xooki.console = ""; // used for debugging purpose only, and only when the 
debug div is not yet created
+
+function t(msg) {
+    // returns the internationalized version of the message, or the message if 
no translation is available
+    // t stands for translate
+// FIXME
+//    if (typeof xooki.c == "object" 
+//        && typeof xooki.c.messages == "object" 
+//        && typeof xooki.c.messages[msg] == "string") {
+//        msg = xooki.c.messages[msg];
+//    }
+    var arr = [];
+    for (var i=1; i<arguments.length; i++) {
+        arr.push(arguments[i]);
+    }
+    return xooki.string.substituteParams(msg, arr);
+}
+
+function css(clss) {
+    // returns the css class or id configured, or the given class (or id) if 
no one is configured
+    if (typeof xooki.c.css[clss] != "undefined") {
+        return xooki.c.css[clss];
+    } else {
+        return clss;
+    } 
+}
+function u(path) {
+  // convert a path relative to the root to a full URL
+  // u stands for Url
+  return xooki.c.root + path;
+}
+function cu(urlCfgProp) {
+  // get a path from a configuration path and convert it to an URL
+  // cu stands for Configured Url
+  if (typeof xooki.c.path[urlCfgProp] == "undefined") {
+    xooki.warn(t("path not configured in xooki: '${0}'", urlCfgProp));
+    return "";
+  }
+  return u(xooki.c.path[urlCfgProp]);
+}
+function pu(id) {
+  // returns the url of the page identified by id
+  // pu stands for Page Url
+  return u(id+".html");
+}
+xooki.p = function(path) {
+  // get a xooki full path from a xooki relative path
+  // p stands for path
+  return xooki.c.path.install+"/"+path;
+}
+xooki.u = function(path) {
+  // convert a path relative to the xooki installation dir to a full URL
+  return u(xooki.p(path));
+}
+xooki.cu = function(urlCfgProp) {
+  // get a xooki path from a configuration path and convert it to an URL
+  if (typeof xooki.c.path[urlCfgProp] == "undefined") {
+    xooki.warn(t("path not configured in xooki: '${0}'", urlCfgProp));
+  }
+  return xooki.u(xooki.c.path[urlCfgProp]);
+}
+
+xooki.util = {
+    isArray: function(it) {
+       return (it && it instanceof Array || typeof it == "array"); // Boolean
+    },
+    mix: function(src, into, override) {
+        if (typeof override == "undefined") {
+            override = true;
+        }
+        for (var k in src) {
+            if (typeof src[k] == "object" && !xooki.util.isArray(src[k])) {
+                if (override || typeof into[k] == "object" || typeof into[k] 
== "undefined") {
+                    if (typeof into[k] != "object") {
+                        into[k] = {};
+                    }
+                    xooki.util.mix(src[k], into[k], override);
+                }
+            } else if (override || typeof into[k] == "undefined") {
+                into[k] = src[k];
+            }
+        }
+    }
+}
+
+xooki.url = {
+        newXmlHttpRequest: function() {
+        // we first try to use ActiveX, because IE7 has a direct support for 
XmlHttpRequest object, 
+        // but which doesn't work with file urls
+               if(window.ActiveXObject)
+               {
+                       try { req = new ActiveXObject("Msxml2.XMLHTTP");
+                       } catch(e) {
+                               try { req = new 
ActiveXObject("Microsoft.XMLHTTP");
+                               } catch(e) { req = false; }
+                       }
+               }
+               else if(window.XMLHttpRequest) {
+                       try { req = new XMLHttpRequest();
+                       } catch(e) { req = false; }
+               }
+        
+               return req;     
+        },
+                
+        loadURL: function( url ) {
+               req = this.newXmlHttpRequest();
+               if(req) {
+                       try {
+                               req.open("GET", url, false);
+                               req.send("");
+               
+                               return req.responseText;
+                       } catch (e) {
+                               xooki.error(e, t("problem while loading URL 
${0}", url));
+                }              
+               }
+               return null;
+        },
+        
+        asyncLoadURL: function( url, callback, obj ) {
+               var req = this.newXmlHttpRequest();
+               if(req) {
+                       try {
+                               req.open("GET", url, true);
+                                   req.onreadystatechange=function() {
+                                       if (req.readyState == 4) {
+                                          if (req.status == 200) {
+                                             callback(req.responseText, obj);
+                                          }
+                                       }
+                                    };                         
+                                    req.send("");
+                       } catch (e) {
+                               xooki.error(e, t("problem while loading URL 
${0}", url));
+                }              
+               }
+        },
+
+        include: function(script_filename) {
+            document.write('<' + 'script');
+            document.write(' language="javascript"');
+            document.write(' type="text/javascript"');
+            document.write(' src="' + script_filename + '">');
+            document.write('</' + 'script' + '>');
+        },
+
+        action: function(action) {        
+            // returns the url for an action on the same page
+            loc = window.location.toString();
+            if (loc.indexOf("#") != -1) {
+                loc = loc.substring(0, loc.indexOf("#"));
+            }
+            return loc+"?action="+action;
+        }
+
+    };
+    
+xooki.string = {
+
+    substituteParams: function(/*string*/template, /* object - optional or ... 
*/hash) {
+    // borrowed from dojo
+    // summary:
+    // Performs parameterized substitutions on a string. Throws an exception 
if any parameter is unmatched.
+    //
+    // description:
+    // For example,
+    //         dojo.string.substituteParams("File '${0}' is not found in 
directory '${1}'.","foo.html","/temp");
+    // returns
+    //         "File 'foo.html' is not found in directory '/temp'."
+    //
+    // template: the original string template with ${values} to be replaced
+    // hash: name/value pairs (type object) to provide substitutions.  
Alternatively, substitutions may be
+    // included as an array
+    
+        var map;
+        if (typeof hash == "object" && hash.length) { // array
+            map = {};
+            for (var i in hash) {
+                map[i+""] = hash[i];
+            }
+        } else {
+            map = hash;
+        }
+    
+       return template.replace(/\$\{(\w+)\}/g, function(match, key){
+               if(typeof(map[key]) != "undefined" && map[key] != null){
+                       return map[key];
+               }
+               xooki.warn("Substitution not found: " + key);
+               return key;
+       }); // string
+       },
+       
+       processTemplate: function(/*string*/template, /* object */hash) {
+          if (typeof template.process == "function") {
+              return template.process(hash);
+       } else {
+            return this.substituteParams(template, hash);
+       }
+    },
+
+    exceptionText: function(e, message) {
+       var s = e.description ? e.description : e.toString();
+       return message ? message+":\n"+s : s;
+    },
+    
+    findXmlSection: function(str, element, from) {
+        return this.findSection(str, new 
RegExp('<'+element+'(\\s*\\w+="[\\w\\s]*")*>'), new RegExp('</'+element+'>'), 
from);
+    },
+    
+    find: function(/*string*/str, /*string or regexp*/exp, /*number, 
optional*/from) {
+        // find an expression (string or regexp) in a string, from an optional 
index
+        // the object returned has two properties:
+        // begin: the index in str of the matching find
+        // end: the index in str of the end of the matching find
+        // returns null if no match is found
+        if (typeof from != "number") {
+            from = 0;
+        }
+        if (typeof exp == "string") {
+            var result = {};
+            result.begin = str.indexOf(exp,from);
+            if (result.begin >= 0) {
+                result.end = result.begin + exp.length;
+                return result;
+            }
+        } else {
+            var m;
+            if (from > 0) {
+                // I haven't found any other way to start from the given index
+                m = exp.exec(str.substring(from));
+            } else {
+                m = exp.exec(str);
+            }
+            if (m != null) {                
+                var result = {};
+                result.begin = m.index + from;
+                result.end = result.begin + m[0].length;
+                return result;
+            }
+        }
+        return null;
+    },
+    
+    findSection: function(/*string*/str, /*string or regexp*/open, /*string or 
regexp*/close, /*number, optional*/from) {
+        // finds a section delimited by open and close tokens in the given 
string
+        // the algorithm looks for matching open and close tokens
+        // the returned object has the following properties:
+        //   outerStart: the index in str where the first open token was found
+        //   innerStart: the index in str just after the found open token
+        //   innerEnd: the index in str where the matching close token was 
found
+        //   outerEnd: the index in str just after the matching close token
+        //   children: an array of similar objects if nested sections where 
found
+        // if no section is found (no open token, an open token with no 
matching 
+        // close token, or a close token before an open token), null is 
returned
+        //
+        // for instance if open=='(' and close==')' then the section will find
+        // a section delimited by the first found open parenthesis and the 
matching
+        // close parentethis, taking into account other opening parentethis
+        // examples:
+        // findSection("a(test)b", "(", ")") == {outerStart: 1, innerStart:2, 
innerEnd:6, outerEnd:7, children:[]}
+        // findSection("a(te(s)(t))b", "(", ")") == {outerStart: 1, 
innerStart:2, innerEnd:10, outerEnd:11, 
+        //      children:[
+        //          {outerStart: 4, innerStart:5, innerEnd:6, outerEnd:7, 
children:[]},
+        //          {outerStart: 7, innerStart:8, innerEnd:9, outerEnd:10, 
children:[]}
+        //      ]}
+        
+        var openResult = this.find(str, open, from);        
+        if (openResult == null) {
+            return null;
+        }
+        var closeResult = this.find(str, close, from);        
+        if (closeResult == null || closeResult.begin < openResult.end) {
+            return null;
+        }
+        if (openResult.end <= openResult.begin || closeResult.end <= 
closeResult.begin) {
+            // empty match are not allowed
+            return null;
+        }
+        
+        var children = [];
+        var child = this.findSection(str, open, close, openResult.end);
+        while (child != null) {
+            if (child.outerEnd > closeResult.begin) {
+                closeResult = this.find(str, close, child.outerEnd);        
+                if (closeResult == null) {
+                    // unmatched open token
+                    return null;
+                }
+            }
+            children.push(child);
+            child = this.findSection(str, open, close, child.outerEnd);
+        }
+
+        return {
+            outerStart: openResult.begin,
+            innerStart: openResult.end,
+            innerEnd: closeResult.begin,
+            outerEnd: closeResult.end,
+            children: children
+        };        
+    }
+};
+    
+xooki.json = {
+        evalJson: function (str) {
+            try {
+                return eval("("+str+")");
+            } catch (e) {
+                return null;
+            }
+        },
+        
+        loadURL: function (url) {
+            return this.evalJson(xooki.url.loadURL(url));
+        }
+    };
+
+// Displays an alert of an exception description with optional message
+xooki.warn = function(e, message) {
+    xooki.display(xooki.string.exceptionText(e, message), "#eecccc");
+}
+
+// Displays an alert of an exception description with optional message
+xooki.error = function(e, message) {
+    xooki.display(xooki.string.exceptionText(e, message), "#ffdddd");
+}
+
+xooki.info = function(message) {
+    xooki.display(message, "#ddddff");
+}
+
+xooki.display = function(message, background) {
+    var messages = document.getElementById('xooki-messages');
+    if (messages) {
+        messages.innerHTML = '<table width="100%" border="0"><tr><td 
align="center">'+message+'</td></tr></table>';
+        messages.style.background = background;
+        messages.style.display = "inline";
+    } else {
+        alert(message);
+    }
+}
+
+xooki.debug = function(message) {
+    var console = document.getElementById('xooki-console');
+    if (console) {
+        console.value += message + "\n";
+    } else {
+        xooki.console += message + "\n";
+    }
+}
+
+xooki.debugShowDetail = function (message) {
+    var detail = document.getElementById('xooki-debug-detail');
+    if (detail) {
+        detail.value=message;
+    } else {
+        alert(message);
+    }
+}
+
+
+xooki.html = {
+    hide: function(divid) {
+          document.getElementById(divid).style.display = 'none';
+    },
+
+    show: function (divid) {
+          document.getElementById(divid).style.display = '';
+    } 
+};
+
+xooki.component = {
+    childrenList: function () {
+       if (xooki.page.children.length > 0) {
+               childrenList = '<ul class="'+css('childrenList')+'">';
+               for (var i in xooki.page.children) {
+                       childrenList+='<li><a 
href="'+pu(xooki.page.children[i].id)+'">'+xooki.page.children[i].title+'</a></li>';
+               }
+               childrenList += "</ul>";
+               return childrenList;
+       } else {
+          return "";
+        }
+    },
+    
+    menu: function () {
+       var menu = '<ul id="'+css("treemenu")+'" class="treeview">';
+       menu += (function (page) {
+               var menu = '';
+               for (var i  in page.children) {
+                       menu += '<li id="xooki-'+page.children[i].id+'"><a 
href="'+pu(page.children[i].id)+'" '+(page.children[i].id == 
xooki.page.id?'class="current"':'')+'>'+page.children[i].title+'</a>';
+                       smenu = arguments.callee(page.children[i]);
+                       if (smenu != '') {
+                               menu += '<ul ';
+                               if 
(smenu.indexOf('id="xooki-'+xooki.page.id+'"') != -1 
+                                       || page.children[i].id == 
xooki.page.id) {
+                                       // either a descendant or the node 
processed is the current page node
+                                       // we specify that the menu must be 
opened by default
+                                       menu += 'rel="open"';
+                               }
+                               menu += '>'+smenu+'</ul>';
+                       } 
+                       menu += '</li>';
+               }
+               return menu;
+        })(xooki.toc);
+       menu += '</ul>';
+       return menu;
+    },
+    
+    messages: function () {
+        return '<div id="xooki-messages" 
onclick="xooki.html.hide(\'xooki-messages\')" 
style="zIndex:999;display:none;position:absolute;top:30px;padding:10px;border-style:solid;background:#eeeeee;"></div>';
+    },
+
+    debugPanel: function () {
+        return '<div id="xooki-debug" 
style="display:none;margin-top:15px;padding:10px;border-style:solid;background:#eeeeee;"><strong>Xooki
 Console</strong><br/><textarea cols="100" rows="15" 
id="xooki-console">'+xooki.console+'</textarea><hr/><a 
href="javascript:xooki.debugShowDetail(document.getElementById(\'xooki-body\').innerHTML)">content</a>
 <a href="javascript:xooki.debugShowDetail(xooki.c.body)">xooki body</a> <a 
href="javascript:xooki.debugShowDetail(document.body.innerHTML)">whole body</a> 
<a href="javascript:xooki.action.evaluate()">evaluate</a><br/><textarea 
cols="100" rows="15" id="xooki-debug-detail"></textarea></div>';
+    },
+
+    printerFriendlyLocation: function () {
+        return xooki.url.action("print");
+    },
+
+    printerFriendlyLink: function () {
+        return '<a href="'+this.printerFriendlyLocation()+'">'+t('Printer 
Friendly')+'</a>';
+    }
+};
+
+xooki.render = {};
+xooki.render.printerFriendlyAsyncLoader = function(source, arr) {
+       var root = arr[0];
+       var page = arr[1];
+    if (source == null) {
+        return;
+    }
+       var level = page.meta.level - root.meta.level + 1;
+       
+    // compute printer friendly block
+    var beginIndex = source.indexOf('<textarea id="xooki-source">');
+    beginIndex += '<textarea id="xooki-source">'.length;
+    var endIndex = source.lastIndexOf('</textarea>');
+    source = source.substring(beginIndex, endIndex);
+    
+    var printerFriendly = "<h"+level+">"+page.title+"</h"+level+">";
+    printerFriendly += xooki.input.format.main(source) + "<hr/>";
+    // inject block in page
+    var pf = document.getElementById('xooki-printerFriendly');
+    pf.innerHTML += printerFriendly;    
+    
+    // continue recursive loading
+       var nextPage = xooki.toc.getNextPage(page, root);
+       if (nextPage != null) {
+       xooki.url.asyncLoadURL(pu(nextPage.id), 
xooki.render.printerFriendlyAsyncLoader, [root, nextPage]);
+       }
+};
+xooki.render.printerFriendly = function() {
+    for (var k in xooki.component) {
+        xooki.c[k] = xooki.component[k]();
+    }
+    
+       xooki.c.body = xooki.c.messages
+       + "<div id='xooki-printerFriendly'></div>" // div where printer 
friendly content will be put
+    + xooki.c.debugPanel;
+    
+    document.body.innerHTML = 
xooki.string.processTemplate(xooki.template.body, xooki.c);
+    
+    // start async loading of content
+    xooki.url.asyncLoadURL(pu(xooki.page.id), 
xooki.render.printerFriendlyAsyncLoader, [xooki.page, xooki.page]);
+};
+
+xooki.render.page = function() {
+    // realize all components available
+    for (var k in xooki.component) {
+        xooki.c[k] = xooki.component[k]();
+    }
+    
+    xooki.input.source();
+    
+    if (xooki.c.allowEdit) {
+       xooki.c.body = xooki.c.messages
+            + xooki.c.toolbar
+            + '<div id="xooki-content">' 
+                + '<div id="xooki-body"></div>'
+            + '</div>'
+            + xooki.c.editZone
+            + xooki.c.debugPanel;
+    } else {
+       xooki.c.body = xooki.c.messages
+            + '<div id="xooki-content">' 
+                + '<div id="xooki-body"></div>'
+            + '</div>'
+            + xooki.c.debugPanel;
+    }
+
+    document.body.innerHTML = 
xooki.string.processTemplate(xooki.template.body, xooki.c);
+    
+    xooki.input.applyChanges();
+    
+    // enable dynamic tree menu 
+       ddtreemenu.createTree(css("treemenu"), false);
+};
+
+xooki.render.main = function() {
+    if (xooki.c.action == "print") {
+        // render the printer friendly version of the page
+        this.printerFriendly();
+    } else {
+        // render the page normally
+        this.page();
+    }
+};
+
+xooki.input = {
+    source: function() {
+        if (document.getElementById('xooki-source') != null) {
+            this._source = document.getElementById('xooki-source').value;
+        }
+        return this._source;
+    },
+    processed: function() {
+        return this.format.main(this.source());
+    },
+    
+    format: {
+        getInputFilters: function (inputFormat) {
+            return xooki.c[inputFormat+"InputFormat"];
+        },
+        define: function (inputFormat, filters) {
+            // define a new inputFormat
+            // inputFormat: the new input format name
+            // filters: an array of input filter names
+            xooki.c[inputFormat+"InputFormat"] = filters;
+        },
+        main: function(source) {
+            // formats an input source
+            if (xooki.c.inputFormat && typeof 
this.getInputFilters(xooki.c.inputFormat) != "undefined") {
+                format = xooki.c.inputFormat;
+            } else {
+                format = xooki.c.defaultInputFormat;
+            }
+            filters = this.getInputFilters(format);
+            for (var i in filters) {
+                f = xooki.input.filters[filters[i]];
+                if (typeof f == "function") {
+                       try {
+                       source = f(source); // process filter
+                    } catch (e) {
+                           xooki.error(e, t("error occured while processing 
filter ${0}", filters[i]));
+                    }
+                } else {
+                    xooki.error(t("unknown filter ${0} used in input format 
${1}", filters[i], format));
+                }
+            }
+            return source;
+        }
+    }, 
+    
+    filters: {
+        url: function (input) {
+            // handle urls
+            return input.replace(new 
RegExp("(?:file|http|https|mailto|ftp):[^\\s'\"]+(?:/|\\b)", "g"), function 
(str, offset, s) {
+                var before = s.substring(0,offset);
+                if (before.match(/(href|src)="$/)) {
+                    return str;
+                } else {
+                    return '<a href="'+str+'">'+str+'</a>';
+                }
+            });
+        },
+        
+        shortcuts: function (input) {
+            // handle shortcut links like this:
+            //    [[svn:build.xml]] => <a 
href="https://xooki.svn.sourceforge.net/svnroot/xooki/trunk/build.xml";>build.xml</a>
+            //    [[svn:test/example.js a good example]] => <a 
href="https://xooki.svn.sourceforge.net/svnroot/xooki/trunk/test/example.js";>a 
good example</a>
+            // needs to be configured in xooki config like this
+            //      xooki.c.shortcuts.<any shortcut>.url = base url of the 
shortcut. 
+            //      ex: xooki.c.shortcuts.svn.url = 
https://xooki.svn.sourceforge.net/svnroot/xooki/trunk/
+            return input.replace(new RegExp("\\[\\[([^:]+):([^\\]]+)\\]\\]", 
"g"), function (str, prefix, code, offset, s) {
+               if (typeof xooki.c.shortcuts[prefix] == "undefined") {
+                       return str;
+               }
+                var index = code.indexOf(' ');
+                var path = index>0?code.substring(0,index):code;
+                
+                var title = index>0?code.substring(index+1):path;
+                var pre = typeof xooki.c.shortcuts[prefix].pre == 
"undefined"?'':xooki.c.shortcuts[prefix].pre;
+                var post = typeof xooki.c.shortcuts[prefix].post == 
"undefined"?'':xooki.c.shortcuts[prefix].post;
+                return '<a href="'+pre+path+post+'">'+title+'</a>';
+            });
+        },
+        
+        xookiLinks: function (input) {
+            // handle xooki links like this:
+            //    [[page/id]]
+            //    [[page/id My Title]]
+            return input.replace(new RegExp("\\[\\[([^\\]]+)\\]\\]", "g"), 
function (str, code, offset, s) {
+                var index = code.indexOf(' ');
+                var id = index>0?code.substring(0,index):code;
+                
+                var title;
+                var url = pu(id);
+                if (index>0) {
+                       title = code.substring(index+1);
+                       } else if (typeof xooki.toc.pages[id] != "undefined") {
+                           title = xooki.toc.pages[id].title;
+                       } else {
+                               title = code;
+                               url = u(code);
+                       }
+                return '<a href="'+url+'">'+title+'</a>';
+            });
+        },
+        
+        wikiMarkup: function (input) { 
+            // handle bold
+            input = input.replace(new RegExp("\\*([^\n]+)\\*", "g"), 
"<b>$1</b>");
+            
+            // handle italic
+            input = input.replace(new RegExp("\\_([^\n]+)\\_", "g"), 
"<em>$1</em>");
+            
+            return input;
+        },
+        
+        jira: function (input) { 
+            // auto replace jira issue ids (like IVY-12) by a link to the issue
+            // needs to be configured in xooki config like this
+            //      xooki.c.jira.ids = an array of jira projects ids (ex: 
["IVY", "ANT"])
+            //      xooki.c.jira.url = the url of the jira server (ex: 
"http://issues.apache.org/jira";)
+            if (typeof xooki.c.jira != "object") {
+                return input;
+            }
+            input = input.replace(new 
RegExp("(("+xooki.c.jira.ids.join("|")+")-\\d+)([^\"\\d])", "g"), '<a 
href="'+xooki.c.jira.url+'/browse/$1">$1</a>$3');
+            
+            return input;
+        },
+        
+        code: function (input) {
+            codeSection = xooki.string.findXmlSection(input, "code");
+            from = 0;
+            while (codeSection != null) {
+                processedSection = "<pre>" 
+                    + input.substring(codeSection.innerStart, 
codeSection.innerEnd).replace(/</g, "&lt;").replace(/>/g, "&gt;") // 
.replace(/\n/g, "<br/>")
+                    + "</pre>";
+                input = input.substring(0, codeSection.outerStart)
+                    + processedSection
+                    + input.substring(codeSection.outerEnd);
+                from = codeSection.outerStart + processedSection.length;
+    
+                codeSection = xooki.string.findXmlSection(input, "code", from);
+            }
+            return input;
+        },
+        
+        lineBreak: function (input) {
+            return input.replace(new RegExp("\r?\n", "g"), function (str, 
offset, s) {
+                var before = s.substring(0,offset);
+                var after = s.substring(offset+str.length);
+                if 
(after.match(/^<\/?(ul|table|li|pre|div)(\s*\w+="[^"]+")*\s*>/i) || 
(before.match(/<\/?\w+(\s*\w+="[^"]+")*\s*\/?>\s*$/i) && 
!before.match(/<\/?(a|b|strong|em|i|big|br 
class="xooki-br")(\s*\w+="[^"]+")*\s*\/?>\s*$/i))) { 
+                    return '\n';
+                } else {
+                    return '<br class="xooki-br"/>'; // the class is not 
really necessary but allow to distinguish generated br from input one
+                }
+            });
+        }
+    },
+    
+    
+    applyChanges: function() {
+       document.getElementById('xooki-body').innerHTML = 
xooki.input.processed();
+    }
+};
+
+
+xooki.postProcess = function() {
+       xooki.render.main();
+       window.onkeypress = keyCtrl;
+};
+
+// init xooki engine
+(function() {
+    
////////////////////////////////////////////////////////////////////////////
+    ////////////////// config init
+    
////////////////////////////////////////////////////////////////////////////
+    initConfigProperty = function(prop, value, defaultValue) {
+        if (typeof this[prop] == "undefined") {
+            if (typeof value == "undefined") {
+                this[prop] = defaultValue;
+            } else if (typeof value == "function") {
+                this[prop] = value();
+            } else {
+                this[prop] = value;
+            }
+        }
+    };
+    xooki.config = {};
+    xooki.c = xooki.config;
+    if (typeof xookiConfig != "undefined") {xooki.util.mix(xookiConfig, 
xooki.config);}
+    xooki.c.initProperty = initConfigProperty;
+    xooki.c.initProperty("level", 0);
+    xooki.c.initProperty("root", function() {
+       root = window.location.toString();
+       // remove trailing parts of the URL to go the root depending on level
+       for (var i=0; i < xooki.c.level + 1; i++) {
+               root = root.substring(0, root.lastIndexOf('/'));
+       }
+       return root + '/';
+    });
+
+    var globalConfig = xooki.json.loadURL(u("config.json"));
+    if (globalConfig != null) {
+        xooki.util.mix(globalConfig, xooki.config, false);
+    }
+
+    xooki.c.initProperty("defaultInputFormat", "xooki");
+    xooki.c.initProperty("xookiInputFormat", ["xooki"]);
+    xooki.c.initProperty("allowEdit", document.location.toString().substr(0,5) 
== "file:");
+    
+    xooki.input.format.define("xooki", ["code", "shortcuts", "url", 
"xookiLinks", "jira", "lineBreak"]);
+    
+    xooki.c.path = (typeof xooki.c.path != "undefined")?xooki.c.path:{};
+    xooki.c.path.initProperty = initConfigProperty;
+    xooki.c.path.initProperty("install", "xooki");
+    xooki.c.path.initProperty("messages", xooki.p("messages.json"));
+    xooki.c.path.initProperty("template", "template.html");
+    xooki.c.path.initProperty("printTemplate", "printTemplate.html");
+    xooki.c.path.initProperty("toc", "toc.json");
+    xooki.c.path.initProperty("blankPageTpl", xooki.p("blankPageTpl.html"));
+    
+    
+    xooki.c.css = (typeof xooki.c.css != "undefined")?xooki.c.css:{};    
+        
+    xooki.c.messages = xooki.json.loadURL(cu("messages")); 
+    xooki.c.browser = {
+        NS: (window.Event) ? 1 : 0
+    };
+    
+    // action
+    // TODO: better handle action extraction
+    xooki.c.action = window.location.search == 
'?action=print'?'print':xooki.c.action;
+    
+    
////////////////////////////////////////////////////////////////////////////
+    ////////////////// TOC init
+    
////////////////////////////////////////////////////////////////////////////
+    xooki.toc = xooki.json.loadURL(cu("toc"));
+    xooki.toc.pages = {}; // to store a by id map of pages objects
+
+       // populate meta data
+       (function(page, parent, index, level) {
+        xooki.toc.pages[page.id] = page;
+        
+        page.meta = {
+            parent: parent,
+            index: index,
+            level: level
+        };
+        if (typeof page.children == 'undefined') {
+            page.children = [];
+        } else {
+            for (var i=0; i<page.children.length; i++) {
+                arguments.callee(page.children[i], page, i, level+1); // 
recurse
+            }
+        }
+    })(xooki.toc, null, 0, -1);
+    
+    xooki.toc.getNextPage = function(page, root) {
+        if (page.children.length > 0) {
+               return page.children[0];
+        } else if (page.meta.parent != null) {
+               var cur = page;
+               var next = xooki.toc.getNextSibling(cur);
+               while (next == null) {
+                       cur = cur.meta.parent;
+                       if (cur == null || cur == root) {
+                               return null;
+                       }
+                       next = xooki.toc.getNextSibling(cur);
+               }
+                       return next;
+        } else {
+               return null;
+        }
+    };
+    xooki.toc.getNextSibling = function(page) {
+       if (page.meta.parent == null) {
+               return null;
+       }
+               if (page.meta.parent.children.length > page.meta.index) {
+                       return page.meta.parent.children[page.meta.index+1];
+               } else {
+                       return null;
+               }
+    };
+       
+       var match = new 
RegExp("^.*\\/((?:.*\\/){"+xooki.config.level+"}[^\\/]*)(?:\\.\\w+)(?:\\?.+)?$",
 "g").exec(window.location.toString());
+       var curPageId;
+       if (match == null || match[1] == '') {
+               curPageId = "index";
+       } else {
+               curPageId = match[1];
+       }
+       xooki.page = xooki.toc.pages[curPageId];
+
+       if (xooki.page == null) {
+               xooki.warn(t('page id not found in TOC: ${0}',curPageId));
+       } else {
+               if (typeof xooki.config.title == 'undefined') {
+                       xooki.config.title = xooki.page.title;
+               }               
+       }
+       xooki.config.page = xooki.page;
+       
+    
////////////////////////////////////////////////////////////////////////////
+    ////////////////// main template loading + head output
+    
////////////////////////////////////////////////////////////////////////////
+       xooki.template = {};
+    xooki.template.source = xooki.url.loadURL(xooki.c.action == 
"print"?cu("printTemplate"):cu("template"));
+       if(xooki.template.source != null) {
+               xooki.template.head = 
xooki.template.source.match(/<head>([^§]*)<\/head>/im)[1];
+               
+        var head = xooki.string.processTemplate(xooki.template.head, 
xooki.config);
+               head = head.replace(/href="([^\\$:"]+)"/g, 
'href="'+xooki.c.root+'$1"');
+               document.write(head);
+
+               var body = 
xooki.template.source.match(/<body>([^§]*)<\/body>/im)[1];
+               body = body.replace(/href="([^\\$:"]+)"/g, 
'href="'+xooki.c.root+'$1"');
+               xooki.template.body = body.replace(/src="([^\\$:"]+)"/g, 
'src="'+xooki.c.root+'$1"');           
+       }
+       
+
+    
////////////////////////////////////////////////////////////////////////////
+    ////////////////// includes
+    
////////////////////////////////////////////////////////////////////////////
+    xooki.url.include(xooki.u("tree/simpletreemenu.js"));
+    if (xooki.c.useTrimPath) {
+        xooki.url.include(xooki.u("trimpath/template.js"));
+    }
+    if (xooki.c.allowEdit) {
+        xooki.url.include(xooki.u("xookiEdit.js"));
+    }
+
+    for (var k in xooki.c) {
+        if (typeof xooki.c[k] == "string" || typeof xooki.c[k] == "number" || 
typeof xooki.c[k] == "boolean") {
+            xooki.debug(k+": "+xooki.c[k]);
+        }
+    }
+})();
+
+xooki.action = {}
+xooki.action.toggleDebug = function() {
+    if (xooki.c.debug) {
+       if (document.getElementById('xooki-debug').style.display == 'none') {
+               xooki.html.show('xooki-debug');
+       } else {
+               xooki.html.hide('xooki-debug');
+       }
+       }
+}
+xooki.action.evaluate = function () {
+    var exp = prompt("Please enter javascript expression to evaluate");
+    xooki.debugShowDetail(eval(exp));
+}
+
+// TODO, review use registration
+function keyCtrl(evt) {
+       var code = xooki.c.browser.NS ? evt.which : event.keyCode;
+       var ctrl = xooki.c.browser.NS ? evt.ctrlKey : event.ctrlKey;
+       var key = String.fromCharCode(code);
+       if (xooki.c.debug && ctrl && "d" == key) {
+               xooki.action.toggleDebug();
+               return false;
+       }
+       if (xooki.c.allowEdit && ctrl && "s" == key) {
+               xooki.action.saveChanges();
+               return false;
+       }
+       if (xooki.c.allowEdit && ctrl && "e" == key) {
+               xooki.action.toggleEdit();
+               return false;
+       }
+}

Added: incubator/ivy/ivyde/trunk/doc/xooki/xookiEdit.js
URL: 
http://svn.apache.org/viewvc/incubator/ivy/ivyde/trunk/doc/xooki/xookiEdit.js?view=auto&rev=501128
==============================================================================
--- incubator/ivy/ivyde/trunk/doc/xooki/xookiEdit.js (added)
+++ incubator/ivy/ivyde/trunk/doc/xooki/xookiEdit.js Mon Jan 29 09:50:00 2007
@@ -0,0 +1,379 @@
+/*
+       Copyright (c) 2006-2007, The Xooki project
+       http://xooki.sourceforge.net/
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+       
+       Some code is largely inspired by code found in the dojo toolkit, 
+       see http://dojotoolkit.org/ for more information.
+*/
+
+// this file is included only in edit mode
+
+xooki.url.include(xooki.u("tiddly/util.js"));
+
+if (typeof xooki.io == "undefined") {
+    xooki.io = {};
+}
+
+xooki.io.removeFile = function (filePath) {
+       var r = null;
+       if((r == null) || (r == false))
+               r = xooki.io.mozillaRemoveFile(filePath);
+       if((r == null) || (r == false))
+               r = xooki.io.ieRemoveFile(filePath);
+       return(r);
+}
+
+xooki.io.mozillaRemoveFile = function(filePath) {
+       if(window.Components)
+               try
+                       {
+                       
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+                       var file = 
Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
+                       file.initWithPath(filePath);
+                       if (!file.exists())
+                               return null;
+                       file.remove(false);
+                       return(true);
+                       }
+               catch(e)
+                       {
+                       return(false);
+                       }
+       return(null);
+}
+
+xooki.io.ieRemoveFile = function(filePath) {
+       try
+               {
+               var fso = new ActiveXObject("Scripting.FileSystemObject");
+               }
+       catch(e)
+               {
+               //alert("Exception while attempting to save\n\n" + 
e.toString());
+               return(null);
+               }
+       fso.DeleteFile(filePath, false);
+       return(true);
+}
+
+
+if (typeof xooki.string == "undefined") {
+    xooki.string = {};
+}
+
+xooki.string.escapeString = function(str) {
+// borrowed from dojo
+//summary:
+//     Adds escape sequences for non-visual characters, double quote and 
backslash
+//     and surrounds with double quotes to form a valid string literal.
+       return ('"' + str.replace(/(["\\])/g, '\\$1') + '"'
+               ).replace(/[\f]/g, "\\f"
+               ).replace(/[\b]/g, "\\b"
+               ).replace(/[\n]/g, "\\n"
+               ).replace(/[\t]/g, "\\t"
+               ).replace(/[\r]/g, "\\r"); // string
+};
+
+if (typeof xooki.json == "undefined") {
+    xooki.json = {};
+}
+
+xooki.json.serialize = function (o, indent) {
+        // borrowed and adapted from dojo
+       // summary:
+       //              Create a JSON serialization of the object.
+       // return:
+       //              a String representing the serialized version of the 
passed object
+       if (!indent) {
+          indent = "";
+        }
+               var objtype = typeof(o);
+               if(objtype == "undefined"){
+                       return "undefined";
+               }else if((objtype == "number")||(objtype == "boolean")){
+                       return o + "";
+               }else if(o === null){
+                       return "null";
+               }
+               if (objtype == "string") { return xooki.string.escapeString(o); 
}
+               if(objtype == "function"){
+                   // do not encode functions
+                       return null;
+               }
+               // recurse
+               var me = arguments.callee;
+               // short-circuit for objects that support "json" serialization
+               // if they return "self" then just pass-through...
+               var newObj;
+               // array
+               if(objtype != "function" && typeof(o.length) == "number"){
+                       var res = [];
+                       for(var i = 0; i < o.length; i++){
+                               var val = me(o[i], indent+"  ");
+                               
+                               if(typeof(val) != "string"){
+                                       val = "undefined";
+                               }
+                               res.push(val);
+                       }
+                       return " [\n" + res.join(",\n") + "\n"+indent+"]\n";
+               }
+               // generic object code path
+               res = [];
+               for (var k in o){
+                   if ("meta" == k) {
+                     continue;
+            }
+                       var useKey;
+                       if (typeof(k) == "number"){
+                               useKey = '"' + k + '"';
+                       }else if (typeof(k) == "string"){
+                               useKey = xooki.string.escapeString(k);
+                       }else{
+                               // skip non-string or number keys
+                               continue;
+                       }
+                       val = me(o[k], indent+"    ");
+                       if(typeof(val) != "string"){
+                               // skip non-serializable values
+                               continue;
+                       }
+                       res.push(indent+"  "+useKey + ":" + val);
+               }
+               return indent+"{\n" + res.join(",\n") + indent+"}";
+};
+
+xooki.component.toolbar = function () {
+       return  '<div style="position:absolute;top:2px;right:30px;" 
id="xooki-toolbar">'
+                               + '<a 
href="javascript:xooki.action.toggleEdit()"><img 
src="'+xooki.u('images/edit.gif')+'" title="toggle edit'+(xooki.c.browser.NS?' 
(CTRL+E)':'')+'"/></a>'
+                               + '<a 
href="javascript:xooki.action.saveChanges()"><img 
src="'+xooki.u('images/save.gif')+'" title="save'+(xooki.c.browser.NS?' 
(CTRL+S)':'')+'"/></a>'
+                               + '<a 
href="javascript:xooki.action.remove()"><img 
src="'+xooki.u('images/delete.gif')+'" title="remove"/></a>'
+                               + '<a 
href="javascript:xooki.action.createChild()"><img 
src="'+xooki.u('images/addchild.gif')+'" title="create child"/></a>'
+                               + '<a 
href="javascript:xooki.action.movePageUp()"><img 
src="'+xooki.u('images/up.gif')+'" title="move page up in TOC"/></a>'
+                               + '<a 
href="javascript:xooki.action.movePageDown()"><img 
src="'+xooki.u('images/down.gif')+'" title="move page down in TOC"/></a>'
+                               + (xooki.c.debug?'<a 
href="javascript:xooki.action.toggleDebug()"><img 
src="'+xooki.u('images/debug.gif')+'" title="toggle xooki debug mode"/></a>':'')
+                       + '</div>';
+};
+    
+xooki.component.editZone = function () {
+    return '<div id="xooki-edit" style="display:none">'
+        + '<table border="0"><tr><td valign="top">Title</td><td><input 
id="xooki-input-title" type="text" 
value="'+xooki.page.title+'"></input></td></tr>'
+        + '<tr><td valign="top">Content</td><td><textarea rows="20" cols="80" 
id="xooki-source">'+xooki.input.source()+'</textarea></td></tr>'
+        + '<tr><td colspan="2" align="right"><input type="button" value="Save" 
onclick="javascript:xooki.action.saveChanges()"/> <input type="button" 
value="Preview" onclick="javascript:xooki.action.previewChanges()"/> <input 
type="button" value="Discard" 
onclick="javascript:xooki.action.discardChanges()"/></td></tr></table></div>';
+}
+
+xooki.url.reload = function() {
+    window.location = window.location;
+}
+
+
+
+xooki.action.quitEdit = function () {
+    xooki.input.applyChanges();
+       xooki.html.hide('xooki-edit');
+       xooki.html.show('xooki-content');
+}
+xooki.action.edit = function () {
+       xooki.html.hide('xooki-content');
+       xooki.html.show('xooki-edit');
+}
+xooki.action.toggleEdit = function () {
+       if (document.getElementById('xooki-edit').style.display == 'none') {
+               xooki.action.edit();
+       } else {
+               xooki.action.quitEdit();
+       }
+}
+xooki.action.remove = function () {
+    if (confirm(t("The current page will be removed from the table of content, 
and deleted on file system.\nNote that all children will be removed from the 
table of content too, but not from the file system!\nAre you sure you want to 
delete the current page?"))) {
+
+        // the page to which we'll be redirected...
+        var nextPage;
+        var index = xooki.page.meta.index;
+        var parent = xooki.page.meta.parent;
+        if (index > 0) {
+            // ... will be the previous sibling if there is one ...
+            nextPage = parent.children[index - 1];
+        } else if (parent.children.length > 1) {
+            // ... or the next sibling if there is one ...
+            nextPage = parent.children[index + 1];        
+        } else if (parent != xooki.toc) {
+            // ... or the parent if the parent is not the toc root ...
+            nextPage = parent;        
+        } else {
+            // ... otherwise it s a problem
+            xooki.error(t("Cannot delete the sole page!"));
+            return;
+        }
+        
+        parent.children.splice(index, 1); // remove node from toc
+        xooki.toc.save();
+        
+        xooki.io.removeFile(xooki.io.getLocalPath(window.location.toString()));
+        
+        window.location = pu(nextPage.id);
+    }
+}
+xooki.action.discardChanges = function () {
+    xooki.url.reload();
+}
+xooki.action.previewChanges = function () {
+    xooki.action.quitEdit();
+}
+xooki.action.saveChanges = function () {
+       var originalPath = document.location.toString();
+       var localPath = xooki.io.getLocalPath(originalPath);
+       
+       // Load the original file
+       var original = xooki.io.loadFile(localPath);
+       if(original == null) {
+               xooki.error(t("Impossible to load original file: ${0}", 
localPath));
+               return;
+       }
+       
+       var startSaveArea = '<textarea id="xooki-source">';
+       var posOpeningArea = original.indexOf(startSaveArea);
+       var posClosingArea = original.indexOf('</textarea>');
+       
+       xooki.page.title = document.getElementById('xooki-input-title').value;
+       xooki.toc.save();
+       
+       var save;
+       try {
+               // Save new file
+               var revised = original.substr(0,posOpeningArea + 
startSaveArea.length) + "\n" +
+                                       xooki.input.source() +
+                                       original.substr(posClosingArea);
+                                       
+               save = xooki.io.saveFile(localPath,revised);
+       } catch (e) {
+               xooki.error(e);
+       } 
+    if(save) {
+               xooki.info(t("saved to ${0}",localPath));
+               
+               // TODO: see if we are able to apply title change without 
reloading
+               setTimeout(function() {xooki.url.reload();}, 800);
+       } else
+               xooki.error(t("Impossible to save changes to ${0}", localPath));
+}
+
+
+xooki.action.movePageUp = function () {
+    xooki.action.movePage(-1);
+}
+xooki.action.movePageDown = function () {
+    xooki.action.movePage(1);
+}
+
+xooki.action.movePage = function (delta) {
+    var index = xooki.page.meta.index;
+    var parent = xooki.page.meta.parent;
+
+    // check if node can move
+    if (index + delta < 0) {
+        xooki.info(t("Can't move first page up"));
+        return;
+    }
+    if (index + delta >= parent.children.length) {
+        xooki.info(t("Can't move last page down"));
+        return;
+    }
+
+    // move node in toc    
+    parent.children.splice(index, 1);
+    parent.children.splice(index+delta, 0, xooki.page);
+    
+    xooki.toc.save();
+    xooki.url.reload();
+}
+
+xooki.action.createChild = function () {
+    titleToId = function (title) {
+        return title.replace(/\s+/g, '');
+    }
+
+    var title = prompt("Child page title?", "");
+    var id = prompt("Child page path?", titleToId(title));
+    
+    xooki.action.createChildPage({"id": id, "title": title, "children": []});
+}
+
+xooki.action.createChildPage = function (child) {
+    if (typeof child.level == 'undefined') {
+        child.level = child.id.split('/').length - 1;
+    }
+        
+    var pagetpl = xooki.url.loadURL(cu("blankPageTpl"));
+    if (pagetpl != null) {
+        var childURL = pu(child.id);
+        var localPath = xooki.io.getLocalPath(childURL);
+        var original = xooki.io.loadFile(localPath);
+        if (original != null) {
+            if (!window.confirm(t("File for child page:\n${0}\nalready 
exists.\nAre you sure you want to continue and overwrite it?", localPath))) 
+                return;
+        }
+        
+        xooki.page.children.push(child);
+        xooki.toc.save();
+        
+        // usually used by templates
+        if (typeof child.relroot == 'undefined') {
+            child.relroot = "";
+               for (var i=0; i < child.level; i++) {
+                       child.relroot += "../";
+               }
+        }
+               var revised = xooki.string.processTemplate(pagetpl, child);
+       var save;
+       try {
+               // Save new file
+               save = xooki.io.saveFile(localPath,revised);
+       } catch (e) {
+               xooki.error(e);
+       } 
+        if(save) {
+               // go to child page
+            window.location = childURL;
+       } else
+               xooki.error(t("Impossible to save changes to ${0}", localPath));
+    }
+}
+
+
+xooki.toc.save = function (revised) {
+    if (!revised) {
+        revised = xooki.json.serialize({children: this.children});
+    }
+       var save;
+       var tocPath = xooki.io.getLocalPath(cu("toc"));
+       try {
+               save = xooki.io.saveFile(tocPath, revised);
+       } catch (e) {
+               xooki.error(e);
+       } 
+    if(!save) 
+               xooki.error(t("Impossible to save changes to ${0}", tocPath));
+}
+
+
+xooki.util = {}
+xooki.util.copy = function(o) {
+    var copy = {};
+    for (var k in o) {
+        copy[k] = o[k];
+    }   
+    return copy;
+}


Reply via email to