I am running some pretty heavy tables on our mobile site, in fact they are so heavy that my iphone7s completely dies for up to 20 seconds before I can start scrolling up and down (safari browser, chrome is only 10 seconds).
The tables are rather heavy on styles and the page contain 8-12 tables with 5 to 50 rows each.
My question is, would it improve the render performance if I re-wrote the page to use DIVs everywhere instead of tables? Or would I just be wasting my time?
Any suggestions from experienced devs is very welcome.
Code from one of the tables (they all pretty much follow the same code std):
<!--Invoice Table-->
<table border="0" cellspacing="0" cellpadding="0" class="start-table start-invoice-table start-invoice-hover" ng-if="vm.invoice.length > 0">
<thead>
<tr class="start-header start-bold start-invoice-bg">
<th colspan="6" class="start-padding overflow start-left">
Invoices to be paid by costumer
</th>
</tr>
<tr class="start-header start-head start-invoice-bg">
<th class="start-left nowrap" style="min-width:66px;">Property</th>
<th class="start-left overflow" style="width:30%">Tenant/Agent</th>
<th class="start-left overflow" style="width:25%">Text</th>
<th class="start-right overflow" style="width:10%">Day</th>
<th class="start-right overflow" style="width:10%">Paid</th>
<th class="start-right overflow" style="width:15%">Amount</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="invoices in vm.invoice | orderBy:'days'" class="start-text" ui-sref="book({id: invoices.booking, property: 'INVOICE', checkin: invoices._id })">
<td class="start-left start-border nowrap">
<span class="chan chan-{{ invoices.source }}">{{ invoices.source }}</span> {{ invoices.property }}
</td>
<td class="start-left start-border overflow">
<img ng-src="{{ vm.validateFlag(invoices.country) }}.png" class="start-flag">
{{ invoices.name }}
<span ng-if="invoices.agency && invoices.name.length < 15"> / {{invoices.agency}}</span>
</td>
<td class="start-left start-border overflow">{{ invoices.lineText }}</td>
<td class="start-right start-border overflow start-bold">
<span ng-class="(invoices.days) > -1 ? 'greennum' : 'rednum'"><b>{{invoices.days}}</b></span>
</td>
<td class="start-right start-border overflow">{{ invoices.receiptTotal | number }}</td>
<td class="start-right start-border overflow"><b>{{ invoices.invoiceTotal | number }}</b></td>
</tr>
</tbody>
</table>
You sometimes can speed up the rendering of tables by setting the table’s CSS property ‘table-layout’ to ‘fixed’.
The browser will then take the first row of the table to calculate the widths of all its columns. So be sure to specify the width of columns in the first row in the CSS of the header.
Because no re-calculation has to be done, this will sometimes speed up the rendering of the table as the browser can render progressively each row.
This will however break the dynamic nature of rendering and may look ugly on some other device. So you might need different CSS for different devices ...
I originally learned this from Website for Internet Explorer
Related
I am using this to create a quotation template for our online project management software (which prints it to a PDF):
<thead>
<tr>
<th colspan="2" align="right" style="width:146px" valign="top">
<img class="body_table img_logo" name="user:logo_url" src="/images/logo.jpg" />
</th>
</tr>
<tr class="address_details" style="font-weight:500;">
<th align="left"><span name="job:company">{{job.company}}</span></th>
<th align="right"><span name="user:company">{{user.company}}</span></th>
</tr>
<tr class="address_details" style="font-weight:400">
<th align="left"><span name="job:address">{{job.address}}</span></th>
<th align="right">
<span name="user:address">{{user.address}}</span>
<br/>
<span name="user:depot_email">{{user.depot_email}}</span>
<br/>
<span name="depot:telephone">{{depot.telephone}}</span>
</th>
</tr>
</thead>
So it works as intended, giving repeated branding on each printed page, but as soon as the last <span name="depot:telephone">{{depot.telephone}}</span> is added, it stops repeating on subsequent pages. It doesn't seem to be that one line though, if I comment out another random bit, it starts working. So, I assume it's a length thing.
I am too much of a newb to HTML to know what I broke, any ideas? Is there a max length that the THEAD can be?
The stuff in the "{{xxx}}}" is what draws data from the online software.
The PDF generator options are "Webkit" which doesn't seem to do the repititions right or "Chromium", which does.
I have multiple tables where I am trying to read the rows together. Here is an example table:
<table class="data-table" role="presentation">
<tr role="rowgroup">
<td role="gridcell">
<strong>Name</strong>
</td>
<td role="gridcell">
John Doe
</td>
</tr>
<tr role="rowgroup">
<td role="gridcell">
<strong>Size</strong>
</td>
<td role="gridcell">
XL
</td>
</tr>
<tr role="rowgroup">
<td role="gridcell">
<strong>Color</strong>
</td>
<td role="gridcell">
blue
</td>
</tr>
</table>
In this rendered example, This should read the first the full row "Name - John Doe". It works as intended on Chrome but fails to read the full row with IE11. Is there a reason why that is happening?
Edit, I looked into it further and it seems to happen if the table is wraped with a tag. Not sure why it is happening but at least I can repoduce the issue more consistently.
This markup is quite complex and I'm not sure what you're aiming to achieve.
This seems like a data table to me. Could you remove the role="presentation" so that the table is exposed to AT as a data table, then mark the first column up as <th> column headers, and the second column as <td> cells? That way you don't need to try and control what the screenreader says and when, and you're using semantic markup.
Most screenreader users know how to interact with data tables to extract the information they need, and trying to mask this interaction and control the user experience is unlikely to work out well.
Trust your users :-)
I'll admit, I'm not very experienced with writing code in general - I do it on a per-needed basis. Our company is researching different frameworks for writing code for emails. We stumbled across Zurb Foundation. I thought, great, it will make writing a lot less convoluted. Then, while going through the tutorials, I see this for making JUST A BUTTON:
<table align="center" class="container">
<tbody>
<tr>
<td>
<table class="row">
<tbody>
<tr>
<th class="small-12 large-12 columns first last">
<table>
<tr>
<th>
<center data-parsed="">
<table class="button float-center">
<tr>
<td>
<table>
<tr>
<td>Centered Button</td>
</tr>
</table>
</td>
</tr>
</table>
</center>
</th>
<th class="expander"></th>
</tr>
</table>
</th>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
WHY..?? Why does it seem that in coding everything has to a table within a table within a table header, within a table row, within a table cell, within a table row. It goes on forever and literally makes me angry when I look at that. I don't see why making a simple button cannot be 1 line of text, that's it.
Why does code have to be so long and convoluted for the simplest things?
Foundation Emails uses Inky - a custom template language (like all other email frameworks), which generates this for you.
https://foundation.zurb.com/emails/docs/inky.html
Emails are a different beast and if you hand write tables this is common. As Daniel pointed out, Inky is the way to avoid this mess.
EDIT: To the person who tagged this as having nothing to do with ADA. This question has everything to do with ADA. I have tons of websites with tables formatted like that which I am trying to figure out how to make them understandable to someone using a screen reader.
Hello I am trying to figure out a way to make a table which has subheadings / separator rows to announce the proper headings when being read by a screen reader.
The first table works as I would like, announcing the rowgroup's TH and then the column heading. However the second table doesn't announce as I was hoping. For example, Jill announces "Field Techs, Name, Jill" Instead of "Office, Name, Jill" as I had expected.
I've tried scope="col" and scope="colgroup" but neither helped. Is this even possible? or just a badly structured table?
Thank you for reading and any help/advice you may offer!
table thead, table th { background:#d3d3d3; }
table { margin-bottom:40px; }
<!-- This table's headings seem to work properly -->
<table width="100%" cellspacing="0" cellpadding="4" >
<thead>
<tr>
<td> </td>
<th id="name_col" scope="col" width="50%">Name</th>
<th id="position_col" scope="col" width="50%">Position</th>
</tr>
</thead>
<tbody>
<tr>
<th id="office_row" scope="rowgroup" rowspan="2">Office</th>
<td headers="office_row name_col">Jill</td>
<td headers="office_row position_col">Office Manager</td>
</tr>
<tr>
<td headers="office_row name_col">Robert</td>
<td headers="office_row position_col">Project Manager</td>
</tr>
<tr>
<th id="field_row" scope="rowgroup" rowspan="2">Field Techs</th>
<td headers="field_row name_col">Jason</td>
<td headers="field_row position_col">Tech</td>
</tr>
<tr>
<td headers="field_row name_col">Mike</td>
<td headers="field_row position_col">Tech</td>
</tr>
</tbody>
</table>
<!-- This table's headings don't announce correctly. Jill announces "Field Techs, Name, Jill"-->
<table width="100%" cellspacing="0" cellpadding="4" >
<thead>
<tr>
<th id="name_col" scope="col" width="50%">Name</th>
<th id="position_col" scope="col" width="50%">Position</th>
</tr>
<tr>
<th id="office_group" colspan="2">Office</th>
</tr>
</thead>
<tbody>
<tr>
<td headers="office_group name_col">Jill</td>
<td headers="office_group position_col">Office Manager</td>
</tr>
<tr>
<td headers="office_group name_col">Robert</td>
<td headers="office_group position_col">Project Manager</td>
</tr>
</tbody>
<thead>
<tr>
<th id="field_group" colspan="2">Field Techs</th>
</tr>
</thead>
<tbody>
<tr>
<td headers="field_group name_col">Jason</td>
<td headers="field_group position_col">Tech</td>
</tr>
<tr>
<td headers="field_group name_col">Mike</td>
<td headers="field_group position_col">Tech</td>
</tr>
</tbody>
</table>
table can only have zero or one thead element (see documentation).
Permitted contents : An optional caption element, followed by zero or more colgroup elements, followed by an optional thead element
By having multiple thead elements only the last one is considered by your browser and your screenreader. You can use ARIA attributes and roles to handle multiple separated heading lines (using for instance aria-labelledby attribute to specify the heading).
One example from WCAG:
ARIA9: Using aria-labelledby to concatenate a label from several text nodes
You are using both the scope method and header/id's method in one table, which will create problems. Also, as others have pointed out, you're using multiple <th> and <tbody> elements, which isn't good either.
I've prepared some code samples here on how to correctly code this table using both the scope method and header/id's method:
https://jsfiddle.net/oody1b8x/
It's worth noting that <th> and <tbody> are not accessibility-related elements, even though they appear to be. These are essentially only used when printing. It lets the printer know that the header rows can be repeated on the next page if the table requires pagination.
Also -- don't use ARIA for this purpose; it will only create more problems. The native HTML semantics are perfectly capable of communicating how this data is structured.
This question takes a bit of time to introduce, bear with me. It will be fun to solve if you can get there. This scrape would be replicated over thousands of pages on this website using a loop.
I'm trying to scrape the website http://www.digikey.com/product-detail/en/207314-1/A25077-ND/ looking to capture the data in the table with Digi-Key Part Number, Quantity Available etc.. including the right hand side with Price Break, Unit Price, Extended Price.
Using the R function readHTMLTable() doesn't work and only returns NULL values. The reason for this (I believe) is because the website has hidden it's content using the tag "aspNetHidden" in the html code.
For this reason I also found difficulty using htmlTreeParse() and xmlTreeParse() with the whole section parented by not appearing in the results.
Using the R function scrape() from the scrapeR package
require(scrapeR)
URL<-scrape("http://www.digikey.com/product-detail/en/207314-1/A25077-ND/")
does return the full html code including the lines of interest:
<th align="right">Digi-Key Part Number</th>
<td id="reportpartnumber">
<meta itemprop="productID" content="sku:A25077-ND">A25077-ND</td>
<th>Price Break</th>
<th>Unit Price</th>
<th>Extended Price
</th>
</tr>
<tr>
<td align="center">1</td>
<td align="right">2.75000</td>
<td align="right">2.75</td>
However, I haven't been able to select the nodes out of this block of code with the error being returned:
no applicable method for 'xpathApply' applied to an object of class "list"
I've received that error using different functions such as:
xpathSApply(URL,'//*[#id="pricing"]/tbody/tr[2]')
getNodeSet(URL,"//html[#class='rd-product-details-page']")
I'm not the most familiar with xpath but have been identifying the xpath using inspect element on the webpage and copy xpath.
Any help you can give on this would be much appreciated!
You've not read the help for scrape have you? It returns a list, you need to get parts of that list (if parse=TRUE) and so on.
Also I think that web page is doing some heavy heavy browser detection. If I try and wget the page from the command line I get an error page, the scrape function gets something usable (but seems different to you) and Chrome gets the full junk with all the encoded stuff. Yuck. Here's what works for me:
> URL<-scrape("http://www.digikey.com/product-detail/en/207314-1/A25077-ND/")
> tables = xpathSApply(URL[[1]],'//table')
> tables[[2]]
<table class="product-details" border="1" cellspacing="1" cellpadding="2">
<tr class="product-details-top"/>
<tr class="product-details-bottom">
<td class="pricing-description" colspan="3" align="right">All prices are in US dollars.</td>
</tr>
<tr>
<th align="right">Digi-Key Part Number</th>
<td id="reportpartnumber"><meta itemprop="productID" content="sku:A25077-ND"/>A25077-ND</td>
<td class="catalog-pricing" rowspan="6" align="center" valign="top">
<table id="pricing" frame="void" rules="all" border="1" cellspacing="0" cellpadding="1">
<tr>
<th>Price Break</th>
<th>Unit Price</th>
<th>Extended Price
</th>
</tr>
<tr>
<td align="center">1</td>
<td align="right">2.75000</td>
<td align="right">2.75</td>
Adjust to your use-case, here I'm getting all the tables and showing the second one, which has the info you want, some of it in the pricing table which you can get directly with:
pricing = xpathSApply(URL[[1]],'//table[#id="pricing"]')[[1]]
> pricing
<table id="pricing" frame="void" rules="all" border="1" cellspacing="0" cellpadding="1">
<tr>
<th>Price Break</th>
<th>Unit Price</th>
<th>Extended Price
</th>
</tr>
<tr>
<td align="center">1</td>
<td align="right">2.75000</td>
<td align="right">2.75</td>
</tr>
and so on.