FiveThirtyEight style in-text footnotes for bookdown - javascript

I'm creating a project using {bookdown}, and I would like to format my footnotes to appear directly in the text when the superscript is selected, as happens in FiveThirtyEight articles (see here for an example). The idea is that when a user clicks on the footnotes, the paragraph expands to show the footnote text, and then compresses back to normal when the footnote is closed.
I have found a few resources where this is implemented:
Stackoverflow question here
https://medium.com/#bnjmnbnjmn/in-line-notes-with-only-html-css-f181c5ceef59
https://www.viget.com/articles/of-note-better-text-annotations-for-the-web/
However, these solutions all seem to assume that the actual footnote text is within a <span> tag that has an associated class. However, this does not appear to be the case for HTML footnotes generated from {bookdown} and Pandoc. The HTML looks like this:
<p>
"Figures and tables with captions will be placed in "
<code>
"figure
</code>
" and "
<code>
"table"
</code>
" environments, respectively."
<sup>1</sup>
</p>
<div class="footnotes">
<hr>
<ol start="1">
<li id="fn1">
<p>
"Here is a fancy footnote."
"<-"
</p>
</li>
</ol>
</div>
So not only are the footnotes placed in an unclassed <p> tag, rather than a classed <span> tag, the footnotes themselves are also in a completely separate <div>, rather than appearing within the same tag as the rest of the text, as is the case in the linked examples.
I've created a bookdown reprex to try and make this work with a combination of CSS and javascript, based on the linked examples above. The GitHub repo is here, and the rendered output here. I've successfully hidden the footnotes at the bottom of the page, but have not been able to get the footnotes to display in-text when the footnote superscript is selected.
Is there a way to style footnotes in this way using {bookdown}? Or is this a constraint of Pandoc?

Pandoc gives you full control over the the output via filters. The following is a Lua filter which uses the HTML/CSS method to hide/show footnotes. See this R Studio article on how to use Lua filters with bookdown.
-- how many notes we've seen yet.
local note_number = 0
local fn_opening_template = [[<span id="fn-%d"><!--
--><label for="fn-%d-toggle"><sup>%d</sup></label><!--
--><input type="checkbox" hidden id="fn-%d-toggle"/>
]]
local fn_close = '</span>'
local style_css = [[<style>
input[type=checkbox][id|=fn] + span {display:none;}
input[type=checkbox][id|=fn]:checked + span {display:block;}
</style>
]]
-- Use custom HTML for footnotes.
function Note (note)
note_number = note_number + 1
local fn_open = fn_opening_template:format(
note_number, note_number, note_number, note_number)
return {
pandoc.RawInline('html', fn_open),
pandoc.Span(
pandoc.utils.blocks_to_inlines(note.content),
pandoc.Attr(string.format('fn-%d-content', note_number))
),
pandoc.RawInline('html', fn_close)
}
end
function Meta (meta)
local header_includes = meta['header-includes']
-- ensure that header_includes is a MetaList
if not header_includes then
header_includes = pandoc.MetaList{}
elseif header_includes.t ~= 'MetaList' then
header_includes = pandoc.MetaList {header_includes}
end
table.insert(
header_includes,
pandoc.MetaBlocks{pandoc.RawBlock('html', style_css)}
)
meta['header-includes'] = header_includes
return meta
end

Related

Internationalization of a HTML + Markdown document (using RemarkJS)

