Skip to main content
Inspiring
January 11, 2011
Question

cfdocument does not respect page-break-inside:avoid

  • January 11, 2011
  • 7 replies
  • 12130 views

Can anybody make page-break-inside work?  below is sample code ... run it and it doesn't respect the page-break-inside...  I think it is time to remove this from the document documentation if nobody can make it work....  can anybody post a proof of concept that shows that cfdocument does respect page-break-inside?

 


<cfdocument    format="pdf"    marginbottom="1"    marginleft="1"    marginright="1"    margintop="1"    overwrite="yes"> 

  <Cfoutput>    


  <cfloop from="1" to="10" index="i"> 

   <cfloop from="1" to="10" index="i"> 

     <!--- alternate colors and font-size so that you can easily see where page-break-inside is failing when you look at the pdf created --->

    <cfif i mod 2> 

          <cfset color="blue"> 

          <cfset fontWeight="normal"> 

          <cfset fontsize="11"> 

    <cfelse> 

          <cfset color="red"> 

          <cfset fontWeight="bold"> 

          <cfset fontsize="14"> 

    </cfif> 


    <p style="color:#color#;page-break-inside:avoid;font-weight:#fontWeight#;font-size:#fontsize#"> 

      <!--- create a random size string for each paragraph using left() --->


    #left( "The problem has been compounded by a strike at the main plant that makes de-icing fluid in France, Transportation Minister Thierry Mariani said in a radio interview with France Inter.   Airlines canceled 400 flights due to land or take off from Charles de Gaulle Friday morning, Heraud told Dow Jones Newswires.   Aeroports de Paris (ADP.FR), the state-controlled airport operator, said on its Twitter account that planned flights were operating with delays of between one and one and a half hours.   Hundreds of passengers had already spent the night at the airport after some 50 flights were canceled Thursday evening, said Elise Hermant, a spokeswoman for Aeroports de Paris.   The airport had only just cleared the backlog from flight delays caused by bad weather earlier in the week.   Scores of trains were also late or canceled in France Friday morning. But the situation at Orly, the other big airport in Paris, was described as normal.   Airlines are supposed to reimburse stranded passengers or to reschedule flights and offer lodging, but the hotel capacity around the airport is limited and some airlines don't play the game, Heraud said.   -By Inti Landauro, Dow Jones Newswires; +33 1 4017 1740; inti.landauro@dowjones.com ",  RandRange(700, 1100) )#  


    </p> 


   </cfloop> 

  </cfloop> 

  </CFOUTPUT> 

