Optimize website to show reader view in Firefox - firefox

Firefox 38.0.5 added a "Reader View" to the address bar:
But not all sites get this icon, It only appears when readable content page is detected. So how do I enable this for my site?
I tried media print and an extra stylesheet for print-view, but that has no effect:
<html>
<head>
<style>
#media print { /* no effect: */
.no-print { display:none; }
}
</style>
<!-- no effect either:
<link rel="stylesheet" href="print.css" media="print"><!-- -->
</head><body>
<h1>Some Title</h1>
<img class="no-print" src="http://dummyimage.com/1024x100/000/ffffff&text=This+banner+should+vanish+in+print+view">
<br><br><br>This is the only text
</body></html>
What code snippets do I have to add into my website sourcecode so this book icon will become visible to the visitors of my site?

As the code stands in May '20 the trigger function (isProbablyReaderable) scores only p or pre elements and div elements that contain at least one decedent br.
A slight oversimplification of the scoring heuristic is:
For each element in ['p', 'pre', 'div > br']:
If textContent length is > 140 chars, increase score by sqrt(length - 140)
if cumulative score > 20, return true

You have to add <div> or <p> tags to achieve a page to iniciate the ReaderView.
I created a simple html that works:
<html>
<head>
<title>Reader View shows only the browser in reader view</title>
</head>
<body>
Everything outside the main div tag vanishes in Reader View<br>
<img class="no-print" src="http://dummyimage.com/1024x100/000/ffffff&text=This+banner+should+vanish+in+print+view">
<div>
<h1>H1 tags outside ot a p tag are hidden in reader view</h1>
<img class="no-print" src="http://dummyimage.com/1024x100/000/ffffff&text=This+banner+is resized+in+print+view">
<p>
123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
123456789 123456
</p>
</div>
</body>
</html>
This is the minimum needed to activate it. This is a somewhat multi-faceted process where scores are added for text chunks.
You can for example activate the reader view in forum's software if you add a <p>-tag around each message block in the view-posts template.
Here are some more details about the mechanism

Related

creating new element and adding it to parent element

I'm trying to add a new paragraph to a document using document.createElement. It's not working for me.
HTML file:
<section class="first">
<h2>Properties Tutorial</h2>
<p>No, no, no. A vigilante is just a man lost in scramble for his own gratification. He can be destroyed or locked up. But if you make yourself more than just a man, if you devote yourself to an ideal and if they can't stop you then you become something
else entirely. Legend, Mr Wayne.</p>
<h2 class="second-heading">I am the DOM</h2>
<p>You know what you said about the structures becoming shackles. You were right and I can't take it, the injustice. I mean, no one ever's gonna know who saved the entire city.</p>
<img class="custom-img" src="" alt="Kitty image" />
</section>
JS file:
const newP = document.createElement('p');
.first.appendChild('newP');
newP.textContent = 'Say my name!';
console.log(newP);
I expect for the element to be created with document.createElement, text to be added with element.textContent and for the element to be added to the children of the section with class of "first" through the appendChild method.
From the snippet you post, you mistyped:
.first.appendChild('newP');
It should have been:
document.getElementsByClassName('first')[0].appendChild(newP)
Try this:
const newP = document.createElement('p');
newP.innerHTML = 'Say my name!'
document.getElementsByClassName('first')[0].appendChild(newP);
<section id="first" class="first">
<h2>Properties Tutorial</h2>
<p>No, no, no. A vigilante is just a man lost in scramble for his own gratification. He can be destroyed or locked up. But if you make yourself more than just a man, if you devote yourself to an ideal and if they can't stop you then you become something
else entirely. Legend, Mr Wayne.</p>
<h2 class="second-heading">I am the DOM</h2>
<p>You know what you said about the structures becoming shackles. You were right and I can't take it, the injustice. I mean, no one ever's gonna know who saved the entire city.</p>
<img class="custom-img" src="" alt="Kitty image" />
</section>
you can try below code
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<section class="first">
<h2>Properties Tutorial</h2>
<p>No, no, no. A vigilante is just a man lost in scramble for his own gratification. He can be destroyed or locked up. But if you make yourself more than just a man, if you devote yourself to an ideal and if they can't stop you then you become somethingelse entirely. Legend, Mr Wayne.</p>
<h2 class="second-heading">I am the DOM</h2>
<p>You know what you said about the structures becoming shackles. You were right and I can't take it, the injustice. I mean, no one ever's gonna know who saved the entire city.</p>
<img class="custom-img" src="" alt="Kitty image" />
</section>
<button id="add">Add Paragraph</button>
<script type="text/javascript">
var first = document.getElementsByClassName('first')[0],
add = document.getElementById('add');
add.onclick = function(){
var p = document.createElement('p');
p.textContent = "Say my name!";
first.appendChild(p);
}
</script>
</body>
</html>
The button will produce tag p inside class first with appendChild method.

