Goal: Create a Print Preview Dialog that shows a Preview of a printable report version that can be manipulated by multiple filter options.
Requirements
In a nutshell:
Left side: preview Iframe window that displays a real new component "printable"
new information card for general information
reuse existing components (if necessary refactor them before to avoid having searchbars in print preview)
Right side: filter options with checkboxes and radio buttons to show/hide certain contents
Workarounds
I tried to comment most parts of the code that could be hard to understand or are workarounds and their reasons, but I'll try to sum up most of them here:
A4 format: We want to display an A4 format and use as much screen space as possible. Therefore we have to calculate the size each time while keeping the desired format. Do calculate this and also get the correct scaling values to fit the iFrame, i tested it by hand and for dynamic calculation used these fix values as transformation base.
Scaling and Margin of IFrame: The IFrame itself has the same proportions as the normal website. Since we just want to display it in a A4 format, we need to scale it down. CSS scaling leaves whitespaces, so we use transform-origin and negative margin to place it in the top left corner and remove the remaining whitespace
Manipulating the contents with checkboxes: Usually we would do it with if.bind or show.bind. Sadly, this approach will only manipulate the actual webpage that is displayed by the iFrame but not the actual iFrame contents. That is why I used iFrameElement.setAttribute("style", "display: none"); or iFrameElement.removeAttribute("style") for showing/hiding content.
note: since manipulation itself is not updated in the iFrame, filtering directly is a problem as well. Therefore there are multiple (differently filtered) versions of tables in the printable-component which are shown or hidden on demand - so there is no real filtering happening
Paging: A goal is to show the user which page he is scrolling to in the preview. ("Page 2/10")
whitepspaces: A problem here was, that due to apexcharts and Aurelia Mdc Components, the contents are always displayed on a new page in the browser-print preview. That means that e.g. headlines would be alone on a different page than the content it belongs to. No provided browser functionality could avoid that. This means that there are lots of white spaces in the browser print preview if the contents do not fit one A4 page perfectly - while in our print preview the contents follow each other without gaps.
To show the correct actual and total number of pages, an estimation of pixels per A4 page was made by testing. Following that, an array was created to keep track of the pixel values that mark a new page in the browser preview. If the scrolling position (page indicator) in the middle of the IFrame passes a new array entry, the page overlay is updated
note: we wanted to use snackbars for the page indicator originally, but these had massive problems with positioning (only possible with negative margin and easy to update because they disappear and are not in the DOM when they are not visible)
loading: Preparing the iFrame and loading the iFrame contents takes a while. In the meantime we want to display a progress bar as used in other components. Usually we would use if.bind or show.bind. If.bind removes the content from the DOM which is not useful when we need the sizes for calculating the iFrame size. show.bind uses display:none; which results in getBoundingClientRect to return 0, which crashes the resizing calculations as well (https://stackoverflow.com/questions/4576295/getboundingclientrect-is-returning-zero-in-xul). Aurelia proposes to overwrite the class that uses display:none but since it is added as
Description
Goal: Create a Print Preview Dialog that shows a Preview of a printable report version that can be manipulated by multiple filter options.
Requirements
In a nutshell:
Workarounds
I tried to comment most parts of the code that could be hard to understand or are workarounds and their reasons, but I'll try to sum up most of them here:
A4 format: We want to display an A4 format and use as much screen space as possible. Therefore we have to calculate the size each time while keeping the desired format. Do calculate this and also get the correct scaling values to fit the iFrame, i tested it by hand and for dynamic calculation used these fix values as transformation base.
Scaling and Margin of IFrame: The IFrame itself has the same proportions as the normal website. Since we just want to display it in a A4 format, we need to scale it down. CSS scaling leaves whitespaces, so we use
transform-origin
and negative margin to place it in the top left corner and remove the remaining whitespaceManipulating the contents with checkboxes: Usually we would do it with if.bind or show.bind. Sadly, this approach will only manipulate the actual webpage that is displayed by the iFrame but not the actual iFrame contents. That is why I used
iFrameElement.setAttribute("style", "display: none");
oriFrameElement.removeAttribute("style")
for showing/hiding content.Paging: A goal is to show the user which page he is scrolling to in the preview. ("Page 2/10")
loading: Preparing the iFrame and loading the iFrame contents takes a while. In the meantime we want to display a progress bar as used in other components. Usually we would use
if.bind
orshow.bind
. If.bind removes the content from the DOM which is not useful when we need the sizes for calculating the iFrame size.show.bind
usesdisplay:none;
which results in getBoundingClientRect to return 0, which crashes the resizing calculations as well (https://stackoverflow.com/questions/4576295/getboundingclientrect-is-returning-zero-in-xul). Aurelia proposes to overwrite the class that usesdisplay:none
but since it is added as