Posts in Category "JavaScript"

Creating a Flip Book CQ Component

The canvas element is a new tag included in HTML 5. This allows for dynamic renderings of 2D shapes and bitmap images. I recently stumbled across a great example of the powerful effects that can be accomplished with the canvas element and javascript on a web app called 20 Things I learned about Browsers and the Web. The web application tells a nice summary of the basic history of the internet and open web technologies. What really makes it cool is that the information is presented as an interactive book and allows the user to “flip” the pages by dragging the mouse.

I thought it would be interesting to take this functionality and create a re-usable component in CQ. This would allow authors to add the component onto any paragraph system and drag text and images from the content finder to populate the “pages” of the book. The following tutorial focuses on creating a custom CQ component that uses its own CSS, images, and Javascript to make it run.

Continue reading…

Compiling a PDF Portfolio in LiveCycle

Situation:

How to merge multiple PDFs (retreived from a Database BLOB) and compile them using DDX and LiveCycle (ADEP). The portfolio will build based on the number of documents stored inside the database.

In this situation we will be compiling a Cover Page, Content Document(s), and a Final Document. Depending on the workflow state, there could be 0-5 documents in the database under the Content Document(s) section. The process is flexible enough to handle this.

Create the DDX File:

  1. Start by looking at the Assembly Descriptor documentation and DDX Reference Guide.
  2. In Workbench: Create a New Application (File>New>Application)
  3. Inside the Application directory, create a new folder and name it Assets.
  4. Locate the Acrobat .nav File you want to use. It will be located on your filesystem here: [Acrobat Location]\Acrobat\Navigators. For this situation AdobeRevolve.nav is being used. Import the .nav file into your Application’s Assets folder.
  5. Create a DDX file
    1. Right Click on Asset Folder> New > Assembly Descriptor.
    2. Provide a name for the DDX document.
    3. Click Finish.
    4. The Document Builder Window should come up inside Workbench
  6. The DDX File in the End will look like this:
    1. Start by Selecting New Result>PDF and Name it CompiledPDF
    2. Drag the Portfolio Component Under the CompiledPDF
    3. Under the Portfolio Editor paste the following elements:
      <Portfolio>
        <ColorScheme scheme="darkblueScheme"/>
        <Header/>
        <WelcomePage/>
        <Schema/>
        <DisplayOrder/>
        <SortOrder/>
        <Navigator source="AdobeRevolve.nav"/>
      </Portfolio>
    4. Press Apply in the Editor
    5. Drag the Navigator icon under the Portfolio Icon
    6. Paste the following under the Navigator Editor:  <Navigator source=”AdobeRevolve.nav”/>
    7. Press Apply in the Editor
    8. Drag the Packaged Files Icon underneath the Portfolio Icon
    9. Then add Seven PDF Documents sources under the Packaged Files and Name them in their Source field accordingly
    10. For Only the CoverPage document (the first one), go under the Basic tab and select both “This is the Base Document” and “There must be at least one valid source in this document” and ensure both of these boxes are deselected for the other PDF Document.
  7. Validate the DDX and Save it

Create a Process that will retrieve the documents from the database BLOB, assign them to a document map, invoke the DDX, Output a single PDF Portfolio document

The process will be built to look something like this:

In this process you will need the following variables:

    • thePortfolio–document–Output–Required
    • retrievedDocument –document
    • mapPortfolioDocs–map <document>
    • totalContentDocs–int
    • counter–int
    • tempContentDocID– string
    • PortfolioAssemblerResult–AssemblerResult
Retrieve a specific PDF document from the Oracle database BLOB and store it in the local variable retrievedDocument by executing the following executeScript service.
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.sql.ResultSet;
import javax.sql.DataSource;
import javax.naming.InitialContext;
 try {
   InitialContext context = new InitialContext();
   String queryQuery = [input your query here to get blob]
   //If you need to pass a process variable use "patExecContext.getProcessDataValue("/process_data/@counter");
   try {
    DataSource ds = (DataSource) context.lookup("java:/DDXDocs_DS");
    connection = ds.getConnection();
    queryStatement = connection.prepareStatement(queryQuery);
    results = queryStatement.executeQuery();
    if (results.next()) {
        java.sql.Blob documentBlob = results.getBlob(1);
        com.adobe.idp.Document document = new com.adobe.idp.Document(documentBlob.getBinaryStream());|
        patExecContext.setProcessDataValue("/process_data/@retrievedDocument", document);
     }
   }catch(Exception ex){
	System.out.println(ex.printStackTrace());
} finally {
    if (results != null) {
    	 results.close();
    }
    if (queryStatement != null) {
        queryStatement.close();
    }
    if (connection != null) {
        connection.close();
    }
   }
 } catch (Exception e) {
   e.printStackTrace();
 }

 

To test if a BLOB had been retrieved use the following route condition:

getDocLength(/process_data/@retrievedDocument)==0

 

If the document  was successfully retrieved, map it to the map <document> variable (mapPortfolioDocs) based on the id you gave it in the DDX source, using the setValue mapping below:

After retrieving all of the documents available, it is time to InvokeDDX. Using the Invoke DDX Service:
Finally, using the setValue operation, map the AssemblerResult to the output document variable (thePortfolio):

 

Silent Print in Acrobat Using JavaScript

I received a question from a customer on whether or not it is possible to create a toolbar button that will perform a silent print in Acrobat.  Well, it turns out that using JavaScript it is possible and really isn’t all that difficult.