Laravel 5.7 View Render Bug on Paragraph

Seems there's a problem on Laravel 5.7.11 view when rendering <p> element that contains child node.
Check the following code:
return view("main");
main.blade.php
<html>
<body>
<p><div>Inside Div</div></p>
<p><h5>Inside H5</h5></p>
<p>Just Plain Text</p>
</body>
</html>
Here's the output of the code:
<html class="gr__localhost">
<head></head>
<body data-gr-c-s-loaded="true">
<p></p><div>Inside Div</div><p></p>
<p></p><h5>Inside H5</h5><p></p>
<p>Just Plain Text</p>
</body>
</html>
It seems that view cannot render <p> that has child nodes since it was able to render <p> containing plain text only while both <div> and <h5> got rendered outside <p>
I tried with different elements and only <p> has this problem.
Did anyone encounter this already?
<div> tag inside a <p> tag is not a valid HTML. From HTML spec:
A p element’s end tag may be omitted if the p element is immediately followed by an address, article, aside, blockquote, details, div, dl, fieldset, figcaption, figure, footer, form, h1, h2, h3, h4, h5, h6, header, hr, main, menu, nav, ol, p, pre, section, table, or ul, element, or if there is no more content in the parent element and the parent element is an HTML element that is not an a, audio, del, ins, map, noscript, or video element.
Source
The closing <\p> tag is likely added by your browser, not Laravel. Same applies to heading elements.

Does source binding require a single root element even for non-arrays?

The documentation on source binding has an aside which states:
Important: A single root element should be used in the template when
binding to an array. Having two first level DOM elements will result
in an erratic behavior.
However, I'm finding that this is the case even for non arrays.
I have the following HTML, which sets up two div's populated by two templates. The only difference is that the working template wraps that databound spans in a div.
<html>
<head>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://cdn.kendostatic.com/2013.3.1119/js/kendo.all.min.js"></script>
<title>JS Bin</title>
<script id="broken-template" type="text/x-kendo-template">
Foo: <span data-bind="text: foo"></span><br/>
Foo Again: <span data-bind="text: foo"></span>
</script>
<script id="working-template" type="text/x-kendo-template">
<div>
Foo: <span data-bind="text: foo"></span><br/>
Foo Again: <span data-bind="text: foo"></span>
</div>
</script>
</head>
<body>
<div id="broken-div" data-template="broken-template" data-bind="source: this">
</div>
<br/>
<br/>
<div id="working-div" data-template="working-template" data-bind="source: this">
</div>
</body>
</html>
And the JavaScript simply creates a view model with a single property and binds it to both divs:
var viewModel = kendo.observable({foo: "bar"});
kendo.bind($("#broken-div"), viewModel);
kendo.bind($("#working-div"), viewModel);
In both cases, only the first root element and it's children are being bound properly. This suggests that every time I databind to template with more than one element I need to make sure it is wrapped in a single root.
Is this behavior documented somewhere? Is there a bug in Kendo or in my sample code? An explanation for why Kendo requires a single root would be great to hear as well.
(Sample code as a jsfiddle)
It's not documented except in the one place you mentioned. Such is the state of Kendo UI documentation - it's less than complete. I've been using Kendo UI for three years and as far as I can tell you, this is its default behavior and not a bug. Unfortunately, it's one of the many quirks you simply learn (stumble upon) from experience.

