/* Create my namespace */
var net;
if(!net) {
	 net = {};
} else if (typeof net != "object") {
  throw new Error("net already exists and is not an object");
}

if(!net.gonote) {
		net.gonote = {};
} else if(typeof net.gonote != "object") {
  throw new Error("net.gonote already exists and is not an object");
}

if(net.gonote.util) {
		    throw new Error("net.gonote.util already exists");
}

net.gonote.util = {};

/**
 * defineClass() -- a utility function for defining JavaScript classes.
 *
 * This function expects a single object as its only argument.  It defines
 * a new JavaScript class based on the data in that object and returns the
 * constructor function of the new class.  This function handles the repetitive
 * tasks of defining classes: setting up the prototype object for correct
 * inheritance, copying methods from other types, and so on.
 * 
 * The object passed as an argument should have some or all of the
 * following properties:
 *
 *      name: the name of the class being defined.
 *            If specified, this value will be stored in the classname
 *            property of the prototype object.
 * 
 *    extend: The constructor of the class to be extended.  If omitted,
 *            the Object() constructor will be used.  This value will
 *            be stored in the superclass property of the prototype object.
 *
 * construct: The constructor function for the class. If omitted, a new
 *            empty function will be used.  This value becomes the return
 *            value of the function, and is also stored in the constructor
 *            property of the prototype object.
 *
 *   methods: An object that specifies the instance methods (and other shared
 *            properties) for the class.  The properties of this object are
 *            copied into the prototype object of the class.  If omitted,
 *            an empty object is used instead.  Properties named
 *            "classname", "superclass", and "constructor" are reserved
 *            and should not be used in this object.
 *
 *   statics: An object that specifies the static methods (and other static
 *            properties) for the class.  The properties of this object become
 *            properties of the constructor function.  If omitted, an empty
 *            object is used instead.
 *
 *   borrows: A constructor function or array of constructor functions.
 *            The instance methods of each of the specified classes are copied
 *            into the prototype object of this new class so that the 
 *            new class borrows the methods of each specified class.
 *            Constructors are processed in the order they are specified,
 *            so the methods of a class listed at the end of the array may
 *            overwrite the methods of those specified earlier. Note that
 *            borrowed methods are stored in the prototype object before
 *            the properties of the methods object above.  Therefore,
 *            methods specified in the methods object can overwrite borrowed
 *            methods. If this property is not specified, no methods are
 *            borrowed.
 *
 *  provides: A constructor function or array of constructor functions.
 *            After the prototype object is fully initialized, this function
 *            verifies that the prototype includes methods whose names and
 *            number of arguments match the instance methods defined by each
 *            of these classes.  No methods are copied; this is simply an
 *            assertion that this class "provides" the functionality of the
 *            specified classes.  If the assertion fails, this method will
 *            throw an exception.  If no exception is thrown, any
 *            instance of the new class can also be considered (using "duck
 *            typing") to be an instance of these other types.  If this
 *            property is not specified, no such verification is performed.
 **/