I have many slides for a presentation made with RemarkJS. It is a HTML file slides_fr.html with a single <textarea id="source"> containing the actual content in Markdown syntax (+ one or two specific markup tags to separate the slides with a page break), and one call to the JS library RemarkJS.
I am translating this document into English (I first duplicated slides_fr.html into slides_en.html and started to translate). Problem: each time I do improvement on the slides in the English version, I'll have to remodify the original file slides_fr.html to keep them in sync. In my experience, this rarely works well on the long-term. It would be better to have both versions in the same file, with markup for language.
Question: in order to avoid having two files slides_fr.html and slides_en.html like this that will ultimately never stay in sync:
<html>
<head></head>
<body>
<textarea id="source">
First slide
My presentation about XYZ
---
Second slide
Hello world
</textarea>
<script src="https://remarkjs.com/downloads/remark-latest.min.js"></script><script>remark.create();</script>
</html>
which options are there, using HTML or Javascript or Markdown-specific syntax to have both languages in the same file like this:
<textarea id="source">
First slide ||| Première diapositive
My presentation about XYZ ||| Ma présentation à propos de XYZ
---
Second slide ||| Seconde diapositive
Hello ! ||| Bonjour
</textarea>
<javascript>
chooseLanguage(document.getElementBydId('source'), 'en'); // there is surely a better solution
// than a parsing and splitting by '|||' ?
</javascript>
As a way to better organize localized texts, you could use CSS classes to mark which language applies to each text.
Remark provides a markdown extension called "Content classes" (https://remarkjs.com/#12), it's used to apply CSS classes to texts.
I think this feature could be exploited to wrap localized texts inside the markdown source, in this fashion:
.lang_en[Second slide]
.lang_fr[Seconde diapositive]
.lang_it[Seconda diapositiva]
These will be transcripted in HTML as:
<span class="lang_en">Second slide</span>
<span class="lang_fr">Seconde diapositive</span>
<span class="lang_it">Seconda diapositiva</span>
Once texts are structured this way, you can easily show / hide them via javascript and CSS.
This fiddle shows the Remark boilerplate localized in english and italian, adapted using the above strategy (javascript language switcher not provided in the snippet): https://jsfiddle.net/k7au5oe3/

How to change color of a search word in HTML?

So in my HTML file, I have
<p class = "result"> {{searchResult}} </p>
where {{searchResult}} is essentially my result.
So if I searched for the term "hot",
{{searchResult}} would contain a string containing the word "hot" in a document.
For example:
"This is hot"
Everything shows up in the webpage perfectly fine but I want to change the color of the search term within the string.
I tried modifying the part where it should output the content in my JS file:
content: result.replace(searchTerm, <span class= "search">searchTerm</span>)
where the class "search" is just changing the color of the word.
But it shows up as the webpage as:
This is <span class = "search">hot</span>
How would I make it so that it changes the color only of the search term?
You're looking to change the style of the html content. This is done using CSS. You can do this in one of three ways:
1) Edit the color of the paragraph using in-line CSS: <p class="result" style="color:red;"> {{searchResult}} </p>
2) Create an external .css file and link your html file to it in the <head> of the document. Use similar css there:
.result {
color:red;
}
3) Edit the DOM using Javascript to similarly change the color:
document.querySelector('.result').style.color='red';

How can I only render certain html tags for my forum?

I am currently building a forum and am trying to print out posts with formatting (bold, italicized, images, etc.) The user inputs the text using http://summernote.org/ My php code is currently set to:
echo nl2br(e($content));
Which prints out: (printing the actual tags)
<p><b>asdffddd d d d d </b></p>
When I surround my echo function with htmlspecialchars_decode, it renders every single html tag. This is obviously not ideal, because users could put things like iframe's or div's and break the layout of my page.
What would be the best way to only render the following tags
<b>
<i>
<u>
<p>
<h1-6>
<img>
<a>
<span>
<ul>
<ol>
<li>
I would still like it to display non-allowed tags in text form, just not render them.
Use strip_tags to achieve this.
<?php
$html = 'Your html';
$allowableTags = '<a><b>'; // add allowable tags
echo strip_tags($html,$allowableTags);
?>
I hope this helps.

Inject html after review widget loads for schema markup

My webstore uses Kudobuzz for product reviews, but our e-commerce platform (PDG) isn't supported for SEO markup data.
This widget does not support schema markup on it's own, so I want to somehow select the relevant pieces and inject the schema markup to the various divs/spans that make up the widget. One problem is figuring out how to inject code that google can parse, and another is figuring out how to make the actual selectors for this super bloated widget.
Here is a codepin of the widget and some markup data that is already on the site: http://codepen.io/anon/pen/GpddpO
Here is a link to a product page if you want to see how everything works: https://www.asseenontvhot10.com/product/2835/Professional-Leather--Vinyl-Repair-Kit
This is (roughly) the markup I'm trying to add if it helps:
<div itemscope itemtype="http://schema.org/Review">
<div itemprop="reviewBody">Blah Blah it works 5 star</div>
<div itemprop="author" itemscope itemtype="http://schema.org/Person">
Written by: <span itemprop="name">Author</span></div>
<div itemprop="itemReviewed" itemscope itemtype="http://schema.org/Thing">
<span itemprop="name">Stop Snore</span></div>
<div><meta itemprop="datePublished" content="2015-10-07">Date published: 10/07/2015</div>
<div itemprop="reviewRating" itemscope itemtype="http://schema.org/Rating">
<meta itemprop="worstRating" content="1"><span itemprop="ratingValue">5</span> / <span itemprop="bestRating">5</span> stars</div>
</div>
Theoretically you could write a very small amount of microdata using css :before and :after - with content but it would need all spaces and symbols converted into ISO format, eg.
#name:before { "\003cspan\2002itemprop\0022name\2033"}
#name:after { content: "\2044\003cspan003e"
even spaces need to be substitued with \2002 or an equivalent whitespace
code
should wrap this microdata to your HTML to any element called name:
<span itemprop="name">...</span>
Clearly this can only work if the widget lets you have clear ids or class names for the elements added, and it may be useless you know the type of object reviewed first (eg Book, Movie, since this needs to go at the start in the example I gave - which is incomplete). The code would need to be nested correctly so if you want further help can you edit your question with example HTML for a completed review.
Writing your own JSON-LD script at the top of the page is another option - it would be a different question (if you get stuck) but isn't embedded within the data itself
Edit
it's a good idea to test the css in a separate environment first, eg setup a jsfiddle

