0

I have a shopping cart that i want someone to be able to download a fairly well format pdf from. At the moment in prints the item names, but if i want to include the prices etc it fails. Is there anyway to also add the pdf data to a table, to make it look a little neater? Or is there a way of being able to save the item names and prices in a hidden array and then output this to the pdf?

Shopping cart code

<div class="shoppingCartItems" id="shoppingCartItems">
  <div class="titles2">
    <div class="item-info">[shoppingcart_items]</div>
    <div class="item-qty">[shoppingcart_quantity]</div>
    <div class="item-price">[shoppingcart_price]</div>
    <div class="item-total">[shoppingcart_total]</div>
    <div class="item-remove">&nbsp;</div>
    <div class="clear"></div>
  </div>

  <!--START: SHOPPING_CART_ITEM-->
  <div class="row">
    <div class="item-info">
      <div class="product-image"><!--START: itemthumbnail--><a href="product.asp?itemid=[ITEM_CATALOGID]"><img src="thumbnail.asp?file=[THUMBNAIL]" height="55" width="55" /></a><!--END: itemthumbnail--><!--START: thumbnailnolink--><img src="thumbnail.asp?file=[THUMBNAIL]" height="55" width="55" id="tnl" /><!--END: thumbnailnolink--></div>
      <div class="product-name-options"> 
           <div id="contentStart">
        <!--START: itemnamelink--><a id="itemName" class ="itemName" href="product.asp?itemid=[ITEM_CATALOGID]">[ITEM_NAME]</a><!--END: itemnamelink--> 
        <!--START: itemnamenolink--><span id="spnItemName">[ITEM_NAME]</span><!--END: itemnamenolink--> 
        <!--START: itemoptions--> 
          </div>
        <br />
        <a href='#' onclick="toggle('opt[ITEM_ID]')">View/Hide options</a><br />
        <div id=opt[ITEM_ID] name=opt[ITEM_ID] style="display:none;">[OPTIONS]</div>
        <!--END: itemoptions--> 
        <!--START: recurring_frequency-->
        <div class="recurring_frequency">This item will Autoship every <strong>[recurring_frequency]</strong></div>
        <!--END: recurring_frequency--> 
        <!--START: giftwraplink-->
        <div class="giftwraplink"> <a onclick="showGiftWrap('[ITEM_ID]')">[giftwrap_link]</a> </div>
        <!--END: giftwraplink--></div>
      <div class="clear"></div>
    </div>
    <div class="item-qty">
      <input type="text" name="qtyitemnum" value="[ITEM_QUANTITY]" size="3" maxlength="5" class="txtBoxStyle" />
      <input type="hidden" name="coliditemnum" value="[ITEM_ID]" size="3" maxlength="5" />
        <div id="itemQty">
      <a href="#" onclick="document.forms['recalculate'].submit();return false;" class="update-qty">[shoppingcart_updatecart]</a>
            </div>
    </div>
    <div class="item-price" id="itemPrice">[ITEM_PRICE] </div>
    <div class="item-total">[ITEM_SUBTOTAL]</div>
    <div class="item-remove"><a href="#" onclick="document.recalculate.qtyitemnum.value=0;document.recalculate.submit();"><i class="icon-cancel"></i></a></div>
    <div class="clear"></div>
  </div>
  <!--END: SHOPPING_CART_ITEM-->
  <div class="shoppingCartTotal" id="totalCartPdf">
    <div class="clear">&nbsp;</div>
    <div class="item-total">[CARTSUBTOTAL]</div>
    <div class="item-price">[shoppingcart_subtotal]</div>
    <div class="clear"></div>
    <!--START: DISCOUNTS-->
    <div class="clear">&nbsp;</div>
    <div class="item-total">[DISCOUNTS]</div>
    <div class="item-price">[checkout1_discounts]</div>
    <div class="clear"></div>
    <!--END: DISCOUNTS-->
    <div class="clear">&nbsp;</div>
    <div class="item-total"><strong>[CARTTOTAL]</strong></div>
    <div class="item-price"><strong>[shoppingcart_total]</strong></div>
    <div class="clear"></div>
  </div>

  </div>
  <button id="submit1">Export to  PDF</button>

js

  $(document).on('click', '#submit1', function() {

         var doc = new jsPDF(); 
var specialElementHandlers = { 
    '#editor': function (element, renderer) { 
        return true; 
    } 
};


    //I dont know what remove was is the example, added quotes around it.
    console.log("clicked");
    doc.fromHTML($('#contentStart').html(), 15, 15, { 
        'width': 190, 
            'elementHandlers': specialElementHandlers 
    }); 
    doc.save('sample-page.pdf'); 
})

