How to manage the overflow data in itext 7 when using canvasrenderer - c#-4.0

I am using iText 7 to generate pdf file from html file which is saved in a database.
I used the following code to generate pdf, but half of a table which is inside the html file is ignored. I guess the size of IBlockElement which contains the table is bigger than the size of canvas.
Any ideas how to solve the issue?
List<IElement> elements = (List<IElement>)HtmlConverter.ConvertToElements(html);
for (int k = 0; k < elements.Count; k++)
{
if (!renderer.IsFull())
{
canvas.Add((IBlockElement)elements[k]);
}
else
{
page = pdfDoc.AddNewPage();
pdfCanvas = new PdfCanvas(page.NewContentStreamBefore(), page.GetResources(),pdfDoc);
rectangle = new Rectangle(offset, offset, pageWidth, pageHeight);
pdfCanvas.Rectangle(rectangle);
pdfCanvas.Stroke();
canvas = new iText.Layout.Canvas(pdfCanvas, pdfDoc, rectangle);
renderer = new MyCanvasRenderer(canvas);
canvas.SetRenderer(renderer);
}
}
Implementation of MyCanvasRenderer:
class MyCanvasRenderer : CanvasRenderer {
protected bool full = false;
public MyCanvasRenderer(Canvas canvas) : base(canvas) {
}
public override void AddChild(IRenderer renderer) {
base.AddChild(renderer);
full = true.Equals(GetPropertyAsBoolean(Property.FULL));
}
public bool IsFull() {
return full;
}
}

Canvas class is primarily aimed at cases when you need to add elements to a specific predefined area on a page / XObject and it is not aimed at overflowing your content to next areas.
As the described use case is just converting HTML to PDF, the appropriate API to use is another method of HtmlConverter which allows you to convert HTML to PDF in one line:
HtmlConverter.ConvertToPdf(html, pdfWriter);
UPD: clarifications on additional requirements from #Saeed
Different margins for the first page
CSS allows you to specify page margins with #page media, and those declarations are picked up by pdfHTML. Here is an example of page margins specification and how to customize them for the first page:
#page {
margin-top: 100pt;
margin-left: 36pt;
margin-right: 36pt;
margin-bottom: 36pt;
}
#page:first {
margin-top: 100pt;
margin-left: 36pt;
margin-right: 36pt;
margin-bottom: 36pt;
}
Avoiding splitting of a table across several pages
CSS has page-break-inside property that controls page-wise appearance of elements. In particular, you are interested in page-break-inside: avoid; declaration that prevents splitting of an element across pages.
You could apply this declaration to all tables in your document:
table {
page-break-inside: avoid;
}
Alternatively, you can create your own class and apply it only whenever necessary:
.avoid-page-breaks {
page-break-inside: avoid;
}
<table class="avoid-page-breaks">
...
</table>
Third option is to apply this style to a table inline:
<table style="page-break-inside: avoid;">
...
</table>

Related

Chrome extension tooltip over text(one word)

I'd like to implement a tooltip dictionary chrome extension. When the user hover the mouse over a chunk or a word in text, It should show the block selection or change its background color and show the tooltip under the word.
How can I implement it?
I just did similar thing with background like this:
core.js
// Unique ID for the className.
var MOUSE_VISITED_CLASSNAME = 'crx_mouse_visited';
// Previous dom, that we want to track, so we can remove the previous styling.
var prevDOM = null;
// Mouse listener for any move event on the current document.
document.addEventListener('mousemove', function (e) {
var srcElement = e.srcElement;
// Lets check if our underlying element is a DIV.
if (srcElement.nodeName == 'DIV' || srcElement.nodeName == 'SPAN') {
// For NPE checking, we check safely. We need to remove the class name
// Since we will be styling the new one after.
if (prevDOM != null) {
prevDOM.classList.remove(MOUSE_VISITED_CLASSNAME);
}
// Add a visited class name to the element. So we can style it.
srcElement.classList.add(MOUSE_VISITED_CLASSNAME);
// The current element is now the previous. So we can remove the class
// during the next iteration.
prevDOM = srcElement;
}
}, false);
core.css
.crx_mouse_visited {
background-color: #bcd5eb !important;
outline: 1px solid #5166bb !important;
}

Javascript issue in Inventory Transfers and Receipts

i have added a new unbound field to display image of Inventory Item in Transaction Details tab, then to set the fixed height of the image I have added some javascript, but after adding javascript the screen is not populating any default values into like RefNbr and Date, Below is the javascript code am using. The same javascript code is working on my custom screen.
<px:PXJavaScript runat="server" ID="CstJavaScript1" Script="var css = '.GridRow > img { width: 100%; height: 40px; }', head = document.head || document.getElementsByTagName('head')[0], style = document.createElement('style'); style.type = 'text/css'; if (style.styleSheet){ style.styleSheet.cssText = css; } else { style.appendChild(document.createTextNode(css)); } head.appendChild(style);" />
Earlier I have added Javascript inside the tab item, but now I moved out of the Tab when it was working without issues.
</px:PXTab>
<px:PXJavaScript runat="server" ID="CstJavaScript1" Script="var css = '.GridRow > img { width: 100%; height: 40px; }', head = document.head || document.getElementsByTagName('head')[0], style = document.createElement('style'); style.type = 'text/css'; if (style.styleSheet){ style.styleSheet.cssText = css; } else { style.appendChild(document.createTextNode(css)); } head.appendChild(style);" />

