General JavaScript utilities for melange.
This script is going to be the core of Melange JS. It provides
a melange namespace and general utilies for logging, loading of
google api, common errors, base class for templates that reads
context from a script tag attribute. It also reads general
options from its script tag.
/* Copyright 2009 the Melange authors.
*
* 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.
*/
/**
* @author <a href="mailto:fadinlight@gmail.com">Mario Ferraro</a>
*/
(function () {
/** @lends melange */
/** General melange package.
* @name melange
* @namespace melange
*/
var melange = window.melange = function () {
return new melange();
};
if (window.jQuery === undefined) {
throw new Error("jQuery package must be loaded exposing jQuery namespace");
}
if (window.JSON === undefined) {
throw new Error("json2 package must be loaded exposing JSON namespace");
}
/** Shortcut to current package.
* @private
*/
var $m = melange;
/** Contains general configuration for melange package.
* @variable
* @public
* @name melange.config
*/
$m.config = {};
(function () {
var configuration =
jQuery("script[melangeConfig][src$='melange.js']").attr("melangeConfig");
if (configuration) {
var configuration_object = JSON.parse("{ " + configuration + " }");
jQuery.extend($m.config, configuration_object);
}
}());
/** Shortcut to clone objects using jQuery.
* @function
* @public
* @name melange.clone
* @param {Object} object the object to clone
* @returns {Object} a new, cloned object
*/
$m.clone = function (object) {
// clone object, see
// http://stackoverflow.com/questions/122102/
// what-is-the-most-efficent-way-to-clone-a-javascript-object
return jQuery.extend(true, {}, object);
};
/** Set melange general options.
* @function
* @public
* @name melange.setOptions
* @param {Object} options Options to set/unset
*/
$m.setOptions = function (options) {
switch (options.debug) {
case true:
$m.logging.setDebug();
break;
case false:
$m.logging.unsetDebug();
break;
default:
$m.logging.setDebug();
}
if (options.debugLevel) {
$m.logging.setDebugLevel(options.debugLevel);
}
};
/** Facility to load google API.
* @function
* @public
* @name melange.loadGoogleApi
* @param {String} modulename Google Ajax module to load
* @param {String|Number} moduleversion Google Ajax module version to load
* @param {Object} settings Google Ajax settings for the module
* @param {Function} callback to be called as soon as module is loaded
*/
$m.loadGoogleApi = function (modulename, moduleversion, settings, callback) {
if (!modulename || !moduleversion) {
throw new TypeError("modulename must be defined");
}
/** Options to be sent to google.load constructor
* @private
* @name melange.loadGoogleApi.options
*/
var options = {
name : modulename,
version : moduleversion,
settings : settings
};
jQuery.extend(options.settings, {callback: callback});
google.load(options.name, options.version, options.settings);
};
(function () {
/** @lends melange.error */
/** Package that handles melange errors
* @namespace melange.error
*/
melange.error = window.melange.error = function () {
return new melange.error();
};
/** Shortcut to current package.
* @property
* @private
*/
var $m = melange.error;
/** List of default custom error types to be created.
* @property
* @private
*/
var error_types = [
"DependencyNotSatisfied",
"notImplementedByChildClass"
];
/** Create errors
* @function
* @public
* @name melange.error.createErrors
* @param {String[]} error_types Array of strings with errors names
*/
$m.createErrors = function (error_types) {
jQuery.each(error_types, function () {
melange.error[this] = Error;
});
};
$m.createErrors(error_types);
}());
(function () {
/** @lends melange.logging */
/** Package that contains all log related functions.
* @name melange.logging
* @namespace melange.logging
*/
melange.logging = window.melange.logging = function () {
return new melange.logging();
};
/** Shortcut to current package.
* @property
* @private
*/
var $m = melange.logging;
/** @private */
var debug = false;
/** @private */
var current_debug_level = 5;
/** Set debug logging on.
* @function
* @public
* @name melange.logging.setDebug
*/
$m.setDebug = function () {
debug = true;
};
/** Set debug logging off.
* @function
* @public
* @name melange.logging.unsetDebug
*/
$m.unsetDebug = function () {
debug = false;
};
/** Check if debug is active.
* @function
* @public
* @name melange.logging.isDebug
* @returns {boolean} true if debug is on, false otherwise
*/
$m.isDebug = function () {
return debug ? true : false;
};
/** Set the current debug level.
* @function
* @public
* @name melange.logging.setDebugLevel
* @param level The log level to set
* @throws {TypeError} if the parameter given is not a number
*/
$m.setDebugLevel = function (level) {
if (isNaN(level)) {
throw new melange.error.TypeError(
"melange.logging.setDebugLevel: parameter must be a number"
);
}
if (level <= 0) {
level = 1;
}
if (level >= 6) {
level = 5;
}
current_debug_level = level;
};
/** Get the current debug level.
* @function
* @public
* @name melange.logging.getDebugLevel
* @returns {Number} The current debug level
*/
$m.getDebugLevel = function () {
return current_debug_level;
};
/** A decorator for logging.
* @function
* @public
* @name melange.logging.debugDecorator
* @param {Object} object_to_decorate The Function/Object to decorate
* @returns {Object} Same object,decorated with log(level,message) func
*/
$m.debugDecorator = function (object_to_decorate) {
/** Function to handle output of logs.
* @function
* @name melange.logging.debugDecorator.log
* @param level The log level
* @param message The string
*/
object_to_decorate.log = function (level, message) {
if (melange.logging.isDebug() && current_debug_level >= level) {
console.debug(message);
}
};
return object_to_decorate;
};
}());
(function () {
/** @lends melange.templates */
/** Package that provides basic templates functions
* @name melange.templates
* @namespace melange.templates
*/
melange.templates = window.melange.templates = function () {
return new melange.templates();
};
/** Shortcut to current package
* @private
*/
var $m = melange.logging.debugDecorator(melange.templates);
melange.error.createErrors([
]);
/** Parent prototype for all templates
* @class
* @constructor
* @name melange.templates._baseTemplate
* @public
*/
$m._baseTemplate = function () {
this.context = {};
var configuration = jQuery("script[melangeContext]")[0];
if (configuration !== undefined) {
configuration = jQuery(configuration).attr("melangeContext");
if (configuration) {
/* FIXME: json2 doesn't parse the object if they have k:"v" instead
of "k":"v", but this is not what gviz outputs, we need to change
gviz source or hack json2 source or use another method. eval()
must be not used anyway
*/
/*jslint evil: true,undef: false */
eval("var configuration_object = " + configuration);
jQuery.extend(this.context, configuration_object);
/*jslint evil: false,undef: true */
}
}
};
}());
}());
window.melange = window.melange.logging.debugDecorator(window.melange);