Source: startControlling.js

/**
 * startControlling.js
 *
 * Created by Matthias Seemann on 15.01.2013.
 * Copyright (c) 2013 Visisoft GbR. All rights reserved.
 */

define(['underscore', 'api/errorCodes', 'api/configuration', 'api/ManagedError', 'lib/DataFormats', 'lib/asyncLoadElement']
, function(_, ErrorCode, Configuration, ManagedError, DataFormats, asyncLoadExternalSourceIntoElement)
{
	var didBeginControlling = false;
	/**
	 * id of the one and only yalst.js.php Javascript in the page
	 * @const
	 * @type {String}
	 * @deprecated
	 */
	var controllingScriptId = "LiveSupport_Controlling_Script_Id";

	/**
	 * Begins identification of the user and opens a command socket in the website
	 * available to the Live Support operator console.<br><br>
	 * This method ensures it is called but once in the page's JavaScript context.
	 * Subsequent calls to this method will fail quietly.
	 * In order to track the user through a whole web presence this method must be called
	 * in each applicable webpage.<br>
	 * <h6>Integration warning</h6>
	 * The current implementation of this method adds a few <em>DOM elements (dialog box drop shadow)</em> to the page.
	 * <br><br><strong>Throws</strong> {@link LiveSupport.ManagedError} in case no callback is provided and
	 * <ul><li>{@link LiveSupport.VisitorAPI.associateWithLiveSupportProduct}
	 * was not called before, or</li>
	 * <li>the method is called for the first time but user controlling is already running
	 * on the page.</li>
	 * </ul>
	 * @param {?string} [department=undefined] a particular yalst department id,
	 * if empty string any department otherwise the previously associated department id applies
	 * @param {?object} [customParameters=empty] parameters in the form
	 * <tt>{key1: value1, key2: value2}</tt>
	 * which become user-defined parameters of yalst' tracking php-script
	 * @param {userCallback} [callback] called when the controlling code
	 * has finished loading  or if an error has occurred
	 * @memberof LiveSupport.VisitorAPI
	 *
	 * @example
LiveSupport.VisitorAPI.startControlling('C', {}, function(error){
	if (error){
		alert("Error: " + error.message + "(#" + error.number + ")");
	}
	else{
		// user should now appear in the yalst console for operators of department 'C'
	}
});
	 */
	function startControlling(department, customParameters, callback)
	{
		if (didBeginControlling)
		{
			if (typeof callback == "function")
			{
				_.defer(callback);
			}

			return;
		}

		var sanityCheckError;

		if (!Configuration.configuration.IS_ASSOCIATED)
		{
			sanityCheckError = new ManagedError(ErrorCode.ServerNotYetAssociated
				, "Illegal API use. Attempt to call the method 'startControlling'" +
					" before associated to a live support server.");
		}

		if (sanityCheckError)
		{
			if (typeof callback != "function")
			{
				throw sanityCheckError;
			}

			_.defer(_.bind(callback, null, sanityCheckError));

			return;
		}

		var queryParameters = {
			site: Configuration.configuration.PRODUCT_SITE
			, button : 'no'
			, y_span_id : 'y' + Math.random().toString()
		};

		if ((typeof department == "string") && (department.length > 0))
		{
			queryParameters.dept = department;
		}
		else if ((typeof department != "string")
			&& (typeof Configuration.configuration.PRODUCT_DEPARTMENT == "string")
			&& (Configuration.configuration.PRODUCT_DEPARTMENT.length > 0))
		{
			queryParameters.dept = Configuration.configuration.PRODUCT_DEPARTMENT;
		}

		if (typeof customParameters == "object")
		{
			_(queryParameters).extend(customParameters);
		}

		var targetSpan = document.createElement('span');
		targetSpan.id = queryParameters.y_span_id;

		document.body.appendChild(targetSpan);

		/// load the traditional yalst.js.php script asynchronously
		var script = document.createElement('script');

		asyncLoadExternalSourceIntoElement(script
			, Configuration.configuration.PRODUCT_URL + "yalst.js.php?"
			+ DataFormats.urlQueryStringFromObject(queryParameters)
			, function()
			{
				if (typeof callback == "function")
				{
					callback();
				}
			}
		);

		didBeginControlling = true;
	}

	return startControlling;
});