;

  • Take a look here: https://github.com/cognitom/paper-css – Craig van Tonder Mar 21 '18 at 08:59
  • does that support dynamically added content? –  Mar 21 '18 at 09:03
  • How you create the HTML is entirely up to you, this css makes your html render beautifully when in print, you could print to PDF or do this programatic manner such as with the note on PDF generation. – Craig van Tonder Mar 21 '18 at 09:12
  • can you select a specific div rather than the whole page? –  Mar 21 '18 at 09:25
  • Also not sure if you're using PHP to dynamically generate the content but i've used this with mixes successes: https://tcpdf.org/ – Craig van Tonder Mar 21 '18 at 09:26
  • unfortunately i'm using javascript –  Mar 21 '18 at 09:30
  • Seems not but you could change that i guess, look at the paper.css file and speaking of css... Look at media queries though because you can create a stylesheet and have it apply to print view, in which case you can hide, style and otherwise change the content that is available within this. – Craig van Tonder Mar 21 '18 at 09:31
  • So in theory i could change the paper.css file, to apply to a specific div and then with a button click someone could click that and have a format pdf printed? –  Mar 21 '18 at 09:35
  • Sure just replace body with whatever element/id/class you're trying to target. – Craig van Tonder Mar 21 '18 at 09:36
  • brilliant, and sorry one last question can i force it to download to a pdf rather than print? –  Mar 21 '18 at 09:40
  • Posted as an answer, might not be 100% accurate as per your use case but it's how I might tackle this aspect of things. – Craig van Tonder Mar 21 '18 at 09:56

1 Answers1

0

Using something like paper-css and in practice you'd have a file like template.html on the backend.

When the user clicks the button:

  1. You send the data that needs to be printed to your API endpoint on the backend.
  2. Validate that the request was made by a user on the website, maybe with csrf or session information.
  3. Sanitize any user input.
  4. Inject the data into the template.
  5. Generate the PDF (as suggested in the readme with electron-pdf) .
  6. Respond with the newly created file.
  7. Finally and on the front end after receiving the successful response, you would prompt the user to download the file within their browser client.

Take a look at the docs on jsPDF too as it would likely be a more simple but less diverse option which would enable you to deal with this on the front end using some HTML5 magic.

There are others too search this site or your favorite search engine for more info on those.

Bear in mind though, not all browsers fully support HTML5 so trying to do this on the front end is not exactly the best option at this point in time.

Craig van Tonder
  • 7,497
  • 18
  • 64
  • 109
  • Thankyou very much for the help so far, i'll read more into jsPDF which is what i'm using in the OP. I've gone ahead and created a template.html file, how do i inject the data from a viewcart.html file into this, and then have that data sent back? –  Mar 21 '18 at 10:01
  • Build an object with the data and post that to the backend, I see you injecting it like: `[shoppingcart_total]`. Less favorable way might be to just copy the relative part of the HTML from the DOM using JS and post that through to the backend. – Craig van Tonder Mar 21 '18 at 10:05
  • using something like jSON? this is starting to become quite of my depth :0 –  Mar 21 '18 at 10:09
  • @johndoi2020 Indeed objects are JSON in Javascript so you could send maybe an object or an array of objects through to the backend and inject that data into your template. You have it available already on the front end, just consolidate it into what you want to export to pdf exactly and send that. Also note that this isnt a direct answer to your question but is an answer to the question in general, i'll leave it to others to provide a solution using jsPDF. That being said, there's "easier" solutions such as commercial API's that offer this type of service. – Craig van Tonder Mar 21 '18 at 10:28
  • Thankyou very much, it's all very complicated but i will look into taking the html dom element, building a json object, sending that to a different html invoice template, and then sending that back, to then download the pdf. –  Mar 21 '18 at 10:31
  • @johndoi2020 my second comment represents two options, you either take the data out of JS as it's there already, you inject it `[myVariable]` and build that into an object of values `{ products: ['item one', 'item two'], subtotal: shoppingcart_subtotal }` which you can then inject into your template on the back end, OR, you could simply take the entire part of the HTML that you want and send that through to the back end, inject the entire html string into your template and generate the pdf from that. I prefer working with the data itsself over a long string of html but both options would work – Craig van Tonder Mar 21 '18 at 10:49
  • I think because this will hopefully end up on a live site, i'll need to use the html long string option as i won't know how many items a user may be buying –  Mar 21 '18 at 10:59