Simple wkhtmltopdf conversion with framesets creating empty pdf

We need to convert/provide our html-based in-app HelpSystem to an on-disc pdf for the client to view outside of the application.
I'm trying to use wkhtmltopdf with a very basic file (3 frames with links to simple .html files) but getting an empty .pdf when I run the following from the command line:
wkhtmltopdf "C:\Program Files (x86)\wkhtmltopdf\index.html" "c:\delme\test.pdf"
I know frames are somewhat deprecated but it’s what I’ve got to deal with. Are the frames causing the empty pdf?
Index.html:
<html>
<head>
<title>Help</title>
</head>
<frameset cols="28%, 72%">
<frameset rows="8%, 92%">
<frame noresize="noresize" src="Buttons.html" name="UPPERLEFT" />
<frame noresize="noresize" src="mytest2.html" name="LOWERLEFT" />
</frameset>
<frame noresize="noresize" src="mytest.html" name="RIGHT" />
</frameset>
</html>
mytest.html:
<html>
<body>
<p>
<b>This text is bold</b>
</p>
<p>
<strong>This text is strong</strong>
</p>
<p>
<em>This text is emphasized</em>
</p>
<p>
<i>This text is italic</i>
</p>
<p>
<small>This text is small</small>
</p>
<p>This is
<sub>subscript</sub> and
<sup>superscript</sup></p>
</body>
</html>
mytest2.html:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<h2>The blockquote Element</h2>
<p>The blockquote element specifies a section that is quoted from another source.</p>
<p>Here is a quote from WWF's website:</p>
<blockquote cite="http://www.worldwildlife.org/who/index.html">For 50 years, WWF has been protecting the future of nature. The
world’s leading conservation organization, WWF works in 100 countries and is supported by 1.2 million members in the United
States and close to 5 million globally.</blockquote>
<p>
<b>Note:</b> Browsers usually indent blockquote elements.</p>
<h2>The q Element</h2>
<p>The q element defines a short quotation.</p>
<p>WWF's goal is to:
<q>Build a future where people live in harmony with nature.</q> We hope they succeed.</p>
<p>
<b>Note:</b> Browsers insert quotation marks around the q element.</p>
</body>
</html>
buttons.html:
![<html>
<body>
<center>
<table>
<tr>
<td>
<form method="link" action="mytest.html" target="LOWERLEFT">
<input type="submit" value="Contents" />
</form>
</td>
<td>
<form method="link" action="mytest2.html" target="LOWERLEFT">
<input type="submit" value="Index" />
</form>
</td>
</tr>
</table>
</center>
</body>
</html>][2]
Taken from the official wkhtmltopdf issues area from a code project member’s answer; emphasis is mine:
wkhtmltopdf calculates the TOC based on the H* (e.g. H1, H2 and so on)
tags in the supplied documents. It does not recurse into frames and
iframes.. It will nest dependend on the number, to make sure that it
does the right thing, it is good to make sure that you only have
tags under a tag and not for some k larger
then 1. 2000+ files sounds like a lot. You might run out of memory
while converting the output. If it does not work for you.. you could
try using the switch to dump the outline to a xml file, to see what it
would but into a TOC.

Phantom <span> element using ImportXML with XPath in Google Spreadsheet

