Jump to content

step

Registered Users - Approved
  • Posts

    962
  • Joined

Posts posted by step

  1. I've run into this issue before as well. Maybe it has something to do with the 'table' markup tags, but vertical alignment doesn't seem to like it if a paragraph tag isn't the last line in the text flow. If you were to type a line underneath '«2_Colums table v2»' in the text editor, you'll notice that the line you entered is correctly aligned to the bottom of the text frame. Obviously the issue with this is that you don't want an additional line of text below the table.

     

    That being said, you can still get it pretty close by inserting a new paragraph after the table with the font size set really small. Just add this to your table rule:

    return myTable.MakeTags()[color="Red"] + '<p><span pointsize=0.1></span>'[/color];
    

    I removed the "replace" in the return line because it was unnecessary – the tables are already left aligned. It's also worth noting that a pointsize of 0 is not valid.

     

    I also noticed that you could probably simplify your code by creating some functions for some of the repetitive code in your table rule:

    function GetTextWidth(field, font, fontSize) {
     var tm = new FusionProTextMeasure;
     tm.pointSize = (fontSize || 7) + " pt";
     tm.font = font || "Arial";
     tm.CalculateTextExtent(field);
     tm.useTags = false;
     return tm.textWidth;
    }
    
    function GetMaxWidth() {
     return Array.prototype.slice.call(arguments)
       .filter(function(s) { return s > 0 })
       .sort(function(a,b) { return a - b }).pop() || 0;
    }
    
    // Put Column A width values in array, sort and set highest as new variable
    var maxAWidth = GetMaxWidth(
     GetTextWidth(Field("Company"), "Arial Bold", 7.3),
     GetTextWidth(Field("Adress 1")),
     GetTextWidth(Field("Adress 2")),
     GetTextWidth(Field("Adress 3")),
     GetTextWidth(Field("Country"))
    );
    
    var maxBWidth = GetMaxWidth(
     GetTextWidth(Field("Tel 1")),
     GetTextWidth(Field("Tel 2")),
     GetTextWidth(Field("Tel 3")),
     GetTextWidth(Field("Email")),
     GetTextWidth(Field("Web"))
    );
    
    // Set frame width total and column gutter
    var frameWidth = 23669; // Total width of text frame (72x100 per inch)
    var frameGutter = 750;  // Width of gutter between columns in frame (72x100 per inch)
    
    var availableWidth = frameWidth - frameGutter - maxBWidth;
    var leftCol = Math.min(maxAWidth, availableWidth);
    var rightCol = maxBWidth + (availableWidth - leftCol);
    
    // Create table
    var myTable = new FPTable;
    myTable.AddColumns(leftCol, frameGutter, rightCol);
    var row = myTable.AddRow();
    var cell = row.Cells[0];
    
    // Declare TableMargin object to adjust margins
    cell.Margins = { 'Top' : 0, 'Bottom': 0, 'Left': 0, 'Right': 0 };
    row.CopyCells(0, 1, 2);
    
    myTable.ShadingColor1 = "Yellow";
    myTable.ShadingPct1 = 10;
    
    row.SetContents(Resource("Resource1").content, '', Resource("Resource2").content);
    
    return myTable.MakeTags() + '<p><span pointsize=0.1></span>';
    

  2. Since 'FindRecords' returns an array of record numbers, you could also splice the first 10 and map them to the correct fields like this:

    var XDF = new ExternalDataFileEx("your file name");
    return XDF.FindRecords("CID", Field("CUSTOMER ID")).splice(0,10).map(function(rec) {
       function ExField(field) { return XDF.GetFieldValue(rec, field) };
       return ExField("CUSTOMER NAME") + " " + ExField("MASTER CUSTOMER ID");
    }).join("\n");
    

  3. Are your pages named 1, 2, 3, and 4? If not you may need to make the page numbers integers instead of strings:

    if (Field("List")=="Local")
    {
    FusionPro.Composition.SetBodyPageUsage(1, true)
    FusionPro.Composition.SetBodyPageUsage(2, true)
    FusionPro.Composition.SetBodyPageUsage(3, false)
    FusionPro.Composition.SetBodyPageUsage(4, false)
    } 
    if (Field("List")=="Out of State")
    FusionPro.Composition.SetBodyPageUsage(1, false)
    FusionPro.Composition.SetBodyPageUsage(2, false)
    FusionPro.Composition.SetBodyPageUsage(3, true)
    FusionPro.Composition.SetBodyPageUsage(4, true)
    }
    

    Or:

    var page = Field("List") == "Local" ? 1 : 3;
    FusionPro.Composition.SetBodyPageUsage(page, true);
    FusionPro.Composition.SetBodyPageUsage(page + 1, true);
    

  4. Oh okay, thank you for attaching your collected template. I see what you're saying. Well this is kind of awkward. After I posted that whole missive about how "AddVariable" works, it turns out I don't know how it works. :o

     

    I think this will give you the results you're looking for, though: Redefine the "Field" function and do the find/replace within it so that calls to the "Field" function within rules return the desired value. Then in your OnRecordStart callback loop through all of the fields, and set their values to the result of the "Field" function which will perform the find/replace on fields inserted directly into text frames.

     

    JavaScript Globals:

    Field = function(str) {
       var res = FusionPro.Fields[str] || '';
    
       // An object of values to find as the keys, and the string to replace them with as the value.
       var charMap = {
           // find     : replace
           "first"     : "FIRST",
           "last"      : "LAST",
       }
    
       // Loop through all of the find/replace values for current field.
       for (var find in charMap) {
           var replace = charMap[find];
           res = ReplaceSubstring(res, find, replace);
       }
    
       return res;
    }
    

     

    OnRecordStart:

    // Loop through all of the fields.
    for (var field in FusionPro.Fields)
       FusionPro.Composition.AddVariable(field, Field(field), true);
    

  5. Isn't this just re-adding (overwriting) and re-defining the variable each iteration through the for loop?

    Yes. But, in doing so it updates the value returned by the "Field" function. Let's assume you have a field in your data called "Salutation" and that field contains "Dear Lance." Naturally, that is too formal and you'd instead like to be addressed as "The Lance-meister":

    var salutation = ReplaceSubstring(
     Field("Salutation"), // Field("Salutation") will return "Dear Lance"
     "Lance",             // This is the value to be replaced
     "The Lance-meister"  // This is the new value
    );
    
    // This line will update the value returned by the "Field" function
    // for the "Salutation" field.
    FusionPro.Composition.AddVariable("Salutation", salutation);
    
    // On second thought, "The Lance-meister" sounds a little too 1985.
    // Let's update that to "The Lance-inator"
    FusionPro.Composition.AddVariable("Salutation", ReplaceSubstring(
     Field("Salutation"), // Field("Salutation") returns "Dear The Lance-meister"
     "-meister",          // This is the value to be replaced
     "-inator"            // This is the new value
    ));
    
    // "Dear?" That's no way to address The Lance-inator. Let's fix that.
    FusionPro.Composition.AddVariable("Salutation", ReplaceSubstring(
     Field("Salutation"), // Field("Salutation") returns "Dear The Lance-inator"
     "Dear",              // This is the value to be replaced
     "Sup"                // This is the new value
    ));
    

    Obviously, you wouldn't really write the code like that but I just wanted to illustrate what the for loop is doing in the original code. The above example could be re-written like so:

    var charMap = {
    // Find       : Replace
      "Lance"    : "The Lance-meister",
      "-meister" : "-inator",
      "Dear"     : "Sup",
    }
    
    for (var field in FusionPro.Fields) {
     for (var find in charMap) {
       var replace = charMap[find];
       FusionPro.Composition.AddVariable(field,
         ReplaceSubstring(Field(field), find, replace), true);
     }
    }
    

    That being said, if you're skeptical of overwriting the field value with AddVariable, you could assign the values to a variable and only update the field value one time once all of the necessary replacements have been made:

    // An object of values to find as the keys,
    // and the string to replace them with as the value.
    var charMap = {
    // Find      : Replace
      "&rsquor;":"’",
      "&rsquor;":"'",
      "¼":"¼",
      "½":"½",
      "¾":"¾",
      "—":"–",
      "—":"—",
    }
    
    // Loop through all of the fields.
    for (var field in FusionPro.Fields) {
     [color="red"]var fieldVal = Field(field);[/color]
     // Loop through all of the find/replace values for current field.
     for (var find in charMap) {
       var replace = charMap[find];
       [color="red"]fieldVal = ReplaceSubstring(fieldVal, find, replace);[/color]
     }
     // Update the field's value
     [color="Red"]FusionPro.Composition.AddVariable(field, fieldVal, true);[/color]
    }
    

  6. I think the problem is that as it loops through each entry in the charMap it is re-adding a variable, overwriting everything it had done up to that point (i.e. the changes aren't cumulative from entry to entry). So really all it is doing is a ReplaceSubstring() on the very last entry in the charMap. If that entry doesn't result in a change, then it appears as nothing has changed. I think.

    The ReplaceSubstring function is replacing each occurrence of the 'find' variable in each FusionPro field with the corresponding 'replace' variable defined in the 'charMap' object and then redefining the value of the field with the result. Here's a static example to show you how the code does replace more than just the last character in the 'charMap':

    var charMap = {
      "R": "F",
      "ond": "and",
      "L" : "S",
      "ov": "m",
      "s": "lls",
      "d": "",
      "ay": "eld",
    }
    
    var field = 'Everyone Loves Raymond';
    
    for (var find in charMap) {
     var replace = charMap[find];
     field = ReplaceSubstring(field, find, replace);
    }
    
    return field; // Everyone Smells Feldman
    

     

    As Dan mentioned in an earlier post, it is hard to say why it's not working for you without being able to see your template.

  7. Essentially what you want to do is set up your imposition to be 4 up and you want each record to produce 4 cards to fill the imposition.

     

    So you'd present the customer with 4 name fields (Name1, Name2, etc) and then based on how many of those fields they actually fill in, you'll determine which name should display on each card. By repeating each record 4 times – each repetition will create another card for the current record until the imposition is full. Then, all you have to do is determine which name to show during each iteration. If the customer filled in all four "Name" fields, you'll fill in "Name1" for the first iteration, "Name2" for the second iteration, etc. If they only filled in two "Name" fields, you'll use "Name1" for the first and second iteration and "Name2" for the third and fourth iteration.

     

    You can do that by putting this in your OnRecordStart callback:

    var imposition = 4;
    var FP = FusionPro.Composition;
    
    var names = [];
    for (var i = 1; i <= 4; i++)
     if (name = Field('Name' + i))
       names.push(name);
    
    FP.repeatRecordCount = imposition;
    FP.AddVariable('Name', names[Math.ceil(FP.repeatRecordNumber / (imposition / names.length)) - 1]);
    

     

    I've also attached a sample template for an example.

    bc.zip

  8. Delete the "NameAdd" rule and change your "OnRecordStart" callback rule to:

    var FP = FusionPro.Composition;
    var graphics = [Field("TribType"), Field("TribType1"), Field("TribType2"), Field("TribType3")].filter(String);
    [color="red"]var txt = [Field("TName"), Field("TName1"), Field("TName2"), Field("TName3")].filter(String);
    [/color]
    
    if (!(FP.repeatRecordCount = graphics.length))
       ReportError('No graphics to compose for record #' + FP.inputRecordNumber);
    
    var graphic = Resource('Graphic' + graphics[FP.repeatRecordNumber - 1]);
    FP.AddGraphicVariable('BackgroundGraphic', graphic);
    [color="Red"]FP.AddVariable('NameAdd', (txt[FP.repeatRecordNumber - 1] || ''));[/color]
    

     

    I noticed in your example that some records (record 11 – for example) don't have names associated with all of the graphics. If you only want to compose the graphics that have names associated with them, you'd need to rewrite the code to be something like this:

    var FP = FusionPro.Composition;
    var fields = [];
    
    for (var i = 0; i < 4; i++) {
     var [graphic, txt] = ['TribType', 'TName'].map(function(s) { return Field(s + (i ? i : '')); }).filter(String);
     if (graphic && txt)
       fields.push({ graphic: Resource('Graphic' + graphic), txt: txt });
    }
    
    if (!(FP.repeatRecordCount = fields.length))
     ReportError('Nothing to compose for record #' + FP.inputRecordNumber);
    
    var content = fields[FP.repeatRecordNumber - 1];
    FP.AddGraphicVariable('BackgroundGraphic', content.graphic);
    FP.AddVariable('NameAdd', content.txt);
    

  9. I think this might work:

    // An object of values to find as the keys,
    // and the string to replace them with as the value.
    var charMap = {
    // Find      : Replace
      "&"   : "&",
      "&rsquor" : "’",
      "'"       : "’",
    }
    
    // Loop through all of the fields.
    for (var field in FusionPro.Fields) {
     // Loop through all of the find/replace values for current field.
     for (var find in charMap) {
       var replace = charMap[find];
       FusionPro.Composition.AddVariable(field,
         ReplaceSubstring(Field(field), find, replace), true);
     }
    }
    

  10. I tried to simplify my project and now it is producing to many pages with nothing on them.

    That's because you need to assign your graphic rule to your graphic frame.

     

    What I need is any field with and "H" to bring in the "H Graphic" and the fields with a "M" to bring in the "M Graphic".

     

    After you assign the rule to your frame, you can delete the rule and populate it from the OnRecordStart callback:

    var FP = FusionPro.Composition;
    var graphics = [Field("TribType"), Field("TribType1"), Field("TribType2"), Field("TribType3")].filter(String);
    
    if (!(FP.repeatRecordCount = graphics.length))
       ReportError('No graphics to compose for record #' + FP.inputRecordNumber);
    
    var graphic = Resource('Graphic' + graphics[FP.repeatRecordNumber - 1]);
    FP.AddGraphicVariable('BackgroundGraphic', graphic);
    

  11. This should do it

    if ((Field("Full Name") != "") && (Field("Credentials") != ""))
    return Field("Full Name") + ", " + Field("Credentials");
    else if ((Field("Full Name") != "") && (Field("Credentials") == ""))
    return Field("Full Name");
    else
    return "";
    

    There are quite a few ways to do this. Here are a few more:

    var result = Field("Full Name");
    if (result && Field("Credentials"))
     result += ", " + Field("Credentials");
    return result;
    

     

    return [Field("Full Name"), Field("Credentials")].filter(String).join(", ");
    

     

    return (Field("Full Name") + ", " + Field("Credentials")).replace(/^,.+|, $/, '');
    

  12. I believe the issue is:

    .replace(/(\u2018)([0-9]{2}[color="Red"][^\u2019]*[/color])(\u2018([^0-9]|$)|$|\u2019[a-z])/ig, '\u2019$2$3');
    

    That's capturing (as $2) two digits followed by 0 or more characters that aren't closing single quotes. So it ends up capturing the entire line.

     

    If you're looking for classes specifically, why not make it a little easier on yourself and just add a little context to your regexp:

    return SmartQuotes('John "Smitty" Smith, class of \'81, Jane Doe, class of \'82')
       .replace(/(class of )\u2018(\d{2})\b/gi, '$1\u2019$2');
    

  13. Try putting this in your OnRecordStart callback. Then you can get rid of OnJobStart and ProductTable rules.

    var keyField = 'Origin';
    FusionPro.Composition.composeThisRecord = FieldChanged(keyField);
    
    var data = new ExternalDataFileEx(PrimaryInputFile(), ',');
    var recs = data.FindRecords(keyField, Field(keyField));
    var table = new FPTable();
    table.AddColumns(5000,8000,4600,3500,4000,4000,3500,4000,15600);
    
    var header = table.AddRow();
    header.Type = 'Header';
    header.Cells[0].Font = 'Open Sans Condensed';
    header.CopyCells(0,1,2,3,4,5,6,7,8);
    header.SetContents("Item #", "Product Name", "Vintage", "Size", "Units", "Case $", "Btl $", "Sale $", "Ratings");
    
    for (var rec in recs) {
     // Helper function.
     function ExField(str) { return data.GetFieldValue(recs[rec], str); }
     var row = table.AddRow();
     var content = ["Product ID","Product","Vintage","Size","Case Pack","Case Price","Bottle Price","Sale Price","Notes"].map(ExField);
     row.SetContents.apply(row, content);
    }
    
    var productTable = table.MakeTags();
    
    FusionPro.Composition.AddVariable("ProductTable", productTable, true);
    

  14. When I upload the template into marcom, the text is all one color (black or white)

     

    I thought that's was your intention? Your code seems like it should work to me. Does it work locally? Maybe the value of the "Banner" field is "yellow" as opposed to "Yellow?" You could try this:

    var color = /yellow|white/i.test(Field("Banner")) ? "Black" : "White";
    return '<span color="' + color + '">' + Field("Banner Text") + '</span>';
    

  15. What kind of imposition are you using? One that's stacked "indefinitely?" It would probably help to attach a collected sample of your job but my first inclination is that you might want to include this in your OnRecordStart rule:

    var imgPath = ".\\Variable Artwork\\"
    var imgName = Trim(Field("fileName"));
    var r = new FusionProResource(imgPath + imgName, "graphic", true);
    
    FusionPro.Composition.repeatRecordCount = r.countPages;
    r.pagenumber = FusionPro.Composition.repeatRecordNumber;
    FindGraphicFrame("ResourcePage").SetGraphic(r);
    [color="Red"]if (FusionPro.Composition.repeatRecordNumber == 1)
     FusionPro.Composition.OpenNewOutputFile();[/color]
    

    And this in your OnJobStart:

    FusionPro.Composition.chunksBreakStacks = true;
    

  16. I know where I need to modify my coding to get this to function how I need to, but I just don't know how to, or if it's possible.

    Right, well that's why I suggested contracting a developer to help.

     

    Basically I have two separate replace functions going on in my Copyfit rule. I need them to work simultaneously, but they seem to work one, then the other.

    Technically there are 3 replace methods but I'm going to assume you're referring to the one that replaces the 'verticalstart" attribute and the one that replaces the leading with the "leadingSizeBody." What do you mean you need them to work simultaneously? You can chain replace methods if that's what you're wanting to do (although I don't know why):

    return '<p br="false" quad="L">First paragraph.'
        + '<p verticalstart="topofpage" quad="L">Second paragraph'
          .replace('verticalstart="topofpage"', '') 
          .replace(/(quad="[A-Z]" )(leading="\d+")?/g, function(s,p) {
             return p + 'leading="' + leadingSizeBody * 10 + '"';
           }); 
    /*
     Returns:
     <p br="false" quad="L" leading="140">First paragraph.
     <p quad="L" leading="140">Second paragraph
    */
    

    I think part of the reason for the confusion is stemming from syntax errors. Let's take a closer look at your code:

    var minSize = 9;
    var leadingSizeBody = 14
    
    [color="Red"]if (FusionPro.Composition.CurrentFlow.name == "MainArticleBodyCopy1-3")
    {[/color]
    var cf = FusionPro.Composition.CurrentFlow;
    // If it doesn't fit, don't start back page at "topofpage"
    [color="Magenta"]if (!cf.fits)
       cf.content = cf.content.replace(/<variable name="([^"]+)">/g, function(s,p) {
           return RuleOrField(p).replace('verticalstart="topofpage"', 'leadbefore="0"');
      });[/color]
               [color="SeaGreen"]if (!Copyfit(new MagnifyAttributes("text", 80, 150, minSize, 10),new MagnifyAttributes("leading", 80, 150, leadingSizeBody, 15)))
                      cf.content = '<para><span pointsize="' + minSize +'">'
       + cf.content.replace(/(quad="[A-Z]" )(leading="\d+")?/g, function(s,p) { return p + 'leading="' + leadingSizeBody * 10 + '"'; })
       + '</span></para>';    [/color]
       ReportWarning("Could not copyfit text in flow " + 
                     FusionPro.Composition.CurrentFlow.name);
    [color="red"]}[/color]
    

    Everything within the red brackets executes if and only if the name of the text flow is "MainArticleBodyCopy1-3." The pink code checks to see if the content fits in the text flow (before attempting to copyfit) and if it doesn't, it replaces the first "verticalstart" attribute with "leadbefore=0." The green code (my apologies if you are red/green colorblind) attempts to copyfit the text flow by adjusting the font size and leading within the limitations you defined and if it can not, it wraps the entire content in span tags (to set the font size to the minimum) and applies the minimum leading to all 'p' tags. The "ReportWarning" part actually executes every time the "MainArticleBodyCopy1-3" text flow is processed. That's resulting in a false error so you might want to only do that if the copyfit fails – in which case you need to wrap that 'if' statement in brackets (because you're executing multiple lines of code):

    if (!Copyfit(new MagnifyAttributes("text", 80, 150, minSize, 10), new MagnifyAttributes("leading", 80, 150, leadingSizeBody, 15))) [color="red"]{[/color]
     cf.content = '<para><span pointsize="' + minSize +'">' + cf.content.replace(/(quad="[A-Z]" )(leading="\d+")?/g, function(s,p) { return p + 'leading="' + leadingSizeBody * 10 + '"'; }) + '</span></para>';    
     ReportWarning("Could not copyfit text in flow " + FusionPro.Composition.CurrentFlow.name);
    [color="Red"]}[/color]
    

  17. The issue I am encountering is due to text frame flowing. The script you have provided takes into account the point size and leading, but this needs to be determined for two frames, where content can flow from frame 1 to frame 2, but even if content on frame 2 fills and there is room on frame 1, text can never flow from frame 1 to frame 2.

    That doesn't make sense to me. Maybe you mistyped that description? As I understand it, the Copyfit function isn't concerned with text frames per se – but rather the text flow. A text frame (or frames) is used to determine if the content will fit but to FusionPro, linked text frames are one single text flow. So I'm not really sure that's the issue.

     

    I have not been successful modifying the code to all scenarios needed.

     

    1) I am using resources to display the text.

    2) The resources are returned as content in rules (set as front / back) to set which resource is front and which is back.

    3) The rules are then returned as RawTextFromTagged in a rule called TextFlow, which joins the front and back copy with <p verticalstart="topofpage">

    4) Linked frames (blue and magenta) display Rule(TextFlow)

     

     

    How this should work:

    1) if Frame 1 does not fill, start Resource 2 [Rule(Set back copy to back)] text on back

    2) if Frame 1 fills, start a new paragraph with Resource 2.

    3) If Frame 1 does not fill but Frame 2 does, copyfit text and leading, while keeping <p verticalstart="topofpage">.

    4) If Frame 1 fills and frame 2 fills reduce font size and leading.

     

     

    Honestly, I don't care if copyfit is set before replacing the vertical start for page 2. I'm just having all sorts of problems. Mainly when frame 2 fills, content flows to frame 1. Also I am not getting my font size to reduce to 9 points.

     

     

    Can you take a look at this for me?

    It sounds like you've got quite a few moving parts but I'm not sure I understand the reasoning behind all of them. I don't understand why you need 2 rules that are set to "re-evaluate for every text flow" to return formatted text resources to yet another rule that's set to "re-evaluate for every text flow."

     

    I think this thread has gotten a little off topic from your original question. Given the complexity of what it seems like you're trying to accomplish, you might consider outsourcing the template development to a contractor on the job board or contact FusionProSupport@PTI.com regarding paid consulting. At the very least, I would start a new thread for relevancy.

  18. Thanks for cleaning up my table rule.

     

    I am having trouble getting the first Code to work. The "Event/Package" straddles correctly, but the "Sec" is only straddling into "Row" and not "Row" and "Seat(s)" and "Seat(s) and "Qty" straddle.

    Looks like you put it in the wrong place. Should be:

    // CREATE CONTENT FOR EXTERNAL DATA FILE RECORDS
    myTable.Rows[i].Cells[0].HAlign = "Left";
    myTable.Rows[i].Cells[1].HAlign = "Left";
    myTable.Rows[i].Cells[2].HAlign = "Center";
    myTable.Rows[i].Cells[3].HAlign = "Center";
    myTable.Rows[i].Cells[4].HAlign = "Center";
    myTable.Rows[i].Cells[5].HAlign = "Center";
    myTable.Rows[i].Cells[6].HAlign = "Right";
    myTable.Rows[i].Cells[7].HAlign = "Right";
    myTable.Rows[i].SetContents(eventMatch[i-1], locationMatch[i-1], secMatch[i-1], rowMatch[i-1], seatMatch[i-1], qtyMatch[i-1], "$"+priceMatch[i-1], "$"+extendedMatch[i-1]);
    [color="Red"]var eventCell = myTable.Rows[i].Cells[0];
    eventCell.HStraddle = 1 + !locationMatch[i-1];
    
    var secCell = myTable.Rows[i].Cells[2];
    secCell.HStraddle = 1 + !rowMatch[i-1] + !seatMatch[i-1];[/color]
    

    On the more versatile code I get an error on this line

     while (!myTable.Rows[i].Cells[c + straddle].Content)
       straddle++;
    

    While it would have been helpful if you had actually included the error you're referencing, I'm just going to assuming you put that code in the wrong place as well. It should be:

    // CREATE CONTENT FOR EXTERNAL DATA FILE RECORDS
    myTable.Rows[i].Cells[0].HAlign = "Left";
    myTable.Rows[i].Cells[1].HAlign = "Left";
    myTable.Rows[i].Cells[2].HAlign = "Center";
    myTable.Rows[i].Cells[3].HAlign = "Center";
    myTable.Rows[i].Cells[4].HAlign = "Center";
    myTable.Rows[i].Cells[5].HAlign = "Center";
    myTable.Rows[i].Cells[6].HAlign = "Right";
    myTable.Rows[i].Cells[7].HAlign = "Right";
    myTable.Rows[i].SetContents(eventMatch[i-1], locationMatch[i-1], secMatch[i-1], rowMatch[i-1], seatMatch[i-1], qtyMatch[i-1], "$"+priceMatch[i-1], "$"+extendedMatch[i-1]);
    
    [color="red"]// For each cell position (c), set the horizontal straddle value.
    for (var c = 0; c < myTable.Rows[i].Cells.length - 1; c++) {
     var straddle = 1;
     // Increment the straddle value of a given cell for every
     // adjacent cell that does not contain a value.
     while (!myTable.Rows[i].Cells[c + straddle].Content)
       straddle++;
     // Assign the straddle value for this cell.
     myTable.Rows[i].Cells[c].HStraddle = straddle;
    }[/color]
    

    Finally, if I can get any of these to work, is it possible to have "Sec" flush left only when it straddles as opposed to centering.

    Sure:

    // For each cell position (c), set the horizontal straddle value.
    for (var c = 0; c < myTable.Rows[i].Cells.length - 1; c++) {
     var straddle = 1;
     // Increment the straddle value of a given cell for every
     // adjacent cell that does not contain a value.
     while (!myTable.Rows[i].Cells[c + straddle].Content)
       straddle++;
     // Assign the straddle value for this cell.
     myTable.Rows[i].Cells[c].HStraddle = straddle;
    [color="Red"]  // Align text to the left if straddling multiple cells.
     if (straddle > 1) 
       myTable.Rows[i].Cells[c].HAlign = "Left";[/color]
    }
    

    Or:

    var secCell = myTable.Rows[i].Cells[2];
    secCell.HStraddle = 1 + !rowMatch[i-1] + !seatMatch[i-1];
    [color="red"]if (secCell.HStraddle > 1)
     secCell.HAlign = "Left";[/color]
    

  19. I'm sure there are many ways to do that. You could add something like this after you set the contents of the row that will set the horizontal straddle property of those specific cells based on whether or not a given field has a value:

    var eventCell = myTable.Rows[i].Cells[0];
    eventCell.HStraddle = 1 + !locationMatch[i-1];
    
    var secCell = myTable.Rows[i].Cells[2];
    secCell.HStraddle = 1 + !rowMatch[i-1] + !seatMatch[i-1];
    

     

    Another (possibly more versatile) option is to use a for loop that sets the horizontal straddle value based on the content of the adjacent cell:

    // For each cell position (c), set the horizontal straddle value.
    for (var c = 0; c < myTable.Rows[i].Cells.length - 1; c++) {
     var straddle = 1;
     // Increment the straddle value of a given cell for every
     // adjacent cell that does not contain a value.
     while (!myTable.Rows[i].Cells[c + straddle].Content)
       straddle++;
     // Assign the straddle value for this cell.
     myTable.Rows[i].Cells[c].HStraddle = straddle;
    }
    

     

    As a side note, there are a few things you could do to clean your code up a little bit. First of all you're setting the content of the row twice – which isn't necessary:

    myTable.Rows[i].Cells[0].VAlign = "Middle";
    myTable.Rows[i].Cells[1].VAlign = "Middle";
    myTable.Rows[i].Cells[2].VAlign = "Middle";
    myTable.Rows[i].Cells[3].VAlign = "Middle";
    myTable.Rows[i].Cells[4].VAlign = "Middle";
    myTable.Rows[i].Cells[5].VAlign = "Middle";
    myTable.Rows[i].Cells[6].VAlign = "Middle";
    myTable.Rows[i].Cells[7].VAlign = "Middle";
    [color="red"]myTable.Rows[i].SetContents(eventMatch[i-1], locationMatch[i-1], secMatch[i-1], rowMatch[i-1], seatMatch[i-1], qtyMatch[i-1], priceMatch[i-1], extendedMatch[i-1]);[/color]
    
    
    myTable.Rows[i].Cells[0].HAlign = "Left";
    myTable.Rows[i].Cells[1].HAlign = "Left";
    myTable.Rows[i].Cells[2].HAlign = "Center";
    myTable.Rows[i].Cells[3].HAlign = "Center";
    myTable.Rows[i].Cells[4].HAlign = "Center";
    myTable.Rows[i].Cells[5].HAlign = "Center";
    myTable.Rows[i].Cells[6].HAlign = "Right";
    myTable.Rows[i].Cells[7].HAlign = "Right";
    [color="Red"]myTable.Rows[i].SetContents(eventMatch[i-1], locationMatch[i-1], secMatch[i-1], rowMatch[i-1], seatMatch[i-1], qtyMatch[i-1], "$"+priceMatch[i-1], "$"+extendedMatch[i-1]);[/color]
    

     

    Secondly, since you're setting the VAlign property of each cell to "Middle," why not move it up a few lines, apply it to the first cell and let the "CopyCells" method apply it to the rest of them:

    myTable.Rows[i].Cells[0].Margins = new FPTableMargins;
    myTable.Rows[i].Cells[0].Margins.Top = 50;
    myTable.Rows[i].Cells[0].Margins.Bottom = 30;
    myTable.Rows[i].Cells[0].Margins.Right = 500;
    myTable.Rows[i].Cells[0].Margins.Left = 500;
    myTable.Rows[i].Cells[0].SetBorders("Very Thin", "Gray", "Top", "Bottom", "Right", "Left");
    myTable.Rows[i].CopyCells(0,1,2,3,4,5,6,7); // Apply the same formating to each cell in this row
    
    
    // CREATE CONTENT FOR EXTERNAL DATA FILE RECORDS
    
    [color="red"]myTable.Rows[i].Cells[0].VAlign = "Middle";
    myTable.Rows[i].Cells[1].VAlign = "Middle";
    myTable.Rows[i].Cells[2].VAlign = "Middle";
    myTable.Rows[i].Cells[3].VAlign = "Middle";
    myTable.Rows[i].Cells[4].VAlign = "Middle";
    myTable.Rows[i].Cells[5].VAlign = "Middle";
    myTable.Rows[i].Cells[6].VAlign = "Middle";
    myTable.Rows[i].Cells[7].VAlign = "Middle";[/color]
    

    myTable.Rows[i].Cells[0].Margins = new FPTableMargins;
    myTable.Rows[i].Cells[0].Margins.Top = 50;
    myTable.Rows[i].Cells[0].Margins.Bottom = 30;
    myTable.Rows[i].Cells[0].Margins.Right = 500;
    myTable.Rows[i].Cells[0].Margins.Left = 500;
    myTable.Rows[i].Cells[0].SetBorders("Very Thin", "Gray", "Top", "Bottom", "Right", "Left");
    [color="red"]myTable.Rows[i].Cells[0].VAlign = "Middle";[/color]
    myTable.Rows[i].CopyCells(0,1,2,3,4,5,6,7); // Apply the same formating to each cell in this row
    

  20. var result = [
     Field("Name"),
     Field("Degree1"),
     Field("Degree2"),
     Field("Degree3")
    ].filter(String).join(', ');
    
    var tm = new FusionProTextMeasure;
    tm.pointSize = "10 pt";
    tm.font = "DINOT-Medium";
    tm.maxWidth = 1.72 * 7200;
    tm.CalculateTextExtent(result);
    
    return tm.textLines > 1 ? result.replace(', ', '<br/>') : result;
    

  21. To be honest, I'm not really sure I understand the problem you're encountering. As far as I can tell, the text within all three frames you mentioned (FrontPhotoCaption, BackPhotoCaption-1, and BackPhotoCaption-2) fit.

     

     

    The issue I am having is that I am trying to set a minimum font and minimum leading. I have modifed the code you provided, with the code from your Copyfit Text and Leading post (http://forums.printable.com/showthread.php?t=4071&highlight=font+size+leading).

     

     

    I think I'm having a similiar issue you had. What I'm trying to accomplish is if the text does not fit the frame, then the font is reduced. Once the pointsize or leading is reduced and cannot copyfit anymore, I want to use my minimum values for pointsize and leading, which are not proportional, but set values.

    If you aren't trying to keep the font size and leading proportional, there's no point in bothering with that code.

     

    I've attempted the following two codes.

     

    if (FusionPro.Composition.CurrentFlow.name == "MyTextFrame")
    {
    var cf = FusionPro.Composition.CurrentFlow;
    if (!cf.fits)
       cf.content = '<span pointsize="' + minSizeCaption +'"><leading newsize="' + leadingSizeCaption + '">' + cf.content + '</leading></span>';
    if (!Copyfit(new MagnifyAttributes("text", 25, 400, 7, 8.5),new MagnifyAttributes("leading", 25, 400, 10, 12)))
    cf.content = '<span pointsize="' + minSizeCaption +'"><leading newsize="' + maxleadingSizeCaption + '">' + cf.content + '</leading></span>';
       ReportWarning("Could not copyfit text in flow " +
                     FusionPro.Composition.CurrentFlow.name);
    }
    

    This works for both to an extent, but if I enter 200 characters and only 100 are visible with copyfit, than the text will reduce to the minimum size but the leading ends up being 12 point.

    In that code, you're setting the font size of the copy to 'minSizeCaption' before you even attempt to Copyfit the copy. And wrapping the copy in leading tags won't work here because FP's text editor has already stealthily added leading tags (and font tags, and color tags, etc) to the copy so that outer tag is useless. You can, however, replace the editor's values with the values you want to insert:

     

    var minSize = 10;
    var minLead = 10;
    
    if (!Copyfit(new MagnifyAttributes("text", 25, 400, minSize, 13), new MagnifyAttributes("leading", 25, 400, minLead, 14))) {
       var cf = FusionPro.Composition.CurrentFlow;
       cf.content = '<para><span pointsize="' + minSize +'">'
         + cf.content.replace(/(quad="[A-Z]" )(leading="\d+")?/g, function(s,p) { return p + 'leading="' + minLead * 10 + '"'; })
         + '</span></para>';
       ReportWarning("Could not copyfit text in flow " + cf.name);
    }
    

     

    Rather than sift through the 628 lines (:eek:) of code in your OnCopyfit rule, I've attached a smaller sample that illustrates how the code works with 3 text frames.

    sample.zip

  22. Technically speaking, failure to copyfit is not necessarily indicative of the text not fitting within the text flow at the specified minimum font size. The Copyfit function also takes into account the min/max magnification factors and if the minimum magnification factor is reached before the minimum font size, copyfit will fail.

     

    That said, if you want to set the font size to the lower limit whenever there text does not fit, you can try this:

    var minSize = 6;
    if (!Copyfit(new MagnifyAttributes("text", 25, 400, minSize, 72))) {
       var cf = FusionPro.Composition.CurrentFlow;
       cf.content = '<para><span pointsize="' + minSize +'">' + cf.content + '</span></para>';
       ReportWarning("Could not copyfit text in flow " + cf.name);
    }
    

×
×
  • Create New...