Source: startLiveChat.js

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

define(['underscore', 'api/errorCodes', 'api/configuration', 'api/ManagedError', 'lib/DataFormats'
, 'lib/UserAgent', 'api/ChatObserver', 'vendor/mobile-detect']
, function(_, ErrorCode, Configuration, ManagedError, DataFormats, UserAgent, ChatObserver, MobileDetect)
{
	/**
	 * Modify the user agent platform detection
	 * @enum {string}
	 * @readonly
	 * @memberof LiveSupport.VisitorAPI
	 */
	var MobilePlatformDetection = {
		/**
		 * attempt to identify automatically
		 * @type {string}
		 */
		AUTO: 'auto',
		/**
		 * assume a mobile touch enabled browser
		 * @type {string}
		 */
		MOBILE: 'mobile',
		/**
		 * assume a traditional desktop browser
		 * @type {string}
		 */
		DESKTOP: 'desktop'
	};

	/**
	 * additional parameters for the {@link LiveSupport.VisitorAPI.startLiveChat} function
	 * <img src="images/additionalParameters.png" style="margin-top:20px; margin-bottom:20px;"/>
	 * @enum {{}}
	 * @memberof LiveSupport.VisitorAPI
	 * @version 2.0
	 */
	var additionalParameters = {
		/**
		 * Custom text of max. 80 characters, appears before the first chat line in the operator's
		 * chat view
		 * @type {string}
		 */
		comment: '',
		/**
		 * Determines the language of the visitor's chat view. A value of <strong>1</strong> corresponds to the default
		 * visitor language, while a value of <strong>2</strong> chooses the secondary visitor language as set in
		 * the <em>yalst</em> miscellaneous settings.
		 * @type {number}
		 */
		newlang: 1,
		/**
		 * Pre-defined custom data fields which add upon the custom additional fields for the chat welcoming page.<br>
		 * The key-value pairs should be given using this syntax: <tt>"field1: value1; field2: value2"</tt><br>
		 * <em>Caution!</em> The field names must not match any name of the custom additional fields shown on the
		 * chat welcoming page.<br>
		 * The maximum total length is 500 characters.<br/>
		 * Along the regular additional fields of the chat welcoming page the <tt>paddfields</tt> data is shown
		 * in the operator's chat view in the lower chat partner info pane. (See screenshot on top)
		 * @type {string}
		 */
		paddfields: "",
		/**
		 * Key-Value pairs of user-defined data which is exposed to the visitor's chat instance. Usually used
		 * for web controlling. This data is disposed of at the end of the chat. </br>
		 * The data is injected into the JavaScript context of the user defined theme (<tt>*.ytf</tt> file).
		 * @type {string}
		 */
		sessionfields: "",
		/**
		 * Skips the welcoming form the visitor usually has to complete in order to start the chat.
		 * <em>Caution!</em>When yalst is configured to allow the visitor to choose a department and
		 * <tt>direct=true</tt>, you need to specify a particular department as parameter to
		 * {@link LiveSupport.VisitorAPI.startLiveChat}.
		 * <em>added in version 2</em>.
		 * @type {boolean}
		 * @since 2.0
		 */
		direct: false,
		/**
		 * presets the visitor's chat name
		 * @type {string}
		 */
		visitor: '',
		/**
		 * specifies the origin of the chat for the operator.
		 * The default case is the URL of the web page.
		 * @type {string}
		 */
		pagetitle: '',
		/**
		 * Indicates that the chat was initiated by help of an active visitor invitation.
		 * This may be useful for tuning the issue frequency of active invitations or statistical evaluation.
		 * @type {boolean}
		 */
		activechat: false
	};

	var uniqueId = (function(seedNumber)
	{
		var counter = seedNumber;

		return function()
		{
			return counter++;
		};
	}(Math.floor(Math.random() * 1.0e+10)));

	function succeededOpeningChatPopup(parameters)
	{
		var originId = _.random(0, 100000000);

		ChatObserver.addOriginId(originId);

		parameters.visitor_api_msg_id = originId;

		var popupSize = { width : 550, height : 572 };

		var windowName = "livechat_"
			+ Configuration.configuration.PRODUCT_SITE.replace(/\-/, '_');

		var popupWindow = window.open(Configuration.configuration.PRODUCT_URL + "index.php?"
			+ DataFormats.urlQueryStringFromObject(parameters)
			, windowName
			,"width=" + popupSize.width + ",height="	+ popupSize.height
				+ ",location=no,menubar=no,statusbar=no"
				+ ",scrollbars=no,dependent=no,screenX=20,screenY=20,left=20,top=20");

		if (!popupWindow)
		{
			/// Popup-Blocker
			return false;
		}

		if (popupWindow.opener == null)
		{
			popupWindow.opener = self;
		}

		popupWindow.focus();

		return true;
	}

	function succeededSchedulingNavigationToMobileChatPage(parameters)
	{
		location.assign(Configuration.configuration.PRODUCT_URL + "mobile/index.php?"
			+ DataFormats.urlQueryStringFromObject(parameters));

		return true;
	}


	/**
	 * creates a new live chat in a popup window on desktops or navigates to the touch optimized
	 * chat page of <em>yalst</em> on mobile browsers<br>
	 * To avoid popup blockers to interfere you should
	 * <em>call this method from the handler of an UI event</em>.<br><br>
	 * <em>Note for chats openend in popup windows:</em><br>
	 * In order to alleviate the risk of one visitor cramming the live support system
	 * with fake chats, creating multiple chats windows to the same site
	 * running in parallel from the same browser tab is not supported.
	 * Any attempt currently will result in a warning inside the already
	 * running chat popup.<br>
	 * To learn about the state of the chat popup window you can employ
	 * {@link LiveSupport.VisitorAPI.ChatObserver}.<br><br>
	 * <em>Security information:</em>
	 * Currently the popup window will initially run under a <tt>http</tt> scheme event though
	 * the actual chat communication is carried out over <tt>https</tt>.
	 * <br><br><strong>Throws</strong> {@link LiveSupport.ManagedError} in case the
	 * {@link LiveSupport.VisitorAPI.associateWithLiveSupportProduct}
	 * was not called before.
	 * @memberof LiveSupport.VisitorAPI
	 * @param {?string} [department=undefined] a particular yalst department id,
	 * if empty string any department otherwise the previously associated department id applies
	 * @param {?LiveSupport.VisitorAPI.additionalParameters} [customParameters=empty] parameters in the form <tt>{key1: value1, key2: value2}</tt>
	 * which become user-defined parameters of the chat window php-script
	 * @param {boolean} [withAutoTitle=false] associates the chat with the title of the current web page
	 * @param {(LiveSupport.VisitorAPI.MobilePlatformDetection|string)} [shouldDetectPlatform='auto']
	 * Flag overrides the internal mobile device detection
	 *
	 * @return {Boolean} true if the popup window was opened or the blocking of the popup by the
	 * browser could not be detected
	 * @example
	 * startButton.addEventListener('click', function(){
	 * 	if (!LiveSupport.VisitorAPI.startLiveChat(null, {paddfields: "Customer: 123456C; OrderCount: 4"})){
		alert("Please allow popups from " + location.hostname + " !");
	}
}, false);
	 */
	function startLiveChat(department, customParameters, withAutoTitle, shouldDetectPlatform)
	{
		if (!Configuration.configuration.IS_ASSOCIATED)
		{
			throw new ManagedError(ErrorCode.ServerNotYetAssociated
				, "Illegal API use. Attempt to call a method before associated to a live support server.");
		}

		var queryParameters = {site: Configuration.configuration.PRODUCT_SITE
			, yinit : true
			, from: document.URL
		};

		var sessionId = Configuration.getYalstSession();
		if (sessionId)
		{
			queryParameters.cookie = sessionId;
		}

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

		if (withAutoTitle)
		{
			queryParameters.pagetitle = document.title;
		}

		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 shouldDetectPlatform != "string")
		{
			shouldDetectPlatform = MobilePlatformDetection.AUTO;
		}

		if (shouldDetectPlatform == MobilePlatformDetection.MOBILE)
		{
			queryParameters.button_click_id = uniqueId();

			return succeededSchedulingNavigationToMobileChatPage(queryParameters);
		}

		if (shouldDetectPlatform == MobilePlatformDetection.AUTO)
		{
			var deviceDetector = new MobileDetect(window.navigator.userAgent);

			if (deviceDetector.mobile())
			{
				queryParameters.button_click_id = uniqueId();

				return succeededSchedulingNavigationToMobileChatPage(queryParameters);
			}

			return succeededOpeningChatPopup(queryParameters);
		}

		return succeededOpeningChatPopup(queryParameters);

	}

	return {
		startLiveChat : startLiveChat,
		MobilePlatformDetection : MobilePlatformDetection
	};
});