/** * Convert a measurement to inches. * @param a measurement property e.g. "49.3mm" * @return the corresponding number of inches. */ function getInches(measurement) { var vUnits = measurement.substr(-2); var vValue = parseFloat(measurement.substr(0, measurement.length - 2)); switch (vUnits) { case "mm": vValue = vValue * 0.0393700787; break; case "cm": vValue = vValue * 0.393700787; break; case "pt": vValue = vValue / 72; } return vValue; } /** * write a measurement in inches * @param the number of inches */ function formatInches(vValue) { // Round a measurement value to the nearest 1000th of an inch return (Math.round(1000 * vValue) / 1000).toString() + "in"; } /** * write a measurement in points * @param the number of inches */ function formatPoints(vValue) { vValue = vValue * 72; // Round a measurement value to the nearest 10th of an point return (Math.round(10 * vValue) / 10).toString() + "pt"; } // Combine a text draw and field into a field + caption // Get the list of selected nodes // for this function to execute we need a text draw and a caption-less field var selection = designer.getSelection(); var validSelection = false; var field = null; var text = null; if (selection.length == 2) { for (var i=0; i<2; i++) { var vItem = selection.item(i); if (vItem.className === "field" && vItem.caption.value.oneOfChild.value.toString() == "") { field = vItem; } else if (vItem.className == "draw" && (vItem.value.oneOfChild.className === "text" || vItem.value.oneOfChild.className === "exData")) { text = vItem; } } if (field != null && text != null) validSelection = true; } if (validSelection) { var bGrowableX = false; var bGrowableY = false; var tx = getInches(text.x); var tw = getInches(text.w); var fx = getInches(field.x); var fy = getInches(field.y); var fw = getInches(field.w); if (fw === 0) { fw = getInches(field.minW); bGrowableX = true; } var ty = getInches(text.y); var th = getInches(text.h); var fy = getInches(field.y); var fh = getInches(field.h); if (fh === 0) { fh = getInches(field.minH); bGrowableY = true; } // Some checks for zero-dimension growable objects... // accuracy of results will not be as good. if (tw === 0) { if (fx === 0) { tw = 1; } else { tw = (fx - tx) + fw; } } if (th === 0) { th = fy - ty; } if (fh === 0) { // field height is a wild guess fh = getInches(field.font.size) * 1.2 + getInches(field.margin.topInset) + getInches(field.margin.bottomInset); } if (fw === 0) { // zero width -- default to text width plus the field margins fw = tw + getInches(field.margin.leftInset) + getInches(field.margin.rightInset); fx = tx; } // Copy the caption value over. // special case for rich text if (text.value.oneOfChild.className === "exData") { field.caption.value.nodes.remove(field.caption.value.oneOfChild); field.caption.value.nodes.append(text.value.oneOfChild); } else { field.caption.value.text = text.rawValue; } // Assign all possible paragraph and font properties from the text object // to the field caption field.caption.reserve = formatInches(fy - ty); field.caption.placement = "top"; field.caption.para.hAlign = text.para.hAlign; field.caption.para.lineHeight = text.para.lineHeight; field.caption.para.marginLeft = text.para.marginLeft; field.caption.para.marginRight = text.para.marginRight; field.caption.para.orphans = text.para.orphans; field.caption.para.preserve = text.para.preserve; field.caption.para.radixOffset = text.para.radixOffset; field.caption.para.spaceAbove = text.para.spaceAbove; field.caption.para.spaceBelow = text.para.spaceBelow; field.caption.para.tabDefault = text.para.tabDefault; field.caption.para.tabStops = text.para.tabStops; field.caption.para.textIndent = text.para.textIndent; field.caption.para.vAlign = text.para.vAlign; field.caption.para.widows = text.para.widows; field.caption.para.wordSpacingMaximum = text.para.wordSpacingMaximum; field.caption.para.wordSpacingMinimum = text.para.wordSpacingMinimum; field.caption.para.wordSpacingOptimum = text.para.wordSpacingOptimum; field.caption.font.baselineShift = text.font.baselineShift; field.caption.font.fontHorizontalScale = text.font.fontHorizontalScale; field.caption.font.fontVerticalScale = text.font.fontVerticalScale; field.caption.font.kerningMode = text.font.kerningMode; field.caption.font.letterSpacing = text.font.letterSpacing; field.caption.font.lineThrough = text.font.lineThrough; field.caption.font.lineThroughPeriod = text.font.lineThroughPeriod; field.caption.font.overline = text.font.overline; field.caption.font.overlinePeriod = text.font.overlinePeriod; field.caption.font.posture = text.font.posture; field.caption.font.size = text.font.size; field.caption.font.typeface = text.font.typeface; field.caption.font.underline = text.font.underline; field.caption.font.underlinePeriod = text.font.underlinePeriod; field.caption.font.weight = text.font.weight; // handle the case where the text starts to the right of the field. Needs to be indented (marginLeft) // to preserve the same starting location if (tx > fx) { field.caption.para.marginLeft = formatPoints(getInches(field.caption.para.marginLeft) + tx - fx); } // The text ends before the field does. If the text is multi-line, // making it wider will result in different wrapping. // Compensate by setting a right margin if ((tx + tw) < (fx + fw)) { field.caption.para.marginRight = formatPoints(getInches(field.caption.para.marginRight) + (fx + fw) - (tx + tw)); } // The text ends after the field. We need to make the field wider to ensure that // there is room for the text. Set field right margin so that the field text area is constant if ((tx + tw) > (fx + fw)) { var delta = (tx + tw) - (fx + fw); field.w = formatInches(fw + delta); fw = fw + delta; field.para.marginRight = formatPoints(getInches(field.para.marginRight) + delta); } // The text starts to the left of the field. We need to make the field wider to ensure that // there is room for the text. Set field left margin so that the field text area is constant if (tx < fx) { var delta = fx - tx; field.w = formatInches(fw + delta); fw = fw + delta; field.x = formatInches(tx); fx = tx; field.para.marginLeft = formatPoints(getInches(field.para.marginLeft) + delta); } // if there is a gap between the text and the field, we want to preserve vertical positioning. // do this by setting paragraph spaceBelow to be the size of the gap. if ((ty + th) < fy) { field.caption.para.spaceBelow = formatPoints(getInches(field.caption.para.spaceBelow) + fy - (ty + th)); } // make the field taller to include the distance between the top of the text to the top of the field. fh = fy - ty + fh; fy = ty; var space = {left: 0, right:0, top: 0, bottom: 0}; // if the field has an outer-border, we want to move it to be a widget border // Otherwise the border will expand to include the new caption. if (field.isPropertySpecified("border") && field.border.presence === "visible") { if (field.isPropertySpecified("margin")) { space.top = getInches(field.margin.topInset); space.left = getInches(field.margin.leftInset); space.bottom = getInches(field.margin.bottomInset); space.right = getInches(field.margin.rightInset); field.nodes.remove(field.margin); } if (!field.ui.oneOfChild.isPropertySpecified("border") || field.ui.oneOfChild.border.presence === "hidden") { field.ui.oneOfChild.nodes.remove(field.ui.oneOfChild.border); // adding the border to the widget also removes it from the field. field.ui.oneOfChild.nodes.append(field.border); // reduce the caption reserve to make room for the width of the top and bottom borders // Normally we might fix this by adjusting the margins inside the widget. problem is that the // Acrobat widget doesn't support arbitrary internal margins -- and there is no UI in Designer // to re-adjust these margins after they've been set. // So we're best to simply use the default (acrobat widget) margins and adjust other box model parameters var nThick; // var nReserve = getInches(field.caption.reserve); var vTopEdge = field.ui.oneOfChild.border.getElement("edge", 0); if (vTopEdge.presence === "visible") { // nReserve = nReserve - getInches(vTopEdge.thickness); nThick = getInches(vTopEdge.thickness) - space.top; if (nThick > 0) { fy = fy - nThick; fh = fh + nThick; } } var vLeftEdge = field.ui.oneOfChild.border.getElement("edge", 3); if (vLeftEdge.presence === "visible") { // nReserve = nReserve - getInches(vTopEdge.thickness); nThick = getInches(vLeftEdge.thickness) - space.left; if (nThick > 0) { fx = fx - nThick; fw = fw + nThick; } } var vRightEdge = field.ui.oneOfChild.border.getElement("edge", 1); if (vRightEdge.presence === "visible") { // nReserve = nReserve - getInches(vTopEdge.thickness); nThick = getInches(vRightEdge.thickness) - space.right; if (nThick > 0) { fw = fw + nThick; } } var vBottomEdge = field.ui.oneOfChild.border.getElement("edge", 2); if (vBottomEdge.presence === "visible") { nThick = getInches(vBottomEdge.thickness) - space.bottom; if (nThick > 0) { fh = fh + nThick; } } // field.caption.reserve = formatInches(nReserve); } } // get rid of the remnant text field. text.parent.nodes.remove(text); // Assign all the computed positions and dimensions. if (bGrowableY) { field.minH = formatInches(fh); } else { field.h = formatInches(fh); } field.y = formatInches(ty); field.x = formatInches(fx); if (bGrowableY) { field.minW = formatInches(fw); } else { field.w = formatInches(fw); } } else { designer.alert("Must select a field(with no caption) and a text object"); }