0

I've had some success creating custom stamps in Bluebeam (great PDF editor) by starting from their existing sample stamps. I've got a stamp that has one custom text field that has a drop down menu with predetermined options to selection. The stamp also has several other text fields, some of which allow the user to input data and some of which pull data - the current date and the users name.

All of this works well but I'd like to add a second text field with predetermined options and there seems to be no way to do this.

The way this software works, there's a "calculation" javascript that's run whenever the stamp is first placed onto a PDF The calculation code creates the UI for the user to input date. The calculation code references a "stampcode' javascript. The "stampcode" references specific elements in the stamp itself (also a PDF file).

I think I've got the stampcode set up correctly. I think the calculation code is what needs to be edited. I get the feeling this is a fairly straightforward process I'm just a fairly novice coder and really don't know where to start with this. I've spent about 4 hours trying to tweak the calculation code and have had no luck with it. Any help would be greatly appreciated. (I'm using visual studio code to edit).

Stampcode:

    var builder = 
{
 // These map to Text Fields in the Stamp
 textBoxes :
 [
  { field:"Client", description:"Client:", default:function() { return ""; } },
  { field:"Project_Number", description:"Project No.:", default:function() { return ""; } },
  { field:"Expense_Date", description:"Date of Exp.:", default:function() { return ""; } },
  { field:"Markup", description:"Markup %:", default:function() { ""; } },
  { field:"CheckedBy", description:"Checked by:", default:function() { return Collab.user; } },
  { field:"Date", description:"Date:", default:function() 
  {  
  var curDate = new Date();
  return (curDate.getMonth() + 1) + "/" + curDate.getDate() + "/" + curDate.getFullYear();
  } 
  }, 
 ],
  // This maps to a Radio Group in the PDF named 'Status'
 radioGroup : "Status", 
 radioButtons :
 [
  // value maps to the 'Choice' of each radio button in the group, description will show on the dialog
  { value:"Approved", description:"Approved" }, 
  { value:"Revise", description:"Revise" },
  { value:"Rejected", description:"Rejected" }
 ],
 // This maps to a Popup Group in the PDF named 'Reimburse' 
 popupGroup: "Reimburse",
 listItems :
 [
  {popupItems :
   {
    //list of items of Popup menu, positive number indicates default selection
    "XXX": -1,
    "XXX": -1,
    "DC": -1,
    "CC": -1
   }
  }
 ],
 // This maps to a Popup Group in the PDF named 'Service' 
 popupGroup: "Service",
 listItems :
 [
  {popupItems :
   {
    //list of items of Popup menu, positive number indicates default selection
    "00": -1,
    "10": -1,
    "20": -1,
    "30": -1,
    "40": -1,
    "50": -1,
    "51": -1,
    "55": -1,
    "60": -1,
    "65": -1,
    "70": -1,
    "80": -1,
    "81": -1,
    "90": -1,
    "91": -1,
    "99": -1
   }
  }
 ],
  // This maps to a Radio Group in the PDF named 'Status'
 radioGroup : "Status", 
 radioButtons :
 [
  // value maps to the 'Choice' of each radio button in the group, description will show on the dialog
  { value:"Billable", description:"Billable" }, 
  { value:"Not Billable", description:"Not Billable" }
 ],
 radioErrorMsg : "Please select a status",
}

Calculation Code:

// WARNING: DO NOT EDIT
// SEE GLOBAL JAVASCRIPT SECTION FOR CUSTOMIZATION

if (event.source.forReal)
{
 var stampDialog = CreateDialog(builder);
 app.execDialog(stampDialog); 

 this.getField(builder.radioGroup).value = stampDialog.radioSelection;
 this.getField(builder.popupGroup).value = stampDialog.popupSelection;

 for (var i = 0; i < builder.textBoxes.length; ++i)
 {
  var t = builder.textBoxes[i];
  this.getField(t.field).value = stampDialog.textBoxResults[i];
 }
}

function CreateDialog(dialogBuilder)
{
 var sd = new Object();
 sd.builder = dialogBuilder;
 sd.radioSelection = "";
 sd.popupSelection = "";
 sd.textBoxResults = new Array();

 var popupElements = new Array();

 popupElements[0] =
 {
  type: "popup",
  item_id: "popupItems",
  field: sd.builder.popupGroup,
  width: 250
 };

 var popupCluster =
 {
  type: "cluster",
  name: builder.popupGroup,
  elements: popupElements
 };

 var stateElements = new Array();

 for (var i = 0; i < dialogBuilder.radioButtons.length; ++i)
 {
  var c = dialogBuilder.radioButtons[i];
  stateElements[i] = 
   {
    type: "radio",
    name: c.description,
    item_id: "rad" + i,
    group_id: "grp1"    
   };  
 } 

 var stateCluster = 
 {
  type: "cluster",
  name: "Status",
  alignment: "align_center",
  align_children: "align_distribute",  
  elements: stateElements
 };

 var optionsElements = new Array(); 

 for (var i = 0; i < dialogBuilder.textBoxes.length; ++i)
 {
  var view = new Object();  
  view.type = "view";
  view.align_children = "align_row";
  view.elements = new Array();

  var t = dialogBuilder.textBoxes[i];

  var s = new Object();
  s.type = "static_text";
  s.item_id = "sta" + i;
  s.name = t.description;
  s.width = 90;  

  var e = new Object();
  e.type = "edit_text";
  e.item_id = "edt" + i;
  e.width = 150;

  view.elements[0] = s;
  view.elements[1] = e;  

  optionsElements[i] = view;
 }

 var optionsCluster = 
 {
  type: "cluster",
  name: "Options",
  elements: optionsElements
 };

 sd.initialize = function(dialog)
 {
  var init = new Object();

  for (var i = 0; i < this.builder.textBoxes.length; ++i)
  {
   var t = this.builder.textBoxes[i];
   var id = "edt" + i;   
   init[id] = t.default();
  }

  dialog.load(init);
  dialog.load(this.builder.listItems[0]);  
 };

 sd.commit = function(dialog)
 {
  var res = dialog.store();

  for (var i = 0; i < this.builder.radioButtons.length; ++i)
  {
   var c = this.builder.radioButtons[i];
   var id = "rad" + i;
   if (res[id] == true)
   {
    this.radioSelection = c.value;
    break;
   }
  }  

  for (var i = 0; i < this.builder.textBoxes.length; ++i)
  {
   var t = this.builder.textBoxes[i];
   var id = "edt" + i;
   this.textBoxResults[i] = res[id];
  }

  for (var i in res["popupItems"])
  if (res["popupItems"][i] >0)
  {
   this.popupSelection = i;
  }
 };

 sd.validate = function(dialog)
 {
  var res = dialog.store();
  for (var i = 0; i < this.builder.radioButtons.length; ++i)
  {
   var c = this.builder.radioButtons[i];
   var id = "rad" + i;
   if (res[id] == true)
    return true;
  }

  app.alert(this.builder.radioErrorMsg);
  return false;
 };

 sd.description = 
 {
  name: "Stamp Dialog",
  elements:
  [
   {
    type: "view",
    align_children: "align_fill",
    elements:
    [
     popupCluster,
     stateCluster,
     optionsCluster
    ]
   },
   {
    type: "ok"
   }
  ]
 };

 return sd;
}
B. Go
  • 1,436
  • 4
  • 15
  • 22
AWH
  • 1
  • 2

2 Answers2

0

I've been having trouble understanding the stamps API in Bluebeam as well. A big help to me was stumbling into the Adobe Javascript API reference. Most of the API for these stamps is part of the Adobe standard. It is not specific to Blubeam.

I reverted your code back to the reference code for a custom stamp template provided on Bluebeam's website.

Calculation Script

// WARNING: DO NOT EDIT
// SEE GLOBAL JAVASCRIPT SECTION FOR CUSTOMIZATION

if (event.source.forReal) {
  var stampDialog = CreateDialog(builder);
  app.execDialog(stampDialog);

  this.getField(builder.radioGroup).value = stampDialog.radioSelection;
  //Popup1
  this.getField(builder.popupGroup).value = stampDialog.popupSelection;
  //Popup2
  this.getField(builder.popupGroup2).value = stampDialog.popupSelection2;

  for (var i = 0; i < builder.textBoxes.length; ++i) {
    var t = builder.textBoxes[i];
    this.getField(t.field).value = stampDialog.textBoxResults[i];
  }
}

function CreateDialog(dialogBuilder) {
  var sd = new Object();
  sd.builder = dialogBuilder;
  sd.radioSelection = "";
  //Popup1
  sd.popupSelection = "";
  //Popup2
  sd.popupSelection2 = "";
  sd.textBoxResults = new Array();

  var popupElements = new Array();
  var popupElements2 = new Array();

  //Popup1
  popupElements[0] = {
    type: "popup",
    item_id: "ppi1",
    field: sd.builder.popupGroup,
    width: 250
  };

  //Popup2
  popupElements2[0] = {
    type: "popup",
    item_id: "ppi2",
    field: sd.builder.popupGroup2,
    width: 250
  };

  var popupCluster = {
    type: "cluster",
    name: builder.popupGroup,
    elements: popupElements
  };

  var popupCluster2 = {
    type: "cluster",
    name: builder.popupGroup2,
    elements: popupElements2
  };

  var stateElements = new Array();

  for (var i = 0; i < dialogBuilder.radioButtons.length; ++i) {
    var c = dialogBuilder.radioButtons[i];
    stateElements[i] = {
      type: "radio",
      name: c.description,
      item_id: "rad" + i,
      group_id: "grp1"
    };
  }

  var stateCluster = {
    type: "cluster",
    name: "Status",
    alignment: "align_center",
    align_children: "align_distribute",
    elements: stateElements
  };

  var optionsElements = new Array();

  for (var i = 0; i < dialogBuilder.textBoxes.length; ++i) {
    var view = new Object();
    view.type = "view";
    view.align_children = "align_row";
    view.elements = new Array();

    var t = dialogBuilder.textBoxes[i];

    var s = new Object();
    s.type = "static_text";
    s.item_id = "sta" + i;
    s.name = t.description;
    s.width = 90;

    var e = new Object();
    e.type = "edit_text";
    e.item_id = "edt" + i;
    e.width = 150;

    view.elements[0] = s;
    view.elements[1] = e;

    optionsElements[i] = view;
  }

  var optionsCluster = {
    type: "cluster",
    name: "Options",
    elements: optionsElements
  };

  sd.initialize = function(dialog) {
    var init = new Object();

    for (var i = 0; i < this.builder.textBoxes.length; ++i) {
      var t = this.builder.textBoxes[i];
      var id = "edt" + i;
      init[id] = t.default();
    }

    dialog.load(init);
    dialog.load(this.builder.listItems[0]);
    dialog.load(this.builder.listItems2[0]);
  };

  sd.commit = function(dialog) {
    var res = dialog.store();

    for (var i = 0; i < this.builder.radioButtons.length; ++i) {
      var c = this.builder.radioButtons[i];
      var id = "rad" + i;
      if (res[id] == true) {
        this.radioSelection = c.value;
        break;
      }
    }

    for (var i = 0; i < this.builder.textBoxes.length; ++i) {
      var t = this.builder.textBoxes[i];
      var id = "edt" + i;
      this.textBoxResults[i] = res[id];
    }

    //Popup1
    for (var i in res["ppi1"])
      if (res["ppi1"][i] > 0) {
        this.popupSelection = i;
      }

    //Popup2
    for (var i in res["ppi2"])
      if (res["ppi2"][i] > 0) {
        this.popupSelection2 = i;
      }
  };

  sd.validate = function(dialog) {
    var res = dialog.store();
    for (var i = 0; i < this.builder.radioButtons.length; ++i) {
      var c = this.builder.radioButtons[i];
      var id = "rad" + i;
      if (res[id] == true) return true;
    }`enter code here`

    app.alert(this.builder.radioErrorMsg);
    return false;
  };

  sd.description = {
    name: "Stamp Dialog",
    elements: [
      {
        type: "view",
        align_children: "align_fill",
        elements: [popupCluster, popupCluster2, stateCluster, optionsCluster]
      },
      {
        type: "ok"
      }
    ]
  };

  return sd;
}

Stamp Code

    var builder = {
  // These map to Text Fields in the Stamp
  textBoxes: [
    {
      field: "CheckedBy",
      description: "Checked by:",
      default: function() {
        return Collab.user;
      }
    },
    {
      field: "Date",
      description: "Date:",
      default: function() {
        var curDate = new Date();
        return (
          curDate.getMonth() +
          1 +
          "/" +
          curDate.getDate() +
          "/" +
          curDate.getFullYear()
        );
      }
    },
    {
      field: "Submittal",
      description: "Submittal #:",
      default: function() {
        return "";
      }
    },
    {
      field: "Spec",
      description: "Spec #:",
      default: function() {
        return "";
      }
    }
  ],
  // This maps to a Radio Group in the PDF named 'Status'
  radioGroup: "Status",
  radioButtons: [
    // value maps to the 'Choice' of each radio button in the group, description will show on the dialog
    { value: "Approved", description: "Approved" },
    { value: "Revise", description: "Revise" },
    { value: "Rejected", description: "Rejected" }
  ],
  radioErrorMsg: "Please select a status",
  // This maps to a Popup Group in the PDF named 'Project'
  popupGroup: "Project",
  listItems: [
    {
      ppi1: {
        //list of items of Popup menu, positive number indicates default selection
        "Project 1": -1,
        "Project 2": -1,
        "Project 3": -1,
        "Project 4": -1,
        "Project 5": -1
      }
    }
  ],
  popupGroup2: "Service",
  listItems2: [
    {
      ppi2: {
        //list of items of Popup menu, positive number indicates default selection
        "1": -1,
        "2": -1,
        "3": -1,
        "4": -1,
        "5": -1
      }
    }
  ]
};
ajgriese
  • 459
  • 5
  • 10
0

Totally realized this may be way too late but I modified the Bluebeam original code because it wasn't exactly what I was looking for, future me / anyone else with this issue I've created a modular approach:

https://github.com/Jacen-crudo/Bluebeam-Stamp-DiagBox

It also has installation and modification instructions.