net.gonote.util.defineClass =  function (data) {
    // Extract the fields we'll use from the argument object.
    // Set up default values.
    var classname = data.name;
    var superclass = data.extend || Object;
    var constructor = data.construct || function() {};
    var methods = data.methods || {};
    var statics = data.statics || {};
    var borrows;
    var provides;

    // Borrows may be a single constructor or an array of them.
    if (!data.borrows) borrows = [];
    else if (data.borrows instanceof Array) borrows = data.borrows;
    else borrows = [ data.borrows ];

    // Ditto for the provides property.
    if (!data.provides) provides = [];
    else if (data.provides instanceof Array) provides = data.provides;
    else provides = [ data.provides ];

    // Create the object that will become the prototype for our class.
    var proto = new superclass();

    // Delete any noninherited properties of this new prototype object.
    for(var p in proto) 
        if (proto.hasOwnProperty(p)) delete proto[p];

    // Borrow methods from "mixin" classes by copying to our prototype.
    for(var i = 0; i < borrows.length; i++) {
        var c = data.borrows[i];
        borrows[i] = c;
        // Copy method properties from prototype of c to our prototype
        for(var p in c.prototype) {
            if (typeof c.prototype[p] != "function") continue;
            proto[p] = c.prototype[p];
        }
    }

    // Copy instance methods to the prototype object
    // This may overwrite methods of the mixin classes
    for(var p in methods) proto[p] = methods[p];

    // Set up the reserved "constructor", "superclass", and "classname"
    // properties of the prototype.
    proto.constructor = constructor;
    proto.superclass = superclass;
    // classname is set only if a name was actually specified.
    if (classname) proto.classname = classname;

    // Verify that our prototype provides all of the methods it is supposed to.
    for(var i = 0; i < provides.length; i++) {  // for each class
        var c = provides[i];
        for(var p in c.prototype) {   // for each property
            if (typeof c.prototype[p] != "function") continue;  // methods only
            if (p == "constructor" || p == "superclass") continue;
            // Check that we have a method with the same name and that
            // it has the same number of declared arguments.  If so, move on
            if (p in proto &&
                typeof proto[p] == "function" &&
                proto[p].length == c.prototype[p].length) continue;
            // Otherwise, throw an exception
            throw new Error("Class " + classname + " does not provide method " + c.classname + "." + p);
        }
    }

    // Associate the prototype object with the constructor function
    constructor.prototype = proto;

    // Copy static properties to the constructor
    for(var p in statics) constructor[p] = data.statics[p];

    // Finally, return the constructor function
    return constructor;
};

net.gonote.util.extend = function(sub, sup) {
   function F() {}
   F.prototype = sup.prototype;
   sub.prototype = new F();
   sub.prototype.constructor = sub;
   sub.superConstructor = sup;
   sub.superPrototype = sup.prototype; // not necessary but nice convenience
};


//UTILITY FUNCTIONS

net.gonote.util.mapArray = function(/*Array*/a, /*function*/f) {
	var r = [];
	var length = a.length;
	for(var i = 0; i < length; i++) r[i] = f(a[i]);
	return r;
};


//This is an object that displays, returns and clears
//comments. Will look for a document element 'comment'
//Element must be a textarea in order to allow user input

net.gonote.util.comment = function() {

	this.node = document.getElementById("comment");
};

net.gonote.util.comment.prototype.getComment = function() {

       return(this.node.getAttribute("value"));
};

net.gonote.util.comment.prototype.clearComment = function() {

       this.node.setAttribute("value", "");
};

net.gonote.util.comment.prototype.setComment = function(/*String*/cmnt) {

       this.node.setAttribute("value", cmnt);
};


net.gonote.util.log = function(/*String*/msg) {

	var log = document.getElementById("log");

//	var oldMsg = log.getAttribute("value");

//	var newMsg = oldMsg + "| |" + msg;
	
//	log.setAttribute("value", newMsg); 
	
	log.appendChild(document.createTextNode(msg + "\n"));
//	var p = document.createElement("p");

//	p.innerHTML = msg;

//	log.appendChild(p);
};


net.gonote.util.report = function() {

       net.gonote.util.log("...util loaded...");
};

net.gonote.util.registerObjectEventHandler = function(element, eventtype, listener, captures) {

	element.addEventListener(eventtype, function(event) {listener.handleEvent(event);}, captures);
};


