Rally API: How to print or export to pdf from Custom HTML - pdf

I have created table with data using "custom html app".
I want now print this page but when I try to do it, it cuts few last columns.
I have tried to set style of body to "width:1000px" and then it prints ok but then it doesn't shows on whole screen and I have table of size 1000px

We usually end up having slightly different css for printing than runtime.
Try this:
#media print {
body {
width: 1000px;
}
}

Related

Ionic4 Print Media Query for Scrollable ion-content

Pretty straightforward problem. Have scroll-able ion-content in my Ionic4 application. I want to be able to print it gracefully by applying #media only print styles. I'm almost there, but I have one major problem. I cannot get the vertical scrollbar to disappear for printing. Additionally, I only ever get one page printed, containing only the content that is in view when I print the page. I've scoured the web for solutions, and come across and tried various suggestions in the context of Ionic3 and earlier, but I haven't found the magic bullet for Ionic4 yet. Has anyone encountered and gotten to the bottom of this yet?
I have been through the ringer on trying to print content in Ionic 4. Some of the steps i followed to print multiple pages.
remove any flex-box styled lists. They just will not print how you want them to across pages, though they have worked fine for me if the content fits in a page.
for items you want to be seperated by page, its best if they are a display: block; styled item, so that that in the print style sheet you can use one of the page-break properties on it
on the item containing your list, the ion-content for example, make sure you remove any max-height attributes from it or any of its ancestor or child elements, as well as removing the overflow: scroll from these elements as well so that it allows your content to go from page to page. for example on my stylesheet for printing (cant share it because of NDAs) I had a lot of overflow-y: visible on elements just to make sure it shows. if you find an element thats cutting off your html, it should be the primary target for experimentation.
you can simulate a print in the dev tools, i found it useful, it's good for iteration here's a link
some other things that may help, but i am not sure as I did so much testing across browsers, and only vaguely remember what impact that css property had is to have the body with a static position, as well as having contain: none on the body to say that the browser should render as normal, little more explanation here
i do not know the specifics of your use case, but if you don't mind foregoing the native print button, and just giving the user a button to click to trigger the print, then that would be more manageable as you do not have to account for all the scaffolding around that specific element that you want to print (the ion-router, ion-page, and all the ancestors)
If you did that then you could put all your items you want to print into a div with an id of printSection or what you prefer, and then the javascript that is responsible for that page you can create your own print function. In my example i will use angular, if you are not using that then preform whatever DOM selecting you need to to get the native html out of your template.
#Component({ ... })
export class Page {
// select the item holding your print content by `#property` you gave it
#ViewChild('printSection', { read: ElementRef }) printSection: ElementRef;
...
customPrint() {
const printContent = this.printSection.nativeElement;
const WindowPrt = window.open('', '', 'left=0,top=0,width=900,height=900,toolbar=0,scrollbars=0,status=0');
WindowPrt.document.write(printContent.innerHTML); // pass in the native html you got
/**
* you should probably use an observable instead of an interval for this,
* but this is just to illustrate a bug where the print would be fired before
* all the content was written
*/
const interval = setInterval(
() => {
if (document.readyState === 'complete') {
WindowPrt.document.close();
WindowPrt.focus();
WindowPrt.print();
clearInterval(interval);
}
},
200);
}
}
I Solved it following this process
First, remove the content to be printed from ion-content. Use a div instead of ion-content(shadow-dom is implemented with ion-content which blocks your CSS classes)
You also need to force the CSS below on ion-page when printing (it is initially set to position: absolute, by default)
In my case I was printing from a modal component which has a default class "show-modal". I was able to print on multiple pages by target that class this way
#media print {
.ion-page {
left: 0;
right: 0;
top: 0;
bottom: 0;
display: block;
position: relative;
flex-direction: column;
justify-content: space-between;
contain: none;
overflow: visible;
z-index: 0;
}
.scroll-content,
ion-modal.show-modal,
ion-modal.show-modal .modal-wrapper,
ion-modal.show-modal .ion-page.show-modal,
ion-modal.show-modal .ion-page.show-modal > ion-content,
.ion-page.show-modal,
.ion-page.show-modal > ion-content,
ion-tab,
ion-tabs,
.app-root,
body {
contain: none;
position: relative !important;
height: auto;
overflow: visible;
}
}
I'm also trying to solve this same issue. I've scoured the Internet, and tried many an idea, but none has worked so far.
Perhaps we could solve this collaboratively. I'd put this as a comment, but I don't have enough rating points, so the system will not let me.
This is what I've found so far. In Chrome Developer Tools, you can click on a settings icon, then scroll to "Rendering," and on "Emulate CSS media type," select "print."
When I do that, it shows what the print view is. I created a separate css file, let's call it print.css, and in it, there is
#media print {
/* add your css styles for print here */
}
I know my print.css is being processed because I've
display: none
for ion-header and some tabs at the bottom, and they do disappear when I select "print" emulation in Chrome.
What is interesting is, I'm seeing the whole page -- scrollable and all -- on the screen in this print mode. However, every time I try to print it, only one page shows up.
That page, however, doesn't always start at the top. It includes the current viewport.
Which is why, I'm wondering if there is something in the css that is trying to keep the whole thing as a page. i.e., preventing a page break?
I'm experimenting with things like this:
ion-content, .foo, .bar, ion-list, ion-tabs, ion-item {
break-inside : auto !important;
break-after : auto !important;
break-before : auto !important;
}
(where foo and bar are classes you might have of your own.)
This above one breaks things. Removing ion-tabs, ion-list, and ion-item shows the full page.
I'm also experimenting with the following. None has worked so far, but that is probably because I haven't selected the right tag or class.
display: block !important;
height: 100%;
overflow-y: visible !important;
max-height: unset !important;
contain: none;
You may want to experiment with the tag in question that might be preventing a page break. Some people are suggesting it's flexbox or grid that's the root cause. I'd love to know how to find the root cause.
Good luck! If something works, let us know, so I'll also try it in my code.

