From c4ecd97fe9e69cba9d3a70951d816e6cd155a4b1 Mon Sep 17 00:00:00 2001 From: Daniele Cinti Date: Wed, 16 Aug 2017 11:26:27 +0200 Subject: [PATCH] Built xcally-motion-dialpad from commit 7f8e441.|1.0.36 --- js/salesforce/interaction.js | 610 ++++++++++++++++++++++++++++++++++++++++++ js/salesforce/lightning.js | 1 + 2 files changed, 611 insertions(+), 0 deletions(-) create mode 100644 js/salesforce/interaction.js create mode 100644 js/salesforce/lightning.js diff --git a/js/salesforce/interaction.js b/js/salesforce/interaction.js new file mode 100644 index 0000000..b765d66 --- /dev/null +++ b/js/salesforce/interaction.js @@ -0,0 +1,610 @@ +/* +* Salesforce.com Interaction Toolkit 40.0 +* Copyright, 2015, salesforce.com, inc. +* All Rights Reserved +*/ + +'use strict'; + +window.sforce = window.sforce || {}; + +sforce.interaction = (function() { + var apiVersion = 40; + var INTERACTION_API = 'interactionApi/'; + var ENTITY_FEED_API = 'entityFeedApi/'; + var frameOrigin = null; + var nonce = null; + var callbacks = {}; + var GET_CALL_CENTER_SETTINGS = 'getCallCenterSettings'; + var GET_SOFTPHONE_LAYOUT = 'getSoftphoneLayout'; + var GET_PAGE_INFO = 'getPageInfo'; + var SET_SOFTPHONE_HEIGHT = 'setSoftphoneHeight'; + var SET_SOFTPHONE_WIDTH = 'setSoftphoneWidth'; + var IS_IN_CONSOLE = 'isInConsole'; + var SCREEN_POP = 'screenPop'; + var SEARCH_AND_GET_SCREEN_POP_URL = 'searchAndGetScreenPopUrl'; + var SEARCH_AND_SCREEN_POP = 'searchAndScreenPop'; + var ENABLE_CLICK_TO_DIAL = 'enableClickToDial'; + var DISABLE_CLICK_TO_DIAL = 'disableClickToDial'; + var RUN_APEX_QUERY = 'runApex'; + var SAVE_LOG = 'saveLog'; + var SET_VISIBLE = 'setVisible'; + var IS_VISIBLE = 'isVisible'; + var AVAILABLE = 'available'; + var CONNECT = 'connect'; + var DISCONNECT = 'disconnect'; + var REFRESH_OBJECT = 'refreshObject'; + var RELOAD_FRAME = 'reloadFrame'; + var REFRESH_PAGE = 'refreshPage'; + var REFRESH_RELATED_LIST = 'refreshRelatedList'; + var NOTIFY_INITIALIZATION_COMPLETE = 'notifyInitializationComplete'; + var GET_DIRECTORY_NUMBERS = "getDirectoryNumbers"; + var listeners = {onClickToDial:'onClickToDial', onFocus:'onFocus', onObjectUpdate:'onObjectUpdate'}; + var methodId = 0; + var entityFeedApi = null; + var servedFromCanvas = false; + + function isApiMessage(event, apiEndPoint) { + return event.data && event.data.indexOf(apiEndPoint) === 0; + } + + function parseAuthParams(params) { + // initialize if sfdcIFrameOrigin and nonce are present + if (params['sfdcIFrameOrigin'] && params['nonce']) { + frameOrigin = params['sfdcIFrameOrigin'] ? params['sfdcIFrameOrigin'].toLowerCase():null; + nonce = params['nonce']; + } else { + // we may use canvas + if (typeof Sfdc !== "undefined" && Sfdc.canvas && Sfdc.canvas.client) { + var sr = Sfdc.canvas.client.signedrequest(); + var parsedRequest; + if (sr) { + if (typeof sr === "string") { + parsedRequest = JSON.parse(sr); + } else { + // assume we're using OAuth + parsedRequest = sr; + } + } + if (parsedRequest) { + var environment; + if (parsedRequest.context) { + environment = parsedRequest.context.environment; + } else if (parsedRequest.payload) { + environment = parsedRequest.payload.environment; + } + if (environment && environment.parameters) { + frameOrigin = environment.parameters.sfdcIframeOrigin; + nonce = environment.parameters.nonce; + servedFromCanvas = environment.parameters.servedFromCanvas; + } + } + } + } + } + + /** + * Process messages received from SFDC by executing callbacks, if any. + * The event object contains the following fields: + * method: the API method that was called. + * result: result returned from the call. + * error: an error message if any errors were encountered. + */ + function processPostMessage(event) { + var params; + try { + // Check if call is for entity feed + if (isApiMessage(event, ENTITY_FEED_API)) { + if (entityFeedApi && entityFeedApi.processPostMessage) { + params = entityFeedApi.processPostMessage(event); + } + if (!params) { + return; + } + } else if (isApiMessage(event, INTERACTION_API)) { + if (event.origin !== frameOrigin || !frameOrigin) { + // Only trust messages from the adapter frame + return; + } + + var message = event.data.replace(INTERACTION_API, ''); // strip off API target + params = parseUrlQueryString(message); + + // convert string true/false to boolean for methods that needs to return boolean values. + if (params && (params.result === 'true' || params.result === 'false')) { + params.result = params.result === 'true'; + } + } else { + // return if postMessage is not targeted to interaction API + return; + } + + // execute callbacks registered for the method called + for (var methodName in callbacks) { + if (callbacks.hasOwnProperty(methodName)) { + if (params.method === methodName) { + for (var i in callbacks[methodName]) { + callbacks[methodName][i](params); + } + if (!listeners[methodName]) { + delete callbacks[methodName]; + } + } + } + } + } catch(e) { + consoleLog("Failed to process API response."); + } + } + + /** + * Makes an API call to SFDC domain. + */ + function doPostMessage(params, callback) { + if (callback) { + params.method = registerCallback(params.method, callback); + } + + // add nonce to params + params.nonce = nonce; + + // add version + params.apiVersion = apiVersion; + + if (frameOrigin) { + var targetWindow = servedFromCanvas ? window.top : window.parent; + targetWindow.postMessage(INTERACTION_API + buildQueryString(params), frameOrigin); + } + } + + function registerCallback(method, callback) { + if (listeners[method]) { + if (callbacks[method]) { + callbacks[method].push(callback); + } else { + callbacks[method] = [callback]; + } + } else { + // API methods that are not listeners needs an ID in case they are call multiple times in an async manner. + method += '_' + methodId; + callbacks[method] = [callback]; + methodId++; + } + return method; + } + + /** + * Utility method to create a query string object. + */ + function parseUrlQueryString(queryString) { + var params = {}; + if (typeof queryString !== 'string') { + return params; + } + + if (queryString.charAt(0) === '?') { + queryString = queryString.slice(1); + } + + if (queryString.length === 0) { + return params; + } + + var pairs = queryString.split('&'); + for (var i = 0; i < pairs.length; i++) { + var pair = pairs[i].split('='); + params[pair[0]] = !!pair[1] ? decodeURIComponent(pair[1]) : null; + } + + return params; + } + + /** + * Utility method to build a query string from key/value object. + */ + function buildQueryString(params) { + var qs = ''; + for (var key in params) { + if (params.hasOwnProperty(key)) { + qs += key + '=' + encodeURIComponent(params[key]) + '&'; + } + } + qs = qs.length > 0 ? qs.substr(0, qs.length-1) : qs; + return qs; + } + + function consoleLog(message) { + if (window.console && console.log) { + console.log(message); + } + } + + function jsonStringify(object) { + if (typeof Sfdc !== "undefined" && Sfdc.JSON) { + return Sfdc.JSON.stringify(object); + } else { + return JSON.stringify(object); + } + } + + function jsonParse(json) { + if (typeof Sfdc !== "undefined" && Sfdc.JSON) { + return Sfdc.JSON.parse(json); + } else { + return JSON.parse(json); + } + } + + /** + * Entity Feed API implementation. + */ + function EntityFeedApi(params) { + var that = this; + var nonce = null; + var apiFrame; + var apiOrigin; + var readyQueue = []; + this.processPostMessage; + + function processApiResponse(event) { + return decodeMessage(event); + } + + function decodeMessage(event) { + if (isApiMessage(event, ENTITY_FEED_API)) { + // Decode message and check authenticity + var wrapper = jsonParse(event.data.substr(ENTITY_FEED_API.length)); + + // Check that message source is the API and that nonce is present unless it is an AVAILABLE broadcast + if (wrapper.message.fromApi && (wrapper.nonce === nonce || (!wrapper.nonce && wrapper.message.method === AVAILABLE))) { + return wrapper.message; + } + } + return null; + } + + function doPostMessage(frames, targetOrigin, message, callback, connect) { + if (!nonce) { + consoleLog("API is not supported in this configuration."); + return; + } + + // Register callback if any + if (callback) { + message.method = registerCallback(message.method, callback); + } + + // Encode message + message.toApi = true; + message.version = apiVersion; + var messageContainer = {message: message, sourceFrameName: window.name}; + if (connect) { + messageContainer.connect = true; + } else { + messageContainer.nonce = nonce; + } + var postData = ENTITY_FEED_API + jsonStringify(messageContainer); + + for (var i = 0, len = frames.length; i < len; i++) { + frames[i].postMessage(postData, targetOrigin); + } + } + + this.callApi = function(message, callback) { + if (apiFrame) { + doPostMessage([apiFrame], apiOrigin, message, callback, false); + } else { + readyQueue.push(function() { + that.callApi(message, callback); + }); + } + }; + + this.reloadFrame = function() { + if (apiFrame) { + if (params.frameName) { + that.callApi({method: RELOAD_FRAME, objectId: params.id, frameName: params.frameName}); + } else { + location.reload(); + } + } + }; + + function initialize() { + nonce = params.entityFeedNonce; + + that.processPostMessage = function(event) { + var message = decodeMessage(event); + if (message == null) { + return; + } else if (message.method === CONNECT && (!params.id || message.objectId === params.id)) { // Inline page frames do not have an id param + apiFrame = event.source; + apiOrigin = event.origin; + that.processPostMessage = processApiResponse; + + for (var i = 0, len = readyQueue.length; i < len; i++) { + readyQueue[i](); + } + readyQueue = null; + } else if (message.method === AVAILABLE && message.objectId === params.id) { + // Detail page frame in console is notifying that API is available, try to connect + doPostMessage([event.source], '*', {method: CONNECT, objectId: params.id}, null, true); + } + }; + + var loadHandler = function() { + // Remove load handler + if (window.removeEventListener) { + window.removeEventListener("load", arguments.callee, false); + } else if (window.detachEvent) { + window.detachEvent("onload", arguments.callee); + } + + // Search for api connection point. + var frames = []; + // Connect to current frame if api is available + if (typeof entityFeedPage != "undefined") { + frames.push(window); + } else { + // Attach to parent if VF custom publisher + frames.push(window.parent); + + // Attach to siblings for console frames if this is not an inline VF page in the entity feed page + if (!params.isCEFP) { + for (var parentFrames = window.parent.frames, i = 0, len = parentFrames.length; i < len; i++) { + if (parentFrames[i] !== window.self) { + frames.push(parentFrames[i]); + } + } + } + } + // Call frames to connect + doPostMessage(frames, '*', {method: CONNECT, objectId: params.id}, null, true); + }; + + var unloadHandler = function() { + // Remove unload handler + if (window.removeEventListener) { + window.removeEventListener("unload", arguments.callee, false); + } else if (window.detachEvent) { + window.detachEvent("onunload", arguments.callee); + } + if (apiFrame) { + doPostMessage([apiFrame], apiOrigin, {method: DISCONNECT}, null, false); + apiFrame = null; + } + }; + + if (window.addEventListener) { + window.addEventListener("load", loadHandler, false); + window.addEventListener("unload", unloadHandler, false); + } else if (window.attachEvent) { + window.attachEvent("onload", loadHandler); + window.attachEvent("onunload", unloadHandler); + } + }; + initialize(); + } + + return { + + /** + * Initializes API to listen for responses from SFDC. + */ + initialize : function() { + // set sfdc frame origin and nonce needed to call API methods + var params = parseUrlQueryString(location.search); + + parseAuthParams(params); + + // initialize entity feed api + if (!entityFeedApi && params.entityFeedNonce && typeof window.postMessage !== "undefined") { + entityFeedApi = new EntityFeedApi(params); + } + + if (frameOrigin || entityFeedApi) { + // attach postMessage event to handler + if (window.attachEvent) { + window.attachEvent('onmessage', processPostMessage); + } else { + window.addEventListener('message', processPostMessage, false); + } + } + + }, + + /** + * Returns true if is in console, false otherwise + */ + isInConsole : function (callback) { + doPostMessage({method:IS_IN_CONSOLE}, callback); + }, + + /** + * Screen pops to targetUrl and returns true if screen pop was successfully called, false otherwise. + * Parameter force must be a boolean. Set this value to true to force screen pop, i.e.: to force screen pop on an edit page. + */ + screenPop : function (targetUrl, force, callback) { + doPostMessage({method:SCREEN_POP, targetUrl:targetUrl, force:!!force}, callback); + }, + + searchAndGetScreenPopUrl : function (searchParams, queryParams, callType, callback) { + doPostMessage({method:SEARCH_AND_GET_SCREEN_POP_URL, searchParams:searchParams, queryParams:queryParams, callType:callType}, callback); + }, + + searchAndScreenPop : function (searchParams, queryParams, callType, callback) { + doPostMessage({method:SEARCH_AND_SCREEN_POP, searchParams:searchParams, queryParams:queryParams, callType:callType}, callback); + }, + + /** + * Returns the current page info parameters: page Url, object Id (if applicable), object Name (if applicable), object (if applicable) as a JSON String. + */ + getPageInfo : function (callback) { + doPostMessage({method:GET_PAGE_INFO}, callback); + }, + + /** + * Registers a callback to be fired when the page gets focused. + * When the callback is fired, it returns the current page info parameters: page Url, entity Id (if applicable), entity Name (if applicable) as a JSON String. + */ + onFocus : function (callback) { + doPostMessage({method:listeners.onFocus}, callback); + }, + + /** + * Save object to database and return true if object was saved successfully, false otherwise. + * objectName is the API name of an object + * saveParams is a query string representing a key-value pair of object fields to save. + * Example: + * // to save a new record + * sforce.interaction.saveLog('Account', 'Name=Acme&Phone=4152125555', callback); + * // to update a new record + * sforce.interaction.saveLog('Account', 'Id=001D000000J6qIX&Name=UpdatedAcmeName', callback); + */ + saveLog : function(objectName, saveParams, callback) { + doPostMessage({method:SAVE_LOG, objectName:objectName, saveParams:encodeURIComponent(saveParams)}, callback); + }, + + /** + * Runs an Apex method from a class with supplied parameters. + */ + runApex : function(apexClass, methodName, methodParams, callback) { + doPostMessage({method:RUN_APEX_QUERY, apexClass:apexClass, methodName:methodName, methodParams:methodParams}, callback); + }, + + /** + * Returns true if widget was successfully shown or hidden, false otherwise. + * Parameter value must be a boolean. + * Parameter callback must be a function. + * If false is returned, an error message is also returned. + */ + setVisible : function (value, callback) { + doPostMessage({method:SET_VISIBLE, value:value}, callback); + }, + + /** + * Returns true if widget is visible, false otherwise. + */ + isVisible : function (callback) { + doPostMessage({method:IS_VISIBLE}, callback); + }, + + /** + * Returns true if page refresh is invoked, false otherwise. + */ + refreshPage : function (callback) { + doPostMessage({method:REFRESH_PAGE}, callback); + }, + + /** + * Returns true if the related list with the given name is refreshed, false otherwise. + */ + refreshRelatedList : function (listName, callback) { + doPostMessage({method:REFRESH_RELATED_LIST, listName:listName}, callback); + }, + + cti: { + /** + * Gets Call Center Settings. + */ + getCallCenterSettings : function (callback) { + doPostMessage({method:GET_CALL_CENTER_SETTINGS}, callback); + }, + + /** + * Gets Softphone Layout. + */ + getSoftphoneLayout : function (callback) { + doPostMessage({method:GET_SOFTPHONE_LAYOUT}, callback); + }, + + /** + * Sets softphone height. Height must be greater or equal than zero + */ + setSoftphoneHeight : function (height, callback) { + doPostMessage({method:SET_SOFTPHONE_HEIGHT, height:height}, callback); + }, + + /** + * Sets softphone width. Width must be greater or equal than zero. + */ + setSoftphoneWidth : function (width, callback) { + doPostMessage({method:SET_SOFTPHONE_WIDTH, width:width}, callback); + }, + + /** + * Enables click to dial. + */ + enableClickToDial : function (callback) { + doPostMessage({method:ENABLE_CLICK_TO_DIAL}, callback); + }, + + /** + * Disables click to dial. + */ + disableClickToDial : function (callback) { + doPostMessage({method:DISABLE_CLICK_TO_DIAL}, callback); + }, + + /** + * Registers callback to be fired when user clicks to dial. + */ + onClickToDial : function (callback) { + doPostMessage({method:listeners.onClickToDial}, callback); + }, + + /** + * Notifies that the adapter url has been successfully loaded. + * Should be used if the standby url has been initialized. + */ + notifyInitializationComplete: function() { + doPostMessage({method:NOTIFY_INITIALIZATION_COMPLETE}); + }, + + /** + * Returns a list of phone numbers from a call center directory. + */ + getDirectoryNumbers : function (isGlobal, callCenterName, callback, resultSetPage, resultSetPageSize) { + var params = {method:GET_DIRECTORY_NUMBERS, isGlobal: isGlobal}; + if (callCenterName) { + params.callCenterName = callCenterName; + } + if (resultSetPage) { + params.resultSetPage = resultSetPage; + } + if (resultSetPageSize) { + params.resultSetPageSize = resultSetPageSize; + } + doPostMessage(params, callback); + } + }, + + /** + * Public API for Entity feed + */ + entityFeed: { + /** + * Notifies that the object has been updated and its display need to be refreshed + */ + refreshObject : function(objectId, refreshFields, refreshRelatedLists, refreshFeed, callback) { + entityFeedApi && entityFeedApi.callApi({method: REFRESH_OBJECT, objectId: objectId || params.id, refreshFields: refreshFields, refreshRelatedLists: refreshRelatedLists, refreshFeed: refreshFeed}, callback); + }, + + /** + * Registers a callback to be fired when the object has been updated. + */ + onObjectUpdate : function(callback) { + entityFeedApi && entityFeedApi.callApi({method: listeners.onObjectUpdate}, callback); + }, + + /** + * Reloads the frame containing this page + */ + reloadFrame : function() { + entityFeedApi && entityFeedApi.reloadFrame(); + } + } + }; +})(); + +sforce.interaction.initialize(); diff --git a/js/salesforce/lightning.js b/js/salesforce/lightning.js new file mode 100644 index 0000000..95858ef --- /dev/null +++ b/js/salesforce/lightning.js @@ -0,0 +1 @@ +!function(e){function t(i){if(a[i])return a[i].exports;var n=a[i]={exports:{},id:i,loaded:!1};return e[i].call(n.exports,n,n.exports,t),n.loaded=!0,n.exports}var a={};return t.m=e,t.c=a,t.p="/assets/",t(0)}([function(e,t,a){"use strict";window.sforce=window.sforce||{},sforce.opencti=a(1),sforce.opencti.initialize()},function(e,t,a){"use strict";var i=a(2),n=a(3),o=/(\.force\.com|\.salesforce\.com)(:\d+)?$/;e.exports={initialize:function(){var e=n.parseUrlQueryString(location.search),t=e.sfdcIframeOrigin;if(!(t&&e.mode&&o.test(t)&&0===t.indexOf(window.location.protocol)))throw"Failed to initialize Open CTI. Ensure that it is loaded from the right frame with correct URL parameters";i.sfdcIframeOrigin=e.sfdcIframeOrigin,i.mode=e.mode,window.addEventListener("message",n.processPostMessage,!1)},setSoftphonePanelVisibility:function(e){n.validateArguments(arguments);var t=e?e.callback:void 0;n.invokeApiCall("setSoftphonePanelVisibility",{visible:e.visible},t)},isSoftphonePanelVisible:function(e){n.validateArguments(arguments),n.validateCallback(e),n.invokeApiCall("isSoftphonePanelVisible",{},e.callback)},SCREENPOP_TYPE:{URL:"url",SOBJECT:"sobject",OBJECTHOME:"objecthome",LIST:"list",SEARCH:"search",NEW_RECORD_MODAL:"newRecord"},screenPop:function(e){n.validateArguments(arguments);var t=e?e.callback:void 0;n.invokeApiCall("screenPop",{type:e.type,params:e.params},t)},CALL_TYPE:{INBOUND:"inbound",OUTBOUND:"outbound",INTERNAL:"internal"},searchAndScreenPop:function(e){n.validateArguments(arguments);var t=e?e.callback:void 0;n.invokeApiCall("searchAndScreenPop",{searchParams:e.searchParams,callType:e.callType,queryParams:e.queryParams,defaultFieldValues:e.defaultFieldValues,deferred:e.deferred},t)},getAppViewInfo:function(e){n.validateArguments(arguments),n.validateCallback(e),n.invokeApiCall("getAppViewInfo",{},e.callback)},saveLog:function(e){n.validateArguments(arguments),n.validateValueObject(e);var t=e?e.callback:void 0;n.invokeApiCall("saveLog",{object:e.value},t)},refreshView:function(e){n.validateArguments(arguments,!0);var t=e?e.callback:void 0;n.invokeApiCall("refreshView",{},t)},setSoftphoneItemLabel:function(e){n.validateArguments(arguments);var t=e?e.callback:void 0;n.invokeApiCall("setSoftphoneItemLabel",{label:e.label},t)},setSoftphonePanelLabel:function(e){n.validateArguments(arguments);var t=e?e.callback:void 0;n.invokeApiCall("setSoftphonePanelLabel",{label:e.label},t)},setSoftphoneItemIcon:function(e){n.validateArguments(arguments);var t=e?e.callback:void 0;n.invokeApiCall("setSoftphoneItemIcon",{key:e.key},t)},setSoftphonePanelIcon:function(e){n.validateArguments(arguments);var t=e?e.callback:void 0;n.invokeApiCall("setSoftphonePanelIcon",{key:e.key},t)},setSoftphonePanelHeight:function(e){n.validateArguments(arguments);var t=e?e.callback:void 0;n.invokeApiCall("setSoftphonePanelHeight",{heightPX:e.heightPX},t)},setSoftphonePanelWidth:function(e){n.validateArguments(arguments);var t=e?e.callback:void 0;n.invokeApiCall("setSoftphonePanelWidth",{widthPX:e.widthPX},t)},getCallCenterSettings:function(e){n.validateArguments(arguments),n.validateCallback(e),n.invokeApiCall("getCallCenterSettings",{},e.callback)},onClickToDial:function(e){n.validateArguments(arguments),n.validateListener(e),n.invokeApiCall("onClickToDial",{},void 0,e.listener)},enableClickToDial:function(e){n.validateArguments(arguments,!0);var t=e?e.callback:void 0;n.invokeApiCall("enableClickToDial",{},t)},disableClickToDial:function(e){n.validateArguments(arguments,!0);var t=e?e.callback:void 0;n.invokeApiCall("disableClickToDial",{},t)},getSoftphoneLayout:function(e){n.validateArguments(arguments),n.validateCallback(e),n.invokeApiCall("getSoftphoneLayout",{},e.callback)},onNavigationChange:function(e){n.validateArguments(arguments),n.validateListener(e),n.invokeApiCall("onNavigationChange",{},void 0,e.listener)},runApex:function(e){n.validateArguments(arguments);var t=e?e.callback:void 0;n.invokeApiCall("runApex",{apexClass:e.apexClass,methodName:e.methodName,methodParams:e.methodParams},t)}}},function(e,t){"use strict";e.exports={API_VERSION:40,API_TYPE:"opencti",sfdcIframeOrigin:null,mode:null}},function(e,t,a){"use strict";var i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n=a(2),o=a(4),l=a(5),r=function(){var e=0;return function(){return e++}}(),s=function(e){var t=e.data;t&&t.apiVersion===n.API_VERSION&&t.apiType===n.API_TYPE&&e.origin===n.sfdcIframeOrigin&&(o.executeCallback(t.methodName,t.callId,t.response),l.executeListeners(t.methodName,t.response))},c=function(e){var t={};if("string"!=typeof e)return t;if("?"===e.charAt(0)&&(e=e.slice(1)),0===e.length)return t;for(var a=e.split("&"),n=0;n