/**
 * XML.XPathExpression is a class that encapsulates an XPath query and its
 * associated namespace prefix-to-URL mapping.  Once an XML.XPathExpression
 * object has been created, it can be evaluated one or more times (in one
 * or more contexts) using the getNode() or getNodes() methods.
 *
 * The first argument to this constructor is the text of the XPath expression.
 * 
 * If the expression includes any XML namespaces, the second argument must
 * be a JavaScript object that maps namespace prefixes to the URLs that define
 * those namespaces.  The properties of this object are the prefixes, and
 * the values of those properties are the URLs.
 *
XML.XPathExpression = function(xpathText, namespaces) {
    this.xpathText = xpathText;    // Save the text of the expression
    this.namespaces = namespaces;  // And the namespace mapping

    if (document.createExpression) {
        // If we're in a W3C-compliant browser, use the W3C API
        // to compile the text of the XPath query
        this.xpathExpr = 
            document.createExpression(xpathText, 
                                      // This function is passed a 
                                      // namespace prefix and returns the URL.
                                      function(prefix) {
                                          return namespaces[prefix];
                                      });
    }
    else {
        // Otherwise, we assume for now that we're in IE and convert the
        // namespaces object into the textual form that IE requires.
        this.namespaceString = "";
        if (namespaces != null) {
            for(var prefix in namespaces) {
                // Add a space if there is already something there
                if (this.namespaceString) this.namespaceString += ' ';
                // And add the namespace
                this.namespaceString += 'xmlns:' + prefix + '="' +
                    namespaces[prefix] + '"';
            }
        }
    }
};
*/
/**
 * This is the getNodes() method of XML.XPathExpression.  It evaluates the
 * XPath expression in the specified context.  The context argument should
 * be a Document or Element object.  The return value is an array 
 * or array-like object containing the nodes that match the expression.
 *
XML.XPathExpression.prototype.getNodes = function(context) {
    if (this.xpathExpr) {
        // If we are in a W3C-compliant browser, we compiled the
        // expression in the constructor.  We now evaluate that compiled
        // expression in the specified context
        var result =
            this.xpathExpr.evaluate(context, 
                                    // This is the result type we want
                                    XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
                                    null);

        // Copy the results we get into an array.
        var a = new Array(result.snapshotLength);
        for(var i = 0; i < result.snapshotLength; i++) {
            a[i] = result.snapshotItem(i);
        }
        return a;
    }
    else {
        // If we are not in a W3C-compliant browser, attempt to evaluate
        // the expression using the IE API.
        try {
            // We need the Document object to specify namespaces
            var doc = context.ownerDocument;
            // If the context doesn't have ownerDocument, it is the Document
            if (doc == null) doc = context;
            // This is IE-specific magic to specify prefix-to-URL mapping
            doc.setProperty("SelectionLanguage", "XPath");
            doc.setProperty("SelectionNamespaces", this.namespaceString);

            // In IE, the context must be an Element not a Document, 
            // so if context is a document, use documentElement instead
            if (context == doc) context = doc.documentElement;
            // Now use the IE method selectNodes() to evaluate the expression
            return context.selectNodes(this.xpathText);
        }
        catch(e) {
            // If the IE API doesn't work, we just give up
            throw "XPath not supported by this browser.";
        }
    }
}
*/

/**
 * This is the getNode() method of XML.XPathExpression.  It evaluates the
 * XPath expression in the specified context and returns a single matching
 * node (or null if no node matches).  If more than one node matches,
 * this method returns the first one in the document.
 * The implementation differs from getNodes() only in the return type.
 *
XML.XPathExpression.prototype.getNode = function(context) {
    if (this.xpathExpr) {
        var result =
            this.xpathExpr.evaluate(context, 
                                    // We just want the first match
                                    XPathResult.FIRST_ORDERED_NODE_TYPE,
                                    null);
        return result.singleNodeValue;
    }
    else {
        try {
            var doc = context.ownerDocument;
            if (doc == null) doc = context;
            doc.setProperty("SelectionLanguage", "XPath");
            doc.setProperty("SelectionNamespaces", this.namespaceString);
            if (context == doc) context = doc.documentElement;
            // In IE call selectSingleNode instead of selectNodes
            return context.selectSingleNode(this.xpathText);
        }
        catch(e) {
            throw "XPath not supported by this browser.";
        }
    }
};

// A utility to create an XML.XPathExpression and call getNodes() on it
XML.getNodes = function(context, xpathExpr, namespaces) {
    return (new XML.XPathExpression(xpathExpr, namespaces)).getNodes(context);
};

// A utility to create an XML.XPathExpression and call getNode() on it
XML.getNode  = function(context, xpathExpr, namespaces) {
    return (new XML.XPathExpression(xpathExpr, namespaces)).getNode(context);
};
*/
