CallOuts In SharePoint

Callouts were introduced in SP2013 to Highlight content and enhance the functionality of SharePoint. Callouts provides a flexible way to engage your user and showcase your SharePoint functionality.
 
Let's see how to create callouts.
 
callout.js is the js, through which we can create custom callouts, so we have to make sure it's referenced in master page and loaded before using callouts.
 
How to load?

make sure callout.js is registered in your master page, if not register it using script block and make sure it's rendered as shown below.

 
Then you have to examine the page on which you are working.

If it's a new webpart/wiki/enterprise page callout.js has to be loaded using SP.SOD.exceuteFunc. 
  1. (function(){  
  2.     SP.SOD.executeFunc("callout.js""Callout"function () {  
  3.           ///logic  
  4.     });  
  5. })();  
If it's an inbuilt or already created page check if any functionality is using callouts or check for calloutManager in console F12. If undefined you have to load the callout.js as shown above. If it's defined there's no need to load but we have to wait untill it's loaded by SP.SOD.executeOrDelayUntilScriptLoaded.
  1. (function(){    
  2.     SP.SOD.executeOrDelayUntilScriptLoaded(function () {    
  3.           ///logic  
  4.     }, "callout.js");    
  5. })();   
Below are the main objects in callouts. Let's see each one by one and how to use them
  1. CalloutManager
  2. CalloutOptions
  3. CalloutOpenOptions
  4. Callout
  5. CalloutAction
  6. CalloutActionOptions
  7. CalloutActionMenuEntry
CalloutManager

The CalloutManager is a singleton that stores references to every Callout object on a page inside an associative array, it exposes different methods.
  • closeAll() : boolean : Closes all callouts on the page.
  • createNew(options : CalloutOptions): Callout : Creates a new callout.
  • createNewIfNecessary(options: CalloutOptions) : Callout : Checks if callout with specified ID already exists. If it doesn't, creates it, otherwise returns the existing one.
  • forEach(callback : (callout: Callout) => void): any : Perform some action for each callout on the page.
  • getFromLaunchPoint(launchPoint: HTMLElement) : Callout : Searches for a callout associated with the specified launch point. Throws error if not found.
  • getFromLaunchPointIfExists(launchPoint: HTMLElement) : Callout : Searches for a callout associated with the specified launch point. Returns null if not found.
  • remove(callout: Callout): any : Detaches callout from the launch point and destroys it.
CalloutOptions

Defines the callout properties(Note: HTMLElement we have to use javascript to get element not Jquery)
  • ID : string : Some unique id for the callout.
  • beakOrientation : string : One of the following: "topBottom" (default) or "leftRight".
  • content : string : String (HTML allowed) that represents contents of the callout window.
  • contentElement : HTMLElement : HTML element that represents contents of the callout window.
  • contentWidth : number : Content element's width in pixels. By default = 350.
  • launchPoint : HTMLElement : Element on that the callout is shown
  • onOpeningCallback : (callout: Callout) => void : Fires after the callout is rendered but before it is positioned
  • and shown
  • onOpenedCallback : (callout: Callout) => void : Fires right after the callout is shown
  • onClosingCallback : (callout: Callout) => void : Fires right before the callout is closed
  • onClosedCallback : (callout: Callout) => void : Fires right after the callout is closed
  • openOptions : CalloutOpenOptions : Defines opening behavior
  • title : string : Title for the callout
CalloutOpenOptions

Defines how callout should open
  • closeCalloutOnBlur: boolean : Callout will be closed on blur
  • event: string : HTML event name, e.g. "click"/"hover"
  • showCloseButton: boolean : Close button will be shown within the callout window with above objects we can create normal callouts.
Create a webpart page and add script editor webpart and add div with id 'my_callout' and add below code