Dividing a text into multiple pages

Currently, I'm creating an application where my client creates invoices and offers. To let him create an offer, I'm using CkEditor. This all works fine but he's also able to export this offer to a PDF-document. Sometimes he sees that some text divides into multiple pages. Because of the fact this sometimes happens at places he don't want this, he asked me to create a function that shows him a page divider while editing.
What I've done now is showing an image (position absolute, behind the text) on a calculated position, 1700px from top or from the last divide-image. For some reason I think this could be better, what do you think is the best way to do this?
Example:
http://i.stack.imgur.com/Q2a7w.jpg
Try if your pdf generator respects page-break-before, page-break-after and page-break-inside.
#media print {
/* Always start a chapter on new page. */
h1 { page-break-before: always; }
/* Keeps lines together */
p { page-break-inside: avoid; }
/* A custom page break element. */
/* Add styling for editing but hide visibility in the rendered document. */
hr { page-break-after: always; visibility: hidden; }
}

Printing PDF documents from Windows 8 App

I'm trying to print a PDF file from my Windows 8 app to connected printer. I'm coding with WinJS, and know that I have to create a print task to initiate printing from a Windows 8 app. So, after reviewing the documentation, I have this code:
onPrintTaskRequested: function (e) {
var self = Application.navigator.pageControl,
printTask = e.request.createPrintTask("Print Test Doc", function (args) {
args.setSource(MSApp.getHtmlPrintDocumentSource(document));
// Register the handler for print task completion event
printTask.oncompleted = self.onPrintTaskCompleted;
});
}
According to the documentation, the MSApp.getHhtmlPrintDocumentSource method accepts a specific set of data types. As stated in the documentation:
This can be the root document, the document in an IFrame, a document
fragment, or a SVG document. Be aware that htmlDoc must be a document,
not an element.
Apparently I cannot simply set the argument for getHtmlPrintDocumentSource to a .PDF or .PNG binary. So, I'm curious: does the WinJS library offer a method for printing so that I can implement the printing of a PDF file to a connected printer? Can anybody offer some tips to implement?
After trial and error, I was finally able implement the printing of a Base64 stream representing a PDF binary from a Windows 8 application.
I'm coding the app in HTML / CSS / WinJS. Essentially here is a brief explanation of how it was accomplished:
Create a new <canvas> element within the default.html file. Place it right after the open tag of the element. Like this:
<body role="application" class="app">
<canvas id="pdf-render-output"></canvas>
.
.
.
</body>
Then inside the default.css file, setup a few rules as well as a print media query. Like this:
body > canvas {
display: none;
}
.
. /* all your app's default css styles */
.
#media print {
body > * {
display:none;
max-width: 100%;
}
html {
max-width: 100%;
border-top-color: none;
border-top: 0;
}
body > canvas {
display: block;
border: none;
max-width: 100%;
width: 100%;
height: 100%;
position: relative;
}
}
Of note is the order in which the rules are declared in CSS. It's important to place the print media query after declaring default CSS rules.
After this is setup, javascript handles the rest. The basic idea is to render the PDF.js output to the "hidden" canvas in the DOM. When the document object gets sent to print, the CSS print media declaration is queried so that all elements under <body> are hidden except for the canvas element. Here is the javascript to print only the first page in the PDF:
//Define a container for the Base64 data we'll use with PDF.js
var pdfPrintData = {};
//Function to render PDF to canvas and begin printing contract with Windows 8 OS
printPrescription: function () {
var self = Application.navigator.pageControl,
printManager = Windows.Graphics.Printing.PrintManager.getForCurrentView();
self.getPDF().done(function () {
var pdfStream = pdfPrintData.base64,
pdfFile = convertDataURIToBinary(pdfStream);
PDFJS.disableWorker = true;
PDFJS.getDocument(pdfFile).then(function (pdf) {
var numPages = pdf.numPages,
renderCanvas = $('#pdf-render-output')[0];
//setup canvas
renderCanvas.height = pdf.getPage(1).data.getViewport(1).height;
renderCanvas.width = pdf.getPage(1).data.getViewport(1).width;
//Setup a render context for pdf.js to out a pdf file to the canvas.
var renderContext = {
canvasContext: renderCanvas.getContext('2d'),
viewport: pdf.getPage(1).data.getViewport(1)
};
//Bring up Windows 8 OS print after PDF is rendered to render context.
pdf.getPage(1).data.render(renderContext).then(function () {
printManager.onprinttaskrequested = self.onPrintTaskRequested;
Windows.Graphics.Printing.PrintManager.showPrintUIAsync();
});
})
});
},
onPrintTaskRequested: function (e) {
var self = Application.navigator.pageControl,
printTask = e.request.createPrintTask("Print Prescription", function (args) {
args.setSource(MSApp.getHtmlPrintDocumentSource(document));
printTask.oncompleted = self.onPrintTaskCompleted;
});
},
onPrintTaskCompleted: function (e) {
if (e.completion === Windows.Graphics.Printing.PrintTaskCompletion.failed) {
console.log("[ERX] : Failed to print!");
}
}
The self.getPDF method is just a function that retrieves the Base64 data stream, and that streams gets set on the .base64 property of the global pdfPrintData object. For some reason, I was not able to render the pdf using pdf.js to a dynamically create canvas in a dynamically created document. I had to render the output of the pdf.js render method to a canvas already present in the DOM.
As far as I know, MSApp.getHtmlPrintDocumentSource(document) is meant to be used with HTML document objects, and nothing else.
If you can assume Windows 8.1, you can try to assemble a new HTML document from your PDF file by exporting each page into a raster image using PdfPage.RenderToStreamAsync. There is a sample project in MSDN for a PDF viewer that uses this new API where you can learn how to use this method.
If you cannot assume Windows 8.1 and you need to support plain Windows 8 or Windows RT (ARM), you might need to use a third party library to create the raster images or to do the printing all together.
Amyuni PDF Creator for WinRT for example can do the printing for you. Disclaimer: I currently work for the company that develops the library

