Siebel Scripting 4

  • Uploaded by: api-3762678
  • 0
  • 0
  • November 2019
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Siebel Scripting 4 as PDF for free.

More details

  • Words: 3,089
  • Pages: 70
Siebel Scripting, Part Four Scripting Concepts: Advanced

Introduction BusComps and BusObjects PropertySets TheApplication Business Services Scripting In Applets Using Windows Script Popups Garbage Disposal Final Thoughts

BusComps And BusObjects The BusComp is a central object used in Siebel Scripting It represents a Siebel Business Component Has Child Objects, such as Fields Must have a BusObject to create a BusComp

BusObjects Represent the Siebel Business Object Two ways to create: – Both created using TheApplication object

ActiveBusObject – Any BusComps created from this way will have data in them

GetBusObject (“BusObjName”) – BusComps created from this will be empty, and must be filled before they can be used

ActiveBusObject Syntax eScript – –

var boContact = TheApplication().ActiveBusObject(); var bcContact = boContact.GetBusComp(“Contact”);

Siebel VB – – – –

Dim boContact As BusObject Dim bcContact As BusCOmp Set boContact = TheApplication.ActiveBusObject Set bcContact = boContact.GetBusComp(“Contact”)

bcContact will have data in it, because it is based on the Active Business Object Generally used only in script on an Applet

GetBusObject Syntax eScript – –

var boContact = TheApplication().GetBusObject(“Contact”); var bcContact = boContact.GetBusComp(“Contact”);

Siebel VB – – – –

Dim boContact As BusObject Dim bcContact As BusCOmp Set boContact = TheApplication.GetBusObject(“Contact”) Set bcContact = boContact.GetBusComp(“Contact”)

bcContact will not have data in it Must be filled by executing a Query on it

Querying a BusComp Sometimes, a BusComp does not have any data (as when using GetBusObject) or does not have the data you need- it is just an empty structure To get data into it, you must use the ExecuteQuery method of the BusComp However, there are other things you must also set before you can call ExecuteQuery

Query Prerequisites SetViewMode ActivateField ClearToQuery SetSearchSpec When you query a Business Component, you are building a SQL query behind the scenes

SetViewMode Method Used to filter data, similar to using the My Views, My Team’s Views, All Across All Organization’s View, and so on Most of the Time, you will be using the AllView Mode, which does not filter any data at all (All Across All Organizations) Syntax (eScript): – bcContact.SetViewMode(AllView);

In the SQL Query, this controls part of the where clause

ActivateField Method Must be done before ClearToQuery When a query is execute on a Business Component, it does not automatically query for every field, only the following: – – – –

Fields that are a part of the current Applet System Fields Fields that are set as Force Active Fields that are Activated via the ActivateField Method

Syntax (Siebel VB): – bcName.ActivateField “FieldName”

In the SQL Query, this controls the Select clause

ClearToQuery Mothod Clears any existing data from the Business Component about to be queried This includes any search spec included with the current Applet Does clear any sort spec In the SQL Query, this empties the where clause from previous queries

SetSearchSpec Method Can have multiple fields, but is usually only consists of one field Syntax and Example(eScript): – bcName.SetSearchSpec(“FieldName”, Value); – bcSR.SetSeachSpec(“Id”, “1-13G5T”);

In SQL, that translates to: – where ROW_ID = ‘1-13G5T’

In the SQL Query, this gives the main part of the where clause If you use the Id field, the record set will contain at most, one record

ExecuteQuery Method Once all the pieces are in place, you can execute the query Syntax (Siebel VB): – bcName.ExecuteQuery Mode

Mode Determines how you can transverse the data – ForwardOnly: You can only go through the data in one direction. You cannot go back to a record once you move to another – ForwardBackward: Allows you to go through the data any direction, or revisit any data already read. Slower and more taxing on the database than ForwardOnly

The with (With) statement With allows you to access many methods or sub-objects of an object without repeating the name of the object Since there are so many pre-requisites to executing a query, all of which are methods of the same business component, with is very useful in executing queries

