Generating PDF from HTML with tables and rows - ios

I am developing a simple application for creating invoices in Swift for iOS.
For this, I have a simple template HTML with tables and rows (td / tr).
I want to convert this HTML template to a multiple page PDF. It's working like a charm thanks to UIPagePrintRenderer but some rows are duplicated on two pages or the row is cut on the two pages.
I have tried to add css "page-break" on my template. I have a good placement when I print template on a web browser.
But, when I export HTML to PDF (thanks to UIPagePrintRenderer), the CSS styles were not applied on the PDF document, and my elements are duplicated.
I am looking for a better solution to convert HTML to PDF. Any one encountered a similar problem?
UPDATE :
Thanks for response guys, below more information of problem and my code.
First this is my function for convert HTML string to a PDF file.
func createPDF(formatter: UIViewPrintFormatter) -> String {
let render = CustomPrintRenderer()
render.addPrintFormatter(formatter, startingAtPageAt: 0)
formatter.maximumContentHeight = 605.0
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, CGRect.zero, nil)
for i in 0...render.numberOfPages {
UIGraphicsBeginPDFPage()
if(i != 0) {
render.setupAfterFirstPage()
}
render.drawPage(at: i, in: UIGraphicsGetPDFContextBounds())
}
UIGraphicsEndPDFContext()
pdfFilename = "\(AppDelegate().getDocDir())/Invoice-\(invoiceNumber!).pdf"
pdfData.write(toFile: pdfFilename, atomically: true)
return pdfFilename
}
Second, this is my CustomPrintRenderer() class for specified printing zone.
class CustomPrintRenderer: UIPrintPageRenderer {
// A4 Gabarit
let A4PageWidth: CGFloat = 595.2
let A4PageHeight: CGFloat = 841.8
let topPadding: CGFloat = 50.0
let bottomPadding: CGFloat = 100.0
let pageInset: CGFloat = 42.5
//let leftPadding: CGFloat = 100.0
//let rightPadding: CGFloat = 100.0
override init() {
super.init()
initFrame()
}
func initFrame() {
// Specify the frame of the A4 page.
let pageFrame = CGRect(x: 0.0, y: 0.0, width: A4PageWidth, height: A4PageHeight)
let printable = CGRect(x: 0.0, y: -topPadding, width : A4PageWidth, height: A4PageHeight - topPadding).insetBy(dx: pageInset, dy: pageInset)
self.setValue(NSValue(cgRect: pageFrame), forKey: "paperRect")
self.setValue(NSValue(cgRect: printable), forKey: "printableRect")
}
func setupAfterFirstPage() {
let printable = CGRect(x: 0.0, y: topPadding, width : A4PageWidth, height: A4PageHeight - topPadding - bottomPadding).insetBy(dx: pageInset, dy: pageInset)
self.setValue(NSValue(cgRect: printable), forKey: "printableRect")
}
}
This is my invoice on HTML (on ios app)
This is my invoice converted to PDF.
You can see on this screenshots than my items are cropped.
So, thanks to "page-break" style in css or other way, i want to display a item in next page if the element can not be placed totally on current page.
UPDATE 2 :
This is my HTML Template :
Home'Invoice - Invoice
body {
max-width:90%;
margin:auto;
padding:30px;
font-size:16px;
line-height:24px;
font-family:'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;
color:#485C74;
}
/*#media print
{
table { page-break-after:auto; }
tr.items { page-break-inside:avoid; page-break-after:auto; }
td.items { page-break-inside:avoid; page-break-after:auto; }
thead { display:table-header-group; }
tfoot { display:table-footer-group; }
}*/
/*#page {
size: A4;
margin: 0;
}
#media print {
html, body {
width: 210mm;
height: 297mm;
}
}*/
.middle {
width: 50%;
}
.invoice-box table td{
padding:5px;
vertical-align:top;
}
.logo-images img {
width:100%;
max-width:300px;
max-height:150px;
}
.invoice-box .left-pos {
text-align: left;
}
.invoice-box .center-pos {
text-align: center;
}
.invoice-box .right-pos {
text-align: right;
}
.invoice-box table thead.heading td{
background:#fab800;
border-bottom:1px solid #485C74;
font-weight:bold;
}
.invoice-box table{
width:100%;
line-height:inherit;
text-align:left;
}
.invoice-box table tr.top table td{
padding-bottom:20px;
}
.invoice-box table tr.top table td.title{
font-size:45px;
line-height:45px;
color:#485C74;
}
.invoice-box table tr.information table td{
padding-bottom:40px;
}
.invoice-box table tr.details td{
padding-bottom:20px;
}
.invoice-box table tr.item td, .invoice-box table tr.service td{
border-bottom:1px solid #eee;
}
.invoice-box table tr.item.last td, .invoice-box table tr.service.last td{
border-bottom:none;
}
.invoice-box .items-last, .invoice-box .services-last{
border-top:2px solid #485C74;
font-weight:bold;
}
footer {
text-align: center;
}
#media only screen and (max-width: 600px) {
.invoice-box table tr.top table td{
width:100%;
display:block;
text-align:center;
}
.invoice-box table tr.information table td{
width:100%;
display:block;
text-align:center;
}
}
</style>
</head>
<body>
<div class="invoice-box">
<table cellpadding="0" cellspacing="0">
<tbody>
<!-- Header Top section -->
<tr class="top">
<td colspan="5">
<table>
<tbody>
<tr>
<td class="logo-images"> <img src="data:image/png;base64, #LOGO_USER#"> </td>
<td class="right-pos">
Invoice : ##INVOICE_NUMBER#
<br>
Date : #INVOICE_DATE#
<br>
Due Date : #DUE_DATE#
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<!-- Payment section -->
<!-- Informations section -->
<tr class="information">
<td colspan="5">
<table>
<tbody>
<tr>
<td class="middle left-pos"> #SENDER_INFO# </td>
<td class="middle right-pos"> #RECIPIENT_INFO# </td>
</tr>
</tbody>
</table>
</td>
</tr>
<!-- Informations section -->
</tbody>
</table>
</div>
<div class="invoice-box">
<table cellpadding="0" cellspacing="0">
<tbody>
<!-- Payment section -->
<thead class="heading">
<td> Payment Method </td>
</thead>
<tr class="details">
<td class="left-pos"> Payment desired : #PAYMENT_METHOD# <br>
A deposit of #PAYMENT_PERCENT# must be paid when signing "good for the agreement" of this invoice, is #PAYMENT_PERCENT_PRICE#.
</td>
</tr>
</tbody>
</table>
</div>
<div class="invoice-box">
<table cellpadding="0" cellspacing="0">
<tbody>
<!-- Items section -->
<thead class="heading">
<td class="left-pos"> Item / Description </td>
<td class="center-pos"> Reference </td>
<td class="center-pos"> Quantity </td>
<td class="center-pos"> Unit cost </td>
<td class="right-pos"> Total Price (excl. tax)</td>
</thead>
#ITEMS#
<tr class="total">
<td></td>
<td></td>
<td></td>
<td></td>
<td class="right-pos items-last">
Subtotal (excl. tax) : #TOTAL_AMOUNT_HT#
<br>
Sales Tax (#VAT_RAT#) : #VAT_PRICE#
<br>
<br>
Total (incl. tax) : #TOTAL_AMOUNT_TTC#
</td>
</tr>
<!-- Items section -->
</tbody>
</table>
</div>
<footer>
<div class="footer_content">
<hr>
<p>Invoice powered By </p>
<div class="logo-images"> <img src="data:image/png;base64, #LOGO_FOOTER#"> </div>
</div>
</footer>
</body>
</html>
single_item.html :
<tr class="item">
<td class="left-pos">#ITEM_NAME# <br> #ITEM_DESC#</td>
<td class="center-pos">#ITEM_REF#</td>
<td class="center-pos">#ITEM_QUANTITY#</td>
<td class="center-pos">#ITEM_UNIT_COST#</td>
<td class="right-pos">#ITEM_TOTAL_PRICE#</td>
</tr>
last_item.html :
<tr class="item last">
<td class="left-pos">#ITEM_NAME# <br> #ITEM_DESC#</td>
<td class="center-pos">#ITEM_REF#</td>
<td class="center-pos">#ITEM_QUANTITY#</td>
<td class="center-pos">#ITEM_UNIT_COST#</td>
<td class="right-pos">#ITEM_TOTAL_PRICE#</td>
</tr>
UPDATE 3 :
When I added this code on my "item" class, these items have a good page-break but the display is bad. But whitout "display:block;" is still not work :
.item {
display:block;
page-break-inside:avoid;
page-break-after: auto;
}

Related

Selecting a specific row from a table using two text criteria (Playwright, js)

I'm having trouble using potential unique identifiers to select a specific row from a table.
Given the following table
#events {
font-family: Arial, Helvetica, sans-serif;
border-collapse: collapse;
width: 100%;
margin: 10px 0 20px 0;
}
#events td,
#events th {
border: 1px solid #ddd;
padding: 8px;
}
#events tr:nth-child(even) {
background-color: #f2f2f2;
}
#events tr:hover {
background-color: #ddd;
}
#events th {
padding-top: 12px;
padding-bottom: 12px;
text-align: left;
background-color: #04AA6D;
color: white;
}
<div>
<table id="events" class="table table-striped">
<thead>
<tr>
<th data-qaid="checkbox"><input type="checkbox" /></th>
<th data-qaid="event">Event</th>
<th data-qaid="date">Date</th>
<th data-qaid="location">Location</th>
<th data-qaid="purchase-date">Ticket Purchased</th>
</tr>
</thead>
<tbody>
<tr>
<td data-qaid="checkbox"><input type="checkbox" /></td>
<td data-qaid="event">Movie</td>
<td data-qaid="date">06/06/2022</td>
<td data-qaid="location">Frankfort</td>
<td data-qaid="purchase-date">06/06/2022</td>
</tr>
<tr>
<td data-qaid="checkbox"><input type="checkbox" /></td>
<td data-qaid="event">Concert</td>
<td data-qaid="date">06/06/2022</td>
<td data-qaid="location">Frankfort</td>
<td data-qaid="purchase-date">06/06/2022</td>
</tr>
<tr>
<td data-qaid="checkbox"><input type="checkbox" /></td>
<td data-qaid="event">Park</td>
<td data-qaid="date">06/10/2022</td>
<td data-qaid="location">Memphis</td>
<td data-qaid="purchase-date">06/06/2022</td>
</tr>
<tr>
<td data-qaid="checkbox"><input type="checkbox" /></td>
<td data-qaid="event">Concert</td>
<td data-qaid="date">06/10/2022</td>
<td data-qaid="location">Memphis</td>
<td data-qaid="purchase-date">06/06/2022</td>
</tr>
<tr>
<td data-qaid="checkbox"><input type="checkbox" /></td>
<td data-qaid="event">Sport</td>
<td data-qaid="date">06/12/2022</td>
<td data-qaid="location">Atlanta</td>
<td data-qaid="purchase-date">06/06/2022</td>
</tr>
</tbody>
</table>
</div>
<div id="change-location">
<label>New Location</label>
<input type="text" />
<button>Update Selected</button>
</div>
Using a playwright Locator, I want to be able to select the row for the Concert on 06/10/2022 and then be able to click the checkbox on that row.
I've been able to do this using a single column locator and selecting the first row encountered (using .nth(#)).
const child_locator = page.locator('[data-qaid="Event"]', { hasText: "Concert" }).nth(0);
const row_locator = page.locator("#events tbody tr", { has: child_locator });
row_locator.locator('[data-qaid="checkbox"] input').setChecked();
But this won't work, since my desired row would not be the first encountered row result.
I'd like to have something more robust / dynamic. And I'm having a hard time figuring out how to do this. I've tried various things like combining locators, using the resultant array of Locators to restrict subsequent searches. I think it comes from my understanding of Playwright locators being as complete as it can be. And I am studying the docs, but haven't figured this out yet.
I think my only real solution may be to get the text of the entire row and just regex on that. But this may have issues with false positives if the text being searched for appears in another column on a row. Such as in the given example, if I wanted to choose the Concert with Date of "06/06/2022", my regex would still select the Concert with Date "06/10/2022" since the Ticket Purchased would also match "06/06/2022"
Well, since you don't have any explicit selectors you can bind to, the only option is to reduce:
You collect all of trs.
You pick trs that have tds of kind Concert
From these, you pick trs that have tds appearing on 06/10/2022
You click on collected element(s)
Here's what I came up with:
/**
* options {{page: Page, search_array: [{column_index: number, needle: string}], tr_selector: Locator}}
*/
static async getRowByValues(options) {
// get the table data
const table_data = await options.page.locator(table_selector).allInnerTexts();
let row_index = table_data.findIndex( (row_text) => {
const text_array = row_text.split("\t");
// loop through the search_array data and match to text_array
for (const col_data of options.search_array) {
// fail immediately if false, continue if true.
if (text_array[col_data.column_index] !== col_data.needle) {
return false;
}
}
return true;
});
if (row_index >= 0) {
return options.page.locator(tr_selector).nth(row_index);
} else {
return null;
}
}
And to use this, one could do:
const desired_row = await getRowByValues({
page: page,
search_array: [
{
column_index: 1,
needle: "Concert"
},
{
column_index: 2,
needle: "06/10/2022"
}
],
tr_selector: page.locator('#events tbody tr')
});
if (desired_row) {
await desired_row.locator('[data-qaid="checkbox"] input').setChecked(true);
await expect(desired_row.locator('[data-qaid="checkbox"] input')).toBeChecked();
}

