Source: VisitorAPI.js

/**
 * VisitorAPI.js
 *
 * Created by Matthias Seemann on 4.01.2013.
 * Copyright (c) 2013 Visisoft GbR. All rights reserved.
 *
 * How to build the documentation with JSDoc3:
 * from inside the visitor_api/v2 directory execute the command line:
 * jsdoc -d ~/Documents/Projects/yalst/yalst-trunk/Documentation/visitor_api/ api/<wildcard star>*.js ../Readme.md
 * JSDoc 3.0 postprocessing:
 *  in index.html add class="prettyprint" to all <pre> tags which contain code
 *
 * JSDoc 3.3.0 postprocessing:
 * Either
 * Include jQuery then fire this script on document ready. The DOM must be loaded in order for the post-processing to have something to act upon. Of course if your target browsers are modern you can use pure JS and not jQuery.
 *
 *	$('code').parent('pre').addClass('prettyprint source linenums');
 *	window.prettyPrint && prettyPrint();
 *
 * or
 *
 * use modified jsdoc/templates/default/tmpl/examples.tmpl + mainpage.tmpl
 *
 *	(see: https://github.com/jsdoc3/jsdoc/pull/424#issuecomment-28893173)
 *
 * How to change the namespace:
 * 1. change 2x in build.js - or use custom build.js file
 * 2. change GLOBAL_NAMESPACE in api/configuration.js
 * 3. change argument of the outer immediate function here in api/VisitorAPI.js
 * 4. change the GLOBAL_NAMESPACE variable in the build.sh script
 * 5. collect the Api under the global namespace with r.js (build script is ./build.sh)
 *
 *
 * @overview Documentation of the public yalst Visitor API
 * @copyright Visisoft OHG 2013-2014
 * @author Matthias Seemann
 * @version 2.0
 * @license License of the yalst Live Support Tool applies
 */

(function(namespaceName){
	return define(['underscore', 'api/errorCodes', 'api/configuration', 'api/ManagedError', 'api/operatorAvailability', 'api/startLiveChat', 'api/startControlling', 'api/ChatObserver'],
			function(_, ErrorCodes, Configuration, ManagedError, OperatorAvailability, StartLiveChat, startControlling, ChatObserver)
		{
			/// global namespace LiveSupport is already defined
			// in the integration code or in the self-hosted loader 'visitorApiLoader.js'

			/// (Re-)define the api root ///
			var LiveSupport = window[namespaceName];

			if (LiveSupport === undefined)
			{
				/**
				 * The yalst namespace
				 * @namespace LiveSupport
				 */
				LiveSupport = window[namespaceName] = {};
			}

			if (LiveSupport.VisitorAPI === undefined)
			{
				/**
				 * The Visitor API namespace
				 * @namespace LiveSupport.VisitorAPI
				 */
				LiveSupport.VisitorAPI = {};
			}

			/// insert the sub-apis

			LiveSupport.ManagedError = ManagedError;

			LiveSupport.VisitorAPI.ErrorCode = ErrorCodes;

			_(LiveSupport.VisitorAPI).extend(Configuration);
			_(LiveSupport.VisitorAPI).extend(OperatorAvailability);
			_(LiveSupport.VisitorAPI).extend(StartLiveChat);
			LiveSupport.VisitorAPI.startControlling = startControlling;
			LiveSupport.VisitorAPI.ChatObserver = ChatObserver;

			/**
			 * Signature of the user provided callback function used to deliver the result of
			 * asynchronous API methods. <br/>
			 * Callbacks are always executed in a later run of the Javascript event loop like
			 * in Node's <tt>process.nextTick(callback)</tt> or <tt>setTimeout(callback, 0)</tt>, i.e.
			 * never immediately or synchronously to the method call.
			 * @function userCallback
			 * @param {*|LiveSupport.ManagedError|Error} resultOrError -
			 * The result of the asynchronous process or an
			 * API error. If the API call has failed <tt>resultOrError instanceof Error</tt> is true.
			 */

			/// redefine the invoke method to directly execute the method rather than queueing it

			/**
			 * Calls API methods regardless whether the browser has finished loading the API or not.
			 * It can be used right after the its definition in the Javascript code which loads
			 * the Visitor API asynchronously into the web page.
			 * If the API is not yet loaded  the calls are FIFO queued and
			 * invoked right when the API is ready.
			 * @param {string} method The method name like 'getVersionString'
			 * @param {array} parameterArray The parameters of the method or an empty array if there are no
			 * parameters required.
			 * @param {userCallback=} invocationCallback An optional invocationCallback function
			 * which receives the result of the immediately and synchronously executed method
			 * or an error
			 * @memberof LiveSupport.VisitorAPI
			 * @example
			 * LiveSupport.VisitorAPI.invoke('getVersionString', [], function(versionOrError){
			 * 	if (versionOrError instanceof Error){
			 * 		alert("Error :" + versionOrError.message; + "(#" + versionOrError.number + ")");
			 * 	}
			 * 	else{
			 * 		document.getElementById('apiVersion').innerHTML = "API version:" + versionOrError;
			 * 	}
			 * });
			 */
			LiveSupport.VisitorAPI.invoke = function(method, parameterArray, invocationCallback)
			{
				if (typeof method != "string")
				{
					if (typeof invocationCallback == "function")
					{
						_.defer(_.bind(invocationCallback, null, new ManagedError(ErrorCodes.ParameterTypeError
							, "invalid argument: 1 must be string")));
					}

					return;
				}

				invocationCallback = invocationCallback || function(){};

				if (!(method in LiveSupport.VisitorAPI))
				{
					_.defer(_.bind(invocationCallback, null
						, new ManagedError(ErrorCodes.CallToUndefinedMethod
							, "Call to unknown method: " + method)
						)
					);
				}
				else
				{
					_.defer(_.bind(invocationCallback, null,
						LiveSupport.VisitorAPI[method].apply(null, parameterArray))
					);
				}
			};

			return LiveSupport.VisitorAPI;
		}
	);
}("LiveSupportDIY"));