Callout manager has an extension though which you can create a callout using createNew or createNewIfNecessary depends on requirement to which we need to pass CalloutOptions object.
  1. (function(){      
  2.     SP.SOD.executeFunc("callout.js""Callout"function () {      
  3.     var myCalloutOptions = new CalloutOptions();  
  4.     myCalloutOptions.ID = "my_callout";  
  5.     myCalloutOptions.beakOrientation = "topBottom";  
  6.     myCalloutOptions.title = "my callout";  
  7.     myCalloutOptions.launchPoint = document.getElementById("my_callout");  
  8.     myCalloutOptions.content = "<div id='my_callout_content'>my callout content</div>";  
  9.     myCalloutOptions.openOptions = {  
  10.         closeCalloutOnBlur: false,  
  11.         event: "click",  
  12.         showCloseButton: true  
  13.     }  
  14.     myCalloutOptions.onOpeningCallback = function(clOut){  
  15.         $("#my_callout_content").html("my callout content changed on onOpeningCallback ")  
  16.     };  
  17.     myCalloutOptions.onOpenedCallback = function(clOut){  
  18.         console.log("onOpenedCallback")  
  19.     };  
  20.     myCalloutOptions.onClosingCallback = function(clOut){  
  21.         console.log("onClosingCallback")  
  22.     };  
  23.     myCalloutOptions.onClosedCallback = function(clOut){  
  24.         console.log("onOpeningCallback")  
  25.     };  
  26.   
  27.     var myCallout = CalloutManager.createNew(myCalloutOptions) //it will return callout object  
  28.     });      
  29. })();  
Output


Now let's see Callout,
  • addEventCallback(eventName: string, callback: (callout: Callout) => void): any : Adds event handler to the callout.(eventName: string
  • one of the following: "opened", "opening", "closing", "closed") we can use this to get data using rest api/jsom and change the content of callout
  • close(useAnimation: boolean): any : Hide the callout. Animation can be used only for IE9+
  • getBeakOrientation(): string : Returns the beak orientation defined for the callout during its creation.
  • getContent(): string : Returns the contents of the callout.
  • getID(): string : Returns the ID of the callout.
  • getLaunchPoint(): HTMLElement : Returns the launch point element of the callout.
  • getOpenOptions(): CalloutOpenOptions : Returns the object that represents open behaivor defined for the callout during its creation.
  • getTitle(): string : Returns the title of the callout.
  • open(useAnimation: boolean): any Display the callout. Animation can be used only for IE9+
  • set(options: CalloutOptions): any : Sets options for the callout. Not all options can be changed for the callout after its creation.
  • addAction(action: CalloutAction): any : Adds a link to the actions panel in the bottom part of the callout window
  •  we can create above callout and bind callback functions using addEventCallback on callout
  1. (function(){      
  2.     SP.SOD.executeFunc("callout.js""Callout"function () {      
  3.     var myCalloutOptions = new CalloutOptions();  
  4.     myCalloutOptions.ID = "my_callout";  
  5.     myCalloutOptions.beakOrientation = "topBottom";  
  6.     myCalloutOptions.title = "my callout";  
  7.     myCalloutOptions.launchPoint = document.getElementById("my_callout");  
  8.     myCalloutOptions.content = "<div id='my_callout_content'>my callout content</div>";  
  9.     myCalloutOptions.openOptions = {  
  10.         closeCalloutOnBlur: false,  
  11.         event: "click",  
  12.         showCloseButton: true  
  13.     }  
  14.     var myCallout = CalloutManager.createNew(myCalloutOptions) //it will return callout object  
  15.     myCallout.addEventCallback("opening"function(clOut){  
  16.         $("#my_callout_content").html("my callout content changed on onOpeningCallback ")  
  17.     })  
  18.     myCallout.addEventCallback("opened"function(clOut){  
  19.         console.log("onOpenedCallback")  
  20.     })  
  21.     myCallout.addEventCallback("closing"function(clOut){  
  22.         console.log("onClosingCallback")  
  23.     })  
  24.     myCallout.addEventCallback("closed"function(clOut){  
  25.         console.log("onclosedCallback")  
  26.     })  
  27.     });      
  28. })();  
But in general, callouts are used to highlight the information and take some action(review the item and aprrove/reject/send back) so we need to add some actions to our callout. So using addAction method on callout object we can add actions to callouts. Below we are creating Approve, Reject and Manage which will have Edit/Delete. steps to add callout action.
  1. create a callout menu actions option objects if required
  2. create a callout action option object
  3. create a callout action object using above callout action option
  4. add the callout action to callout by using addAction 
CalloutActionOptions