print specific div from the page position cant controled

i have html page
<table class='table table-responsive table-hover table-responsive sortable draggable' id='print' border='5'>
<thead>
<tr class='warning'>
<td>head1 <a class='delete'>delete</a></td>
<td>head2 <a class='delete'>delete</a></td>
<td>head3 <a class='delete'>delete</a></td>
</tr>
</thead>
<tbody>
<tr>
<td>body1 body1 body1dfsffffffffffffffffffffffff </td>
<td>body2</td>
<td>body3</td>
</tr>
<tr>
<td>body4</td>
<td>body5</td>
<td>body6</td>
</tr>
<tr>
<td>body7</td>
<td>body8</td>
<td>body9</td>
</tr>
</tbody>
<tfoot>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</tfoot>
</table>
and when i need to print the page i just want to print the table
i used this css ..
#media print
{
body *
{
visibility: hidden;
}
#print, #print *
{
visibility: visible;
}
#print
{
position: absolute;
left: 0;
top: 0;
}
}
and when i print the screen the table come in the center not in the top 0px
how cound i let the table be absolute;
its not working
thank you

Can't set innerHTML of a div with Html.Action("_TaskDetail", "ProTask")

In a Click handler I am trying to set the innerHTML of a div(detail_popup) with a MvcHtmlString.
MvcHtmlString Bobo = #Html.Action("_TaskDetail", "ProTask");
Note: _TaskDetail is a partial view.
If I look at Bobo in debug using the HTML visualizer it is perfect.
I then assign innerHTML as such: detail_popup.innerHTML = #Bobo;
This generates a script error ... SCRIPT1002: Syntax error
I am about to lose my gourd! Any help would be much appreciated.
Bob
This is the MvcHtmlString Bobo whose assignment gives me script errors:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Details</title>
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
font: 12px Nautilus Pompilius;
}
th, td {
padding: 3px;
text-align: left;
}
table#t01 {
width: 35%;
background-color: #ffd800;
}
</style>
</head>
<body>
<div>
11/23/2016 1:08:14 PM
<table id="t01">
<tr>
<th>Name</th>
<th>Description</th>
<th>Owner</th>
</tr>
<tr>
<td>Excavate Foundation</td>
<td>Trench will be 36 inches deep by 25 inches wide</td>
<td>Robert L. Wells</td>
</tr>
<tr>
<th>Duration</th>
<th>Completion</th>
<th>Options</th>
</tr>
<tr>
<td>12:00:00</td>
<td>50%</td>
<td>7</td>
</tr>
<tr>
<th>Revision DT</th>
<th>Project ID</th>
<th>Task ID</th>
</tr>
<tr>
<td>5/29/2016 12:00:00 PM</td>
<td>15</td>
<td>7</td>
</tr>
<tr>
<th>StartDateAct</th>
<th>StartDateSched</th>
</tr>
<tr>
<td>6/9/2016 1:15:00 PM</td>
<td>6/9/2016 1:15:00 PM</td>
</tr>
<tr>
<th>FinishDateAct</th>
<th>FinishDateSched</th>
</tr>
<tr>
<td>6/12/2016 1:15:00 PM</td>
<td>6/12/2016 1:15:00 PM</td>
</tr>
<tr>
<th>EstIntCost</th>
<th>EstExtCost</th>
<th>EstTotCost</th>
</tr>
<tr>
<td>20.00</td>
<td>14.00</td>
<td>34.00</td>
</tr>
<tr>
<th>ActIntCost</th>
<th>ActExtCost</th>
<th>ActTotCost</th>
</tr>
<tr>
<td>0.00</td>
<td>0.00</td>
<td>0.00</td>
</tr>
<tr>
<th>BudIntCost</th>
<th>BudExtCost</th>
<th>BudTotCost</th>
</tr>
<tr>
<td>20.00</td>
<td>14.00</td>
<td>34.00</td>
</tr>
<tr>
<th>SurIntCost</th>
<th>SurExtCost</th>
<th>SurTotCost</th>
</tr>
<tr>
<td>0.00</td>
<td>0.00</td>
<td>0.00</td>
</tr>
</table>
</div>
</body>
</html>
I have pulled my hair out
Following is an abbreviated version of my partial view:
#model PromanV3.Models.ProTask
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Details</title>
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
font: 12px Nautilus Pompilius;
}
th, td {
padding: 3px;
text-align: left;
}
table#t01 {
width: 35%;
background-color: #ffd800;
}
</style>
</head>
<body>
<div>
#System.DateTime.Now
<table id="t01">
<tr>
<th>Name</th>
<th>Description</th>
<th>Owner</th>
</tr>
<tr>
<td>#Html.DisplayFor(model => model.TaskName)</td>
<td>#Html.DisplayFor(model => model.TaskDesc)</td>
<td>#Html.DisplayFor(model => model.TaskOwnerName)</td>
</tr>
<tr>
<th>Duration</th>
<th>Completion</th>
<th>Options</th>
</tr>
<tr>
<td>#Html.DisplayFor(model => model.Duration)</td>
<td>#Html.DisplayFor(model => model.CompPercentage)%</td>
<td>#Html.DisplayFor(model => model.TaskOptions)</td>
</tr>
<tr>
<th>Revision DT</th>
<th>Project ID</th>
<th>Task ID</th>
</tr>
<tr>
<td>#Html.DisplayFor(model => model.RevisionDT)</td>
<td>#Html.DisplayFor(model => model.ProjectId)</td>
<td>#Html.DisplayFor(model => model.TaskId)</td>
</tr>
</table>
</div>
</body>
</html>
The is my div
<!-- Begin section that generates the detail popup for the task -->
<div id="DetailBox"
style="display: none;
z-index: 1000;
border: 2px solid blue;
background: yellow;
fill: white;
color: black;
padding-left: 8px;
padding-right: 8px;
padding-top: 3px;
padding-bottom: 3px;
position: absolute;
font: 14px Nautilus Pompilius;
width: 150px;
height: 65px;
">
<script>
#{
ViewBag.vwbProject = 15;
if (ViewBag.vwbTask==null)
{ViewBag.vwbTask = 1;}
}
</script>
</div>
This is my click handler:
function setMouseClickmt(xpos, ypos, width, height, message)
{
function inner()
{
var MultTxtBoxID = this.node.getAttribute("id"); // 'this' refers to the clear_rect (clear rectangle) of the SVG MultTxtBox
var MultTxtBoxElement = document.getElementById(MultTxtBoxID); // grab the element
var task_ID = MultTxtBoxElement.getAttribute("id");
var detail_popup = document.getElementById('DetailBox');
var task_index = getTaskPos(task_ID, arr_of_Tasks);
detail_popup.setAttribute('data-task',task_index);
detail_popup.setAttribute('data-project',15);
var tt = detail_popup.getAttribute('data-task');
var pp = detail_popup.getAttribute('data-project');
var ldt = new Date();
var ldts = ldt.toLocaleString();
//detail_popup.innerHtml = ldts + '</br>' + tt ;
#{
MvcHtmlString Bobo = #Html.Action("_TaskDetail", "ProTask");
};
detail_popup.innerHTML = #Bobo;
/* Make the 'DetailBox' div appear */
detail_popup.style.display = 'block';
detail_popup.style.top = (100) + 'px';// '400px';//works//mTop + 'px';
detail_popup.style.left = (1200) + 'px';// //works//mLeft + 'px';
detail_popup.style.width = 250;//width;
detail_popup.style.height = 500;//height;
}
return inner;
}
This is the script output that it chokes on:
detail_popup.innerHTML =
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Details</title>
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
font: 12px Nautilus Pompilius;
}
th, td {
padding: 3px;
text-align: left;
}
table#t01 {
width: 35%;
background-color: #ffd800;
}
</style>
</head>
<body>
<div>
11/23/2016 1:21:34 PM
<table id="t01">
<tr>
<th>Name</th>
<th>Description</th>
<th>Owner</th>
</tr>
<tr>
<td>Excavate Foundation</td>
<td>Trench will be 36 inches deep by 25 inches wide</td>
<td>Robert L. Wells</td>
</tr>
<tr>
<th>Duration</th>
<th>Completion</th>
<th>Options</th>
</tr>
<tr>
<td>12:00:00</td>
<td>50%</td>
<td>7</td>
</tr>
<tr>
<th>Revision DT</th>
<th>Project ID</th>
<th>Task ID</th>
</tr>
<tr>
<td>5/29/2016 12:00:00 PM</td>
<td>15</td>
<td>7</td>
</tr>
<tr>
<th>StartDateAct</th>
<th>StartDateSched</th>
</tr>
<tr>
<td>6/9/2016 1:15:00 PM</td>
<td>6/9/2016 1:15:00 PM</td>
</tr>
<tr>
<th>FinishDateAct</th>
<th>FinishDateSched</th>
</tr>
<tr>
<td>6/12/2016 1:15:00 PM</td>
<td>6/12/2016 1:15:00 PM</td>
</tr>
<tr>
<th>EstIntCost</th>
<th>EstExtCost</th>
<th>EstTotCost</th>
</tr>
<tr>
<td>20.00</td>
<td>14.00</td>
<td>34.00</td>
</tr>
<tr>
<th>ActIntCost</th>
<th>ActExtCost</th>
<th>ActTotCost</th>
</tr>
<tr>
<td>0.00</td>
<td>0.00</td>
<td>0.00</td>
</tr>
<tr>
<th>BudIntCost</th>
<th>BudExtCost</th>
<th>BudTotCost</th>
</tr>
<tr>
<td>20.00</td>
<td>14.00</td>
<td>34.00</td>
</tr>
<tr>
<th>SurIntCost</th>
<th>SurExtCost</th>
<th>SurTotCost</th>
</tr>
<tr>
<td>0.00</td>
<td>0.00</td>
<td>0.00</td>
</tr>
</table>
</div>
</body>
</html>
;
Please try this...
From the razor page, pass the value of Model (#Bobo) to your JS file
<script>
var tempValue = '#Bobo';
setMouseClickmt(tempValue , yourOtherValues....);
</script>
and assign the value passed in your click handler in your JS
detail_popup.innerHTML = tempValue ;
Add the single quotes around #Bobo when you use it in the script tag of the razor page.
Hope it helps

IOS 8 ignoring my Media Queries

I've built a responsive email however, on IOS8 (in Apple mail client and in phones browser) the media queries are being ignored. Note: this is across all the IOS 8 iPhones
I've not provided a JSFIDDLE as it doesn't really work for emails since the code is all in one place.
Email can be found here
http://news.yfish.co.uk/e/9F640D904C5C4FC1AAD220AFAE5C37B3/4/preview/
<!DOCTYPE HTML>
<html>
<head>
<title>Rugby World Cup 2015</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<meta content="width=device-width, initial-scale=1" name="viewport" />
<style type="text/css">
#outlook a { padding: 0; }
.ReadMsgBody { width: 100%; } .ExternalClass { width:100%; }
.ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div { line-height: 100%; }
body, table, td, a { -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }
table, td { mso-table-lspace: 0pt; mso-table-rspace: 0pt; }
img { -ms-interpolation-mode: bicubic; }
body { margin: 0; padding: 0; }
img { border: 0; height: auto; line-height: 100%; outline: none; text-decoration: none; }
table { border-collapse: collapse!important; }
body { height: 100%!important; margin: 0; padding: 0; width: 100%!important; background-color: #e6e6e7; }
a:visited { color: #ffffff; }
#media screen {
#font-face {
font-family: 'humanst';
src: url(http://news.yfish.co.uk/repository/news.yfish.co.uk/34/14553/HUM521N-webfont.eot);
src: url(http://news.yfish.co.uk/repository/news.yfish.co.uk/34/14553/HUM521N-webfont.eot?#iefix) format('embedded-opentype'),
url(http://news.yfish.co.uk/repository/news.yfish.co.uk/34/14553/HUM521N-webfont.woff2) format('woff2'),
url(http://news.yfish.co.uk/repository/news.yfish.co.uk/34/14553/HUM521N-webfont.woff) format('woff'),
url(http://news.yfish.co.uk/repository/news.yfish.co.uk/34/14553/HUM521N-webfont.ttf) format('truetype'),
url(http://news.yfish.co.uk/repository/news.yfish.co.uk/34/14553/HUM521N-webfont.svg#humanst521_btroman) format('svg');
font-weight: normal;
font-style: normal;
}
}
#fade {
-webkit-animation: fadeIn 1.5s forwards;
-moz-animation: fadeIn 1.5s forwards;
-o-animation: fadeIn 1.5s forwards;
animation: fadeIn 1.5s forwards;
}
#-webkit-keyframes fadeIn {
0% {opacity: 0; }
70% {opacity: 0; }
100% {opacity: 1; }
}
#-moz-keyframes fadeIn {
0% {opacity: 0; }
70% {opacity: 0; }
100% {opacity: 1; }
}
#-o-keyframes fadeIn {
0% {opacity: 0; }
70% {opacity: 0; }
100% {opacity: 1; }
}
#keyframes fadeIn {
0% {opacity: 0; }
70% {opacity: 0; }
100% {opacity: 1; }
}
#fadeUp {
-webkit-animation: imagefadeInUp 2s 0.8s forwards;
-moz-animation: imagefadeInUp 2s 0.8s forwards;
-o-animation: imagefadeInUp 2s 0.8s forwards;
animation: imagefadeInUp 2s 0.8s forwards;
visibility: hidden!important;
}
#-webkit-keyframes imagefadeInUp {
0% {opacity: 0; -webkit-transform: translateY(50px);}
50% {opacity: 0; -webkit-transform: translateY(50px); visibility: visible; }
100% {opacity: 1; -webkit-transform: translateX(0); visibility: visible;}
}
#-moz-keyframes imagefadeInUp {
0% {opacity: 0; -moz-transform: translateY(50px);}
50% {opacity: 0; -moz-transform: translateY(50px); visibility: visible;}
100% {opacity: 1; -moz-transform: translateX(0); visibility: visible;}
}
#-o-keyframes imagefadeInUp {
0% {opacity: 0; -o-transform: translateY(50px);}
50% {opacity: 0; -o-transform: translateY(50px); visibility: visible;}
100% {opacity: 1; -o-transform: translateX(0); visibility: visible;}
}
#keyframes imagefadeInUp {
0% {opacity: 0; transform: translateY(50px);}
50% {opacity: 0; transform: translateY(50px); visibility: visible;}
100% {opacity: 1; transform: translateX(0); visibility: visible;}
}
#media screen and (max-width: 600px), and screen (max-device-width: 600px) {
body { width: auto!important; }
table[class="fullWidth"] { width: 100%!important; }
table[class="contentWidth"] { width: 90%!important; }
td[class="center"] { text-align: center!important; }
table[class="centerTable"] { display: block!important; float: none!important; margin: 0 auto!important; }
td[class="fullCell"] { display: block!important; float: none!important; width: 100%!important; }
td[id="padding"] { padding-bottom: 20px!important; }
}
#media screen and (max-width: 520px), and screen (max-device-width: 520px) {
table[class="mainTitle"] { width: 95%!important; }
img[class="imgScale"] { width: 100%!important; height: auto!important; }
}
#media screen and (max-width: 480px), and screen (max-device-width: 480px) {
td[class="mobileCell"] { display: block!important; float: left!important; width: 100%!important; padding: 0!important; }
td[class="mobileHide"] { display: none!important; }
table[class="logoCenter"] { display: block!important; float: none!important; margin: 0 auto!important; margin-bottom: 20px!important; }
table[class="gifScale"] { width: 95%!important; }
}
#media screen and (max-width: 370px), and screen (max-device-width: 370px) {
table[class="mobileTitle"] { width: 90%!important; }
}
</style>
</head>
<body bottommargin="0" leftmargin="0" marginheight="0" marginwidth="0" rightmargin="0" topmargin="0" bgcolor="#e6e6e7">
<table width="100%" cellpadding="0" cellspacing="0" border="0" align="center" bgcolor="#e6e6e7" style="background-color: #e6e6e7;"><!-- wrapper -->
<tr>
<td bgcolor="#e6e6e7">
<table width="100%" cellpadding="0" cellspacing="0" border="0">
<tr>
<td valign="top" bgcolor="#595959">
<table width="99%" cellpadding="0" cellspacing="0" border="0" align="left" bgcolor="#595959"><!-- header -->
<tr>
<td height="25">
</td>
</tr>
<tr>
<td width="33%" style="padding-left: 20px;" class="mobileCell">
<table width="105" cellpadding="0" cellspacing="0" border="0" align="left" class="logoCenter">
<tr>
<td>
<img src="http://news.yfish.co.uk/repository/news.yfish.co.uk/34/14553/logo.png" width="105" height="36" alt="THINK OUTSIDE THE TANK" border="0" style="display: block; border: 0;" class="img-scale">
</td>
</tr>
</table>
</td>
<td width="33%" align="center" class="mobileCell">
<table width="91" cellpadding="0" cellspacing="0" border="0" align="center"><!-- social -->
<tr>
<td>
<img src="http://news.yfish.co.uk/repository/news.yfish.co.uk/34/14553/facebook.png" width="13" height="21" alt="Like us on Facebook" border="0" style="display: block; border: 0;">
</td>
<td width="20">
</td>
<td>
<img src="http://news.yfish.co.uk/repository/news.yfish.co.uk/34/14553/twitter.png" width="22" height="15" alt="Follow us Twitter" border="0" style="display: block; border: 0;">
</td>
<td width="20">
</td>
<td>
<img src="http://news.yfish.co.uk/repository/news.yfish.co.uk/34/14553/mail.png" width="16" height="11" alt="Contact us!" border="0" style="display: block; border: 0;">
</td>
</tr>
</table><!-- end social -->
</td>
<td width="33%" style="font-family: 'humanst', arial, helvetica, sans-serif; font-size: 11px; color: #ffffff; line-height: 15px; text-align: right; vertical-align: middle; padding-right: 20px;" valign="middle" class="mobileHide">
It's a crime, not to view online
</td>
</tr>
<tr class="block">
<td height="25">
</td>
</tr>
</table><!-- end header -->
</td>
</tr>
<tr>
<td bgcolor="#ffc216">
<table width="100%" cellpadding="0" cellspacing="0" border="0" align="center" bgcolor="#ffc216">
<tr>
<td height="50">
</td>
</tr>
<tr>
<td align="center">
<table width="680" cellpadding="0" cellspacing="0" border="0" align="center" class="contentWidth">
<tr>
<td align="center">
<table width="505" cellpadding="0" cellspacing="0" border="0" align="center" class="mainTitle">
<tr>
<td>
<img src="http://news.yfish.co.uk/repository/news.yfish.co.uk/34/14553/title.png" width="505" height="61" alt="Rugby World Cup" style="display: block; border: 0;" class="imgScale" id="fade">
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td height="25">
</td>
</tr>
<tr>
<td align="center">
<table width="437" cellpadding="0" cellspacing="0" border="0" align="center" class="gifScale">
<tr>
<td>
<img src="http://news.yfish.co.uk/repository/news.yfish.co.uk/34/14553/flag.gif" width="437" height="233" alt="Rugby" style="display: block; border: 0;" class="imgScale" id="fadeUp">
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td height="30">
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td height="25">
</td>
</tr>
<tr>
<td align="center">
<table width="680" cellpadding="0" cellspacing="0" border="0" align="center" bgcolor="#ffffff" class="fullWidth">
<tr>
<td height="50" bgcolor="#ffffff">
</td>
</tr>
<tr>
<td bgcolor="#ffffff">
<table width="356" cellpadding="0" cellspacing="0" border="0" align="center" class="mobileTitle">
<tr>
<td>
<img src="http://news.yfish.co.uk/repository/news.yfish.co.uk/34/14553/titletwo.png" width="356" height="52" alt="Join us on the 19th September" style="display: block; border: 0;" class="imgScale">
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td height="25" bgcolor="#ffffff">
</td>
</tr>
<tr>
<td style="font-family: georgia, verdana, sans-serif; font-size: 18px; line-height: 22px; color: #424242; text-align: center; font-style: italic;" bgcolor="#ffffff">
Your V.I.P invitation
</td>
</tr>
<tr>
<td height="25" bgcolor="#ffffff">
</td>
</tr>
<tr>
<td bgcolor="#ffffff">
<table width="520" cellpadding="0" cellspacing="0" border="0" align="center" class="contentWidth">
<tr>
<td style="font-family: 'humanst', arial, helvetica, sans-serif; font-size: 13px; line-height: 17px; color: #424242; text-align: left;" class="center">
Previewer I’d love if you could join me at our Yellow Fish table for an afternoon and night of hospitality, Yellow Fish style!<br><br>
Aside of full hospitality and category A seats at the fabulous AMEX stadium, I’d like to invite you to stay overnight in Brighton, provide you with transfers to/from the match, enjoy a bit of Brighton nightlife and then brunch on Sunday before you head off. All you have to do is get to Brighton!<br><br>
Kick off is at 16:45 so I’d plan for being in to Brighton around lunch time and once I have more information I’ll firm up details.
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td height="25" bgcolor="#ffffff">
</td>
</tr>
<tr>
<td align="center" bgcolor="#ffffff">
<table width="520" cellpadding="0" cellspacing="0" border="0" align="center" class="contentWidth">
<tr>
<td width="50%" valign="top" class="fullCell" id="padding">
<table width="248" cellpadding="0" cellspacing="0" border="0" align="left" class="centerTable">
<tr>
<td>
<img src="http://news.yfish.co.uk/repository/news.yfish.co.uk/34/14553/attending.png" width="248" height="45" alt="I can attend" style="display: block; border: 0;">
</td>
</tr>
</table>
</td>
<td width="50%" valign="top" class="fullCell">
<table width="248" cellpadding="0" cellspacing="0" border="0" align="right" class="centerTable">
<tr>
<td>
<img src="http://news.yfish.co.uk/repository/news.yfish.co.uk/34/14553/unable.png" width="248" height="45" alt="I'm unable to attend" style="display: block; border: 0;">
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td height="25" bgcolor="#ffffff">
</td>
</tr>
<tr>
<td bgcolor="#ffffff">
<table width="520" cellpadding="0" cellspacing="0" border="0" align="center" class="contentWidth">
<tr>
<td style="font-family: 'humanst', arial, helvetica, sans-serif; font-size: 13px; line-height: 17px; color: #424242; text-align: left;" class="center">
It should be great fun, a great game watching the Bokkers in Brighton and I really hope you can join me.<br><br>
Best
</td>
</tr>
<tr>
<td>
</td>
</tr>
<tr>
<td>
<table width="112" cellpadding="0" cellspacing="0" border="0" align="left" class="centerTable">
<tr>
<td>
<img src="http://news.yfish.co.uk/repository/news.yfish.co.uk/34/14553/maria.png" width="112" height="33" alt="Maria" style="display: block; border: 0;">
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td height="100" bgcolor="#ffffff">
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td height="25">
</td>
</tr>
<tr>
<td bgcolor="#595959">
<table width="680" cellpadding="0" cellspacing="0" border="0" align="center" bgcolor="#595959" class="fullWidth"><!-- footer -->
<tr>
<td height="25">
</td>
</tr>
<tr>
<td align="center">
<table width="105" cellpadding="0" cellspacing="0" border="0" align="center">
<tr>
<td>
<img src="http://news.yfish.co.uk/repository/news.yfish.co.uk/34/14553/logo.png" width="105" height="36" alt="THINK OUTSIDE THE TANK" border="0" style="display: block; border: 0;">
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td height="25">
</td>
</tr>
<tr>
<td style="font-family: arial, helvetica, sans-serif; font-size: 11px; line-height: 15px; color: #ffffff; text-align: center;">
Tel +44 (0) 1273 223 500 | Fax +44 (0) 1273 323 257 | contact#yfish.co.uk<br><br>
Copyright © 2014 Yellow Fish
</td>
</tr>
<tr>
<td height="25">
</td>
</tr>
</table><!-- end footer -->
</td>
</tr>
</table>
</td>
</tr>
</table><!-- end wrapper -->
</body>
</html>
I've tried removing all other queries and also tried altering Query widths. No luck!
Thanks in advance
Unfortunately, nobody has been able to provide me with a solution.
Fortunately, I have figrued it out. IOS 8 DOES NOT like commas in media queries.
When removing the comma:
#media screen and (max-width: 480px), and screen (max-device-width: 480px) {}
to
#media screen and (max-width: 480px) and screen (max-device-width: 480px) {}
This fixes everything. However, the comma did not cause issues on IOS 7

