Wednesday 21 August 2013

Predictive search on a field in standard page with home page components


I had a requirement to add a predictive search (auto complete) on a field in standard page. The exact requirement was like whenever the user types some characters on a field then automatically a suggestion drop down should come and that should list all the values currently in the system for that field.

The requirement can be easily fulfilled by home page component, little java script and jQuery.

I am not going to discuss how can we add home page component to a standard page, all the documentation is available from sales force.

I have used the following code in my home page component

<link rel="stylesheet" href="https://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.9.1.js"></script>
<script src="https://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<link rel="stylesheet" href="/resources/demos/style.css">
<script src="/soap/ajax/15.0/connection.js" type="text/javascript"></script>
<script src="/soap/ajax/15.0/apex.js" type="text/javascript"></script>
<script>
var url = document.URL;
if(url.indexOf('006')!=-1)    
{        
        var sid = document.cookie.match(' sid=([^;]*)')[1];        
        sforce.debug.trace=true;        
        sforce.connection.sessionId = sid;        
        var stages = sforce.apex.execute("opportunitySearch", "getFieldValues", {});        
        var staheArray = stages.toString().split("+");        
        $ = jQuery.noConflict();       
        $(function()             
        {                
            var availableTags = staheArray;               
            $( "#00N90000006ikQJ" ).autocomplete({source: availableTags});           
        }        );    
}
</script>

I have created the below apex class for the above code to work.
global class opportunitySearch{ 
   webService static String getFieldValues()
   {
       String pickValues='';
       for( Schema.PicklistEntry f : Opportunity.StageName.getDescribe().getPicklistValues())
       {
           pickValues = pickValues +f.getValue()+'+';
       }         
       return pickValues ;
   }
}



EXPLANATION

Since sales force allows us to execute java script code from home page component we can use JavaScript or jQuery to implement some functionality in a standard page through home page component. Here I need to fetch the data from back end and populated it on the page I should be able to execute some query/apex code to do that. In the above example I fetch all the opportunity stage values from a pick list and populated on another field on the standard page.

To execute the apex class from java script I cannot use the java scrip remoting since it is not supported in the home page component. So I used sales force ajax toolkit to establish the connection between home page component and apex class.


The below lines of code is required for the Ajax tool kit to work.


<script src="/soap/ajax/15.0/connection.js" type="text/javascript"/>

<script src="/soap/ajax/15.0/apex.js" type="text/javascript"/>
 



Then I took the sales force session id from cookie through java script , the below line of code does that

document.cookie.match(' sid=([^;]*)')[1];


As we got the seesion id we need to set it on the sales force connection. Once we set the session id for sfoce we can execute the apex method from a class using the below piece of code

sforce.apex.execute(“Give apex class name here”,”Give apex methos here “,{“give apex method parameters here”});
The apex class should be declared as global and we need to have a webservice method also be there in the class for java script to execute. In the apex class I have got all the picklist values and I made it as a string separated with + sign. So the method returns all the picklist values separated with + symbol.
So in the java script I filter each status value with reference to the + symbol and I moved them into an array (stageArray).

From now I am using the jQuery to do the autocomplete job through autocomplete () function on a particular element by using the element id.
 

Thursday 15 August 2013

How to populate textbox in a pageblock table based on a checkbox and input text box using java script

Sometimes it might be hurting if you have a page block and records have a check box, and you want to update all/some the records particular field value based on one input text box. All move into <apex: actionFunction>, but there is a good option with JavaScript.
The advantages of using JavaScript here is
  1.  No delay in populating the field values, it’s getting populated instantly.
  2.  You don’t need your browser to send request to server, resources are saved. 
  3.  The old values for each field can be recovered instantly  if someone wrongly fill the field value before saving the record
The visual force page code is given below.

 

 
        
        

        Name

        
        

apex:column >

