4Example of Customizing Siebel Open UI

Example of Customizing Siebel Open UI

Roadmap for Customizing Siebel Open UI

You do the following tasks to customize Siebel Open UI:

You can use this sequence as a general guideline to create your own customizations. To summarize, you do the following work:

  • Modify a presentation model. You customize the presentation model that implements the recycle bin that contains the records that a user deletes in a view. You add a Select list column and modify the Delete button so that the user can choose more than one record, and then delete them from the server database. You configure Siebel Open UI to do a local backup on the client of the chosen records. This configuration requires you to modify the metadata that Siebel Open UI uses in the client and to modify client behavior. It does not require you to modify rendering. So, you only modify the presentation model. You do not modify the physical renderer to implement this part of the example.

  • Modify a physical renderer. You customize a physical renderer for a third-party carousel control that displays the recycle bin contents and that allows the user to restore deleted records. You modify the physical renderer so that Siebel Open UI displays a local back up copy of the deleted records in a carousel control, and then allows the user to choose and restore each of these records. This configuration modifies the physical representation of the records so that Siebel Open UI displays them in a modified grid. It also modifies the physical interactivity that allows the user to choose records in the carousel.

  • Modify a plug-in wrapper. You customize a specific control by writing a plug-in wrapper (PW). In this example, if the customization is on the Opportunity List applet, a custom PW will be written for the probability field which will add a colorbox to the field, which will then change colors based on the value in the probability field. Also, clicking on the box will open a legend that explains the colors.

For background information about the architecture that this example uses, see Stack That Siebel Open UI Uses to Render Objects and Life Cycle of User Interface Elements.

Creating the Presentation Model

This task is a step in Process of Customizing the Presentation Model.

The presentation model uses the Init method to configure the properties, methods, and bindings of the presentation model, and the Setup method to extract the values that a property set contains. For more information about these methods, see Life Cycle of User Interface Elements.

The following figure illustrates the code you use to create the presentation model. Each number in this figure identifies the corresponding step number in the numbered task list that this book includes immediately after this figure.

Setting Up the Presentation Model

To create the presentation model

  1. Create the custom presentation model file:

    1. Download a copy of the recyclebinpmodel.js file to the following folder:

      INSTALL_DIR\applicationcontainer\webapps\siebel\scripts\siebel\custom
      

      This topic describes how to modify code that resides in the recyclebinpmodel.js file. It is recommended that you get a copy of this file to assist in your understanding of how to implement the example that this topic describes. This file includes all the code that this example uses. It also includes more comments that describe code functionality. To get a copy of this file, see Article ID 1494998.1 on My Oracle Support.

      For more information about the folders you can use to store your customizations, see Organizing Files That You Customize. For more information about the language_code, see Languages That Siebel Open UI Supports.

    2. Use a JavaScript editor to open the recyclebinpmodel.js file that you downloaded in Step a.

  2. Make sure the RecycleBinPModel class does not exist and that you do not configure Siebel Open UI to override this class. You add the following code:

    if(typeof(SiebelAppFacade.RecycleBinPModel) === "undefined"){
    
  3. Make sure a namespace exists that Siebel Open UI can use to prevent conflicts:

    SiebelJS.Namespace("SiebelAppFacade.RecycleBinPModel");
    
  4. Use the Define method to identify the presentation model file:

    define("siebel/custom/recyclebinpmodel", [], function(){
    

    You must use the Define method to make sure Siebel Open UI can identify the constructor. You must include the relative path and the name of the presentation model file without the file name extension. For more information, see Define Method.

  5. Define the class:

    SiebelAppFacade.RecycleBinPModel = (function(){
    
  6. Load the SiebelApp.Constants namespace that defines the constants that Siebel Open UI uses:

    var consts = SiebelJS.Dependency("SiebelApp.Constants"); 
    
  7. Define the class constructor:

    function RecycleBinPModel(){
      SiebelAppFacade.RecycleBinPModel.superclass.constructor.apply(this, arguments);
    }
    
  8. Set up the injected dependency:

    SiebelJS.Extend(RecycleBinPModel, SiebelAppFacade.ListPresentationModel);
    

    For more information about injected dependency, see About Dependency Injection.

  9. Return the constructor:

    return RecycleBinPModel;
      } ());
      return "SiebelAppFacade.RecycleBinPModel";
    });
    
  10. Save the recyclebinpmodel.js file.

Customizing the Setup Logic of the Presentation Model

This task is a step in Process of Customizing the Presentation Model.

In this topic, you customize the setup logic of the presentation model so that it adds the Selected list column to an applet. You add the control that you configure for this example to the ListColumns list that resides in the client.

The following figure illustrates the code you use to customize the setup logic of the presentation model. Each number in this figure identifies the corresponding step number in the numbered task list that this book includes immediately after this figure.

Customizing the Setup Logic of the Presentation Model

To customize the setup logic of the presentation model

In the recyclebinpmodel.js file, identify the property or method of the object that you must modify.

  1. To do this identification, you can examine the JavaScript API methods to identify the method that most closely matches the behavior that your example requires. For more information about this JavaScript API, see Application Programming Interface

    You can use the following list as a guide to get you started, depending on the area of the Siebel application that your customization must modify:

    In this example, you can examine the presentation model that Siebel Open UI uses for list applets to identify the property or method that the object you must modify uses. To identify this property, see Properties of the Presentation Model That Siebel Open UI Uses for Applets.

    After examining these properties, assume that you determine that Siebel Open UI uses the GetListOfColumns method that the presentation model references. In general, when you examine a property or method in a list applet, it is recommended that you first examine the list presentation model that a list uses, and then the applet presentation model that a form applet uses.

    You must add the Selected list column to a list applet. The Selected list column is a control that Siebel Open UI displays in the client. So, you add it to the list of listOfColumns that Siebel Open UI already uses.

  2. Specify the method that the presentation model runs as part of the Setup life cycle:

    RecycleBinPModel.prototype.Setup = function(propSet){
    

    In this example, you configure Siebel Open UI to create a control that it displays only in the client, and then insert it into the GetListOfColumns property of the applet. You add this code in the Setup life cycle method of the presentation model because this logic is related to the work that Siebel Open UI does to create the applet. Siebel Open UI must create the applet first, and then insert the control. For more information, see Summary of Presentation Model Methods.

  3. Create a new instance of the AppletControl object:

    var mycontrol = SiebelApp.S_App.GetAppletControlInstance
    

    This example requires Siebel Open UI to create a new listOfColumns and to add it to the GetListOfColumns array. You can use the GetAppletControlInstance method to create a new instance of the AppletControl object. For more information, see GetAppletControlInstance Method.

  4. Name the instance:

    "Client_Select",
    

    You must specify a unique name for the instance. This example uses Client_Select, which is a unique value that Siebel Open UI can use to determine the operation that it must perform.

  5. Specify the control type:

    consts.get("SWE_CTRL_CHECKBOX"),
    "Select",
    "Select",
    "50");
    this.Get("GetListOfColumns")["SelectionBox"] = mycontrol;
    SiebelAppFacade.RecycleBinPModel.superclass.Setup.call(this, propSet);
    };
    

    where:

    • consts.get("SWE_CTRL_CHECKBOX") specifies the control as a check box.

    • Select specifies the display name. You can specify any display name.

    • 50 specifies the width of the column.

    For more information about control types, see Applet Control Class.

  6. Save the recyclebinpmodel.js file.

Customizing the Presentation Model to Identify the Records to Delete

This task is a step in Process of Customizing the Presentation Model.

In this topic, you modify the list column control that you created in Step 3. This control uses a check box, so you must make sure that Siebel Open UI stores the value of this check box when the user toggles it.

The following figure illustrates the code that you use to customize the presentation model logic to identify the records to delete. Each number in this figure identifies the corresponding step number in the numbered task list that this book includes immediately after this figure.

Customizing the Presentation Model Logic to Identify the Records to Delete