Here’s some code:

    
    // if the application is Adobe Acrobat...
    //then create the silent print button
    if(app.viewerType == "Exchange-Pro") {

        app.trustedFunction(customSilentPrint);

        app.addToolButton({
            cName: "customSilentPrint",
            cExec: "customSilentPrint()",
            cTooltext: "Print Silent",
            cLabel: "Print Silent",
            cEnable: "event.rc = (app.doc != null)" });
        }

    function customSilentPrint(){

        // explicitly raise privileges
        app.beginPriv();

        try{
            // get the printer params
            var pp = this.getPrintParams();

            // don't show the print dialog window
            pp.interactive = pp.constants.interactionLevel.silent;
        }
        catch(err){
            app.alert("Error setting up printing parameters.\n\n" + err);
        }

        try{
            this.print(pp);
        }
        catch(err){
            app.alert("Error Printing.\n\n" + err);
        }

        // end explicit privileges
        app.endPriv();
    }



As you can see, there really isn’t much to this code, but let’s break it down.

First we check to ensure we are in Acrobat and, if so, we add the button called “Print Silent” to the Acrobat toolbar:

    // if the application is Adobe Acrobat...then create the silent print button
    if(app.viewerType == "Exchange-Pro") {

        app.trustedFunction(customSilentPrint);

        app.addToolButton({
            cName: "customSilentPrint",
            cExec: "customSilentPrint()",
            cTooltext: "Print Silent",
            cLabel: "Print Silent",
            cEnable: "event.rc = (app.doc != null)" });
    }


Next we create the function called customSilentPrint and raise privileges:

    function customSilentPrint(){

        // explicitly raise privileges
        app.beginPriv();


Within the function we get to the meat of the work by creating a print params object and setting the interactionLevel to silent.

        try{
            // get the printer params
            var pp = this.getPrintParams();
        
            // don't show the print dialog window
            pp.interactive = pp.constants.interactionLevel.silent;
        }


Now that we are set up to print silent, call the print function with these lines:

        try{
            this.print(pp);
        }
        catch(err){
            app.alert("Error Printing.\n\n" + err);
        }


To finish off our code we lower our privileges and close out the function:

        // end explicit privileges
        app.endPriv();

    }


As you can see there’s really no magic here, but this JavaScript code is a nifty little way to print silently in Acrobat.

Also, I haven’t researched silent printing using reader, but if you have tried it and succeeded or failed, please feel free to add to the post via comments.

BTW – If you don’t know how to create a toolbar button or install JavaScript in Acrobat, check out my collegue Venkata’s post here.

LC Designer: Single Web Service with Many Services

One side-effect of using Web Services in LC Designer is that you create a lot of data connections; in LC Designer and other IDEs consuming Web Services is not a big deal. For Form Desingers in particular, they seem to be consuming a lot more than the other development groups like: Java, AJAX, etc. And what amounts to is a tens of unique Web Services called within a single form. The problem is keeping up with all the WSDL and server changes. I’ve watched a developer change twenty forms because a single webservice was changed. I’ll show you a simple technique that can solve these problems.

What I do instead of creating many web services is that I create a single web service: invoke(Stirng in, String out)

This web service does nothing else but take a String as input parameter and write a String out as an output parameter. For the format of the String I use JSON. So the web service is more like: invoke(JSON in, JSON out).

Within the JSON in my object has the following:

jsonInputObject:{

       serviceID, //Says which service to invoke.

       messageObject:  {

              //Message specific stuff here

        }

}

I like JSON since its natively represented in JavaScript and I can represent what ever I want. Since most of the web service calls from LC Designer are stateless, I don’t worry about the overhead of using a stateful mechanism which adds bloat. 

Using a single web service that makes a call for you on the server side has the following advantages:

  • Don’t have to stub out a unique service call for every service
  • All services are available to you during design time.
  • Unit testing is easier because you can test your JavaScript on the form against a fixed JSON test object.
  • Adding an optional input parameter or adding a additional return parameters doesn’t require regeneration of your stubbed code.

So below is an example of what my LC Worflow process looks like:

 

ExampleService.png

In this implementation, there are only two services. One to retreive group information and other for office information. Instead of creating two web services, I just have one. For this project I’ll keep adding services to this process. I’ve had projects where are twenty service calls are represented with a single web service call.

 

Dynamically creating a table with data in LiveCycle form using JavaScript

Stefan Cameron wrote an article on scripting table columns a while back. Taking that idea, how would you dynamically create a table based on some data? Well, there are a couple of ways and this blog post will show you one way of achieving it.

Continue reading…

Generating JavaScript Documentation for Script Objects

One of the things many developers often fail to do is to document their code. Code and documentation comments are not only useful to yourself but also to other developers who may have to contribute to your work or use your work as part of their work. They help increase maintainability, code readability and ease of use. As previously posted, you can create script objects in Adobe LiveCycle Designer to extend standard JavaScript classes with prototype functions and properties. Your script objects can then be distributed among teams for reuse. However, if your script objects contain a large number of functions and properties, your end users may request for documentation.

Continue reading…

Using JSON to Exchange Data with Web Services in XFA Forms

Continuing from my previous post on extending the JavaScript prototype property, another most under-utilized technique is the use of JavaScript Object Notation (JSON) as a data exchange format between a form and web services. Did you ever think of using JSON in form development? No? Me neither. I never thought of it until one of my customers suggested the possibility. It was an elegant solution, as our web services were getting more complex, we were wrestling on reading the data versus implementing solutions. JSON gave us a way to reduce hassle of working with complex objects.

Continue reading…

Extending JavaScript with Prototypes in XFA Forms

Do you sometimes wish you had functions that standard JavaScript does not provide? For instance, a trim or strip function that removes leading and trailing white spaces from a string object. In LiveCycle Designer, the traditional way is to create a script object and a function. Then to use it, you would have a function call similar to the following statement:

var newString = ScriptObject.trim(oldString);

These function calls can become lengthy in situations where the script object is located on a different page than your method call. For example:

var newString = form1.page1.subform1.ScriptObject.trim(oldString);

Continue reading…