DOMPDF: page_script(): Check current page content?

I am using dompdf to generate reports which sometimes has a front page, and sometimes has some attachments. The main content has a header and a footer, but the front page and the attachments (the last 3 to 5 pages of the pdf) should not contain header and footer. I'm placing the header and footer with a inline php page_script(), like this:
<script type="text/php">
if (isset($pdf) ) {
$pdf->page_script('
if ( $PAGE_COUNT > 10 && $PAGE_NUM == 1) {
//front page footer
}else{
//other pages' header and footer
}
');
}
</script>
The whole report is built by a database engine which outputs it all as a temporary html.txt-file which is then read into DOMPDF.
Now, to recognize the front page I just have to check if the page number is = 1. If any attachments are added (which are comprised of 1000px-height jpg images, each on their own page)
Does anyone have an idea for how to identify these "attachment"-pages and get DOMPDF to not render a header and footer on those pages? Or is there any way I could check within the page_script()-script whether the current page contains only an image (or perhaps an image with a specific class or identifier)?
Thanks for any help,
David
Detecting the current page contents may be possible, but I'd have to research exactly what you can do at this level. An easier method would be if you could inject some inline script in your generated document. After the main content and before the attachments you could add something like $GLOBALS['attachments'] = true; and then add a check on the status of this variable to your conditional.
<script type="text/php">
if (isset($pdf) ) {
$pdf->page_script('
if ( $PAGE_COUNT > 10 && $PAGE_NUM == 1) {
//front page footer
}elseif ($GLOBALS['attachments']) {
//attachments actions
}else{
//other pages' header and footer
}
');
}
</script>
Of course, don't forget to initialize the variable to false at the top of the document.
(from https://groups.google.com/d/topic/dompdf/mDsYi8Efnhc/discussion)

Add a dynamic text to SP21010 Rich Text Editor when a particular Markup Style is applied

In Sharepoint 2010, I have built a custom page layout and have applied custom styles. Page layout consist of single rich text editor HTML field. Now I have a need to add some custom text next to the selected text when a particular markup Style is applied.
I can do that using jQuery once the page is saved but that is after the user has finished editing.
The requirement is for them to see the text while they are still in edit mode so that they get a true WYSIWYG experience . Below is the jQuery code I am using to display the text after page is saved:
<script type="text/javascript">
$(document).ready(function () {
$('.topicpagelayout2-styleElement-H3').wrap('<div class="hd leftcontent" />');
$('.topicpagelayout2-styleElement-H3').append('<span class="top">Top</span>');
$('.topicpagelayout2-styleElement-H3').addClass('header2');
var count=0;
$('.leftcontent').each(function(index) {
count++;
$(this).attr('id','div_'+count);
});
//$("span.ms-formfieldlabel").css("display", "none");
setLeftContent();
});
</script>
You can use use css content for this.
See this if it may give you some idea
http://www.quirksmode.org/css/content.html