I am new to iTextSharp, currently working on conversion of HTML to PDF using Html2pdf (iTextSharp extension). I am able to generate pdf but not able to add logo to pdf on every page.
Image coming but I can't change width of images.
CSS what I am using for pdf logo is below:
#page {
#top-left {
content:"test ";
background:url(../images/template/test_logo_pdf.jpg) no-repeat 0px 0px;
border:1px solid red;
background-color: #cccccc;
margin-top:10px;
}
#top-right {
content: flow(header);
}
#bottom-right {
content: "Page " counter(page) " of " counter(pages);
font: 8pt Arial, sans-serif;
}
#bottom-left {
content: string(repname);
font: 8pt Arial, sans-serif;
}
}
It's indeed not entirely easy to control dimensions of images added to the page margin boxes. One possible approach that I can suggest is to add image as a content (rather than as background-image) and make use of custom tag worker, that would specify height and width as desired for page margin box children images:
HTML:
#top-left {
content: url(../images/template/test_logo_pdf.jpg);
border:1px solid red;
background-color: #cccccc;
margin-top:10px;
}
This is Java code, however .NET version has exact same API, only differing in code style (captial letters in the beginning of method names, etc.):
private static class PageMarginBoxImagesTagWorkerFactory extends DefaultTagWorkerFactory {
#Override
public ITagWorker getCustomTagWorker(IElementNode tag, ProcessorContext context) {
if (tag.name().equals(PageMarginBoxContextNode.PAGE_MARGIN_BOX_TAG)) {
return new PageMarginBoxImagesWorker(tag, context);
}
return super.getCustomTagWorker(tag, context);
}
}
private static class PageMarginBoxImagesWorker extends PageMarginBoxWorker {
public PageMarginBoxImagesWorker(IElementNode element, ProcessorContext context) {
super(element, context);
}
#Override
public boolean processTagChild(ITagWorker childTagWorker, ProcessorContext context) {
if (childTagWorker.getElementResult() instanceof Image) {
// Or set fixed dimensions via setWidth/setHeight
((Image) childTagWorker.getElementResult()).setAutoScale(true);
}
return super.processTagChild(childTagWorker, context);
}
}
And make use of the PageMarginBoxImagesTagWorkerFactory by specifying it in ConverterProperties:
HtmlConverter.convertToPdf(htmlSrc, pdfDocument,
new ConverterProperties()
.setTagWorkerFactory(new PageMarginBoxImagesTagWorkerFactory()));
Related
I have a button web component built that I am trying to style using CSS parts. In my web component below you can see that the button is colored tomato because I have used exportparts and then in my consumer CSS I have styled it using btn-comp::part(btn) { ... }.
However, I would prefer to not have to style it using btn-comp, instead I would like to just use :root to style it like this author does.
For example I should be able to do this:
:root::part(btn) { /* my styles here */ }
But that does not work, it only works when I use the component name. How can I style my CSS parts using :root?
const template = document.createElement('template');
template.innerHTML = `<button part="btn">I should be a green button</button>`;
class BtnComp extends HTMLElement {
connectedCallback() {
this.attachShadow({mode: 'open'});
this.shadowRoot.appendChild(template.content.cloneNode(true));
const button = this.shadowRoot.querySelector("button");
button.addEventListener("click", () => alert('Clicked'));
}
}
window.customElements.define('btn-comp', BtnComp);
:root::part(btn) {
background-color: green !important; /* I want this color to be applied! */
}
btn-comp::part(btn) {
background-color: tomato;
color: white;
padding: 1rem 2rem;
border: 0;
cursor: pointer;
}
<btn-comp exportparts="btn" />
I would like to create a UiBinder feature with a button on top of an image.
Normally, image opacity=1, button opacity=0.1.
MouseOver, image opacity=0.1, button opacity=1
ImageBinder.java
public class ImageBinder extends Composite {
private static ImageBinderUiBinder uiBinder = GWT.create(ImageBinderUiBinder.class);
interface ImageBinderUiBinder extends UiBinder<Widget, ImageBinder> {
}
#UiField
Image image;
#UiField
Button button;
public ImageBinder() {
initWidget(uiBinder.createAndBindUi(this));
button.setHTML("<span class=\"fa-stack fa-lg\">\r\n" +
" <i class=\"fa fa-user-large fa-stack-1x\" aria-hidden=\"true\"></i>\r\n" +
"</span>");
}
}
ImageBinder.ui.xml
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:style>
.image {
width:400px;
opacity: 1;
height:400px;
}
.image:hover{
opacity: 0.1;
}
.image:hover .imgButton{ <------This line does not work as expected
opacity: 1;
}
.imgButton {
display: block;
width: 50px;
height: 50px;
padding: 0px 0px !important;
background: red !important;
opacity: 0.1;
}
</ui:style>
<g:HTMLPanel>
<div class="container">
<g:Image addStyleNames='{style.image}' ui:field="image" url="https://url/image.jpg></g:Image>
<div class="middle">
<g:Button ui:field="button" addStyleNames='{style.imgButton}'></g:Button>
</div>
</div>
</g:HTMLPanel>
</ui:UiBinder>
The image hover works as expected. The opacity becomes 0.1 when mouse over.
But the button does not hover at all. There is a problem for the following.
image:hover .imgButton{ <------This line does not work as expected
opacity: 1;
}
It seems that the translation from css is not that simple for UiBinder.
Thanks
If you are using UI binder correctly it will attach the styles that you define.
Have you tested it in a static HTML page, no GWT, just HTML and CSS?
If that works...
Using your browser's development tools (Chrome, Firefox), inspect the image button element and look at the classes/styles attached to it.
You should see the .imgButton class there.
But some of its styles, such as the opacity on hover, may be struck out because there is another class that you see there (e.g. from GWT's own styling) that has a higher priority.
In this situation you can try marking your style as !import to give it priority over other styles. e.g.
image:hover .imgButton {
opacity: 1 !important;
}
Or perhaps you need to be more specific: e.g.
.imgButton:hover { ...
I have created my first web application and have .html, .dart, and .css files. I want to create a modal page that will a bit smaller than my page and be centered on it. I don't really want any visible borders. The function of this page is to allow the user to display, using clickable elements, 'Help' and 'About' pages and a page that allow the user to see a list of the data files that have been collected.
I've found a couple of examples of modal pages but they are old. One appears to be easy to understand but the Dart editor flags a couple of errors and has a line that I don't understand at the head of the .dart file.
#import('dart:html'); // OK just remove the '#"
#resource('modal.css'); // ???
This example is in a blog DartBlog that does not appear to be active and did not allow me to leave a comment.
I would appreciate an help understanding the example or pointing me to working examples.
This import statement is outdated Dart syntax.
use instead
import 'dart:html';
I never saw the #resource thing and I'm sure this is not available anymore as well.
You can either put a style tag to your HTML file like
<html>
<head>
<style>
.black_overlay{
display: block;
position: absolute;
top: 0%;
left: 0%;
width: 100%;
height: 100%;
background-color: black;
z-index:1001;
-moz-opacity: 0.8;
opacity:.80;
filter: alpha(opacity=80);
}
.white_content {
display: block;
position: absolute;
top: 25%;
left: 25%;
width: 50%;
height: 50%;
padding: 16px;
border: 16px solid orange;
background-color: white;
z-index:1002;
overflow: auto;
}
</style>
</head>
<body>
</body>
</html>
or put the CSS content in a file like styles.css and import it to your HTML
<html>
<head>
<link rel='stylesheet' href='styles.css'>
</head>
<body>
</body>
</html>
I tried to update the code to current syntax (not tested though) and I added some comments
import 'dart:html';
void main() {
//setup the screen elements...
ButtonElement button = new ButtonElement();
button.text = "click me";
//add an event handler
button.onclick.listen((event) {
ModalDialog dialog = new ModalDialog("This is a <strong>message</strong>
with html formatting");
dialog.show();
});
//add the button to the screen
document.body.append(button);
//add the modal dialog stylesheet
document.head.append(getStylesheet());
}
/**
* Our modal dialog class
*/
class ModalDialog {
final DivElement _content;
final DivElement _blackOverlay;
final ButtonElement _button;
//Constructor
ModalDialog(String message) :
//constructor pre-init
_content = new DivElement(),
_blackOverlay = new DivElement(),
_button = new ButtonElement()
{
//constructor body
_content.id = "modalContent";
_content.classes.add("white_content"); //set the class for CSS
_blackOverlay.id = "modalOverlay";
_blackOverlay.classes.add("black_overlay"); //set the class for CSS
//Our message will go inside this span
SpanElement span = new SpanElement();
span.innerHTML = message;
_content.append(span);
//This is the button that will "clear" the dialog
_button.text = "Ok";
_button.onClick.listen((event) {
hide();
});
_content.append(_button);
}
//remove the modal dialog div's from the dom.
hide() {
//find the element and remove it.
//there is no list.remove(x) statement at present,
// so we have to do it manually. - UPDATE: now there is
_content.remove();
_blackOverlay.remove();
}
//add the modal dialog div's to the dom
show() {
document.body.append(_content);
document.body.append(_blackOverlay);
}
}
/**
* Utility method to get a stylesheet object
*/
getStylesheet() {
LinkElement styleSheet = new LinkElement(); // maybe
styleSheet.rel = "stylesheet";
styleSheet.type="text/css";
styleSheet.href="modal.css"; // UPDATE: you don't need to add your CSS to your HTML as shown above because it's done in this code
return styleSheet;
}
Well I've been working with some GWT code...
I'm trying to apply some Style to my Template, but when I apply CSS to Hyperlink on it, I find that a:focus method is acting as a:active, I mean it's just lasting while I press on Hyperlink but if I double click on the same Hyperlink it magically works!, I've tried with Anchor widget, but if I do this I must rewrite a lot of code and can't use History with it
I made an hypothesis about what's happening, not sure if wrong or right, I believe that as GWT uses AJAX it simply refreshes the page
.Template-link
{
COLOR: #ab1e2c;
FONT-FAMILY: Tahoma;
FONT-SIZE: 10pt;
LINE-HEIGHT: 43px;
TEXT-ALIGN: center;
TEXT-DECORATION: none;
}
.Template-link a:focus
{
COLOR: green !important;
}
So, do you have any idea of what's happening in here?
thanks in advance
More code (from Public Template)
package com.test.web.ui;
import com.foboa.fbwt.user.client.Page;
import com.foboa.fbwt.user.client.Template;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.Anchor;
import com.test.web.client.Item;
import com.test.web.client.css.TestCssBundle;
import com.test.web.client.constants.TestConstants;
import com.test.web.client.images.IconBundle;
#Singleton
public class PublicTemplate extends Template {
private final DockPanel main = new DockPanel();
private final IconBundle iconBundle;
private final TestConstants constants;
private final TestCssBundle cssBundle;
#Inject
private PublicTemplate(IconBundle iconBundle, TestConstants constants,
TestCssBundle cssBundle) {
this.iconBundle = iconBundle;
this.constants = constants;
this.cssBundle = cssBundle;
}
#Override
public final void loadPage() {
Page page = getPage();
main.add(page, DockPanel.CENTER);
main.setCellHorizontalAlignment(page,
HasHorizontalAlignment.ALIGN_CENTER);
}
#Override
public final void loadTemplate(){
main.setWidth("100%");
setWidget(main);
loadHeader();
loadFooter();
}
private void loadFooter(){
//create footer panel
HorizontalPanel footerPanel = new HorizontalPanel();
footerPanel.setWidth("100%");
//include footer content
main.add(footerPanel, DockPanel.SOUTH);
}
private void loadHeader(){
HorizontalPanel headerPanel = new HorizontalPanel();
HorizontalPanel linkPanel = new HorizontalPanel();
headerPanel.setWidth("950px");
headerPanel.setHeight("86px");
Hyperlink contact = new Hyperlink(Item.CONTACT.getLabel(),
Item.CONTACT.getTarget());
contact.setWidth("94px");
contact.addStyleName(cssBundle.testCss().testTemplateLink());
linkPanel.add(contact);
linkPanel.setHeight("43px");
headerPanel.add(linkPanel);
DOM.setStyleAttribute(linkPanel.getElement(), "backgroundImage","url(menu.png)");
headerPanel.setCellVerticalAlignment(linkPanel,
HasVerticalAlignment.ALIGN_BOTTOM);
main.add(headerPanel, DockPanel.NORTH);
}
}
What i think happening here is this,
If we use give "focus" to the Hyperlink, it now enters its :focus state(navigate to it using "Tab"). On clicking (or press space when has focus), the Hyperlink enters its (:active) state.
When you click (or press space on focus) on an element, you give it focus, which also gives the allusion that :focus and :active are the same. They are not the same. When clicked the button is in :focus:active state.
I see a missing declaration in the code that you have provided
.Template-link a:focus{}
Also try adding
.Template-link a:focus a:active{}
SOLVED
I added the following code to my Public Template
home.addClickHandler(new ClickHandler(){
public void onClick(ClickEvent event){
home.addStyleName(cssBundle.testCss().
contact.removeStyleName(cssBundle.testCss().
testTemplateLink2());
}
});
contact.addClickHandler(new ClickHandler(){
public void onClick(ClickEvent event){
home.removeStyleName(cssBundle.testCss().
testTemplateLink2());
contact.addStyleName(cssBundle.testCss().
testTemplateLink2());
}
});
for each link and also my styles are:
.Template-link
{
COLOR: #808080;
FONT-FAMILY: Tahoma;
FONT-SIZE: 10pt;
LINE-HEIGHT: 43px;
TEXT-ALIGN: center;
TEXT-DECORATION: none;
}
.Template-link a
{
COLOR: #808080;
TEXT-DECORATION: none;
VERTICAL-ALIGN:text-middle;
}
.Template-link2
{
COLOR: #AB1E2C;
FONT-FAMILY: Tahoma;
FONT-SIZE: 10pt;
LINE-HEIGHT: 43px;
TEXT-ALIGN: center;
TEXT-DECORATION: none;
}
.Template-link2 a
{
COLOR: #AB1E2C;
TEXT-DECORATION: none;
VERTICAL-ALIGN:text-middle;
}
I leave these methods and my solution just in case someonelse has the same problem.
I've read a lot of web-sites about printing page numbers, but still I couldn't make it display for my html page when I try to print it.
So the CSS code is next:
#page {
margin: 10%;
#top-center {
font-family: sans-serif;
font-weight: bold;
font-size: 2em;
content: counter(page);
}
}
I've tried to put this page rule inside
#media all {
*CSS code*
}
And outside of it, tried to put it in #media print, but nothing helped me to display the page numbers on my page. I've tried to use FireFox and Chrome(based on WebKit as you know). I think the problem is in my html or css code. Could somebody show me an example of implementing this #page rule in the big html page with several pages? I just need the code of html page and the code of css file, that works.
P.S. I have the latest supported versions of browsers.
As #page with pagenumbers don't work in browsers for now I was looking for alternatives.
I've found an answer posted by Oliver Kohll.
I'll repost it here so everyone could find it more easily:
For this answer we are not using #page, which is a pure CSS answer, but work in FireFox 20+ versions. Here is the link of an example.
The CSS is:
#content {
display: table;
}
#pageFooter {
display: table-footer-group;
}
#pageFooter:after {
counter-increment: page;
content: counter(page);
}
And the HTML code is:
<div id="content">
<div id="pageFooter">Page </div>
multi-page content here...
</div>
This way you can customize your page number by editing parametrs to #pageFooter. My example:
#pageFooter:after {
counter-increment: page;
content:"Page " counter(page);
left: 0;
top: 100%;
white-space: nowrap;
z-index: 20;
-moz-border-radius: 5px;
-moz-box-shadow: 0px 0px 4px #222;
background-image: -moz-linear-gradient(top, #eeeeee, #cccccc);
}
This trick worked for me fine. Hope it will help you.
Try to use https://www.pagedjs.org/. It polyfills page counter, header-/footer-functionality for all major browsers.
#page {
#bottom-left {
content: counter(page) ' of ' counter(pages);
}
}
It's so much more comfortable compared to alternatives like PrinceXML, Antennahouse, WeasyPrince, PDFReactor, etc ...
And it is totally free! No pricing or whatever. It really saved my life!
This javascript will add absolute positioned div's with pagenumbers on the right bottom corner and works in all browsers.
A4 height = 297mm = 1123px(96dpi)
<html>
<head>
<style type="text/css">
#page {
size: A4;
margin: 0;
}
body {
margin: 0;
}
</style>
</head>
<body>
<script type="text/javascript">
window.onload = addPageNumbers;
function addPageNumbers() {
var totalPages = Math.ceil(document.body.scrollHeight / 1123); //842px A4 pageheight for 72dpi, 1123px A4 pageheight for 96dpi,
for (var i = 1; i <= totalPages; i++) {
var pageNumberDiv = document.createElement("div");
var pageNumber = document.createTextNode("Page " + i + " of " + totalPages);
pageNumberDiv.style.position = "absolute";
pageNumberDiv.style.top = "calc((" + i + " * (297mm - 0.5px)) - 40px)"; //297mm A4 pageheight; 0,5px unknown needed necessary correction value; additional wanted 40px margin from bottom(own element height included)
pageNumberDiv.style.height = "16px";
pageNumberDiv.appendChild(pageNumber);
document.body.insertBefore(pageNumberDiv, document.getElementById("content"));
pageNumberDiv.style.left = "calc(100% - (" + pageNumberDiv.offsetWidth + "px + 20px))";
}
}
</script>
<div id="content">
Lorem ipsum....
</div>
</body>
</html>
Can you try this, you can use content: counter(page);
#page {
#bottom-left {
content: counter(page) "/" counter(pages);
}
}
Ref: http://www.w3.org/TR/CSS21/generate.html#counters
http://www.princexml.com/doc/9.0/page-numbers/
If you are looking to add page numbers when printing under Chrome/Chromium, one easy solution is to use Paged.js.
This JS library takes your HTML/CSS and cuts it into pages, ready to print as a book, that you will preview in your browser. It makes the #page and most the CSS3 specifications work for Chrome.
Solution 1 (easy) if you are OK with cutting your view into pages, ready to print
Just add their CDN in the head tag of your page :
<link href="path/to/file/interface.css" rel="stylesheet" type="text/css">
You can then add page numbers by using the automated counter page. Example :
HTML to put anywhere you want to display the current page number:
<div class="page-number"></div>
CSS to make the number appear in the div :
.page-number{
content: counter(page)
}
The library also allows to easily manage page margins, footers, headers, etc.
Solution 2 (trickier) if you want to show numbers (and page breaks) only when printing
In this case, you need to apply the Paged.js CDN only when printing the document.
One way I can think of would be to add a print me button that fires Javascript to :
add the CDN to the page
and then execute window.print(); to launch the printing prompt of the navigator
I don't know if someone still out there needs the answer, try this, it might work for you
in your html file put a div element your html like this
<div class="page-number"></div>
and do your css like this
.page-number:before {
content: "Page: " counter(page);}
hope it works for you
I know this is not a coding answer but it is what the OP wanted and what I have spent half the day trying to achieve - print from a web page with page numbers.
Print to pdf without the numbers
Run it through ilovepdf here https://www.ilovepdf.com/add_pdf_page_number which adds the page numbers
Yes, it is two steps instead of one but I haven't been able to find any CSS option despite several hours of searching. Real shame all the browsers removed the functionality that used to allow it.
This is what you want:
#page {
#bottom-right {
content: counter(page) " of " counter(pages);
}
}
I use page numbers styled in CSS to generated PDF documents, and it works:
#page {
size: A4 portrait;
margin-top: 1.2cm;
margin-bottom: 1.2cm;
margin-left: 1.2cm;
margin-right: 1.2cm;
background-image: url('../../images/logo_small.png');
background-repeat: no-repeat;
background-position: 40px 10px;
#bottom-center {
content: counter(page);
}
}
**#page {
margin-top:21% !important;
#top-left{
content: element(header);
}
#bottom-left {
content: element(footer
}
div.header {
position: running(header);
}
div.footer {
position: running(footer);
border-bottom: 2px solid black;
}
.pagenumber:before {
content: counter(page);
}
.pagecount:before {
content: counter(pages);
}
<div class="footer" style="font-size:12pt; font-family: Arial; font-family: Arial;">
<span>Page <span class="pagenumber"/> of <span class="pagecount"/></span>
</div >**