The controller for the above class is :
public with sharing class AccountList 
{
 public string infrmpage{get;set;}
 Map mapAccount = new Map();
 List listAccount = new List();
 
 public class accounts
 {
  public boolean selected{get;set;}
  public String name{get;set;}
  public String type{get;set;}
  public String test{get;set;}
  public Id accid{get;set;}
 }
 public List accList = new List();
 public string text{get;set;}
 
 public AccountList() 
 {
 }
 public String test{get;set;}
 
 public AccountList(ApexPages.StandardController controller) 
 {
 }
 
 public List getAccounts()
 {
  accList.clear();
  for(Account a: [select id,name,type, test__c from account where Name!=null limit 10])
  {
   Accounts acc = new Accounts();
   acc.name = a.name;
   acc.type = a.type;
   acc.test = a.test__c;
   acc.accid = a.id;
   accList.add(acc);
   mapAccount.put(a.id,a);
  }

  return accList;
 }
 
 public void saveAll()
 {
  listAccount.clear();
  
  for(Accounts ac :accList)
  {
   if(ac.selected)
   {
    Account a = mapAccount.get(ac.accid);
    a.test__c = infrmpage;
    listAccount.add(a);
   }
  }
  update listAccount;
 }
}


Explanation:

1.Java Script

The method1 javascript function gets called whenever there is a change happen on the input text box. The parameter passed into the method1 function is the input text box element id from the page. So I will get the element value in script using id.

I used apex input text box for showing the text box in pageblock table. And then I fetched all the input text elements from the page using java script function-document.getElementsByTagName("input");
So inside the list of input elements I have all my check boxes and input text boxes and I need to filter them. To filter the elements I have placed id for each text boxes and check boxes. Based on the id of the element I have filtered the elements and I copied text box elements into an array textbox in java script.
Next, I want to link the checkboxes and text boxes since I have to populate the text box based on the check box.  So here in the second if condition inside the for loop I am filtering the input check boxes. Then I am checking whether it’s checked or not. If yes then I am adding index of the text box element  to an array[updateElmnts] where I need to update the value.  From my analysis the index for corresponding text boxes = index of checkbox+1.

So the updateElmnts array contains the index of the page block input text boxes which needs to be updated with value from the input text box.

Finally the second for loop update the page block input text box value with text entered in the input text box.
 
The text box elements got input text box values in UI.

The second java script function dataCheck() is used to populate the input text box data into a record once the user moved out from the input text box and clicked on the input check box later. Also it does the recover function if the user uncheck the check box.

The three parameters for the dataCheck() functions are
  •   elem – Input check box element id
  •   input – input text box element id
  •   updateele – the text box id which needs to be updated.


2. Apex Class

To update the same values in the controller I have used the following.

  1. To get the text box values from page I get-set a string variable (infrmpage).
  2. I used the wrapper class to populate the elements to the page block table, and in the save method I am checking if the corresponding element is checked in the page. If yes then I will populate the element field value from the input text box value from the page. And finally I will do an update on the element to save update to the data base.

Force.com and Google integration with oAuth Authentication





In this post I will be explaining how to integrate Google Calendar with Sales force.com.Once we are integrated,  the events in the Google Calendar will get synced with Sales force.

The summary of oAuth Authentication


First create an Api project in Google.

Redirect the user to Google oAuth Authentication url, Then will user asked to login to the Google.

Once the user successfully logged in then Google redirect the user to the application. While redirecting the user to application, Google add a code parameter in the url, that indicates the proof of authentication. The code is called authentication code.

The user then request for two other tokens: access token, refresh token. The access token will expire in one hour for offline based access and we use refresh token to get new access token after it expires. So we need to store the refresh token in the system for future access. Google recommends storing refresh token along with user id and making the user id as an indexed field in database. 


Step 1: Create an API Project in Google API Console

API Project determines which API the client is allowed to utilize from external application via oAuth authentication. 

Goto  https://code.google.com/apis/console/