ExecuteQuery With Siebel VB With bcContact – .SetViewMode AllView – .ActivateField “Last Name” – .ActivateField “Email Address” – .ClearToQuery – .SetSearchSpec “Id”, sRowId – .ExecuteQuery ForwardOnly

End With

ExecuteQuery with eScript with (bcContact) { – SetViewMode(AllView); – ActivateField(“Last Name”); – ActivateField(“Email Address”); – ClearToQuery(); – SetSearch Spec (“Id”, sRowId); – ExecuteQuery(ForwardOnly);

}

GetFieldValue As expected, used to retrieve the value of a field in a business component Example: – sLName = bcContact.GetFieldValue(“Last Name”)

Takes an argument of a field of the BC (same spelling and case) Returns the value in that field in the current record If the field is not active, will cause an error

SetFieldValue Sets a field in a BC to a specified value in the current record Field does NOT have to be active Takes two arguments, no return – The Field to be updated (same spelling and case as in the BC in Tools) – The value to update it with (in string format)

Transversing BusComp Data FirstRecord NextRecord PreviousRecord LastRecord

FirstRecord Method Moves the record pointer to the first record, if it exists If it does, returns non-zero in SiebelVB, true in eScript If no first record exists (which means that the query returned no records), returns 0 (zero) in Siebel VB and false in eScript If BusComp was queried in ForwardOnly mode, FirstRecord cannot be called once the record pointer moves to any other

NextRecord Method Moves record pointer to the next record in the data set If there are no more records, returns 0 or false If there are, returns non-zero or true

PreviousRecord Method Same as NextRecord, including return values, except it moves the record pointer to the previous record May only be used on BusComps that have been queried in ForwardBackward mode

LastRecord Method Moves the record pointer to the last record in the data set If there is a record, returns non-zero or true If there are no records in the record set, returns 0 or false Unless the query was made in ForwardBackward mode, cannot move to any other record after using this method

NewRecord Method Begins creating a new record in the Business Component – New record is not saved until WriteRecord method is used

Use SetFieldValue to assign values to whatever fields you need to in the new record – Fields that have a pre or post default value will also get values in them

Use WriteRecord to save the new record once all values have been set

NewRecord Arguments The NewRecord requires one argument that specifies where in the current data set to save the new record NewAfter saves the record after the current one NewBefore Saves the record before the current one