</cfdocument>

    This topic has been closed for replies.

    7 replies

    Participant
    July 28, 2014

    I found a way to do it, and although it's far from ideal, it allows for choosing any group of data to not break over a page if possible. The basic principle is to put divs around all of the nobreak data groups with a class on them, pop all of the text into a div appended to body, and .each() the class with a height counter that adds up the heights until it goes over a page, then inserts chr(30) and resets the height counter. Then submit the modified html to coldfusion, run a loop on a list with chr(30) as the delimiter, and make each page followed by cfdocumentitem type=pagebreak.

    JS Code:

    function paginateForPdf(report_body){

      // Put a div on the page to render heights

      $('body').append('<div id="pdf_render_container"></div>');

      // Put the response into the div

      $('#pdf_render_container').show().html(report_body);

      // Summing variable for each section's height

      var page_height = 0;

      var page_height_max = 762;

      // Container for the assembled html of the pages and page break characters

      var assembled_html = "";

      // Iterate over the unbreakable groups

      $('#pdf_render_container .height_group').each(function(){

      // Add the page height of this div to the previous total

      if(page_height <= page_height_max){ // Don't page break if it's a really big one

      page_height += $(this).height();

      // If more than one page

      if(page_height > page_height_max){

      // Add a record separator before this div so page is not overfull

      assembled_html += String.fromCharCode(30);

      // Set the page height to this div only

      page_height = $(this).height();

      }

      } else page_height -= page_height_max;

      // Add this div's contents to the assembled html

      assembled_html += $(this).html();

      });

      // Purpose served, remove the renderer div

      $('#pdf_render_container').remove();

      return assembled_html;

    }

    CF document:

    <cfdocument format="pdf" name="report_PDF">

    <style>

    <!--- Rendering Style here --->

    </style>

    <cfset var counter = 1>

    <!--- Loop over the assembled html with the record separator as the list delimiter to get whole pages --->

    <cfloop list="#report_body#" delimiters="#chr(30)#" index="page">

    #Trim(page)# <!--- Trim to prevent hanging spaces/newlines from tripping into the next page --->

    <cfif counter LT ListLen(report_body,#chr(30)#)><!--- don't break after the last page --->

    <cfdocumentitem type="pagebreak"></cfdocumentitem> <!--- page break after a page --->

    </cfif>

    <cfset counter ++>

    </cfloop>

    </cfdocument>

    All you need to do is run an ajax call to get your html (or not if it's already on the page), submit all of it to the paginate function, and submit the returned result to the coldfusion code

    762 seems to be the right number for the page height for me, not sure if that's universal. Hope this helps!

    Participant
    February 28, 2013

    We had a similar problem with table rows inside a cfloop query and tried to use, to no avail as we are on CF9 as well

    This is what we did to resolve it - placing this code right before the item that is breaking in the undesired location

    <span> </span><BR>

    BKBK
    Community Expert
    Community Expert
    November 24, 2011
    Participant
    January 13, 2013

    I had the same issue with CF 10.  Seems the issue is not the page break, but the table.

    If I inserted code, something along these lines:

      1 - use mod to test for whether or not you wish to insert a page break at a certain number of rows (my issue).

      2 - when the break is determined, close the table and start a new table on the next page.

      <cfif modValue EQ 0 >
            </tr>
            </table>
            <cfdocumentitem type="pagebreak" />
            <table width="95%" border="0" cellspacing="0" cellpadding="5" align="center" >
            <tr>
          <cfelse>
            </tr>
       </cfif>

    I know this doesn't make everyone happy, but it is what I needed to do.  And of course, if your table headers are needed on each page ... duplicate that as well.

    
    Participant
    November 23, 2011

    Check out Raymond Camdens pdfutils (http://pdfutils.riaforge.org/)
    It allows the text from a pdf to be read page by page.

    It has enabled me to do a workaround fix for the problem where cfdocument does not support
    style="page-break-inside: avoid;"

    The following code is not overly efficient, in that it recreates the entire report for each instance where
    a page break needs to be repositioned, but the preliminary test results look good. Others may like to embellish the following.
    It creates hidden fields in the pdf, formatted as
    keep_together_start_001, keep_together_end_001, keep_together_start_002, keep_together_end_002 etc
    If the matching tags are not on the same page, then the pdf is recreated with an appropriate page break.


    In the style sheet
    div.hidden1{position:absolute;
    left:-3000px;
    top:auto;
    width:1px;
    height:1px;
    overflow:hidden;}

    div.hidden2{position:absolute;
    left:-4000px;
    top:auto;
    width:1px;
    height:1px;
    overflow:hidden;}

    On initialisation of the page that creates the pdf
    <cfif not isdefined("url.keep_together")>
         <cfset session.keep_together_list = "">
         <cfset keep_together_count = 0>
    </cfif>

    ...

    At the start of a section of output that I want kept together, put the following

      <cfset keep_together_count += 1>
      <cfif ListFind(session.keep_together_list,"#NumberFormat(keep_together_count,"000")#","|") gt 0>
            <cfdocumentitem type="pagebreak"></cfdocumentitem>
      <cfelse>
            <cfoutput>
                  <div class="hidden1">keep_together_start_#NumberFormat(keep_together_count,"000")#</div>

            </cfoutput>
      </cfif>

    ...

    At the end of the section to be kept together

    <cfif ListFind(session.keep_together_list,"#NumberFormat(keep_together_count,"000")#","|") eq 0>
         <cfoutput>
                <div class="hidden2">keep_together_end_#NumberFormat(keep_together_count,"000")#</div>

         </cfoutput>
    </cfif>

    Once the PDF file has been created, use Raymond's pdfutils to check each page for a start without a matching end.
    If found, indicate which section of code need to have a page break inserted before it, and then reproduce the report.

    <!--- Check for keep_togethers that were split --->
    <cfset pdf = createObject("component", "pdfutils")>
    <cfset mypdf = expandPath("my_report.pdf")>
    <cfset pdf_struct = pdf.getText(mypdf)>

    <cfloop index="idx" from="1" to="#ArrayLen(pdf_struct)#">
         <cfset next_start = 1>
         <cfset start_offset = findnocase("keep_together_start_", pdf_struct[idx].text, next_start)>
         <cfloop condition="start_offset neq 0">
                <cfset next_start = start_offset + 20>
                <cfset keep_together_id = Mid(pdf_struct[idx].text,start_offset + 20,3)>
                <cfset end_offset = findnocase("keep_together_end_#keep_together_id#",pdf_struct[idx].text)>
                <cfif end_offset eq 0>
                      <cfset session.keep_together_list = session.keep_together_list & "|" & keep_together_id>
                      <cflocation addtoken="No" url="sft_report.cfm?keep_together">
                </cfif>
                <cfset start_offset = findnocase("keep_together_start_", pdf_struct[idx].text, next_start)>
         </cfloop>
    </cfloop>

    

    Message was edited by: Phil0707 - tidied up a few things - works well now

    Participant
    April 8, 2011

    Increasing the page margin top seems to have helped me. But again it's not fail proof.

    WolfShade
    Legend
    January 28, 2011

    I'm curious about something.

    You have nested CFLOOPS, and you give them both the same index:

      <cfloop from="1" to="10" index="i"> 

       <cfloop from="1" to="10" index="i">

    ...

       </cfloop>

      </cfloop>

    ??

    ^_^

    Owainnorth
    Inspiring
    January 28, 2011
    You have nested CFLOOPS, and you give them both the same index

    Oooooh, you don't wanna do that.

    Inspiring
    January 28, 2011

    Actually it makes no difference , but anyway I changed the inner loop variable to x... you can run the code below with the change and the original code and both illustrate the problem... but thanks for trying!

    you can see the results yourself http://staging29.zynite.com/test.cfm

    Date: Fri, 28 Jan 2011 07:15:32 -0700

    From: forums@adobe.com

    To: gdavis321@hotmail.com

    Subject: cfdocument does not respect page-break-inside:avoid

    You have nested CFLOOPS, and you give them both the same index

    Oooooh, you don't wanna do that.

    >

    tclaremont
    Inspiring
    January 11, 2011

    I believe this is a known problem that any amount of google searching will result in the answer to. I think there is a patch that needs to be applied

    to the CF server that helps with this.

    I am not at my desk right now to validate, so don't quote me on that though.

    Inspiring
    January 11, 2011

    Thanks for suggesting google ... I have done plenty of googling and seen plenty of dispair but no answers that work.

    The code I posteded is extrememly simple... just a <p style="page-break-inside:avoid">with random length paragraphs...  what other magic can anyone suggest?  if it can't work with such a simple example (no other html) please any one show me ANY example where it does work!

    btw I submitted this as a bug to adobe and of course got no response... and i see others have submitted this same bug too!

    Inspiring
    January 11, 2011

    btw I am using coldfusion 9 ... there is only one hotfix for cf9 and it does not address this problem  (hot fix stuff posted below)

    http://kb2.adobe.com/cps/825/cpsid_82536.html

    ...  I believe you are referring to the hot fixes to stop the

    text from getting cut of back in cf 7 (please correct me if I am wrong)

    Cumulative Hot Fix 1 for ColdFusion 9

    Issue

    The following fixes are contained in ColdFusion 9 Cumulative Hot Fix 1 (CHF1). Adobe recommends that you apply CHF1 to ColdFusion 9 only if you are experiencing one or more of the issues listed below. This cumulative hot fix is specific to ColdFusion 9 and need not be applied to any other releases.

    Bug IDDescriptionAdded in Cumulative Hot Fix
    80624Fix for the NullPointerException error thrown when deploying a car file from ColdFusion 7 containing data sources to ColdFusion 91
    80621Fix for the issue where ColdFusion was ignoring local variable assignment when the variable is assigned to a struct at runtime1
    80601Fix for the “java.util.regex.PatternSyntaxException: Illegal repetition{}” error thrown when using {} as delimiter with the listtoarray function1
    80429Fix for the issue where in any cfscript style function declarations, function parameter types were not accepting the dotted CFC type1
    80412Fix for the issue where ColdFusion deployed on JBoss was unable to render maps using cfmap1
    80375Fix for the “Error casting an object of type java.lang.Double cannot be cast to  java.lang.String to an incompatible type” error thrown when calling a CFC remotely with returnFormat=json1
    80335Fix for the issue where an implicit struct/array passed to a function call as a value is not working1
    80231Fix for the issue where cfscript style function declaration was not accepting implicit struct/array as a default value for the second argument onward1
    80230Fix for the “ashx image format is not supported on this operating system” error thrown when assigning an image returned from a .NET webservice to a CFImage tag1
    79756Fix for the “Cannot drop the table '<tableName>'” error thrown when requesting the CFC for the first time with the ORM setting dbcreate set to dropcreate1