Incorrect reading order

I am evaluating some code that was sent to me, and I don't follow why it is happening.
[edit]: The code is generated by Lectora, an e-learning software, so nothing was done by hand. The ugly inline code cannot by shoved in a stylesheet.
[Edit 2] The buttonxxx is some feature it looks like in lectora to allow you to make invisable hotspots, sort of like an image map. I don't have the software, and the person making it isn't too tech savvy.
HTML
<p style="margin-left:0px;text-indent:0px;line-height:1.160;margin-top:0px;margin-bottom:0px;text-align:left;" >
<a href="##Action 7515" ><span class="text3708Font1" >Table of
Contents</span ></a ><a href="##Action 7515" ><span class="text3708Font2" style="background-color:transparent" >
</span ></a ></p >
<p style="margin-left:0px;text-indent:0px;line-height:1.160;margin-top:0px;margin-bottom:0px;text-align:left;" >
<span class="text3708Font3" style="background-color:transparent" >
</span ></p >
<p style="margin-left:0px;text-indent:0px;line-height:1.160;margin-top:0px;margin-bottom:0px;text-align:left;" >
<a href="##Action 3710" ><span class="text3708Font4" >Edgar's
Dilemma</span></a ><span class="text3708Font5" style="background-color:transparent" >
</span ></p >
The JavaScript that I think is applicable. There is about 530 lines of JS in the page.
button6458 = new ObjButton('button6458','table of contents',1,69,70,37,1,8,'div')
button6458.setImages('transbtn.gif',null,null,'images/')
button6458.onUp = button6458onUp
button6458.hasOnUp = true
button6458.capture=4
button6458.build()
button6459 = new ObjButton('button6459','course beginning story',2,112,67,36,1,9,'div')
button6459.setImages('transbtn.gif',null,null,'images/')
button6459.onUp = button6459onUp
button6459.hasOnUp = true
button6459.capture=4
button6459.build()
But if I navigate this using a screen reader, it is announced as:
Table of Contents [link], [link] (a space after the s in contents), Edgar’s Dilemma [link], [link] (a space character in the space between edgar & what is 508), Table of Contents (now announced as “go to table of contents [link]”), Edgar’s Dilemma (now announced as “Go to course beginning story [link]”)
Any ideas as to why the anchors are read, then the javascript would be great.
Solution:
About halfway into the source code, some JS was wrote. This makes the second set of links via the JS code block above. If we strip the junk out, the source code essentially becomes:
Table of contents
Edgar's Delimma
go to Table of contents
go toEdgar's Delimma
I haven't figured out how the is being created.
Your source code in the first block can be simplified to
<p>Table of Contents</p>
<p> </p>
<p>Edgar's Dilemma</p >
and it appears that your output is stripping the <p> </p> element because there is no content there to be read, but it's assuming that the link after the "Table of Contents" link is significant and retaining that. Because there is no text to form the link, it's doing its best.
I suspect that the link which is being announced after "Edgar's Dilemma" is similarly coded.
Quite why there should be an empty link in the code may be down to Lectora or the person who put the e-learning package together. Given the change of text style in the source code, it could be because of a font change at the end of the "Table of Contents" link — Microsoft Word can do this, when a paragraph mark retains a font setting which has been overridden for the text itself.

Categories