Google ask you to sign in first

If you don’t have any project created then the below screen will get displayed.





Click on Create Project it will direct you to choose API for your project.
By default all the API services are disabled.


Click on the off button in next to the Calendar API and activate the Google Calendar API.
Click on the API Access on the sidebar.



Click on Create oAuth 2.0 Client ID button, It will ask you to enter the product name, logo,Branding info, home page with etc..

Click next and it will ask Client ID settings here choose Application Type as Web Application.

Click on More Option link

In the first text box enter the url to which Google redirect the user once Authentication is succeeded.
And click on Create Client ID.

This will create Client Id , Client secret etc. for API Project.


Step 2: Authenticate with Google from Sales force.com.
To authenticate with Google in oAuth authentication redirect the user to the url below.

https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force&client_id=<INSERT YOUR CLIENTID HERE>&redirect_uri=<INSERT YOUR REDIRECT URL HERE >&response_type=code&scope=https://www.googleapis.com/auth/calendar

This redirect uri should be same as the redirect url given in the API Project otherwise Google will reject the request.

Once the user is successfully redirected to Google the user will be prompted to enter the credentials and the user will be redirected to the redirect uri specified in the api project.The redirected url from Google contains code parameter as well. This code is the authentication code for the auth Authentication, this will be used in the later part for getting access token and refresh token.


Once you get the authentication code then we can request for the access token, refresh token.
For every API request to Google requires access token and this access token will expire in one hour for offline based access. To get new access token we need to make another request with help of refresh token to receive new access token.

To request for access token you need

1.Authentication code
2.Client Id, Client secret.
3. Redirect uri of your API project.
The apex code for getting new access and refresh token is give below. The response from Google is in the form of JSON object.

Before making the external request add the endpoint url to the sales force remote sites. The remotes sites can be found under setup-> Security Controls-> Remote Site Settings.

 

http htp = new http();//Creating instance of http object
HttpRequest htp_req =  new HttpRequest();//Creating instance of http request object
HttpResponse htp_res = new HttpResponse();//Creating instance of http response object
htp_req.setMethod('POST'); //Creating instance of http request type
htp_req.setEndPoint('https://accounts.google.com/o/oauth2/token');//To which url the request is made.
String body = 'code='+[insert authentication code]+'&&redirect_uri=[insert redirect uri here]&[insert client id here] &scope=&client_secret=[insert client secret here]&grant_type=authorization_code';
htp_req.setBody(body);
try
        {
            htp_res = htp.send(htp_req);            
            JSONParser parser = JSON.CreateParser(htp_res.getBody());
            while(parser.nextToken()!=null)
            {
                if(parser.getText()=='access_token')
                {
                    parser.nextToken();
                    accessToken = parser.getText();
                }
                if(parser.getText()=='refresh_token')
                {
                    parser.nextToken();
                    refreshToken = parser.getText();
                }
            }
        }
        catch(Exception ex)
        {
            System.debug(htp_res+','+ex.getMessage());
        }

Once we are received the access token and refresh token we can make all supported API request.
3.Sample API Request to get all calenders.


Example to List all the calendars from a Google account.

http hp = new http();

httpRequest req = new httpRequest();

httpResponse res = new httpResponse();

req.setMethod(‘GET’);


req.setHeader(‘Authorization’,’Bearer ‘+<INSERT ACCESS TOKEN HERE);


req.setEndPoint(‘https://www.googleapis.com/calendar/v3/users/me/calendarList‘);

try

{ 

res = hp.send(req);

return res.getBody();

}

catch(Exception e)

{

System.debug('********EXCEPTION**********'+e.getMessage());

return null;

}


The response JSON object contain the list of calendars for currently login.

Finally Google allows developers to test the api request in oAuth playground. This is just an environment to learn how to use API requests and see responses in real time.
The url for oAuth playground is : https://developers.google.com/oauthplayground