defines properties of callout actions,
  • disabledTooltip : string : tool tip when action is disabled.
  • isEnabledCallback : (action: CalloutAction) => boolean : Callback which returns if the action link is enabled
  • isVisibleCallback : (action: CalloutAction) => boolean : Callback which returns if the action link is visible
  • onClickCallback : (event: Event, action: CalloutAction) => any : Callback that is executed when the action link is clicked.
  • text : string : Text for the action link
  • tooltip: string : tool tip of action 
  1. var approveActionOptions = new CalloutActionOptions();  
  2. approveActionOptions.disabledTooltip = "Approve";  
  3. approveActionOptions.isEnabledCallback = function(action){  
  4.     //logic to decide enable/disable if not mentioned default is true  
  5.     return true;  
  6. };  
  7. approveActionOptions.isVisibleCallback =  = function(action){  
  8.     //logic to decide hide/show if not mentioned default is true  
  9.     return true;  
  10. };  
  11. approveActionOptions.onClickCallback =  = function(evt, action){  
  12.     //rest api to update;  
  13. };  
  14. approveActionOptions.text = "Approve";  
  15. approveActionOptions.tooltip = "Approve";  
  16.   
  17.   
  18. var rejectActionOptions = new CalloutActionOptions();  
  19. rejectActionOptions.disabledTooltip = "cant rejectas it is created by PRAVEEN";  
  20. rejectActionOptions.isEnabledCallback = function(action){  
  21.     //logic to decide enable/disable if not mentioned default is true  
  22.     return false;  
  23. };  
  24. rejectActionOptions.isVisibleCallback =  = function(action){  
  25.     //logic to decide hide/show if not mentioned default is true  
  26.     return true;  
  27. };  
  28. rejectActionOptions.onClickCallback =  = function(evt, action){  
  29.     //rest api to update;  
  30. };  
  31. rejectActionOptions.text = "Reject";  
  32. rejectActionOptions.tooltip = "Reject";  
CalloutActionMenuEntry

Defines properties of Menu actions, create menu entries and assign them to calloutaction options.
  • constructor(text: string, onClickCallback: (actionMenuEntry: CalloutActionMenuEntry, actionMenuEntryIndex: number) => void, wzISrc: string, wzIAlt: string, wzISeq: number, wzDesc: string): CalloutActionMenuEntry
    • Parameters
    • text: string
    • Text to be displayed as the menu item text
  • onClickCallback: (actionMenuEntry: CalloutActionMenuEntry, actionMenuEntryIndex: number) => void Callback that will be fired when the item is clicked
    1. wzISrc: string
    2. Url of the icon

    3. wzIAlt: string
    4. Alternative text for the icon image
       
    5. wzISeq: number
    6. Sequence for the menu item
       
    7. wzDesc: string
    8. Description of the menu item
  1. var editMenu = new CalloutActionMenuEntry("Edit"function(actionMenuEntry, actionMenuEntryIndex){  
  2.     alert("edit")  
  3. });  
  4.   
  5. var deleteMenu = new CalloutActionMenuEntry("Delete"function(actionMenuEntry, actionMenuEntryIndex){  
  6.     alert("Delete")  
  7. });  
  8.   
  9. var menuEntries = [editMenu, deleteMenu];
  10.  
  11. var reviewActionOptions = new CalloutActionOptions();  
  12. reviewActionOptions.disabledTooltip = "Manage";  
  13. reviewActionOptions.isEnabledCallback = function(action){  
  14.     //logic to decide enable/disable if not mentioned default is true  
  15.     return true;  
  16. };  
  17. reviewActionOptions.isVisibleCallback =  = function(action){  
  18.     //logic to decide hide/show if not mentioned default is true  
  19.     return true;  
  20. };  
  21. reviewActionOptions.text = "Manage";  
  22. reviewActionOptions.tooltip = "Manage";  
  23. reviewActionOptions.menuEntries = menuEntries;  
Add callout actions to callout using CalloutAction;
 
CalloutAction: Object which will host CalloutActionOptions.
  1. var approveAction = new CalloutAction(approveActionOptions);  
  2. var rejectAction = new CalloutAction(rejectActionOptions);  
  3. var reviewAction = new CalloutAction(reviewActionOptions);  
  4. myCallout.addAction(approveAction);  
  5. myCallout.addAction(rejectAction);  
  6. myCallout.addAction(reviewAction);  