NewRecord Example with bcContact { – NewRecord NewAfter; – SetFieldValue(“Last Name”, “Harrison”); – SetFieldValue(“First Name”, “James”); – SetFieldValue(“Home Phone #”, “7195550234”); – WriteRecord();

}

NewAfter(Before)Copy You can also use NewAfterCopy or NewBeforeCopy to create a Copy of the current record Just like right clicking in the application and selecting “Copy Record” Must still use WriteRecord to Save the new record Example: – bcContact.newRecord(NewAfterCopy); – bcContact.WriteRecord();

Other Important BC Methods UndoRecord Pick DeleteRecord GetMVGBusComp GetPicklistBusComp GetUserProperty ParentBusComp

Property Sets Simple description: name-value pairs What that really means is that a property set can hold a number of separate string variables Name: name of the string variable – Name can be whatever you choose, it is also stored as a string – Just be sure to be consistent

Value: value of that variable

Passing Data Between Objects Can be used to pass information from one object to another – Set the values in one object – Retrieve them in the other, using the names you created when setting

Can pass all related data, such as different fields from the same BC record Can also pass unrelated data, such as some BC fields, the BC name, and the number of current records in the BC record set

Hierarchical Property Sets Property Sets not only contain name-value pairs, but can also contain other property sets This means that a property set hierarchy can be set up One of the most important uses for this is seen in it’s comparison with XML:

XML EXstensible Markup Language Like HTML, is made up of tags and values, but the similarity ends there With HTML, there is , <body>, <table>, <br>, <p> and so on In XML, there are no pre-defined tags, but there is structure – Opening and closing tags – Hierarchy of tags<br /> <br /> XML Example <Contact> – <FirstName>”Jay”</FirstName> – <LastName>”Smith”</LastName> – <Phone>”8055551234”</Phone> – <MiddleName></MiddleName> – <Email/><br /> <br /> </Contact><br /> <br /> XML And Property Sets XML tags can contain data Property Sets can also contain data XML tags can contain other XML tags Property Sets can contain other property sets Property Sets are ideal for representing XML files in Siebel Script Several pre-defined Business Services exits in Siebel that take advantage of this<br /> <br /> Property Set Methods NewPropertySet SetProperty GetProperty AddChild GetChild PropertyExists GetPropertyCount GetChildCount<br /> <br /> NewPropertySet Method Is a method of TheApplication Creates a new property set object or reinitializes (erases all previous data) of an existing property set Syntax: – Dim psIn As PropertySet – Set psIn = TheApplication.NewPropertySet – var psIn = TheApplication().NewPropertySet();<br /> <br /> SetProperty GetProperty Get or set a property in the property set Syntax for Set: – psName.SetProperty(“PropName”, Value); – psIn.SetProperty(“LastName”, “Smith”);<br /> <br /> Syntax for Get: – var sVar = psName.GetProperty(“PropName”); – Var sLName = psIn.GetProperty(“Last Name”);<br /> <br /> AddChild Method AddChild sets an existing property set as a child PS of another existing property set Both entities must be property sets- in eScript, if they aren’t, they will be changed into property sets Syntax: – var psOuter = TheApplication().NewPropertySet(); – var psInner = TheApplication().NewPropertySet(); – psOuter.AddChild(psInner);<br /> <br /> GetChild Method Takes an integer as an argument – Child PropertySets are stored as if in an array that is numbered from 0 as the first Child PropertySet added<br /> <br /> Returns a child property set or null, if no such PS exists Syntax: – Dim psNew As PropertySet – Set psNew = psOld.GetChild(0)<br /> <br /> PropertyExists Method Very simple method- used to find out whether or not a specific name property exists in a PropertySet Takes a string (the name of the property) as an argument Returns a boolean (or integer in VB) of either true (or non-zero) if the property exists or false (0) if the property does not Using a GetProperty with a property that does not exist will create an error- you can use this method to ensure that doesn’t happen<br /> <br /> GetPropertyCount Method Simply returns the number of properties in a Propset Each time SetProperty is used with a new name, this count is increased by one SetProperty with the same name simply changes the value of an existing property, thus the count does not increase RemoveProperty will decrease the count by one<br /> <br /> GetChildCount Method Only returns the number of child propsets that belong directly to the PS it is used on- it does not tell anything about any children those propsets may have iCount = psIn.GetChildCount(); But it can be “stacked” with GetChild iCount = psIn.GetChild (2).GetChildCount(); This returns the number of children of the 3rd child of psIn (remember, starts at 0), not the number of children of psIn itself<br /> <br /> Property Sets Property Sets are one of the most important objects in Siebel It is important to learn all you can about using them Using a Property Sets to their full potential is the mark of a good Siebel scripter<br /> <br /> TheApplication Object TheApplication is a special object in the Siebel World It represents the actual Application you are using (Call Center, Financial Services, etc) in code Any code placed on the Application Object is a part of TheApplication object In eScript, this code (methods and objects) can be accessed from anywhere else in the system<br /> <br /> Business Services As previously mentioned, Business Services are Siebel object with one purpose: To hold scripts They are the best place to hold scripts that will be accessed from elsewhere – For some simple scripts, consider using TheApplication with eScript<br /> <br /> The PreInvokeMethod Event In each Siebel Object that can be scripted, there are a few important events: – PreCanInvokeMethod – PreInvokeMethod – InvokeMethod<br /> <br /> Each time a method in the object is called, these events fire However, there are internal events that fire first<br /> <br /> Internal Events Whenever a method is called, the following events happen – – – –<br /> <br /> Internal PreInvokeMethod Scripted PreInvokeMethod Internal InvokeMethod Scripted InvokeMethod<br /> <br /> If Internal Invoke Method is called on any Method that is not declared internally in Siebel, an error is generated Therefore, you must put the code you wish to execute in your Methods in the PreInvokeMethod event, and then tell Siebel to cancel the operation<br /> <br /> Canceling The Operation Each event returns an integer constant, either ContinueOperation or CancelOperation CancelOperation tells the system to stop trying to run InvokeMethod on the named method InvokeMethod can only be run on methods that have been declared internally, so you must return this from the PreInvokeMethod of any method you create<br /> <br /> Canceling The Invoke Syntax In PreInvokeMethod Event: if (MethodName == “MyMethod”) { – // Code that you need to accomplish in your – // method – return (CancelOperation);<br /> <br /> } Better way is demonstrated on the white board<br /> <br /> Functions Instead of putting all of your code into the PreInvokeMethod event, consider creating functions in the object and calling those function MyFunction() { – // put all my method code here<br /> <br /> } Call this function from the PreInvokeMethod event<br /> <br /> Function Example function GetName (sRowId) { – – – – –<br /> <br /> var boCnct = TheApplication().GetBusObject(“Contact”); var bcContact = boCnct .GetBusComp(“Contact”); var sName = “”; with (bcContact) { SetViewMode(AllView); ActivateField(“Last Name”); ClearToQuery(); SetSearchSpec(“Id, sRowId); ExecuteQuery(ForwardOnly);<br /> <br /> – – –<br /> <br /> }<br /> <br /> } sName = bcContact.GetFieldValue(“Last Name”); return (sName);<br /> <br /> Calling The Function In BS PreInvokeMethod Event: var iRetVal = ContinueOperation; if (MethodName == “GetLName”) { – – – – – – – –<br /> <br /> // Make sure to cancel InvokeMethod iRetVal = CancelOperation; // Get Data var sContactId = Inputs.GetProperty(“Contact Id”); //Call Function var sLName = GetName(sContactId); //Send the data back out of the BS Outputs.SetProperty(“Last Name”, sLName);<br /> <br /> } return (iRetVal);<br /> <br /> Calling A Method In A Business Service 1) Declare the service and property sets 2) Get the Service 3) Set any appropriate input property set 4) Invoke the Method, passing the method name, input property set, and output property set 5) Retrieve any returned data from the output property set<br /> <br /> Declare The Objects var psIn = TheApplication().NewPropertySet(); var psOut = TheApplication().NewPropertySet(); Var bsCode = TheApplication.GetService(“Service Name”);<br /> <br /> Set Up The Input Property Set Set Properties in input property set of any data that needs to be passed to the business service psIn.SetProperty(“Contact Id”, “1-145FT”); psIn.SetProperty(“BC Name”, “Contact”);<br /> <br /> InvokeMethod The InvokeMethod method is a special method in Siebel Use it to call a method from any object Take 3 arguments: – A string that is the name of the method – A property set that includes all of the data being passed into the method – A property set that can be used to pass data back out of the object<br /> <br /> Syntax: – Object.InvokeMethod(“MethodName”, InPS, OutPS);<br /> <br /> Retrieve Returned Data In your objects, use the output property set to pass data back out Notice that the PreInvokeMethod event has three arguments passed to it: MethodName, Inputs, Outputs –just like what you pass in the InvokeMethod method Syntax: – var sName = psOut.GetProperty(“Last Name”);<br /> <br /> Full Example WebApplet_PreInvokeMethod { – – –<br /> <br /> var iRetVal = ContinueOperation; if (MethodName == “GetLName”) { iRetVal = CancelOperation; GetLastName();<br /> <br /> –} – return (iRetVal);<br /> <br /> }<br /> <br /> GetLastName Function function GetLastName() { – var sRowId = this.BusComp.GetFieldValue(“Id”); – Var bsGetName = TheApplication().GetService(“Contact Name BS”); – var psIn = TheApplication().NewPropertySet(); – var psOut = TheApplication().NewPropertySet(); – psIn.SetProperty(“Contact Id”, sRowId); – bsGetName.InvokeMethod(“GetLName”, psIn, psOut); – var sName = psOut.GetProperty(“Last Name”); – this.BusComp.SetFieldValue(“Alias”, sName);<br /> <br /> }<br /> <br /> Applet Scripting The primary use for scripting in applets is to make buttons First, create a button on the web layout of the applet (copying an existing one is easiest) – Set the Name Property, the MethodInvoked property, and the Caption Property<br /> <br /> Then add code to the PreCanInvokeMethod and the PreInvokeMethod events using the MethodInvoked value as your MethodName<br /> <br /> PreCanInvokeMethod The PreCanInvokeMethod event is an event that fires for every control on the applet as soon as the applet is loaded, and often after that It takes two arguments – The MethodName – A string called CanInvoke (by Reference)<br /> <br /> Set CanInvoke to “TRUE” in order to make your button clickable<br /> <br /> PreCanInvoke Example WebApplet_PreCanInvokeMethod(MethodName , &CanInvoke) { – var iRetVal = ContinueOperation; – if (MethodName == “MyMethod”) –{ iRetVal = CancelOperation; CanInvoke = “TRUE”;<br /> <br /> – –<br /> <br /> }<br /> <br /> } return (iRetVal);<br /> <br /> Example Explanation All that code is simply to make the button clickable (not grayed-out) Note that you must also return CancelOperation in PreCanInvokeMethod as well, just like PreInvokeMethod –if you don’t, it will cause an error<br /> <br /> Applet Considerations Use PreCanInvoke to make button clickable Always best to use function in the declarations section for your actual workcode, rather than putting it in the PreInvokeMethod event Even better is to create a business service and call that from your applet code – Makes your script more modularized and reusable<br /> <br /> Windows Script Object Useful for debugging only Can be used to create popup windows, but since they are made with a Windows Script, they are created on the machine that they are called on – In other words, they only work with a Mobile Client, not with a Web Client<br /> <br /> Creating a WScript Object eScript: – var WShell; – WShell = COMCreateObject(“WScript.Shell”);<br /> <br /> Siebel VB: – Dim WShell as Object – Set WShell = CreateObject(“WScript.Shell”)<br /> <br /> Using the WScript Popup WShell.Popup(“Message”); WShell.Popup(“Hello World”); WShell.Popup(bcContact.GetFieldValue(“Id”);<br /> <br /> Garbage Disposal Objects are dynamically created by the Siebel system using memory allocation The system cleans them up automatically, but it doesn’t do a very good job –it doesn’t necessarily clean them up in the proper order For example, since a BusComp is created from a BusObject, if the BusObject happens to get cleaned up before the BusComp, there is no more access to the BusComp to clean it up with<br /> <br /> Garbage Disposal cont Therefore, you should clean it up yourself Always remove objects in the reverse order than they were created eScript: – bcContact = null; – boCnct = null;<br /> <br /> Siebel VB: – Set bcContact = Nothing – Set boCnct = Nothing<br /> <br /> Scripting Final Thoughts We have just scratched the surface on what scripting can do Always continue studying scripting and practicing it All of the Use Scenarios (full assignments) at the end of the course will include some scripting (In my opinion) A Siebel Consultant who can’t script isn’t worth a damn to anyone </div> </div> <hr /> <h4>Related Documents</h4> <div class="row"> <div class="col-lg-2 col-md-4 col-sm-6 col-6"> <div class="card item-doc mb-4"> <a href="https://pdfcoke.com/documents/siebel-scripting-4-w63y6gn1yomx" class="d-block"><img class="card-img-top" src="https://pdfcoke.com/img/crop/300x300/w63y6gn1yomx.jpg" alt=""/></a> <div class="card-body text-left"> <h5 class="card-title"><a href="https://pdfcoke.com/documents/siebel-scripting-4-w63y6gn1yomx" class="text-dark">Siebel Scripting 4</a></h5> <small class="text-muted float-left"><i class="fas fa-clock"></i> November 2019</small> <small class="text-muted float-right"><i class="fas fa-eye"></i> 12</small> <div class="clearfix"></div> </div> </div> </div> <div class="col-lg-2 col-md-4 col-sm-6 col-6"> <div class="card item-doc mb-4"> <a href="https://pdfcoke.com/documents/siebel-scripting-2-09o8240e6orx" class="d-block"><img class="card-img-top" src="https://pdfcoke.com/img/crop/300x300/09o8240e6orx.jpg" alt=""/></a> <div class="card-body text-left"> <h5 class="card-title"><a href="https://pdfcoke.com/documents/siebel-scripting-2-09o8240e6orx" class="text-dark">Siebel Scripting 2</a></h5> <small class="text-muted float-left"><i class="fas fa-clock"></i> November 2019</small> <small class="text-muted float-right"><i class="fas fa-eye"></i> 9</small> <div class="clearfix"></div> </div> </div> </div> <div class="col-lg-2 col-md-4 col-sm-6 col-6"> <div class="card item-doc mb-4"> <a href="https://pdfcoke.com/documents/siebel-scripting-1-q6zpdp72gzpk" class="d-block"><img class="card-img-top" src="https://pdfcoke.com/img/crop/300x300/q6zpdp72gzpk.jpg" alt=""/></a> <div class="card-body text-left"> <h5 class="card-title"><a href="https://pdfcoke.com/documents/siebel-scripting-1-q6zpdp72gzpk" class="text-dark">Siebel Scripting 1</a></h5> <small class="text-muted float-left"><i class="fas fa-clock"></i> November 2019</small> <small class="text-muted float-right"><i class="fas fa-eye"></i> 5</small> <div class="clearfix"></div> </div> </div> </div> <div class="col-lg-2 col-md-4 col-sm-6 col-6"> <div class="card item-doc mb-4"> <a href="https://pdfcoke.com/documents/siebel-scripting-3-0935n4j0d3e8" class="d-block"><img class="card-img-top" src="https://pdfcoke.com/img/crop/300x300/0935n4j0d3e8.jpg" alt=""/></a> <div class="card-body text-left"> <h5 class="card-title"><a href="https://pdfcoke.com/documents/siebel-scripting-3-0935n4j0d3e8" class="text-dark">Siebel Scripting 3</a></h5> <small class="text-muted float-left"><i class="fas fa-clock"></i> November 2019</small> <small class="text-muted float-right"><i class="fas fa-eye"></i> 11</small> <div class="clearfix"></div> </div> </div> </div> <div class="col-lg-2 col-md-4 col-sm-6 col-6"> <div class="card item-doc mb-4"> <a href="https://pdfcoke.com/documents/siebel-configuration-4vz082mw838l" class="d-block"><img class="card-img-top" src="https://pdfcoke.com/img/crop/300x300/4vz082mw838l.jpg" alt=""/></a> <div class="card-body text-left"> <h5 class="card-title"><a href="https://pdfcoke.com/documents/siebel-configuration-4vz082mw838l" class="text-dark">Siebel Configuration</a></h5> <small class="text-muted float-left"><i class="fas fa-clock"></i> October 2019</small> <small class="text-muted float-right"><i class="fas fa-eye"></i> 25</small> <div class="clearfix"></div> </div> </div> </div> <div class="col-lg-2 col-md-4 col-sm-6 col-6"> <div class="card item-doc mb-4"> <a href="https://pdfcoke.com/documents/siebel-architect-kpol9xrgpoxn" class="d-block"><img class="card-img-top" src="https://pdfcoke.com/img/crop/300x300/kpol9xrgpoxn.jpg" alt=""/></a> <div class="card-body text-left"> <h5 class="card-title"><a href="https://pdfcoke.com/documents/siebel-architect-kpol9xrgpoxn" class="text-dark">Siebel Architect</a></h5> <small class="text-muted float-left"><i class="fas fa-clock"></i> October 2019</small> <small class="text-muted float-right"><i class="fas fa-eye"></i> 29</small> <div class="clearfix"></div> </div> </div> </div> </div> </div> </div> </div> </div> <footer class="footer pt-5 pb-0 pb-md-5 bg-primary text-white"> <div class="container"> <div class="row"> <div class="col-md-3 mb-3 mb-sm-0"> <h5 class="text-white font-weight-bold mb-4">Our Company</h5> <ul class="list-unstyled"> <li><i class="fas fa-location-arrow"></i> 3486 Boone Street, Corpus Christi, TX 78476</li> <li><i class="fas fa-phone"></i> +1361-285-4971</li> <li><i class="fas fa-envelope"></i> <a href="mailto:info@pdfcoke.com" class="text-white">info@pdfcoke.com</a></li> </ul> </div> <div class="col-md-3 mb-3 mb-sm-0"> <h5 class="text-white font-weight-bold mb-4">Quick Links</h5> <ul class="list-unstyled"> <li><a href="https://pdfcoke.com/about" class="text-white">About</a></li> <li><a href="https://pdfcoke.com/contact" class="text-white">Contact</a></li> <li><a href="https://pdfcoke.com/help" class="text-white">Help / FAQ</a></li> <li><a href="https://pdfcoke.com/account" class="text-white">Account</a></li> </ul> </div> <div class="col-md-3 mb-3 mb-sm-0"> <h5 class="text-white font-weight-bold mb-4">Legal</h5> <ul class="list-unstyled"> <li><a href="https://pdfcoke.com/tos" class="text-white">Terms of Service</a></li> <li><a href="https://pdfcoke.com/privacy-policy" class="text-white">Privacy Policy</a></li> <li><a href="https://pdfcoke.com/cookie-policy" class="text-white">Cookie Policy</a></li> <li><a href="https://pdfcoke.com/disclaimer" class="text-white">Disclaimer</a></li> </ul> </div> <div class="col-md-3 mb-3 mb-sm-0"> <h5 class="text-white font-weight-bold mb-4">Follow Us</h5> <ul class="list-unstyled list-inline list-social"> <li class="list-inline-item"><a href="#" class="text-white" target="_blank"><i class="fab fa-facebook-f"></i></a></li> <li class="list-inline-item"><a href="#" class="text-white" target="_blank"><i class="fab fa-twitter"></i></a></li> <li class="list-inline-item"><a href="#" class="text-white" target="_blank"><i class="fab fa-linkedin"></i></a></li> <li class="list-inline-item"><a href="#" class="text-white" target="_blank"><i class="fab fa-instagram"></i></a></li> </ul> <h5 class="text-white font-weight-bold mb-4">Mobile Apps</h5> <ul class="list-unstyled "> <li><a href="#" class="bb-alert" data-msg="IOS app is not available yet! Please try again later!"><img src="https://pdfcoke.com/static/images/app-store-badge.svg" height="45" /></a></li> <li><a href="#" class="bb-alert" data-msg="ANDROID app is not available yet! Please try again later!"><img style="margin-left: -10px;" src="https://pdfcoke.com/static/images/google-play-badge.png" height="60" /></a></li> </ul> </div> </div> </div> </footer> <div class="footer-copyright border-top pt-4 pb-2 bg-primary text-white"> <div class="container"> <p>Copyright © 2024 PDFCOKE.</p> </div> </div> <script src="https://pdfcoke.com/static/javascripts/jquery.min.js"></script> <script src="https://pdfcoke.com/static/javascripts/popper.min.js"></script> <script src="https://pdfcoke.com/static/javascripts/bootstrap.min.js"></script> <script src="https://pdfcoke.com/static/javascripts/bootbox.all.min.js"></script> <script src="https://pdfcoke.com/static/javascripts/filepond.js"></script> <script src="https://pdfcoke.com/static/javascripts/main.js?v=1728076701"></script> <!-- Global site tag (gtag.js) - Google Analytics --> <script async src="https://www.googletagmanager.com/gtag/js?id=UA-144986120-1"></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'UA-144986120-1'); </script> </body> </html>