Selecting a LI element from Dropdown

I'm having problems with my data driven coded-ui test. I'm supposed to replace the info typed in the test with csv data.
I can succesfully replace login and password inputs with the csv data.. but I'm failing to replace a selected LI in the test with it's csv data.
I don't know how to select the LI since it seems to be a custom generated control element but I may be drifting.
The HTML looks like this:
<div id="cphCont_cphContAut_ddlTipoJur" class="ComboAzul" style="display:inline-block;">
<table id="cphCont_cphContAut_ddlTipoJur_ddlTipoJur_Table" class="ajax__combobox_inputcontainer" style="border-width:0px;border-style:None;border-collapse:collapse;display:inline-block;position:relative;top:5px;" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td class="ajax__combobox_textboxcontainer">
<input name="ctl00$ctl00$cphCont$cphContAut$ddlTipoJur$ddlTipoJur_TextBox" id="cphCont_cphContAut_ddlTipoJur_ddlTipoJur_TextBox" tabindex="3" autocomplete="off" style="width: 260px; margin: 0px;" type="text">
</td>
<td class="ajax__combobox_buttoncontainer">
<button style="height: 18px; width: 18px; margin: 0px; padding: 0px; visibility: visible;" id="cphCont_cphContAut_ddlTipoJur_ddlTipoJur_Button" type="button"></button>
</td>
</tr>
</tbody>
</table>
<ul id="cphCont_cphContAut_ddlTipoJur_ddlTipoJur_OptionList" class="ajax__combobox_itemlist" style="visibility: hidden; z-index: 1000; overflow: hidden; width: 310px; position: absolute; height: 133px; left: 638px; top: 425px; display: none;">
<li style=""> </li>
<li style="">Cons / Ou</li>
<li style="">Coop</li>
<li style="">Empr Ind</li>
<li style="">Req E</li>
<li>Soc A</li>
<li>Soc E</li>
</ul>
<input name="ctl00$ctl00$cphCont$cphContAut$ddlTipoJur$ddlTipoJur_HiddenField" id="cphCont_cphContAut_ddlTipoJur_ddlTipoJur_HiddenField" value="0" type="hidden">
</div>
In the UIMap.Designer.cs the UL ( I believe ) look like this:
[GeneratedCode("Coded UITest Builder", "12.0.21005.1")]
public class UICphCont_cphConteCustom : HtmlCustom
{
public UICphCont_cphContCustom(UITestControl searchLimitContainer) :
base(searchLimitContainer)
{
#region Search Criteria
this.SearchProperties["TagName"] = "UL";
this.SearchProperties["Id"] = "cphCont_cphContAut_ddlTipoJur_ddlTipoJur_OptionList";
this.SearchProperties[UITestControl.PropertyNames.Name] = null;
this.FilterProperties["Class"] = "ajax__combobox_itemlist";
this.FilterProperties["ControlDefinition"] = "class=\"ajax__combobox_itemlist\" id=\"cphC";
this.FilterProperties["TagInstance"] = "1";
this.WindowTitles.Add("Test");
#endregion
}
Selected LI element looks like this:
public HtmlCustom UISocaCustom
{
get
{
if ((this.mUISocaCustom == null))
{
this.mUISocaCustom = new HtmlCustom(this);
#region Search Criteria
this.mUISocaCustom.SearchProperties["TagName"] = "LI";
this.mUISocaCustom.SearchProperties["Id"] = null;
this.mUISocaCustom.SearchProperties[UITestControl.PropertyNames.Name] = null;
this.mUISocaCustom.FilterProperties["Class"] = null;
this.mUISocaCustom.FilterProperties["ControlDefinition"] = null;
this.mUISocaCustom.FilterProperties["InnerText"] = "Soc A";
this.mUISocaCustom.FilterProperties["TagInstance"] = "6";
this.mUISocaCustom.WindowTitles.Add("tEST");
#endregion
}
return this.mUISocaCustom;
}
}
The code I'm using to replace the login and password with the csv data is :
public void MetdG()
{
this.UIMap.TesterParams.UITxtLoginEditText = TestContext.DataRow["login"].ToString();
this.UIMap.TesterParams.UITxtSenhaEditPassword = Playback.EncryptText(TestContext.DataRow["senha"].ToString());
this.UIMap.Tester();
// To generate code for this test, select "Generate Code for Coded UI Test" from the shortcut menu and select one of the menu items.
}
Any idea on how to proceed ?
Edit : As instructed by Ryan Cox
It was created a static class to hold the browser window :
[CodedUITest]
public static class GlobalVars
{
public static BrowserWindow myWindow;
}
Test Initializer method was edited to match this change :
[TestInitialize()]
public void BrowserStarter()
{
GlobalVars.myWindow = BrowserWindow.Launch(new Uri("www.google.com"));
}
MainG method was edited so the window could execute the script :
GlobalVars.myWindow.ExecuteScript("var xpath = li[text()='Soca'];var matchingElement = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;);matchingElement.innerHTML = arguments[0];", TestContext.DataRow["type"].ToString());
Now the problem is that the script is throwing an exception. I believe it's because it's searching for the element before it exists ( The test goes thru 2 or 3 pages before this point )
What you're trying to do is change the inner html on a list item, not enter text as you would in your <input> elements, so you'll need to execute a script to do this and modify the DOM. Since it's not a normal action for a user (click on this, enter text there, expand this combo box, etc.), you'll have to use javascript to complete it.
browserWindow.ExecuteScript("var elements = document.getElementsByTagName('li')
for (var i = 0; i < elements.length; i++) {
if (elements[i].innerHTML.indexOf("Soc A") !== -1) {
elements[i].innerHTML = arguments[0];
break;
}
}", TestContext.DataRow["type"].ToString());
//Comment to fill space
Of course, if you had an id on your list items, this would be even easier:
browserWindow.ExecuteScript("document.getElementById("Soc A list item").innerHTML = arguments[0];", TestContext.DataRow["type"].ToString());
Major props to Ryan Cox for all the help he provided yesterday !
The issue got solved with by adding this line of code :
this.UIMap.TestWindow.TestDocument5.UIContCustom.UISocaCustom.
SearchProperties[HtmlCustom.PropertyNames.InnerText] =
TestContext.DataRow["type"].ToString();
Being TestDocument5 the 5th page in the test ( as intended ), UIContCustom the UL element and UISocaCustom the custom HTML element the test generated.
It is worth noting that trying to change the value of InnerText through GetProperty will fail since it will spit out a read-only message.

display icons in p:column filteroptions

i'm trying to display icons as filterOptions on my p:datatable.
the current situation is that i display a list of unicode symbols , but the client wants them to be colorful.
the code below shows how i fill my list of states (my filter options) in my backingbean.
private static final String LABEL_DEACTIVATED = "\u24E7";
private static final String LABEL_ACTIVATED = "\u2714";
private void fillSelectItem() {
userStates = new SelectItem[3];
userStates[0] = new SelectItem("", LABEL_ALL);
userStates[1] = new SelectItem(USER_ACTIVATED.name(), LABEL_ACTIVATED);
userStates[2] = new SelectItem(USER_DEACTIVATED.name(),
LABEL_DEACTIVATED);
}
You could use CSS to style each individual icon, as long as your target browser supports CSS2 attribute selectors (ie. almost all modern browsers). Put the following in your css file:
option[value='USER_ACTIVATED'] {
/* for example */
background-image: url(.....);
background-color: #123456;
color: #123123;
}
option[value='USER_DEACTIVATED'] {
/* for example */
background-image: url(.....);
background-color: #888111;
color: #222222;
}

Select drop down menu for nav on collapse

I’m not a fan of the collapsed 3 line nav button when bootstrap collapses for smaller viewports. Is there a way to get the navbar collapse to a select drop down menu, as well as place it somewhere else on the page, other than in the top right? Just like this: http://filamentgroup.com/examples/rwd-nav-patterns/
Looking at what happens on the filamentgroup site, you can see that below a certain width, the body gets the class nav-menu and removes if when sized larger. This is their rwd-nav.js complete with comments:
jQuery(function($){
$('.nav-primary')
// test the menu to see if all items fit horizontally
.bind('testfit', function(){
var nav = $(this),
items = nav.find('a');
$('body').removeClass('nav-menu');
// when the nav wraps under the logo, or when options are stacked, display the nav as a menu
if ( (nav.offset().top > nav.prev().offset().top) || ($(items[items.length-1]).offset().top > $(items[0]).offset().top) ) {
// add a class for scoping menu styles
$('body').addClass('nav-menu');
};
})
// toggle the menu items' visiblity
.find('h3')
.bind('click focus', function(){
$(this).parent().toggleClass('expanded')
});
// ...and update the nav on window events
$(window).bind('load resize orientationchange', function(){
$('.nav-primary').trigger('testfit');
});
});
Then in their rwd-nav.css, this repositions based on width
/* Media queries
------------------------------ */
#media screen and (min-width: 640px) {
.nav-primary,
.nav-primary ul {
float: left;
}
.nav-primary ul {
float: left;
}
.nav-primary li {
float: left;
font-size: 1.5em;
border-bottom: 0;
}
}
#media screen and (min-width: 910px) {
.nav-primary {
float: right;
clear: none;
}
}
Hope that helps!

Resources