ASP.NET MVC Razor engine show three data in each row?

In the ASP.NET MVC Razor engine I want to show three data entries in each row so I write this:
<table width="100%" border="0" cellspacing="22" cellpadding="0" style="line-height:18px;">
<tr>
<td align="center" valign="top">
<table border="0" cellspacing="0" cellpadding="0">
<tr>
#{
int counter = 0;
foreach (MVCTaranehMah.Models.Folder item in ViewBag.items)
{
counter++;
if(counter%3 == 0)
{
<tr>
}
<td width="205" height="180" align="center" valign="top"><br />
<p align="center" valign="top" class="header3">#item.title</p>
</td>
#if(counter%3 == 0)
{
</tr>
}
}
}
</tr>
</table>
</td>
</tr>
</table>
But I get this error
The code block is missing a closing "}" character. Make sure you have a matching "}" character for all the "{" characters within this block, and that none of the "}" characters are being interpreted as markup.
What's the problem and how can I do something like this?
I think the code does not like that you seemingly have unclosed HTML tags.
Place before the tr, #:
Remove # from the front of the other if statement.
For example:
if (counter%3 == 0)
{
#:<tr>
}
Rather than trying to force the list into a table, you could just render it as a list:
<ul class="thumbs">
#foreach (var item in ViewBag.Items)
{
<li>
<a href="galleryDetails?id=#item.id">
<img src="#Url.Content(item.thumb)">
#item.title
</a>
</li>
}
</ul>
Styling the list to display with three items per row is trivial. Start here, and tweak it as needed:
ul.thumbs {
overflow: hidden;
}
ul.thumbs li {
float: left;
width: 205px;
height: 180px;
margin: 22px;
text-align: center;
}
ul.thumbs img {
width: 173px;
height: 173px;
border: 0;
}

Resources