To customize the presentation model to identify the records to delete

  1. In the recyclebinpmodel.js file, add the method that Siebel Open UI must call:

    this.AddMethod("LeaveField", PreLeaveField, {sequence:true, scope:this});
    

    where:

    • AddMethod adds the LeaveField method. To identify the method that you must add when you do your own customization work, you can examine the life cycles that Siebel Open UI uses that most closely meets your business requirement. To view these life cycles, see Life Cycle Flows of User Interface Elements.

    • In this example, the business requirement is to save the value in a control. Siebel Open UI saves the value of a control when the user navigates away from the control, so it calls the LeaveField method to handle this requirement. For more information, see LeaveField Method and Flow That Handles Focus Changes in List Applets.

    • PreLeaveField, {sequence : true, scope : this} configures Siebel Open UI to call your custom LeaveField method before it calls the predefined LeaveField method. It does this during the Init life cycle when it runs the AddMethod method. It is recommended that you set up the presentation model methods at the beginning of the Init life cycle call that contains most of the properties and dependency injections, including predefined and custom methods. For more information about Init, see Life Cycle of User Interface Elements. For more information, see About Dependency Injection.

    It is recommended that you use a named method to specify the Prexxx customization method, such as PreLeaveField. This configuration makes sure that Siebel Open UI uses the same method for all presentation model instances. It is not recommended that you specify the Prexxx customization method as an anonymous method in the AddMethod call because Siebel Open UI creates this anonymous method for every presentation model instance that resides in memory, possibly for more than one applet in the same view. Defining an anonymous method in this situation might cause a conflict.

  2. Create the condition:

    if (ctrl.GetName() === "Client_Select"){
    

    The Setup method uses the GetName method with a literal return value of Client_Select. It identifies the method that Siebel Open UI uses for your custom control. For more information, see GetName Method for Applets.

  3. Make sure Siebel Open UI returns your custom logic after it sets the CancelOperation part of the return value to true:

    returnStructure[ "CancelOperation" ] = true;
    

    This configuration overrides the predefined code when Siebel Open UI calls LeaveField for your new list column. In this example, you must implement LeaveField for the control, so it is not desirable to call the predefined code for this control after Siebel Open UI finishes running your customization of the LeaveField method. For more information about using ReturnStructure when you modify a method, see AddMethod Method.

  4. Configure Siebel Open UI to return a value of true after it sets the CancelOperation part of returnStructure to true:

    returnStructure[ "ReturnValue" ] = true;
    

    The LeaveField method returns a value of true to indicate success in this example, so you must make sure Siebel Open UI uses the same logic after your customization finishes running and returns a value. This configuration makes sure the Init life cycle continues on the success path after the custom LeaveField method runs. You can use ReturnValue to make sure Siebel Open UI sets the return value of your custom implementation to the required value. In this example, you set this value to true.

  5. Disable the processing that Siebel Open UI does for the control that is in focus:

    this.ExecuteMethod("SetActiveControl", null);
    

    This code sets the active control to null. For more information, see Disabling Automatic Updates and SetActiveControl Method.

  6. Add the property that Siebel Open UI uses to store the set of records that are pending deletion:

    this.AddProperty("DeletionPendingSet", []);
    

    The set of records that are pending deletion represent the state of your custom presentation model, so you add the DeletionPendingSet property to store the field values for this set of records.

  7. Identify the records that Siebel Open UI must delete:

    var delObj = this.Get("DeletionPendingSet");
    var currentSelection = this.Get("GetSelection");
    if(value === "Y"){
      delObj[currentSelection] = this.Get("GetRecordSet")[currentSelection];
    }
    else{
      delObj[currentSelection] = null;
    }
    

    Siebel Open UI must identify the records that the user chooses to delete so that it can populate a value into the DeletionPendingSet property. To identify this property, you can examine the properties that the presentation model uses for the applet. This work is similar to the work you do in Step 1 to identify the property in the presentation model that Siebel Open UI uses for lists, except in this topic you examine the properties described in Properties of the Presentation Model That Siebel Open UI Uses for List Applets.

    After examining these properties, assume you determine that Siebel Open UI uses the GetSelection property to get the index of the record that the user has chosen from among all the records that Siebel Open UI displays. You also determine that you can use the GetRecordSet property to get this full set of records.

  8. Save the recyclebinpmodel.js file.

About Dependency Injection

Dependency injection is a software development technique that Siebel Open UI uses to create a dependency between a presentation model and a physical renderer. If Siebel Open UI modifies a method or property that resides in the presentation model, then it also modifies a method or property that resides in the physical renderer. It allows Siebel Open UI to implement logic at run-time rather than during a compile. These dependency injections allow it to use an injected dependency chain, which is a series of two or more dependency injections.

You can modify Siebel Open UI to make this chaining depend on conditions that Siebel Open UI modifies at run time. It can use all the methods that the Init method references in Summary of Presentation Model Methods for dependency injection. For an example that uses dependency injection, see Customizing the Physical Renderer to Refresh the Carousel.

Disabling Automatic Updates

Siebel Open UI sends updated field values to the Siebel Server for any fields that the user has modified in the client. In this example, you must disable this update functionality for the current control. You can reference the documentation for the predefined applet to identify the presentation model property that you must modify. In this situation, the documentation indicates that you can configure Siebel Open UI to use the SetActiveControl property of the active control on the applet and set it to null. For more information, see Disabling Automatic Updates, SetProperty Method, and SetActiveControl Method.

ExecuteMethod calls a method that the presentation model references. It makes sure that Siebel Open UI runs all injected dependency chains that the method requires when it runs. You must use ExecuteMethod to call any predefined or custom method that a presentation model references. For more information, see About Dependency Injection and ExecuteMethod Method.

Customizing the Presentation Model to Delete Records

This task is a step in Process of Customizing the Presentation Model.

The following figure illustrates the code you use to configure the presentation model to delete records. In this topic, you configure Siebel Open UI to customize and conditionally override the InvokeMethod method. Each number in this figure identifies the corresponding step number in the numbered task list that this book includes immediately after this figure.

Customizing the Presentation Model to Delete Records

To customize the presentation model to delete records

  1. In the recyclebinpmodel.js file, add the method that Siebel Open UI uses to delete a record:

    this.AddMethod("InvokeMethod", PreInvokeMethod, {sequence:true, scope:this});
    

    You must identify the method that Siebel Open UI uses when the user clicks Delete. To do this identification, it is recommended that you examine the flowchart that Siebel Open UI uses during a typical life cycle when it calls methods that reside on the Siebel Server. For this example, the life cycle flowchart indicates that Siebel Open UI calls the DeleteRecord method when it calls the InvokeMethod method. You add this code in the Init method. For more information, see Life Cycle Flows That Create New Records in List Applets and DeleteRecord Method.

    This configuration is similar to the configuration you added in Step 1 in the topic Creating the Presentation Model that includes the AddMethod method and the sequence statement.

  2. Call the custom logic only if Siebel Open UI calls the DeleteRecord method:

    if ((methodName === "DeleteRecord") && !this.Get("InDeletion")){
    

    This code examines the value of the InDeletion property.

  3. Set the InDeletion property to true only if Siebel Open UI starts the deletion process:

    this.SetProperty("InDeletion", true);
    

    This code determines whether or not Siebel Open UI is already running an instance of your custom delete process, and then makes sure that no more than one of these instances runs at the same time. The InDeletion property determines whether or not the deletion process is currently running.

    You could use the following code in the Init method to add this property:

    this.AddProperty("inDeletion", false)
    

    This example demonstrates how you can use SetProperty to use a property temporarily so that it is similar to a conditional flag. This example uses SetProperty to create this property only when necessary. If Siebel Open UI calls the Get method before it calls the SetProperty method, then the JavaScript returns a value of undefined, which is the default value that JavaScript assigns to any variable that is not defined.

  4. Get the set of records where the Selected value of each of these records includes a check mark:

    var deletionPending = this.Get("DeletionPendingSet");
    

    This code gets the state of the set of records before the user clicks Delete. Siebel Open UI stores this information in the DeletionPendingSet property in the LeaveField customization that you added in Step 6.

  5. Determine whether or not the user has chosen at least one record for deletion:

    if (deletionPending.length > 0){
    

    This code represents this condition as > 0, where 0 indicates the number of records chosen.

  6. Iterate through all the records that the user has chosen to delete:

    for (var counter = deletionPending.length - 1; counter >= 0; counter--){
      var currentObj = deletionPending[counter];
      if (currentObj){
      }
    }
    
  7. Disable the processing that Siebel Open UI does for the control that is in focus:

    For more information, see Disabling Automatic Updates and SetActiveControl Method.

    this.ExecuteMethod("SetActiveControl", null);
    
  8. Modify the application state so that Siebel Open UI references the record that it must delete:

    this.ExecuteMethod ("HandleRowSelect", counter, false, false);
    

    To identify this code when you customize Siebel Open UI, it is recommended that you examine Flow That Handles Navigation to Another Row in List Applets. In this example, this flow indicates that you must use the HandleRowSelect method. The presentation model that Siebel Open UI uses for list applets references HandleRowSelect, so you can configure Siebel Open UI to use ExecuteMethod to call it. For more information, see HandleRowSelect Method.

  9. Make sure that Siebel Open UI can call the DeleteRecord method:

    if(this.ExecuteMethod("CanInvokeMethod", "DeleteRecord")){
    

    It is recommended that you configure Siebel Open UI to call CanInvoke before it calls another method to make sure that it can call this other method in the context of the object that is currently in scope. Siebel Open UI can use the CanInvoke method to model complex logic for any record that exists in the Siebel Database that resides on the Siebel Server. This logic can determine whether or not Siebel Open UI can call an operation according to the scope that it applies to the current object, such as a record that is in scope. In this example, it determines whether or not it can call the DeleteRecord method.

    You can use the method descriptions in Application Programming Interface to identify the method that you must use in your customization work.

    For more information about the method that this example uses, see CanInvokeMethod Method for Presentation Models.

  10. Add a property that Siebel Open UI can use to store information about the records that it sends to the Siebel Server for deletion:

    this.AddProperty("ObjectsUnderDeletion", []);
    
  11. Delete the record:

    this.Get("ObjectsUnderDeletion")[this.Get("GetSelection")] = currentObj;
    var inputPS = SiebelApp.S_App.NewPropertySet();
    this.ExecuteMethod ("InvokeMethod", "DeleteRecord", inputPS);
    

    where:

    • ObjectsUnderDeletion inserts the record into a backed up record set, and if this insert occurs at an index location that is equal to the index of the selected row, then Siebel Open UI can reference the selected row to identify the correct index to use when processing the NotifyDeleteNotification reply. The Siebel Server sends this reply. Siebel Open UI must identify the record where it set the notification when it handles the NotifyDeleteNotifications notification. You can configure Siebel Open UI to call HandleRowSelect to select the row before it sends the request to delete the record.

    • GetSelection is a property of the applet presentation model that includes an index that identifies the chosen record. This record resides in the record set that resides in the client. When you develop your own customization, you can reference the documentation to identify the property that your customization requires. For more information, see Properties of the Presentation Model That Siebel Open UI Uses for Applets.

    • InvokeMethod is a method that resides in the presentation model that Siebel Open UI uses for a list applet. You can use ExecuteMethod to call it.

    • false configures Siebel Open UI to make a synchronous request to the Siebel Server. A synchronous request makes sure that Siebel Open UI sends all DeleteRecord requests to the server before it exits the loop. If it exits the loop during a synchronous request, then it sends all DeleteRecord requests sequentially. In this situation, it sends the requests to the server so that the server can process a reply for the previous request, including the delete completion notifications. The server does this processing during a synchronous request before it sends the next DeleteRecord request.

  12. Set the DeletionPendingSet property to zero:

    this.SetProperty("DeletionPendingSet", []);
    

    This code sets the DeletionPendingSet property to zero after Siebel Open UI finishes running all the DeleteRecord calls on the Siebel Server.

  13. Set the CancelOperation member of the returnStructure to true:

    returnStructure ["CancelOperation"] = true;
    

    You configure Siebel Open UI to set this member before it exits the outer loop that processes the deletionPending records. You do this so that Siebel Open UI does not use the DeleteRecord argument to make another call to the predefined InvokeMethod method. For more information about ReturnStructure, see AddMethod Method.

  14. Set the InDeletion flag to false:

    this.SetProperty("InDeletion", false);
    

You configure Siebel Open UI to set this property before it exits the conditional block that does the InvokeMethod processing for the DeleteRecord method.

Save the recyclebinpmodel.js file.

About Synchronous Requests

A synchronous request is a type of request that Siebel Open UI sends to the Siebel Server, and then waits for a reply to this request before it continues any other processing.

The GetSelection request is synchronous, so Siebel Open UI cannot send another request to move the selection to a different record before the Siebel Server sends a reply notification that indicates a successful deletion. When processing this notification, the intended row is the same row that Siebel Open UI most recently selected. Siebel Open UI can use the selected row as a common index that it can use to reference the record.

Overriding Predefined Methods in Presentation Models

This task is a step in Process of Customizing the Presentation Model.

If Siebel Open UI calls the GetFormattedFieldValue method for a control that it only displays in the Siebel Open UI client, then this client cannot not find the field in the list of fields that it uses, and the client creates an error. To avoid this situation, in this topic you customize Siebel Open UI to override the predefined GetFormattedFieldValue method so that it does not create an error when it calls GetFormattedValue for your new list column. For more information, see GetFormattedFieldValue Method.

To override predefined methods in presentation models

  1. Use the flowcharts to identify the method that you must modify.

    Siebel Open UI displays values for applet controls and list columns after it gets these values from the client. It caches these values in the client after it downloads them from the Siebel Server. To identify the method that handles these values, you can examine the flowchart that describes how Siebel Open UI creates a new record in a list applet, and then updates the client. In this example, the flowchart indicates that it calls the GetFormattedFieldValue method. If the physical renderer requires the ShowControlValue method, then it calls the presentation model to run the GetFormattedFieldValue method. For more information, see Flows That Create New Records in List Applets, Updating the User Interface.

  2. In the recyclebinpmodel.js file, configure Siebel Open UI to conditionally override and customize the method:

    RecycleBinPModel.prototype.Init = function(){
      SiebelAppFacade.RecycleBinPModel.superclass.Init.call(this);
      this.AddMethod("GetFormattedFieldValue", PreGetFormattedFieldValue, 
    {sequence:true,scope:this});
      .
      .
      .
    function PreGetFormattedFieldValue(control, bUseWS, recIndex, returnStructure){
      if (control.GetName() === "Client_Select"){
        returnStructure["CancelOperation"] = true;
        returnStructure["ReturnValue"] = "";
      }
    }
    

    Where:

    • this.AddMethod adds the PreGetFormattedFieldValue method in the Init life cycle and specifies PreGetFormattedFieldValue as the customization.

    • sequence: true specifies to call the custom PreGetFormattedFieldValue before it calls the predefined GetFormattedFieldValue method.

    • The following code in the custom method determines whether or not the control that Siebel Open UI is currently examining is the client-only control:

      if (control.GetName() === "Client_Select")
      

      If it is, then Siebel Open UI sets the CancelOperation member of the returnStructure to true and the ReturnValue to null. For more information about returnStructure, see AddMethod Method.

  3. Save the recyclebinpmodel.js file.

Customizing the Presentation Model to Handle Notifications

This task is a step in Process of Customizing the Presentation Model.

The Siebel Server sends a record deletion confirmation when it receives the InvokeMethod request for the DeleteRecord method. You can write a handler for the NotifyDeleteRecord notification to process this confirmation in the client. For more information, see DeleteRecord Method.

Siebel Open UI packages the notification that it gets from the Siebel Server in the business component layer as part of a reply property set. This property set includes information about server state modifications or replies to requests for state information. For example, if Siebel Open UI deletes a record that resides on the server, then the following work occurs:

  1. Siebel Open UI sends a NotifyDeleteRecord notification to the client.

  2. The client sends a request to the server.

  3. The server processes the request.

  4. Siebel Open UI examines the relevant modifications that exist on the server, and then collects and packages notifications that are ready to communicate to the client.

  5. If the client sends an InvokeMethod call for the DeleteRecord method to the server, then the Siebel Web Engine sends a NotifyDeleteRecord notification from the business component layer to the client.

For more information about the business component layer, see Configuring Siebel Business Applications.

The following figure illustrates the code you use to customize the presentation model to handle notifications. Each number in this figure identifies the corresponding step number in the numbered task list that this book includes immediately after this figure.

Customizing the Presentation Model to Handle Notifications

To customize the presentation model to handle notifications

  1. Identify the notification type that Siebel Open UI must handle.

    Examine the notification types in the Notifications That Siebel Open UI Supports topic. Look for a notification type that indicates it might include the information that your customization requires. For this example, the notification type for the NotifyDeleteRecord notification is SWE_PROP_BC_NOTI_DELETE_RECORD.

  2. Examine the methods that the presentation model references that indicate they might be useful for your customization.

    The AttachNotificationHandler method is the appropriate method to use for this example. For more information, see AttachNotificationHandler Method.

  3. In the recyclebinpmodel.js file, add the AttachNotificationHandler to the Init method of the presentation model:

    this.AttachNotificationHandler(consts.get("SWE_PROP_BC_NOTI_DELETE_RECORD"), 
    HandleDeleteNotification);
    
  4. Add the custom method that Siebel Open UI uses to handle replies from NotifyDeleteRecord and to populate the recycle bin:

    function HandleDeleteNotification(propSet){
    
  5. Get the property that you use to identify the objects that Siebel Open UI has flagged for deletion:

    var objectsUnderDeletion = this.Get("ObjectsUnderDeletion");
    

    You configured this property in Step 10 in the topic Customizing the Presentation Model to Delete Records to back up the records that Siebel Open UI is in the process of deleting.

  6. Determine whether or not any records exist in the In Progress list:

    if(objectsUnderDeletion.length > 0){
    

    Siebel Open UI must process these records, and then move them to the recycle bin. In this step and in several subsequent steps, you do more than one examination to make sure the notification instance that Siebel Open UI is handling is the instance that it requires for the notification handler. Some repeating notifications might exist that you must process to avoid duplication.

  7. Identify the row that is involved with the NotifyDeleteRecord notification:

    var activeRow = propSet.GetProperty(consts.get("SWE_PROP_BC_NOTI_ACTIVE_ROW"));
    

    In this example, you use the SWE_PROP_BC_NOTI_ACTIVE_ROW property. For more information about this property, see Summary of Notifications That Siebel Open UI Supports.

  8. Make sure that this notification confirms the deletion, and make sure that this notification is not a duplicate:

    if(activeRow == this.Get("GetSelection") && objectsUnderDeletion[activeRow]){
    

    where:

    • The following code determines whether or not the record that the NotifyDeleteRecord method references is the currently selected record:

      activeRow == this.Get("GetSelection") 
      

      This example uses a synchronous request, so Siebel Open UI selects the record that the DeleteRecord method references in the context of PreInvokeMethod. It selects no other record after it makes this initial selection while the Siebel Server sends the delete confirmation notification to the client. For more information, see About Synchronous Requests.

    • The following code makes sure that this notification is not a duplicate:

    objectsUnderDeletion[ activeRow ]
    

    It determines whether or not Siebel Open UI has already removed the record that it is examining in a previous instance of handling the same notification for the same record.

  9. Add a property that Siebel Open UI can use to store the list of records that the user deletes but might retrieve from the recycle bin:

    this.AddProperty("DeletionCompleteSet", []);
    
  10. Store the deleted record:

    this.Get("DeletionCompleteSet").push(objectsUnderDeletion[activeRow]);
    

    The conditional block where this code resides determines that this notification is not a duplicate NotifyDeleteRecord notification for the record that the DeleteRecord method requests deletion. So, this push statement pushes the deleted record into the DeletionCompletedSet property that you defined in Step 9.

  11. Remove the record from the Deletion in Progress list:

    objectsUnderDeletion[ activeRow ] = null;
    
  12. Add the RefreshList method:

    this.AddMethod("RefreshList", function(){});
    

    Siebel Open UI must refresh the recycle bin after Step 11 adds a record to this recycle bin. You can use dependency injection through the AttachPMBinding method to inform the physical renderer that the recycle bin requires a refresh. For more information, see About Dependency Injection. For more information, see How Siebel Open UI Uses Nondetailed Data to Indicate Modifications That Occur in Detailed Data.

  13. Run the RefreshList method:

    this.ExecuteMethod("RefreshList");
    
  14. Save the recyclebinpmodel.js file.

How Siebel Open UI Uses Nondetailed Data to Indicate Modifications

Siebel Open UI uses the dependency that exists between the presentation model and the physical renderer to indicate a high-level modification in a property or method, such as a modifying the list of records that it must display. This dependency configures Siebel Open UI to run a high-level renderer method, such as a method that repopulates the entire physical markup of columns and data in the grid container. The renderer method then gets the detailed presentation model attributes, such as columns and data, through properties or methods that the presentation model contains.

This example uses the RefreshList method as an indicator that Siebel Open UI modified something in the DeletionCompletedSet property. When you configure the physical renderer in Customizing the Physical Renderer to Refresh the Carousel, you configure Siebel Open UI to use the AttachPMBinding method to bind a physical renderer method to the RefreshList method. You also configure it to use this physical renderer method to get the detailed data that the DeletionCompletedSet method references. Siebel Open UI gets this data from the presentation model so that the physical renderer can render it. For more information, see AttachPMBinding Method.

Attaching an Event Handler to a Presentation Model

This task is a step in Process of Customizing the Presentation Model.

At this point in this example, you have set up and customized the presentation model to choose records to delete, to delete them, and then to move them to the recycle bin. In this topic, you modify the presentation model to allow the user to click an item in the carousel, and then click the plus sign (+) to restore the record.

The following figure illustrates the code you use to attach an event handler to a presentation model. Each number in this figure identifies the corresponding step number in the numbered task list that this book includes immediately after this figure.

Attaching an Event Handler to a Presentation Model

To attach an event handler to a presentation model

  1. In the recyclebinpmodel.js file, add the method that handles the event:

    function OnClickRestore(index){
    

    The name of an event handler typically starts with the following prefix:

    On
    

    Siebel Open UI calls this method when the user clicks the plus sign (+).

  2. Bind the OnClickRestore method to the RESTORE custom event:

    this.AttachEventHandler("RESTORE", OnClickRestore);
    

    This code adds the RESTORE custom event. The physical renderer sends this event to the presentation model, and then this presentation model runs OnClickRestore. The AttachEventHandler method sets up a dependency injection, so you add it in the Init method. For more information, see AttachEventHandler Method and About Dependency Injection.

  3. Identify the method that Siebel Open UI uses when a user creates a record.

    Examine the Flow That Creates New Records in List Applets, Calling the Siebel Server. Note that Siebel Open UI uses the NewRecord method, and then uses the WriteRecord method as an input argument for the InvokeMethod method when it runs InvokeMethod in the presentation model. For more information, see NewRecord Method.

  4. Determine how Siebel Open UI stores the field values of a new record that a user creates.

    Examine Flow That Handles Focus Changes in Form Applets. This flow describes the process that occurs between the initial NewRecord call and the WriteRecord call when Siebel Open UI creates a record in the client. It stores the field values in the client while the user enters these values and navigates from one field to another field. For more information, see WriteRecord Method.

    Siebel Open UI can do the following to create a record that it restores through the OnClickRestore event handler:

    • Run the InvokeMethod method for the NewRecord.

    • Store values that the user enters in each field, and use values from the records that Siebel Open UI stores in the recycle bin.

    • Run the InvokeMethod method for WriteRecord with the client already configured to include the field values for the record.

  5. Make sure Siebel Open UI can use the NewRecord method in the applet:

    if(this.ExecuteMethod("CanInvokeMethod", "NewRecord")){
    

    If Siebel Open UI cannot run the NewRecord method, then it exits this conditional statement.

  6. Add the property that Siebel Open UI uses to store the index that identifies the record it must restore:

    this.AddProperty("restorationIndex", -1);
    

    The physical renderer must specify the record to restore. To do this, it uses the DeletionCompletedSet property to get the restorationIndex of this record from the client and store it. It then sends this index to the presentation model as part of a request to restore the record. The restorationIndex is an index that resides in the DeletionCompletedSet property of the record.

    Siebel Open UI sends this value from the recycle bin record that the user chooses to restore. The OnClickRestore method receives this property, and then Siebel Open UI stores this value in the restorationIndex property of the presentation model.

  7. Configure the OnClickRestore method:

    this.SetProperty("inRestoration", true);
    this.SetProperty("restorationIndex", index);
    this.ExecuteMethod("InvokeMethod", "NewRecord", null, false);
    this.ExecuteMethod("InvokeMethod", "WriteRecord", null, false);
    

    where:

    • NewRecord and WriteRecord are input arguments to the InvokeMethod method. In Step 3 you determined that Siebel Open UI uses the NewRecord method or the WriteRecord method as an input argument for the InvokeMethod, so you specify these methods in this code.

    Siebel Open UI stores the field values of a record in the WriteRecord request before it sends this request to the Siebel Server. It stores these values differently depending on whether it creates a record from the recycle bin or whether the user creates a new record. The physical user interface layer does not store these values if the user attempts to restore a record from the recycle bin. It stores these values only if the user creates a new record. You write this customization in the next topic in this example, Customizing Methods in the Presentation Model to Store Field Values.

    This customization runs only while WriteRecord is running to restore a record from the recycle bin. It does not run when the user creates a new record and Siebel Open UI calls WriteRecord. When you start this restoration logic in the OnClickRestore method, you set a presentation model property that serves as a flag that indicates that a recycle bin restoration is in progress. An explicit AddProperty call does not exist for this property, so Siebel Open UI creates this property only if the user uses the recycle bin.

  8. Save the recyclebinpmodel.js file.

Customizing Methods in the Presentation Model to Store Field Values

This task is a step in Process of Customizing the Presentation Model.

In this topic, you use the ExecuteMethod method to store the values of the record that the user is attempting to restore from the recycle bin.

The following figure illustrates the code you use to customize a method in the presentation model to store the field values of records. Each number in this figure identifies the corresponding step number in the numbered task list that this book includes immediately after this figure.

Customizing a Method in the Presentation Model to Store the Field Values of Records

To customize methods in the presentation model to store field values

  1. In the recyclebinpmodel.js file, add a condition that makes sure Siebel Open UI runs the customization logic only if the user is restoring a record from the recycle bin, and not adding a new record:

    else if(methodName === "WriteRecord" && this.Get("inRestoration")){
    

    This if statement examines the value of the methodName in the WriteRecord argument and the value of the inRestoration property. For more information, see WriteRecord Method.

  2. Get the set of records for the recycle bin:

    var recordSet = this.Get("DeletionCompleteSet");
    

    In Step 10 in the topic Customizing the Presentation Model to Handle Notifications, you configured the DeletionCompletedSet property of the presentation model to store each record that the user adds to the recycle bin.

  3. Get the back up copy of the record that the physical renderer requests to restore:

    var record = recordSet[this.Get("restorationIndex")];
    

    To get this value, you access the restorationIndex property that you added in Step 6 in the topic Attaching an Event Handler to a Presentation Model.

  4. Identify the method that Siebel Open UI uses to indicate that the user navigated away from an applet.

    To do this, you can examine Flow That Handles Focus Changes in List Applets. Note that Siebel Open UI calls the LeaveField method as the last step in the flow. This method determines whether or not Siebel Open UI removed the focus from a field in an applet, so Siebel Open UI uses this step in the flow as a flag to signal that it must store the field values. To get information about the methods that the flowcharts describe when you develop your own customization, you can use the descriptions in Application Programming Interface

  5. Get the list of columns that the list applet contains. This list is identical to the list of columns that the DeletionCompleteSet property contains:

    var listOfColumns = this.Get("ListOfColumns");
    
  6. Get the list of controls that the list applets contains:

    var controls = this.Get("GetControls");
    

    For more information about the GetControls property, see Properties of the Presentation Model That Siebel Open UI Uses for Applets.

  7. Store the field values:

    for(var i = 0, len = listOfColumns.length; i < len; i++){
      var control = controls[listOfColumns[i].name];
      if(control){
        this.ExecuteMethod("LeaveField", control, record[control.GetFieldName()],
        true);}
      }
    }
    

    where:

    • The following code iterates through the applet controls that correspond to the list columns of that the record that the DeletionCompleteSet property identifies:

      for(var i = 0, len = listOfColumns.length; i < len; i++) 
      
    • this.ExecuteMethod calls the LeaveField method that you identified in Step 4. It calls this method one time for each iteration. It sends the field value from the corresponding control of the record that DeletionCompleteSet identifies. It sends this value to an argument. When this code iterates, it runs the LeaveField method for every control that Siebel Open UI must populate in the new record that it is using to restore the deleted record from the recycle bin.

    • Siebel Open UI must send the LeaveField method as a control and store a value for this control. In this example, it iterates through each control that the list applet contains, and sends the value of the corresponding list column that it uses for the control from the record that the DeletionCompleteSet property gets in Step 2.

    • For a description of the arguments that LeaveField uses, Summary of Methods That You Can Use with the Presentation Model for Applets.

    • record stores the field value of the record that Siebel Open UI is restoring. The subsequent WriteRecord call packages and sends these values to the Siebel Server.

      Siebel Open UI stores these values when it runs the LeaveField method. For more information about this flow, see Flow That Handles Focus Changes in List Applets.

  8. Save the recyclebinpmodel.js file.

Customizing the Presentation Model to Call the Siebel Server and Delete a Record

This task is a step in Process of Customizing the Presentation Model.

In this topic, you configure the presentation model to remove the record from the recycling bin. You use a dependency injection to call a method on the Siebel Server after the stack that Siebel Open UI uses to call the server has finished processing. For more information, see About Dependency Injection and Customizing Events.

To customize the presentation model to call the Siebel Server and delete a record

  1. In the recyclebinpmodel.js file, add the following code to the Init method:

    this.AttachPostProxyExecuteBinding("WriteRecord", PostWriteRecord);
    

    You use the Init method to send a WriteRecord call to the Siebel Server. For more information, see WriteRecord Method and AttachPostProxyExecuteBinding Method.

  2. Add the following code anywhere in the recyclebinpmodel.js file:

    function PostWriteRecord(methodName, inputPS, outputPS){
      if(this.Get("inRestoration")){
        this.Get("DeletionCompleteSet")[this.Get("restorationIndex")] = null;
        this.ExecuteMethod("RefreshList");
        this.SetProperty("inRestoration", false);
    }
    

    where:

    PostWriteRecord does the following work:

    • Removes the record that Siebel Open UI restored in Step 7 in the topic Customizing Methods in the Presentation Model to Store Field Values. It removes this record from the DeletionCompleteSet property.

    • Calls the RefreshList method to start another round of binding to the physical renderer. In the next topic in this example, you configure Siebel Open UI to call the HandleDeleteNotification method to refresh the list and to remove the record from the recycle bin in the client.

    • Sets the inRestoration property of the presentation model to false. You set this property to true in Step 7 in the topic Customizing Methods in the Presentation Model to Store Field Values to indicate that Siebel Open UI is restoring a record. The restoration is now finished, so you can configure Siebel Open UI to set inRestoration to false.

  3. Save the recyclebinpmodel.js file.

Process of Customizing the Physical Renderer

This task is a step in Roadmap for Customizing Siebel Open UI.

To customize the physical renderer, do the following tasks:

  1. Setting Up the Physical Renderer

  2. Customizing the Physical Renderer to Render the Carousel

  3. Customizing the Physical Renderer to Bind Events

  4. Customizing the Physical Renderer to Bind Data

  5. Customizing the Physical Renderer to Refresh the Carousel

  6. Modifying CSS Files to Support the Physical Renderer

In this topic, you customize the JQGridRenderer physical renderer that Siebel Open UI uses with a presentation model for a typical Siebel list applet so that it renders this applet as a grid. You add the rendering capabilities for the carousel that Siebel Open UI uses to render the recycle bin. You also modify the grid style to accommodate the carousel control. You use methods in the physical renderer to do this work. For a description of these methods, including the sequence you use to configure them, see Life Cycle of a Physical Renderer.

Setting Up the Physical Renderer

This task is a step in Process of Customizing the Physical Renderer.

The following figure illustrates the code that you use to set up the physical renderer. Each number in this figure identifies the corresponding step number in the numbered task list that this book includes immediately after this figure.

Setting Up the Physical Renderer

To set up the physical renderer

  1. Download a copy of the recyclebinrenderer.js file to the following folder:

    INSTALL_DIR\applicationcontainer\webapps\siebel\scripts\siebel\custom
    

    It is recommended that you get a copy of this file to assist in your understanding of how to implement the example that this topic describes. This file includes all the code that this example uses. It also includes more comments that describe code functionality. To get a copy of this file, see Article ID 1494998.1 on My Oracle Support.

    For more information about the folders you can use to store your customizations, see Organizing Files That You Customize. For more information about the language_code, see Languages That Siebel Open UI Supports.

  2. Use a JavaScript editor to open the recyclebinpmodel.js file that you downloaded in Step 1.

  3. Verify that the RecycleBinRenderer class does not exist, and that you do not configure Siebel Open UI to override this class:

    if(typeof(SiebelAppFacade.RecycleBinRenderer) === "undefined"){
    
  4. To prevent potential conflicts, create a namespace that Siebel Open UI can use:

    SiebelJS.Namespace("SiebelAppFacade.RecycleBinRenderer");
    
  5. Use the Define method to identify the physical renderer file:

    define("siebel/custom/recyclebinrenderer", ["3rdParty/jcarousel/lib/
    jquery.jcarousel.min", "siebel/jqgridrenderer"], function () {
    

    You must use the Define method to make sure Siebel Open UI can identify the constructor. You must include the relative path and the name of the presentation model file without the file name extension. For more information, see Define Method.

  6. Define the class:

    SiebelAppFacade.RecycleBinRenderer = (function(){
    
  7. Declare the variables that Siebel Open UI uses throughout the physical renderer code:

    var siebConsts = SiebelJS.Dependency("SiebelApp.Constants");
    
  8. Create the class constructor:

    function RecycleBinRenderer(pm){
      SiebelAppFacade.RecycleBinRenderer.superclass.constructor.call(this, pm);
      this.listOfCols = ["Name", "Location"];
    }
    
  9. Define the inheritance:

    SiebelJS.Extend(RecycleBinRenderer, SiebelAppFacade.JQGridRenderer);
    

    For more information about inheritance, see About Dependency Injection.

  10. Save the recyclebinrenderer.js file.

Customizing the Physical Renderer to Bind Events

This task is a step in Process of Customizing the Physical Renderer.

In this topic, you add the following functionality to the carousel:

  • If the user hovers the mouse over a record in the carousel, then display a restore button as a plus sign (+).

  • If the user removes the hover, then hide the restore button.

  • If the user clicks the plus sign (+), then call the presentation model to restore the record.

  • To the HTML node that Siebel Open UI uses for the restore button.

  • Styling changes that affect the appearance of the carousel based on user actions.

The following figure illustrates the code you use to customize the physical renderer to bind events to the carousel. Each number in this figure identifies the corresponding step number in the numbered task list that this book includes immediately after this figure.

Customizing the Physical Renderer to Bind Events to the Carousel

To add this functionality, you must customize Siebel Open UI to attach an event handler to each of the following items:

  • The carousel item, for every hover activity.

  • The HTML node that Siebel Open UI uses for the Restore button.

  • The Next and Previous icons in the carousel.

To customize the physical renderer to bind events

  1. In the recyclebinrenderer.js file, call the BindEvents method of the physical renderer:

    SiebelAppFacade.RecycleBinRenderer.superclass.BindEvents.call(this);
    

    For more information, see BindEvents Method.

  2. Identify the placeholder:

    var placeHolder = "s_" + this.GetPM().Get("GetFullId") + "_div";
    
  3. Attach three event handlers for hover and click:

    $("#" + placeHolder)
     .parent()
     .delegate("div.siebui-carousel-item", "mouseenter", { ctx: this }, 
    ShowRestoreButton)
     .delegate("div.siebui-carousel-item", "mouseleave", { ctx: this }, 
    HideRestoreButton)
     .delegate("a.siebui-citem-add", "click", { ctx: this }, AddFromRecycleBin);
    

    ShowRestoreButton is called when a user hovers on a carousel item, and HideRestoreButton is called when the hovering ends. If the user clicks the Add button, then AddFromRecycleBin is called.

  4. Attach styling events to the Previous and Next buttons of the carousel:

    $("#" + placeHolder + "_recycle")
     .parent()
     .find('.siebui-jcarousel-prev')
      .on('jcarouselcontrol:active', function () {
       $(this).removeClass('siebui-jcarousel-ctrl-inactive');
      })
      .on('jcarouselcontrol:inactive', function () {
       $(this).addClass('siebui-jcarousel-ctrl-inactive');
      })
      .jcarouselControl({
       target: '-=1'
      });
    
    $("#" + placeHolder + "_recycle")
     .parent()
     .find('.siebui-jcarousel-next')
      .on('jcarouselcontrol:active', function () {
       $(this).removeClass('siebui-jcarousel-ctrl-inactive');
      })
      .on('jcarouselcontrol:inactive', function () {
       $(this).addClass('siebui-jcarousel-ctrl-inactive');
      })
      .jcarouselControl({
       target: '+=1'
      });
    

    In this example, the first part of the code is finding the Previous button in the carousel container, and then attaching jcarousel:active and jcarousel:inactive events to it. When these events are triggered by the third-party plug-in, we call methods that set and unset styling classes on the buttons. Similarly, the styling classes are attached and removed for the Next button.

  5. Define the handler methods:

    1. Use the following code to find the child for the add button and show it:

      function ShowRestoreButton(evt) {
       if (evt && evt.currentTarget) {
        $(evt.currentTarget).children("a.siebui-citem-add").show();
       }
      
      }
      
    2. Use the following code to find the child for the add button and hide it:

      function HideRestoreButton(evt) {
       if (evt && evt.currentTarget) {
        $(evt.currentTarget).children("a.siebui-citem-add").hide();
       }
      
      }
      
    3. Use the following code to call the Restore method on the PM with the relevant index parameter

      function AddFromRecycleBin(evt) {
       var pm = evt.data.ctx.GetPM();
       if (evt && evt.currentTarget) {
        pm.OnControlEvent("RESTORE", $(evt.currentTarget).parent().data("index"));
       }
      }
      
  6. Save the recyclebinrenderer.js file.

Customizing the Physical Renderer to Bind Data

This task is a step in Process of Customizing the Physical Renderer.

The carousel in this example does not render data. Siebel Open UI only renders data in this example if it adds a record to or deletes a record from the recycle bin.

To customize the physical renderer to bind data

  1. In the recyclebinrenderer.js file, add the following code to SiebelAppFacade.RecycleBinRenderer = (function(){:

    RecycleBinRenderer.prototype.BindData = function(){
      SiebelAppFacade.RecycleBinRenderer.superclass.BindData.apply(this, arguments);
    };
    

    For more information, see BindData Method.

  2. Save the recyclebinrenderer.js file.

Modifying CSS Files to Support the Physical Renderer

This task is a step in Process of Customizing the Physical Renderer.

In this topic, you modify the CSS files so that they support the CSS classes that the physical renderer uses.

To modify CSS files to support the physical renderer

  1. Open the CSS file, add the following code, and then save your changes:

    .siebui-list-recyclebin {
     margin : 0px;
    }
    .siebui-jcarousel-wrapper {
     position: relative;
     height: 450px;
    }
    .siebui-jcarousel {
     position: relative;
     overflow: hidden;
     height: 100% !important;
     margin: 5px;
     width : 80%;
     border: 10px solid #fff;
     -webkit-border-radius: 5px;
     -moz-border-radius: 5px;
     border-radius: 5px;
     -webkit-box-shadow: 0 0 2px #999;
     -moz-box-shadow: 0 0 2px #999;
     box-shadow: 0 0 2px #999;
    }
    .siebui-jcarousel ul {
     width: 98%;
     position: relative;
     list-style: none;
     margin: 0;
     padding: 0;
    }
    .siebui-jcarousel ul li {
     margin-bottom : 5px;
    }
    .siebui-jcarousel-prev,
    .siebui-jcarousel-next {
     transform: rotate(90deg);
      transform-origin: left top 0;
     float : left;
     position: absolute;
     width: 30px;
     height: 30px;
     text-align: center;
     background: #4E443C;
     color: #fff;
     text-decoration: none;
     text-shadow: 0 0 1px #000;
     font: 24px/27px Arial, sans-serif;
     -webkit-border-radius: 30px;
     -moz-border-radius: 30px;
     border-radius: 30px;
     -webkit-box-shadow: 0 0 2px #999;
     -moz-box-shadow: 0 0 2px #999;
     box-shadow: 0 0 2px #999;
    }
     .siebui-jcarousel-prev {
     top : 0px;
     left : 45%;
    }
     .siebui-jcarousel-next {
     top : 450px;
     left: 45%;
    }
     .siebui-jcarousel-prev:hover span,
    .siebui-jcarousel-next:hover span {
     display: block;
    }
     .siebui-jcarousel-prev.inactive,
    .siebui-jcarousel-next.inactive {
     opacity: .5;
     cursor: default;
    }
    div.siebui-carousel-col{
     display : block;
    }
    div.siebui-carousel-item{
     height : 75px;
     padding : 5px;
     border : 1px solid #acacac;
     text-align : center;
     padding-top: 20px;
     word-wrap : break-word;
     -webkit-border-radius: 5px;
     -moz-border-radius: 5px;
     border-radius: 5px;
    }
    a.siebui-citem-add{
     display : block;
     top : 2px;
     right : 2px;
     float : right;
     width : 16px;
     height : 16px;
     background: url(../images/plus.png) no-repeat center center;
    }
    
  2. Add the CSS files that the third-party uses:

    1. In Windows Explorer, navigate to the following folder:

      INSTALL_DIR\applicationcontainer\webapps\siebel\scripts\3rdParty
      
    2. Add the following subfolder hierarchy to the 3rdParty folder:

      \jcarousel\skins\tango\
      
    3. Save the following files to the tango folder that you added in Step b:

      next-horizontal.png
      next-vertical.png
      prev-horizontal.png
      prev-vertical.png
      skin.css
      

      To get a copy of these files, see Article ID 1494998.1 on My Oracle Support. For more information about the CSS files and renderers that Siebel Open UI uses to render a list applet as a carousel, see Customizing List Applets to Render as Carousels.

  3. Save the jquery.jcarousel.js file to the following folder:

    INSTALL_DIR\applicationcontainer\webapps\siebel\scripts\3rdParty
    

    Siebel Open UI uses this file to render a carousel. To get a copy of this file, see Article ID 1494998.1 on My Oracle Support.

Creating the Plug-in Wrapper

This task is a step in Process of Customizing the Plug-in Wrapper.

The plug-in wrapper uses the Init method to configure the properties, methods, and bindings. For more information about these methods, see Life Cycle of User Interface Elements.

The following figure illustrates the code you use to create the plug-in wrapper. Each number in this figure identifies the corresponding step number in the numbered task list that this book includes immediately after this figure.

Creating the Plug-in Wrapper

This topic describes how to modify code that resides in the ColorBoxPW.js file. It is recommended that you get a copy of this file to assist in your understanding of how to implement the example that this topic describes. This file includes all the code in this example. It also includes more comments that describe code functionality. To get a copy of this file, see Article1494998.1 on My Oracle Support.

For more information about the folders you can use to store your customizations, see Organizing Files That You Customize. For more information about the language_code, see Languages That Siebel Open UI Supports.

To create the plug-in wrapper

  1. Create the plug-in wrapper file:

    1. Download a copy of the ColorBox.js file to the following folder:

      INSTALL_DIR\applicationcontainer\webapps\siebel\\language_codefiles\custom
      
    2. Use a JavaScript editor to open the ColorBoxPW.js file that you downloaded in Step a.

  2. Make sure the ColorBoxPW class does not exist and that you do not configure Siebel Open UI to override this class. You add the following code:

    if(typeof(SiebelAppFacade.ColorBoxPW) === "undefined"){
    
  3. Make sure a namespace exists that Siebel Open UI can use to prevent conflicts:

    SiebelJS.Namespace("SiebelAppFacade.ColorBoxPW");
    
  4. Use the Define method to identify the presentation model file:

    define("siebel/custom/ColorBoxPW", [siebel/basePW], function(){
    

    You must use the Define Method to ensure that Siebel Open UI can identify the constructor. You must include the relative path and the name of the presentation model file without the file name extension. For more information, see Define Method.

    Note: Any third-party files that the plug-in wrapper uses must be mentioned in the dependencies section of the define statement.
  5. Define the class:

    SiebelAppFacade.ColorBoxPW = (function(){
    
  6. Define the class constructor:

    function ColorBoxPW(){
    SiebelAppFacade.ColorBoxPW.superclass.constructor.apply(this,
    arguments);
    }
    
  7. Set up the injected dependency:

    SiebelJS.Extend(ColorBoxPW, SiebelAppFacade.DropDownPW);
    

    For more information about injected dependency, see About Dependency Injection.

  8. Return the constructor:

    return ColorBoxPW;
    } ());
    return SiebelAppFacade.ColorBoxPW;
    });
    
  9. Attach the plug-in wrapper:

    SiebelApp.S_App.PluginBuilder.AttachPW(consts.get("SWE_CTRL_COMBOBOX"), 
    SiebelAppFacade.ColorBoxPW, function (control) {
    
  10. Write the condition for which the plug-in wrapper should kick in:

    return (control.GetName() === "Probability2");
    
  11. Save the ColorBoxPW.js file.

Customizing the Plug-in Wrapper to Display the Control Differently

This task is a step in Process of Customizing the Plug-in Wrapper.

In this step, you customize the setup logic of the plug-in wrapper so that it adds a color-box to the control.

In this example, the ShowUI method will be overridden to add a different element on to the DOM as a part of this control. The functionality of the control will remain unaffected, effectively, you will be decorating it with a new element.

This is an optional step: the base functionality of how a control looks and behaves can be completely changed based on your requirements. An out-of-the-box example of this type of modification is a flip switch that appears instead of a check box on touch devices in Siebel Open UI, which is accomplished using a plug-in wrapper.

The following figure illustrates the code you use to customize the ShowUI method of the plug-in wrapper. Each number in this figure identifies the corresponding step number in the numbered task list that this book includes immediately after this figure.

Customizing the Plug-in Wrapper to Display the Control Identity

To customize the plug-in wrapper to display the control differently

  1. In the colorboxpw.js file, introduce the ShowUI method that is a part of the life cycle of rendering a control.

    ColorBoxPW.prototype.ShowUI = function (control) {
    
  2. Call the superclass method to get the dropdown to appear:

    SiebelAppFacade.ColorBoxPW.superclass.ShowUI.call(this, control);
    

    This will call the ShowUI method of the DropDownPW class, which is responsible for showing the drop down field in the Siebel Open UI client.

  3. Get a reference to the existing element, and if it exists, get the parent element:

    var el = this.GetEl();
    if (el && el.length) {
    parent = el.parent();
    
    Note: This step is required to position the new DOM element as a sibling to the current element.

    The GetEl() API framework method is a plug-in wrapper space that retrieves the jQuery element representing the control. parent() is a jQuery call which retrieves the parent node of the element in the DOM. For more information about the GetEl() API method, see Architecture of Siebel Open UI.

  4. Add a new HTML div, which will serve as our color box:

    parent.append("<div id='colorbox_" + el.attr("name") + "' ></div>");
    

    You must specify a unique name for the element. In this example, colorbox_ is added to the existing name of the original element. The append() and attr() specifications are both jQuery APIs. The former adds DOM elements at the end of a given element and the latter extracts the specified attribute.

  5. Style the newly created div. This will serve as our colorbox:

    parent.find("div[id^=colorbox]").css({
             "width": "inherit",
             "height": "20px",
             "background-color": "inherit"
          });
    

    The css()is a JQuery API that applies CSS styles to the given element. In this example, the colorbox gets the same width as the original dropdown and a height of 20 pixels. The original background color is inherited from the dropdown.

  6. Save the ColorBoxPW.js file.

Customizing the Plug-in Wrapper to Bind Custom Events to a Control

This task is a step in Process of Customizing the Plug-in Wrapper.

In this topic, you attach behavioral methods to the colorbox element that you created in Creating the Plug-in Wrapper.

In this example, the BindEvent method will be overridden to attach custom handlers to a new element. The event handlers of the control will remain unaffected, and the new element will be decorated with some events.

This is an optional step: the base functionality of how a control looks and behaves can be completely changed based on your requirements. An out-of-the-box example of this type of modification is a flip switch that appears instead of a check box on touch devices in Siebel Open UI, which is accomplished using a plug-in wrapper.

The following figure illustrates the code you use to customize the BindEvents method of the plug-in wrapper. Each number in this figure identifies the corresponding step number in the numbered task list that this book includes immediately after this figure.

Customizing the Plug-In Wrapper to Bind Custom Events to a Control

To customize the plug-in wrapper to bind custom events to a control

  1. In the colorboxpw.js file, introduce the BindEvents method that is a part of the life cycle of rendering a control.

    ColorBoxPW.prototype.BindEvents = function () {
    
  2. Call the superclass method to attach the event handlers from the dropdown element:

    SiebelAppFacade.ColorBoxPW.superclass.BindEvents.call(this);
    

    This step calls the BindEvents of the DropDownPW class, which is responsible for attaching the events that the drop down field requires to operate correctly.

  3. Get the element that was created and attached as a sibling to the actual dropdown element, and the Event Helper object:

    var colorbox = this.GetEl().parent().find("div[id^=colorbox]"),
             evHelper = this.Helper("EventHelper");
             if (colorbox && colorbox.length && evHelper) {
    

    The Helper API is the framework method in the plug-in wrapper space that enables retrieving helper objects by name. For more information about the Helper API, see Architecture of Siebel Open UI.

  4. Attach the required events to the new DOM element that was created. In this example, three handlers are attached to one element:

    evHelper
          .Manage(colorbox, "mouseenter", { ctx: this }, OnMouseEnter)
          .Manage(colorbox, "mouseleave", { ctx: this }, OnMouseLeave)
          .Manage(colorbox, "click", { ctx: this }, OnClick)
    

    The Helper API is a method in the Event Helper object that takes the following four elements: the DOM element to which events should be attached, the event to be attached, the handler to be run, and other arguments. In this case, you are attaching one event for the each user hovering over the element, exiting the hover, and clicking on the element. For more information about the Helper API, see Architecture of Siebel Open UI.

Customizing the Plug-in Wrapper to Define Custom Events

This task is a step in Process of Customizing the Plug-in Wrapper.

In this topic, you define the behavioral methods that have been attached to the colorbox element that you created in you created in Creating the Plug-in Wrapper.

The following figure illustrates the code you use to define the handlers of the plug-in wrapper. Each number in this figure identifies the corresponding step number in the numbered task list that this book includes immediately after this figure.

Customizing the Plug-In Wrapper to Define Custom Events

To define the event handlers for the plug-in wrapper

  1. In the colorboxpw.js file, introduce the following private methods that will get called when the attached events occur on the element:

    1. The OnMouseEnter handler:

      function OnMouseEnter() {
            $(this).append("<div id='info'>Click for Info...</div>");
      }
      

      In this example, OnMouseEnter gets called when the mouseenter event occurs on the color box piece of the DOM. The context passed during the attachment of the events will be passed on to the handler method. Consequently, the this definition refers to the plug-in wrapper. In this example, a div is attached with an id of info that displays the following text: Click for Info….

    2. The OnMouseLeave handler:

      function OnMouseLeave() {
            $(this).find("#info").remove();
      }
      

      This is the complementary method to the OnMouseEnter handler, and gets called when the onmouseleave event occurs on the color box DOM. This method removes the div that was previously added, consequently removing the display text.

      Note: The two events will not run on touch devices, since they have no equitable actions.
  2. Introduce the OnClick handler.

    Click is standardized by the event helper object to achieve uniformity across different devices. Consequently, it may be translated to different events based on the user’s device. The click handler shows a popup that defines the meaning of the different colors that the box can take on. In the first piece of the handler in this example, HTML built of a few styled divs and some corresponding text that forms the content of the information we are trying to show in the popup is constructed. The handler, and the content that is attached to the parent element are displayed here:

    var parent = $(this).parent(),
    html = "<div id='legend' title='Legend'>"
          + "<br><br>"
          + "<div style='width: 200px; height: 20px; background-color: rgb(255, 0, 
    0);'>&emsp;&emsp;Do Not Pursue</div><br>"
          + "<div style='width: 200px; height: 20px; background-color: 
    orange;'>&emsp;&emsp;Pursue If Time Permits</div><br>"
          + "<div style='width: 200px; height: 20px; background-color: rgb(255, 255, 
    0);'>&emsp;&emsp;Pursue</div><br>"
          + "<div style='width: 200px; height: 20px; background-color: rgb(0, 128, 
    0);'>&emsp;&emsp;Pursue Aggressively</div><br>"
          + "</div>";
    parent.append(html);
    
  3. Make the section into a popup.

    For this, use the jQuery-UI provided dialog() API. In this example, the element is located by id using find, and converted to a modal dialog box:

    parent.find("#legend").dialog({
       resizeable: false,
       height: 275,
       width: 225,
       modal: true,
       buttons: {
          Cancel: function () {
             $(this).dialog("close");
          }
       }
    
    });
    

    This sets properties for the popup and adds a cancel button that closes the popup.

  4. Attach the required events to the new DOM element that we have created. Here we will attach three handlers on to this element.

    evHelper
          .Manage(colorbox, "mouseenter", { ctx: this }, OnMouseEnter)
          .Manage(colorbox, "mouseleave", { ctx: this }, OnMouseLeave)
          .Manage(colorbox, "click", { ctx: this }, OnClick)
    

    The Helper API is a method in the Event Helper object that takes the DOM element in order to attach events. The attached event and the handler are deployed, along with other arguments.n this case, we are attaching one event each for the user hovering over the element, exiting the hover, and clicking on the element. For more information about the Helper API, see Architecture of Siebel Open UI.

Customizing the Plug-in Wrapper to React to Value Changes of a Control

This task is a step in Process of Customizing the Plug-in Wrapper.

In this topic, you define behavioral customizations when changes occur in a control value. These changes affect the appearance of the colorbox element that you created in Creating the Plug-in Wrapper.

The following figure illustrates the code you use to style the color box based on the value that is being set on a control. Each number in this figure identifies the corresponding step number in the numbered task list that this book includes immediately after this figure.

Customizing the Plug-In Wrapper to React to Value Changes of a Control

To define the value based modifications in the plug-in wrapper

  1. In the colorboxpw.js file, introduce the SetValue method that is a part of the life cycle of a control's existence.

    ColorBoxPW.prototype.SetValue = function (value, index) {
    

    The SetValue API is called as part of a control life cycle when a value change occurs on the control, either directly by the user, or by the Siebel application. This call is responsible for the value change to appear in the DOM. In this example, SetValue is overridden in order to read into the value change that is happening on the control, and consequently makes modifications to the color box based on the value. For more information about the SetVAlue API, see Architecture of Siebel Open UI.

  2. Call the superclass method to make sure that the dropdown receives the intended value:

    SiebelAppFacade.ColorBoxPW.superclass.SetValue.call(this);
    

    This will call the SetValue of the DropDownPW class, which is responsible for applying the correct value on to the dropdown field itself.

  3. Get the new DOM element and the value that is being set:

    var colorbox = this.GetEl(index).parent().find("div[id^=colorbox]");
    if (colorbox && colorbox.length) {
          var val = parseInt(value);
    

    Because the value is in string form, and our future actions on this value involve treating it as a number, we need to convert it into a number form. The standard JavaScript method that is used for the purpose is parseInt.

  4. Validate the value and specify values that modify the color box in different ways:

    if (!isNaN(val)) {
       if (val >= 0 && val < 25) {
          colorbox.css("background-color", "red");
    
       }
       else if (val < 50) {
          colorbox.css("background-color", "orange");
       }
       else if (val < 75) {
          colorbox.css("background-color", "yellow");
       }
       else {
          colorbox.css("background-color", "green");
       }
    }
    else {
       colorbox.css("background-color", "inherit");
    }
    

    In this example, the value is verified to ensure that it is a number. If it is not, the background color is set to inherit, which sets the color to the same color as the dropdown element. This behavior would be applicable, for example, in cases where the user has entered a blank value, or inadvertently provided a string. If the value is a number, then use an if-else construct to define ranges and apply different colors on to the color box DOM element.

Attaching the Plug-in Wrapper to a Control Conditionally

This task is a step in Process of Customizing the Plug-in Wrapper.

This topic describes how to attach the plug-in wrapper you created in Creating the Plug-in Wrapper to a control.

The following figure illustrates the code you use to attach the plug-in wrapper to a control conditionally. Each number in this figure identifies the corresponding step number in the numbered task list that this book includes immediately after this figure.

Attaching the Plug-in Wrapper to a Control

To attach the plug-in wrapper to a control conditionally

  1. In the colorboxpw.js file, introduce the AttachPW method from the PluginBuilder namespace that attaches the presently defined plug-in wrapper to a given type of control:

    SiebelApp.S_App.PluginBuilder.AttachPW(consts.get("SWE_CTRL_COMBOBOX"), 
    SiebelAppFacade.ColorBoxPW, function (control) {
    

    In this customization, the intention is to apply the plug-in wrapper to a dropdown type of control. To achieve this customization the SWE_CTRL_COMBOBOX is used for the dropdown type. All controls are customizable. With this customization, every dropdown encountered by the Siebel Open UI client will use this method.

  2. Define the condition under which the attachment should occur, and to which specific instance of the control. The return value of the method used in Step 1 decides whether the plug-in wrapper attaches to a particular control. Returning true will mean a positive attachment.

    return (control.GetName() === "Probability2");
    

    Use the control object to create this condition. Since the intention is to attach the plug-in wrapper for all repository controls that have a name of Probability2, true will be returned when the name of the condition matches.

    Note: Plug-in wrappers are not restricted to any Presentation Model or Physical Renderer. Also, a customization defined on a plug-in wrapper will be applicable throughout the Siebel Open UI client, as long as the condition is satisfied. In this example, any control having a repository name of "Probability2" in any screen or view will be attached to this plug-in wrapper.
  3. Define conditions for plug-in wrapper attachments. Conditions used can be as complex as necessary, based on the requirements. Use following examples as guidance for defining conditions:

    Attach a plug-in wrapper to all TextArea fields in Opportunity List applet:
    SiebelApp.S_App.PluginBuilder.AttachPW(consts.get("SWE_CTRL_TEXTAREA"), 
    SiebelAppFacade.CustomPW, function (control) {
          return (control.GetAppplet().GetName() === "Opportunity List Applet");
    });
    
    1. Attach a plug-in wrapper to all Date Fields in Contact Form applet and Account Form Applet:

      SiebelApp.S_App.PluginBuilder.AttachPW(consts.get("SWE_CTRL_DATE_PICK"), 
      SiebelAppFacade.CustomPW, function (control) {
            var appletName = control.GetAppplet().GetName();
            return (appletName === "Contact Form Applet" || appletName === "Account Form 
      Applet");
      });
      
    2. Attach a plug-in wrapper to a specific Text Box in a specific applet only:

      SiebelApp.S_App.PluginBuilder.AttachPW(consts.get("SWE_CTRL_TEXT"), 
      SiebelAppFacade.CustomPW, function (control) {
            var appletName = control.GetAppplet().GetName();
            return (appletName === "Contact Form Applet" && control.GetName() === "Last 
      Name");
      });
      
    3. Attach a plug-in wrapper to all Dropdowns in a particular application:

      SiebelApp.S_App.PluginBuilder.AttachPW(consts.get("SWE_CTRL_COMBOBOX"), 
      SiebelAppFacade.CustomPW, function (control) {
            return (SiebelApp.S_App.GetName() === "Siebel EPharma")
      });
      
    4. Attach a plug-in wrapper to all check boxes in a view when they are accessed on touch devices:

      SiebelApp.S_App.PluginBuilder.AttachPW(consts.get("SWE_CTRL_CHECKBOX"), 
      SiebelAppFacade.CustomPW, function (control) {
            return (SiebelAppFacade.DecisionManager.IsTouch() && 
      control.GetApplet().GetView().GetName === "Opportunity Detail View")
      });
      

Configuring the Manifest for the Recycle Bin Example

This task is a step in Roadmap for Customizing Siebel Open UI.

This topic describes how to configure the manifest for the recycle bin example. For more information, see Configuring Manifests.

To configure the manifest for the recycle bin example

  1. Make sure your presentation model and physical renderer use the define method.

    You do this in Step 4 in the topic Creating the Presentation Model for the presentation model and in Step 5 in the topic Setting Up the Physical Renderer for the physical renderer.

  2. Log in to a Siebel client with administrative privileges.

  3. Navigate to the Administration - Application screen, and then the Manifest Files view.

  4. In the Files list, add the following files:

    siebel/custom/recyclebinrenderer.js
    siebel/custom/recyclebinpmodel.js
    siebel/custom/carouselrenderer.js
    3rdParty/jcarousel/skins/tango/skin.css
    files/theme-aurora.css
    

    The file that resides in the files folder is the predefined file that you use in this example.

  5. Administer the manifest for the physical renderer:

    1. Navigate to the Administration - Application screen, and then the Manifest Administration view.

    2. In the UI Objects list, specify the following applet.

      Field Value

      Type

      Applet

      Usage Type

      Physical Renderer

      Name

      SIS Account List Applet

    3. In the Object Expression list, add the following expression. The physical renderer uses this expression to render the applet in a desktop platform.

      Field Value

      Expression

      Desktop

      Level

      1

    4. In the Files list, add the following files:

      siebel/custom/recyclebinrenderer.js
      
    5. In the UI Objects list, specify the following applet.

      Field Value

      Type

      Applet

      Usage Type

      Presentation Model

      Name

      SIS Account List Applet

    6. In the Object Expression list, add a record with no value in the Expression field.

    7. In the Files list, add the following file:

      siebel/custom/recyclebinpmodel.js
      

Configuring the Manifest for the Color Box Example

This task is a step in Roadmap for Customizing Siebel Open UI.

In this topic, you will configure the manifest for the color box plug-in wrapper example. For more information, see Configuring Manifests.

To configure the manifest for the color box example

  1. Verify that your plug-in wrapper uses the define method.

  2. Log in to the Siebel Open UI client with administrative privileges.

  3. Navigate to the Administration - Application screen, and then the Manifest Files view.

  4. In the Files list, add the following file:

    siebel/custom/colorboxpw.js
    
  5. Modify the manifest for the physical renderer:

    1. Navigate to the Administration - Application screen, and then the Manifest Administration view.

    2. In the UI Objects list, add a new record with the following values:

      Field Value

      Type

      Application

      Usage Type

      Common

      Name

      PLATFORM INDEPENDENT

    3. In the Object Expression list, add the following subexpression.

      Field Value

      Group Name

      Leave empty

      Expression

      Desktop

      Level

      1

      Operator

      Leave empty

      Web Template Name

      Leave empty

    4. In the Files list, add the file that you created in Step 4.

      siebel/custom/colorboxpw.js
      

Testing Your Modifications

This task is a step in Roadmap for Customizing Siebel Open UI.

In this topic, you test your modifications.

To test your modifications

  1. Log in to the Siebel Open UI client, and then navigate to the Accounts screen.

  2. Use the Select column to choose five account records, and then click Delete.

  3. Siebel Open UI deletes the records and adds them to the carousel recycle bin.

  4. To restore a record, click the following plus (+) icon in the carousel recycle bin:

  5. Verify that Siebel Open UI recreates the record on the Siebel Server and adds it back to the Account list.

  6. Navigate to the Opportunities screen, then to the Opportunities List view

  7. Verify that the Probability field in the Opportunity form applet displays the color box and exhibits the correct behavior based on changes to values and clicks.