Complete code Example. 
  1. (function(){      
  2.     SP.SOD.executeFunc("callout.js""Callout"function () {    
  3.     //Define Callout Options    
  4.     var myCalloutOptions = new CalloutOptions();  
  5.     myCalloutOptions.ID = "my_callout";  
  6.     myCalloutOptions.beakOrientation = "topBottom";  
  7.     myCalloutOptions.title = "my callout";  
  8.     myCalloutOptions.launchPoint = document.getElementById("my_callout");  
  9.     myCalloutOptions.content = "<div id='my_callout_content'>my callout content</div>";  
  10.     myCalloutOptions.openOptions = {  
  11.         closeCalloutOnBlur: false,  
  12.         event: "click",  
  13.         showCloseButton: true  
  14.     }  
  15.   
  16.     //Creat a callout using callout manager  
  17.     var myCallout = CalloutManager.createNew(myCalloutOptions) //it will return callout object  
  18.       
  19.     //Add Events  
  20.     myCallout.addEventCallback("opening"function(clOut){  
  21.         $("#my_callout_content").html("my callout content changed on onOpeningCallback ")  
  22.     })  
  23.     myCallout.addEventCallback("opened"function(clOut){  
  24.         console.log("onOpenedCallback")  
  25.     })  
  26.     myCallout.addEventCallback("closing"function(clOut){  
  27.         console.log("onClosingCallback")  
  28.     })  
  29.     myCallout.addEventCallback("closed"function(clOut){  
  30.         console.log("onclosedCallback")  
  31.     })  
  32.   
  33.     //Adding Actions  
  34.   
  35.     //Create Action Options  
  36.     var approveActionOptions = new CalloutActionOptions();  
  37.     approveActionOptions.disabledTooltip = "Approve";  
  38.     approveActionOptions.isEnabledCallback = function(action){  
  39.     //logic to decide enable/disable if not mentioned default is true  
  40.         return true;  
  41.     };  
  42.     approveActionOptions.isVisibleCallback = function(action){  
  43.         //logic to decide hide/show if not mentioned default is true  
  44.         return true;  
  45.     };  
  46.     approveActionOptions.onClickCallback = function(evt, action){  
  47.         //rest api to update;  
  48.     };  
  49.     approveActionOptions.text = "Approve";  
  50.     approveActionOptions.tooltip = "Approve";  
  51.   
  52.   
  53.     var rejectActionOptions = new CalloutActionOptions();  
  54.     rejectActionOptions.disabledTooltip = "cant rejectas it is created by PRAVEEN";  
  55.     rejectActionOptions.isEnabledCallback = function(action){  
  56.         //logic to decide enable/disable if not mentioned default is true  
  57.         return false;  
  58.     };  
  59.     rejectActionOptions.isVisibleCallback = function(action){  
  60.         //logic to decide hide/show if not mentioned default is true  
  61.         return true;  
  62.     };  
  63.     rejectActionOptions.onClickCallback = function(evt, action){  
  64.         //rest api to update;  
  65.     };  
  66.     rejectActionOptions.text = "Reject";  
  67.     rejectActionOptions.tooltip = "Reject";  
  68.       
  69.   
  70.     //Menu Actions Entries  
  71.     var editMenu = new CalloutActionMenuEntry("Edit"function(actionMenuEntry, actionMenuEntryIndex){  
  72.         alert("edit")  
  73.     });  
  74.   
  75.     var deleteMenu = new CalloutActionMenuEntry("Delete"function(actionMenuEntry, actionMenuEntryIndex){  
  76.         alert("Delete")  
  77.     });  
  78.   
  79.     var menuEntries = [editMenu, deleteMenu];  
  80.       
  81.     //Action with Menu entries  
  82.     var reviewActionOptions = new CalloutActionOptions();  
  83.     reviewActionOptions.disabledTooltip = "Manage";  
  84.     reviewActionOptions.isEnabledCallback = function(action){  
  85.         //logic to decide enable/disable if not mentioned default is true  
  86.         return true;  
  87.     };  
  88.     reviewActionOptions.isVisibleCallback = function(action){  
  89.         //logic to decide hide/show if not mentioned default is true  
  90.         return true;  
  91.     };  
  92.     reviewActionOptions.text = "Manage";  
  93.     reviewActionOptions.tooltip = "Manage";  
  94.     reviewActionOptions.menuEntries = menuEntries;  
  95.   
  96.     //Creating Callout Actions  
  97.     var approveAction = new CalloutAction(approveActionOptions);  
  98.     var rejectAction = new CalloutAction(rejectActionOptions);  
  99.     var reviewAction = new CalloutAction(reviewActionOptions);  
  100.   
  101.     //Adding Actions to callout  
  102.     myCallout.addAction(approveAction);  
  103.     myCallout.addAction(rejectAction);  
  104.     myCallout.addAction(reviewAction);  
  105.     });      
  106. })();   
 Final output
 
 
 All is well...