I have the following code in my component.ts file on one particular page, because that page needs to use it's own css for when the page is printed:
#Component({
selector: "dashboard",
templateUrl: "./dashboard.component.html",
styleUrls: ["./dashboard.component.scss"],
encapsulation: ViewEncapsulation.None
})
However, when i navigate off that page, i want the encapsulation to go back to normal for everywhere else. Is there a way to do this?
Or is there a way to only set the encapsulation when the print button is clicked? And then when closed it goes back to normal?
If I navigate away from this page and refresh, then the other pages go back to normal, but I don't want to have to refresh.
EDIT
I had to add in the encapsulation in order to get the page to print landscape using this code in the scss file:
#media print {
#page {
size: landscape
}
.no-print,
.no-print * {
display: none !important;
}
body {
-webkit-print-color-adjust: exact;
}
canvas {
max-width: 100%;
height: auto;
}
.printClass {
display: inline-block;
}
}
Otherwise, it would just take the global scss and print portrait every time.
Yes. In this example we use ngx-print. This is a library you can see on GitHub. You do not use it, but it is using the right way and it is very straight forward.
npm install ngx-print
Using
<!--
1)- Add an ID here
-->
<div id="print-section">
<!--Your html stuff that you want to print-->
</div>
<!--
2)- Add the directive name in your button (ngxPrint),
3)- Affect your ID to printSectionId
-->
<button printSectionId="print-section" ngxPrint>print</button>
You can set things in css. Here is a sample:
When I do not apply css using [useExistingCss]="true", the Layout dropdown option (portrait or landscape) is present when trying to print.
My css contains a #media print{#page {size: landscape}} line, but it seems to be ignored by ngx-print.
If I use {size: landscape !important}, it will print in landscape.
If I use {size: auto !important}, the Layout option is provided.
Here is the heart of it:
public print(): void {
let printContents, popupWin, styles = '', links = '';
const baseTag = this.getElementTag('base');
if(this.useExistingCss) {
styles = this.getElementTag('style');
links = this.getElementTag('link');
}
printContents = this.getHtmlContents();
popupWin = window.open("", "_blank", "top=0,left=0,height=auto,width=auto");
popupWin.document.open();
popupWin.document.write(`
<html>
<head>
<title>${this.printTitle ? this.printTitle : ""}</title>
${baseTag}
${this.returnStyleValues()}
${this.returnStyleSheetLinkTags()}
${styles}
${links}
</head>
<body>
${printContents}
<script defer>
function triggerPrint(event) {
window.removeEventListener('load', triggerPrint, false);
${this.previewOnly ? '' : `setTimeout(function() {
closeWindow(window.print());
}, ${this.printDelay});`}
}
function closeWindow(){
window.close();
}
window.addEventListener('load', triggerPrint, false);
</script>
</body>
</html>`);
popupWin.document.close();
Related
On load and if browser width is greater than 540px, the modal containing an image is cut-off (see figure below). What should I do to make the vertical scroll-bar immediately appear?
This existing project that I'm working on is using tingle modal plug-in. It is linked like so:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="tingle.min.css">
<style>
html, body {
height: 100%;
}
img {
height: auto;
width: 100%;
}
</style>
<title>Tingle Modal</title>
</head>
<body>
<script src="tingle.min.js"></script>
<script src="modal.js"></script>
</body>
</html>
modal.js is where I create the modal containing the image:
function createModal(content) {
let $modal = new tingle.modal({
footer: false,
stickyFooter: false,
closeMethods: ["overlay", "button", "escape"],
closeLabel: "Close",
cssClass: ["modal"],
beforeClose: function() {
return true; // close the modal
},
onClose: function() {
$modal.destroy();
}
});
$modal.setContent(content);
$modal.open();
}
createModal("<div id='modal'><img id='sample' src='sample.jpg' /></div>");
console.log(document.getElementById("sample").offsetHeight);
I noticed that when you zoom-in or zoom-out, or resize the browser, I then get the expected behavior of having the scroll-bar. I also noticed that on load, the image height is 0. I can't set the image height to a pixel value because I'll have several modals containing different images that vary on sizes.
You can also see the behavior here: CodeSandbox. Please do make the embedded browser width in CodeSandbox bigger first, then refresh to see what I mean.
I have tried the following. But it then adds the scroll bar even when the entire modal fits in 100vh, which is not desirable.
.tingle-modal {
overflow-y: scroll;
}
Try adding these styles
.tingle-modal {
overflow-y: auto;
}
If you need to save the position of the close button, then add:
.tingle-modal__close {
position: sticky;
align-self: end;
}
And instead of
createModal("<div id='modal'><img src='sample.jpg' /></div>");
use it
const img = new Image();
img.onload = () => {
createModal("<div id='modal'><img src='sample.jpg' /></div>");
};
img.src = "sample.jpg";
I looked at the code in tingle.min.js. It checks if the height of the modal overflows, if so, it adds a tingle-modal--overflow class. However, the image isn't loaded yet when it checked the height. So I had to redo the checking after calling the createModal function like so:
document.getElementsByTagName("img")[0].onload = function() {
const $modal = document.getElementsByClassName("tingle-modal")[0];
if (window.innerHeight <= $modal.clientHeight)
$modal.classList.add("tingle-modal--overflow");
};
Here's a jQuery version of the solution:
$(".tingle-modal-box img").on("load", function() {
const $modal = $(".tingle-modal");
if (window.innerHeight <= $modal.height())
$modal.addClass("tingle-modal--overflow");
});
ref: Display helpers
Is there a way to change differrent css style dynamically depend on size of current breakpoint.
Something like when windows are current on xs size/position/color are differ from md and so on....
For vuetify utility classes, you insert the breakpoint in the class name. pa-2 defaults for xs and up, to change it to pa-4 from md breakpoint up, you apply both pa-2 and pa-md-4 to your element. Same goes for all other predefined utility classes for spacing, text, colors, etc.
For applying your own classes in vue without repeating the breakpoint settings in each component (and duplicating/decentralising breakpoint management), you can either:
Set classes dynamically with a computed property that returns a string of classes based on the value of this.$vuetify.breakpoint
<template>
<div :class="userCardClasses" />
</template>
<script>
export default {
...
computed: {
userCardClasses() {
if (this.$vuetify.breakpoint.mdAndUp) return 'userCard userCard--md'
// You can check the value of the helpers (mdAndUp) or write a switch/case for this.$vuetify.breakpoint.name
return 'userCard userCard--xs'
}
}
}
</script>
<style>
.userCard {
padding: 8px;
}
.userCard--xs {
background-color: blue;
}
.userCard--md {
background-color: red;
}
</style>
Import Vuetify breakpoint variables in your component and use them when writing media queries.
<style lang="scss">
#import '~vuetify/src/styles/styles.sass';
.custom-class {
display: block
}
#media #{map-get($display-breakpoints, 'md-and-down')}
.custom-class {
display: none;
}
</style>
Please consider the following hidden div element. I am using it as a hidden element to construct the PDF contents and trying to download as PDF.
HTML elements declared as below.
<div id="griddata" style="display:none;">
<div id="reportHeader" style="display:none;">
Consider other elements that I want to show in the PDf here
</div>
</div>
And below is the Kendo Export chart as PDF code, Which I will call through the LoadPDF function.
function LoadPDF() {
try {
$("#griddata").show();
$("#reportHeader").show();
if ($("#chartDiv").html() != null && $("#griddata").html() != '') {
setTimeout(function () {
kendo.drawing.drawDOM($("#griddata"))
.then(function (group) {
// Render the result as a PDF file
return kendo.drawing.exportPDF(group, {
paperSize: "auto",
margin: { left: "1cm", top: "1cm", right: "1cm", bottom: "1cm" }
});
})
.done(function (data) {
// Save the PDF file
kendo.saveAs({
dataURI: data,
fileName: window.sessionStorage.getItem('XXXName') + ".pdf",
proxyURL: "/Account/Export"
});
$("#reportHeader").hide();
$("#griddata").hide();
});
}, 2000);
}
}
catch (e) {
$("#reportHeader").hide();
$("#griddata").hide();
UMGenerateAlert('Error while exporting data');
}
finally {
}
}
The above method works fine, but the problem is, before exporting the "griddata" div elements as PDF, I am forced to ENABLE the div. Otherwise the exported PDF returns no data. This causing the "griddata" div to appear on the screen till the PDF gets exported and gets hidden once the document is downloaded.
Please suggest me how we can handle this, without displaying it in the UI.
Try CSS Print Media Query:
#media print {
/* All your print styles go here */
#header, #footer, #nav { display: none !important; }
#griddata, #reportHeader { display: block !important; }
}
Or the old way:
<link href="/print.css" rel="stylesheet" media="print" type="text/css" />
Regarding the grid part, have you already tried using visibility: hidden;? since the space and dimensions of the element are preserved.
If I were you, I would just show an overlay layer with a loading progress bar that covers the grid area and hide it after finish hidding the grid.
Anyway, display: none is still part of the DOM, I'll update my answer if there is a workaround.
I just came across similar question myself couple days ago and got it working based on this answer, which is to overlay your pdf div with another div. Here render-pdf is the div where your kendo pdf gets loaded.
<div id="pdf-with-overlay" style="position: relative; width: 100%;">
<div id="render-pdf"></div>
<div id="pdf-overlay" style="width:100%;height:100%;position: absolute;top:0;left:0;z-index:10;"></div>
</div>
PS. In the scenario I mention I do an overlay instead of hiding, as found hiding also has some limitations e.g. if you want to draw pdf to canvas, hidden one will show no content.
I have been trying to get a report that we have built with jasperreports and rendered via visualize.js to be centered horizontally on a page (regardless of the page or browser dimensions).
My current code is:
<!DOCTYPE html>
<html>
<head>
<script src="https://mobiledemo.jaspersoft.com/jasperserver-pro/client/visualize.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mootools/1.5.1/mootools-core-full-compat.min.js"></script>
<script type='text/javascript'>
window.addEvent('load', function() {
visualize({
auth: {
name: "joeuser",
password: "joeuser",
organization: "organization_1"
}
}, function(v) {
//render dashboard from provided resource
v("#container").report({
resource: "/public/Samples/Reports/06g.ProfitDetailReport",
scale: "container",
error: handleError
});
//show error
function handleError(err) {
alert(err.message);
}
});
});
</script>
<style>
html,
body {
height: 100%;
width: 100%;
margin: 0 auto;
background-color: #000000;
}
#container {
display: block;
width: 100%;
height: 100%;
border: 0px;
margin: 0 auto;
background: blue;
}
</style>
</head>
<body>
<div id="container"></div>
</body>
</html>
The following fiddle should show the current issue:
https://jsfiddle.net/g207h68x/
If you resize the result window, you can see that as the report is scaled (via the scale:"container" entry in the render function it sticks to the left of the screen.
I can't use any specific sizes for the <div> as each dashboard has their own unique dimensions depending on what is being displayed in the report or dashboard (some may be 300x500 and others may be up to 1920x1080).
I have tried to wrap the <div> inside flexboxes which didn't seem to help..unless I was not doing it correctly (entirely possible).
Another approach was to try and nest the div within a parent div, but that didn't seem to work either (again, I may have not done it correctly either).
I have also tried to make the <div> an inline-block, but that seems to throw off the scaling entirely for visualize.js as it reads the container dimensions (I think).
I looked into the visualize.js documentation, but there is really not much there for dynamic sizing and spacing on the page.
I even tried to put the <div> within a table...but that didn't seem to help as the table cells would just span across the page or container.
I did read somewhere that the JQuery UI can be used to further manipulate what visualize.js is doing, but I could not find any examples or references on where that was documented.
If anyone knows how to center this type of content, I would greatly appreciate your input.
Thank you in advance.
The centering does not work in your jsfiddle because the report gets scaled inside the container and its transform-origin is set to top left. To overcome most of the issues I have come up with the following script based on the one you posted.
The main idea is to add some margins to the ".jrTable" table with the beforeRender event, then to intercept the CSS transform-origin from within visualize.js and set the new one.
Please note that this is not a complete script and does not work on some narrow window setups. I did not run it on a dashboard either.
You will have to decide when to set this new origin based on some measurements. Also, the jQuery's cssHook will probably need adjustments for different vendor prefixes if you intend to target other browsers. I tested it only in Chrome and Safari with the default one. More info on jQuery cssHooks.
EDIT: It seems that the initial solution based on changing the margin and the transform-origin produces unpredictable results and does not scale correctly in all cases. Keeping it for reference here, though.
Better results can be achieve just by adjusting the offset after the transform-origin is applied:
window.addEvent('load', function() {
var hookRegistered = new $.Deferred();
var $container = $("#container");
function adjustPageOffset($jrPage) {
var pageWidth = $jrPage[0].getBoundingClientRect().width,
containerWidth = $container.width();
(pageWidth<containerWidth) ? $jrPage.offset({left:(containerWidth-pageWidth)/2}) : $jrPage.offset({left:0});
}
__visualize__.require(["jquery"], function($) {
$.cssHooks["transformOrigin"] = {
set: function( elem, value ) {
elem.style["transformOrigin"] = value;
if ($(elem).is(".jrPage") && "top left" === value) {
adjustPageOffset($(elem));
}
}
};
hookRegistered.resolve();
});
// wait for the hook to register in visualize's embedded jQuery
// then load the report
hookRegistered.then(function() {
visualize({
auth: {
name: "joeuser",
password: "joeuser",
organization: "organization_1"
}
}, function (v) {
//render dashboard from provided resource
v("#container").report({
resource: "/public/Samples/Reports/06g.ProfitDetailReport",
scale: "container",
error: handleError
});
//show error
function handleError(err) {
alert(err.message);
}
});
});
});
And the modified jsfiddle.
app.js
$stateProvider.state('tenant.propertyGoogleMap', {
url: '/PropertyGoogleMap',
templateUrl: '~/App/tenant/views/propertymanagement/propertyGoogleMap.cshtml',
menu: 'PropertyGoogleMap.Tenant'
});
JS
Here I have loaded the new browser window tab when user clicks the button.
vm.propertyGoogleMap = function () {
var url = $state.href('tenant.propertyGoogleMap', {}, { absolute: false });
$window.open(url, '_blank');
};
propertyGoogleMap.cshtml
<div ng-controller="tenant.views.propertymanagement.propertyGoogleMap as vm">
<style type="text/css">
.angular-google-map-container {
height: 400px;
}
</style>
<div class="row">
<ui-gmap-google-map center="vm.map.center" zoom="vm.map.zoom" options="vm.options"></ui-gmap-google-map>
</div>
</div>
So my question is,could you tell me how can I load the new tab window without the layout page details ? I mean without menus and etc.. If I want, I can load angular and other related js files on that page (propertyGoogleMap.cshtml) manually.Thanks.
Note : The problem here is, when I use new window tab then it is being loaded whole application with the layout page and etc. If I can stop that then I think this should work.So how can I do that ?
I have tried with #{Layout = null;} also.But no luck :(
I just need to remove it from the above mentioned page.So I have used CSS to do so :D
.page-sidebar-wrapper, .page-header, .page-footer {
display: none !important;
}