TroyM68 Posted May 26, 2016 Share Posted May 26, 2016 I have a client that is having difficulty using copyfit. They are trying to create a business card template as follows: Let me preface, this is a hospital and the Drs. like their certifications and credentials. For the purpose of this example, we are just calling them "Cert(s)". 1) First and Last Name, Cert, Cert, Cert 2) Cert, Cert, Cert, Cert, Cert, Cert, Cert 3) Title 4) Department 5) Address | City, St. Zip 6) Phone1 | Phone2 7) Phone3 | Phone4 8) Email They would like the field "Certs", shown above in red, to be able to fill the remaining space on line 1 of the text frame. Since Doctors like to show all of their certifications, the customer would like to have multiple certifications roll to line 2, if necessary (if they all don't fit on line 1). (All certifications will be entered into 1 field separated by commas) They do not, however, want certifications to roll to a 3rd line of text. If the certifications exceed the space on line 2 of the text frame, the customer would like to return "Certifications exceed the allotted space". When they were doing these cards manually, they would adjust the spacing between the letters and the letter width, while not affecting the font height. When experimenting with CopyFit, they found all the text shrunk by a percentage and would role to more then to two line limitation. I haven't been able to figure this one out on my own, so I am reaching out to see if anyone has run into something similar in the past...or... has any suggestions on how I can accomplish this? Thank you!!! Quote Link to comment Share on other sites More sharing options...
Dan Korn Posted May 26, 2016 Share Posted May 26, 2016 Are you really trying to copyfit the certs, or are you just trying to limit them to two lines? In other words, should the rule try to shrink the certs down to a specific size to try to fit them onto two lines? Or is the idea just to see if they fit on two lines at the original point size, and report an error if they don't? Quote Link to comment Share on other sites More sharing options...
TroyM68 Posted May 27, 2016 Author Share Posted May 27, 2016 What They currently do is one of two things pending the number of certs. They either squeeze the text (width-wise) as much as 85% (to get the certs all on only the first line) or...If the certs still can't fit on line 1, they abandon the "Text Squeeze" and wrap the text to a second line with no adjustment to the font whatsoever. Right now the customer doesn't know if they can have both options. The perfect scenario would be for a rule to look at the space available in the first line of text to see if the certs could be "squeezed", no more then 85%, to keep all the text on line 1... If it is too long to fit on that first line... They would like to abandon the "text squeeze", and instead, roll the text to a second line, but not to exceed the spaces available on line two... If that limit is exceeded...they would like a message telling them the maximum number of characters has been exceeded. If this is too crazy... please let me know... But thanks for listening and for your input1 Troy Quote Link to comment Share on other sites More sharing options...
ScottHillock Posted May 31, 2016 Share Posted May 31, 2016 Based off of Dan's and Step's code here on the forum. //Field names var v_field = [Field('First and Last Name'), Field('Cert1'), Field('Cert2'), Field('Cert3'), Field('Cert4')].filter(String); //Font var font_name = "2Volkswagon Heavy-K"; //Font Size var v_size = "12"; //Frame Width in inches var v_frame = "3"; var var1_n = '<f name="' + font_name + '">'; var var1_s = '<z newsize="' + v_size + '">'; var var2 = v_field.join(', '); //combine fields var var3 = v_frame*72; //get frame width in points var var4 = var1_n + var1_s + var2; var tm = new FusionProTextMeasure; tm.CalculateTextExtent(var4); var tmwidth = tm.textWidth; if (tmwidth < var3*100){return var4;} //if no scaling needed return without magnify var factor = Round(var3 / tm.textWidth * 10000, 0) - 1; if (factor >= 85){return "<magnify type=setwidth factor=" + factor + ">" + var4 + "</magnify>";} //if scaling is above 85% return with scaling if (tmwidth < var3*200){return var4;} //if it can fit 2 lines without scaling return //error Message Print ("the maximum number of characters has been exceeded"); return "Certifications exceed the allotted space"; The line that contains "if (tmwidth < var3*200){return var4;}" might need the 200 value adjusted lower. Since some text breaks at different points. Quote Link to comment Share on other sites More sharing options...
step Posted May 31, 2016 Share Posted May 31, 2016 One thing you could do is to create a text rule to return your name and credentials called "Name": var name = Field('name'); var creds = Field('creds'); return [] .concat(name, creds.split(',')) .map( function(s) { return Trim(s); }) .filter(String) .join(', '); Then you could insert that into a text frame along with other rules/variables and let onCopyfit handle the resizing of your text by inserting this into the onCopyFit callback: var cf = FusionPro.Composition.CurrentFlow var rule = 'Name'; if (!Copyfit(new MagnifyAttributes("text", 25, 400, 6, 72))) { ReportWarning("Could not copyfit text in flow " + FusionPro.Composition.CurrentFlow.name); } else { if (Rule(rule)) { var factor = Int((cf.content.match(/factor="(\d+)"/) || ['','100'])[1]) / 100; var tag = '<variable name="' + rule + '">'; var find = new RegExp('<para.*?(?='+tag+')', '') var paragraph = (cf.content.match(find) || [''])[0]; var font = (paragraph.match(/<f name="([^"]+)"/) || ['','Arial'])[1]; var size = Int((paragraph.match(/<z newsize="([^"]+)"/) || ['','12'])[1]) * factor; var tm = new FusionProTextMeasure; tm.font = font; tm.pointSize = Int(size) + 'pt'; tm.maxWidth = GetSettableTextWidth(FindTextFrame(cf.name)); tm.CalculateTextExtent(Rule(rule)); if (tm.textLines > 2) cf.content = cf.content.replace(new RegExp(tag, ''), '<color name="Red">Certifications exceed the allotted space</color>'); } } That allows you to more accurately determine if "Name" will require 1 or 2 lines after the frame has been "copyfit" to ensure the text flow fits in the frame. I suppose you could play around with those settings in order to reduce the tracking to a minimum of 85% before wrapping the "Name" to a second line if you wanted to but I'll leave that up to you. Quote Link to comment Share on other sites More sharing options...
TroyM68 Posted June 1, 2016 Author Share Posted June 1, 2016 Scott, when I re-create your rule: //Field names var v_field = [Field('First Name') + " " + Field('Last Name ') + ", " + Field('Credentials') ].filter(String); //Font var font_name = "Arial"; //Font Size var v_size = "11"; //Frame Width in inches var v_frame = "2.05"; var var1_n = '<f name="' + font_name + '">'; var var1_s = '<z newsize="' + v_size + '">'; var var2 = v_field.join(' '); //combine fields var var3 = v_frame*72; //get frame width in points var var4 = var1_n + var1_s + var2; var tm = new FusionProTextMeasure; tm.CalculateTextExtent(var4); var tmwidth = tm.textWidth; if (tmwidth < var3*100){return var4;} //if no scaling needed return without magnify var factor = Round(var3 / tm.textWidth * 10000, 0) - 1; if (factor >= 85){return "<magnify type=setwidth factor=" + factor + ">" + var4 + "</magnify>";} //if scaling is above 85% return with scaling if (tmwidth < var3*200){return var4;} //if it can fit 2 lines without scaling return //error Message Print ("the maximum number of characters has been exceeded"); return "Certifications exceed the allotted space"; I receive the following message when I try to validate: <f name="Arial"><z newsize="11">Troy Marshall, cred, cred, cred, cred, cred, cred, This is also what appears on the Business Card. What am I doing wrong??? Quote Link to comment Share on other sites More sharing options...
ScottHillock Posted June 1, 2016 Share Posted June 1, 2016 The v_field is a variable array. So it should only include values separated by a comma. The concatenation with the + is not needed, as that is handled later on. So I would change it to: var FirstLast = Field('First Name') + " " + Field('Last Name ') + ", "; var v_field = [FirstLast, Field('Credentials') ].filter(String); This way we can modify the FirstLast later if needed, while still using the rest of the code. Quote Link to comment Share on other sites More sharing options...
TroyM68 Posted June 1, 2016 Author Share Posted June 1, 2016 Step, When I change the OnCopyFit rule (modified below) var cf = FusionPro.Composition.CurrentFlow var rule = 'name'; if (!Copyfit(new MagnifyAttributes("text", 25, 400, 6, 72))) { ReportWarning("Could not copyfit text in flow " + FusionPro.Composition.CurrentFlow.name); } else { if (Rule('name')) { var factor = Int((cf.content.match(/factor="(\d+)"/) || ['','100'])[1]) / 100; var tag = '<variable name="' + rule + '">'; var find = new RegExp('<para.*?(?='+tag+')', '') var paragraph = (cf.content.match(find) || [''])[0]; var font = (paragraph.match(/<f name="([^"]+)"/) || ['','Arial'])[1]; var size = Int((paragraph.match(/<z newsize="([^"]+)"/) || ['','12'])[1]) * factor; var tm = new FusionProTextMeasure; tm.font = font; tm.pointSize = Int(size) + 'pt'; tm.maxWidth = GetSettableTextWidth(FindTextFrame(cf.name)); tm.CalculateTextExtent(Rule(rule)); if (tm.textLines > 2) cf.content = cf.content.replace(new RegExp(tag, ''), '<color name="Red">Certifications exceed the allotted space</color>'); } } I receive the following error message when I try to validate the rule. C:\Program Files (x86)\PTI\FusionPro\Builtins.js line 3316 ERROR: in FindFrame(), no frame specified Any ideas? Quote Link to comment Share on other sites More sharing options...
TroyM68 Posted June 1, 2016 Author Share Posted June 1, 2016 Thanks Scott, I will give this a try! Quote Link to comment Share on other sites More sharing options...
step Posted June 1, 2016 Share Posted June 1, 2016 Step, When I change the OnCopyFit rule (modified below) var cf = FusionPro.Composition.CurrentFlow var rule = 'name'; if (!Copyfit(new MagnifyAttributes("text", 25, 400, 6, 72))) { ReportWarning("Could not copyfit text in flow " + FusionPro.Composition.CurrentFlow.name); } else { if (Rule('name')) { var factor = Int((cf.content.match(/factor="(\d+)"/) || ['','100'])[1]) / 100; var tag = '<variable name="' + rule + '">'; var find = new RegExp('<para.*?(?='+tag+')', '') var paragraph = (cf.content.match(find) || [''])[0]; var font = (paragraph.match(/<f name="([^"]+)"/) || ['','Arial'])[1]; var size = Int((paragraph.match(/<z newsize="([^"]+)"/) || ['','12'])[1]) * factor; var tm = new FusionProTextMeasure; tm.font = font; tm.pointSize = Int(size) + 'pt'; tm.maxWidth = GetSettableTextWidth(FindTextFrame(cf.name)); tm.CalculateTextExtent(Rule(rule)); if (tm.textLines > 2) cf.content = cf.content.replace(new RegExp(tag, ''), '<color name="Red">Certifications exceed the allotted space</color>'); } } I receive the following error message when I try to validate the rule. C:\Program Files (x86)\PTI\FusionPro\Builtins.js line 3316 ERROR: in FindFrame(), no frame specified Any ideas? You need to name the frame that the Rule('name') is shown in. Quote Link to comment Share on other sites More sharing options...
step Posted June 1, 2016 Share Posted June 1, 2016 The v_field is a variable array. So it should only include values separated by a comma. The concatenation with the + is not needed, as that is handled later on. So I would change it to: var FirstLast = Field('First Name') + " " + Field('Last Name ') + ", "; var v_field = [FirstLast, Field('Credentials') ].filter(String); This way we can modify the FirstLast later if needed, while still using the rest of the code. Doing this pretty much defeats the purpose of the 'filter' method. Consider a situation where both fields ("First Name" and "Last Name") are empty: var FirstLast = Field('First Name') + " " + Field('Last Name ') + ", "; // FirstLast = [color="Red"]" , "[/color] var v_field = [FirstLast, Field('Credentials') ].filter(String); // v_field = [[color="red"]" , "[/color], Field('Credentials')] A more appropriate way to handle that is: var FirstLast = Field('First Name') + ' ' + Field('Last Name'); // FirstLast = ' ' if (FirstLast = Trim(FirstLast)) FirstLast += ', '; var v_field = [ FirstLast, Field('Credentials') ].filter(String); // v_field = [ Field('Credentials') ] Or: var v_field = [[Field('First Name'),Field('Last Name')].filter(String).join(' '), Field('Credentials')].filter(String).join(', '); // v_field = [ Field('Credentials') ] Quote Link to comment Share on other sites More sharing options...
TroyM68 Posted June 2, 2016 Author Share Posted June 2, 2016 Scott, I made the change and I still get the <f name="Arial"><newsize="12">FirstLast, Credentials Credentials are rolling to a third line. I have to be missing something! Quote Link to comment Share on other sites More sharing options...
step Posted June 2, 2016 Share Posted June 2, 2016 Scott, I made the change and I still get the <f name="Arial"><newsize="12">FirstLast, Credentials Are the literal tags showing in the text frame when you preview/compose? If so, there's a pretty good chance that you didn't check the "Treat returned strings as tagged text" checkbox at the top of the rule editor. Checking that box will cause FP to actually interpret those tags and apply the font and size to your text rather than print them. Quote Link to comment Share on other sites More sharing options...
TroyM68 Posted June 2, 2016 Author Share Posted June 2, 2016 The text frame is named "name" The rule is named "name" in that text field. I am still getting the error: Builtins.js line 3316 ERROR: in FindFrame(), No frame specified. Also... Without this working... All the text font size reduces (ex: from 11pt to 6pt) Font size needs to remain at 11pt. Just the spacing between characters needs to adjust from no more then 100% down to no less then 85% of normal spacing. This may be because the OnCopyFit rule isn't working??? Quote Link to comment Share on other sites More sharing options...
Dan Korn Posted June 6, 2016 Share Posted June 6, 2016 You don't actually have to do all of this in the OnCopyfit callback rule, but if you do, then you want to write the rule like this, with your actual frame name on the first line: if (FusionPro.Composition.CurrentFlow.name == "Name of frame with custom copyfitting") { // Custom copyfitting logic here. return; } //else // default copyfitting if (!Copyfit(new MagnifyAttributes("text", 25, 400, 6, 72))) ReportWarning("Could not copyfit text in flow " + FusionPro.Composition.CurrentFlow.name); Quote Link to comment Share on other sites More sharing options...
TroyM68 Posted June 7, 2016 Author Share Posted June 7, 2016 Gentlemen, I finally got this rule working thanks to all of you! I really appreciate all of your help and advice on this one!!! Quote Link to comment Share on other sites More sharing options...
TroyM68 Posted June 28, 2016 Author Share Posted June 28, 2016 Ran into a glitch... This rule works great until the credentials field is left blank (it's not a required field). When the credentials field is blank... the return is: First Last, (It returns a comma) When the credentials are present the return is: First Last, Credential (exactly as it should be) How would I modify the rule to address this issue? Only use a "," if the credentials field is not empty? Thanks again! Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.