I am trying to get the value of an element attribute from this site via importXML in Google Spreadsheet using XPath.
The attribute value i seek is content found in the <span> with itemprop="price".
<div class="left" style="margin-top: 10px;">
<meta itemprop="currency" content="RON">
<span class="pret" itemprop="price" content="698,31 RON">
<p class="pret">Pretul tau:</p>
698,31 RON
</span>
...
</div>
I can access <div class="left"> but i can't get to the <span> element.
Tried using:
//span[#class='pret']/#content i get #N/A;
//span[#itemprop='price']/#content i get #N/A;
//div[#class='left']/span[#class='pret' and #itemprop='price']/#content i get #N/A;
//div[#class='left']/span[1]/#content i get #N/A;
//div[#class='left']/span/text() to get the text node of <span> i get #N/A;
//div[#class='left']//span/text() i get the text node of a <span> lower in div.left.
To get the text node of <span> i have to use //div[#class='left']/text(). But i can't use that text node because the layout of the span changes if a product is on sale, so i need the attribute.
It's like the span i'm looking for does not exist, although it appears in the development view of Chrome and in the page source and all XPath work in the console using $x("").
I tried to generate the XPath directly form the development tool by right clicking and i get //*[#id='produs']/div[4]/div[4]/div[1]/span which does not work. I also tried to generate the XPath with Firefox and plugins for FF and Chrome to no avail. The XPath generated in these ways did not even work on sites i managed to scrape with "hand coded XPath".
Now, the strangest thing is that on this other site with apparently similar code structure the XPath //span[#itemprop='price']/#content works.
I struggled with this for 4 days now. I'm starting to think it's something to do with the auto-closing meta tag, but why doesn't this happen on the other site?
Perhaps the following formulas can help you:
=ImportXML("http://...","//div[#class='product-info-price']//div[#class='left']/text()")
Or
=INDEX(ImportXML("http://...","//div[#class='product-info-price']//div[#class='left']"), 1, 2)
UPDATE
It seems that not properly parse the entire document, it fails. A document extraction, something like:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<div class="product-info-price">
<div class="left" style="margin-top: 10px;">
<meta itemprop="currency" content="RON">
<span class="pret" itemprop="price" content="698,31 RON">
<p class="pret">Pretul tau:</p>
698,31 RON
</span>
<div class="resealed-info">
» Vezi 1 resigilat din aceasta categorie
</div>
<ul style="margin-left: auto;margin-right: auto;width: 200px;text-align: center;margin-top: 20px;">
<li style="color: #000000; font-size: 11px;">Rata de la <b>28,18 RON</b> prin BRD</li>
<li style="color: #5F5F5F;text-align: center;">Pretul include TVA</li>
<li style="color: #5F5F5F;">Cod produs: <span style="margin-left: 0;text-align: center;font-weight: bold;" itemprop="identifier" content="mol:GA-Z87X-UD3H">GA-Z87X-UD3H</span> </li>
</ul>
</div>
<div class="right" style="height: 103px;line-height: 103px;">
<form action="/?a=shopping&sa=addtocart" method="post" id="add_to_cart_form">
<input type="hidden" name="product-183641" value="on"/>
<img src="/templates/marketonline/images/pag-prod/buton_cumpara.jpg"/>
</form>
</div>
</div>
</html>
works with the following XPath query:
"//div[#class='product-info-price']//div[#class='left']//span[#itemprop='price']/#content"
UPDATE
It occurs to me that one option is that you can use Apps Script to create your own ImportXML function, something like:
/* CODE FOR DEMONSTRATION PURPOSES */
function MyImportXML(url) {
var found, html, content = '';
var response = UrlFetchApp.fetch(url);
if (response) {
html = response.getContentText();
if (html) content = html.match(/<span class="pret" itemprop="price" content="(.*)">/gi)[0].match(/content="(.*)"/i)[1];
}
return content;
}
Then you can use as follows:
=MyImportXML("http://...")
At this time, the referred web page in the first link doesn't include a span tag with itemprop="price", but the following XPath returns 639
//b[#itemprop='price']
Looks to me that the problem was that the meta tag was not XHTML compliant but now all the meta tags are properly closed.
Before:
<meta itemprop="currency" content="RON">
Now
<meta itemprop="priceCurrency" content="RON" />
For web pages that are not XHTML compliant, instead of IMPORTXML another solution should be used, like using IMPORTDATA and REGEXEXTRACT or Google Apps Script, the UrlFetch Service and the match JavasScript function, among other alternatives.
Try smth like this:
print 'content by key',tree.xpath('//*[#itemprop="price"]')[0].get('content')
or
nodes = tree.xpath('//div/meta/span')
for node in nodes:
print 'content =',node.get('content')
But i haven't tried that.

Resources