Commit 8fa65a24 authored by julien's avatar julien
Browse files

Merge branch 'config-update' into 'master'

Update Hyphens to use config, and add preview version

See merge request tools/experiments!1
parents cf7e0ca9 8df3a97d
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta lang="en-US">
<link href="css/main.css" rel="stylesheet">
</head>
<script src="js/paged.js"></script>
<script>
var Hyphenopoly = {
require: {
"en-us": "FORCEHYPHENOPOLY"
},
paths: {
patterndir: "./js/hyphens/patterns/",
maindir: "./js/hyphens/"
},
setup: {
classnames: {
"hyphenate": {
// hyphen: "•"
}
}
},
handleEvent: {
hyphenopolyEnd: function (e) {
let previewer = new Paged.Previewer();
previewer.preview();
}
}
};
</script>
<script src="js/hyphens/Hyphenopoly_Loader.js"></script>
<body class="hyphenate" lang="en-US">
<div id="cover"> </div>
<section data-type="chapter">
<div class="running-chapter">Running chapter</div>
<div class="running-part">Running part</div>
<p>introduction of Peru’s CCT program, Juntos, a World Bank–supported program intended to tackle the acute impacts of poverty.</p>
<p>CCTs originated in Latin America, and today they are among the most evaluated social programs on the planet. The majority of evidence on CCT impacts comes from the Mexican program now called Progresa, which is one of the earliest, and now largest, CCTs. Regular evaluations were built into the program administration at the outset, and this set a significant precedent. Today, we have a robust body of evidence that policy makers draw on to maintain and expand existing programs and to support implementation of new initiatives. Most of the available evidence derives from quantitative research, especially experimental methods such as randomized control trials and quasi-experimental methods (e.g., regression discontinuity, propensity score matching, instrumental variable, and difference-in- differences; Lagarde et al. 2007; Leroy et al. 2009; Kabeer and Waddington 2015). This literature is largely concerned with measuring primary program objectives related to household consumption and the uptake of health and education services. While acknowledging some variation related to program design, the existing quantitative evidence tells us that CCTs are, overall, effective and efficient mechanisms for altering the health- and education-seeking behavior of poor households.</p>
<p>For instance, regarding health and nutrition, we know that CCTs are effectiveat increasing utilization of health services (Gertler 2000; Attanasio et al. 2005; Levy and Ohls 2007; Galasso 2011) and increasing household food consumption (Hoddinott and Skoufias 2004; Angelucci and Attanasio 2009; Resende and Oliveira 2008; Handa et al. 2009). Where CCT programs have been implemented with the goal of reducing maternal mortality, they have effectively increased pregnant women’s use of health services, including antenatal care and in-facility births (Lim et al. 2010; Glassman et al. 2013). CCTs have been linked to a reduction in neonatal, infant, and child mortality and, in particular, deaths attributable to poverty-related causes such as malnutrition and diarrhea (Barham 2011; Rasella et al. 2013). CCTs have been shown to produce better growth outcomes in children (i.e., reduction in stunting; Gertler 2004; Fernald et al. 2010; Andersen et al. 2015; Kandpal et al. 2016) and improvement in children’s motor skills and cognitive development (Fernald et al. 2008). Both outcomes are likely related to uptake of health services and increased household consumption. CCTs have also been successfully deployed to increase vaccination rates for such diseases as tuberculosis, measles, diphtheria, pertussis, tetanus, and polio (Morris et al. 2004; Barham 2005; Barham and Maluccio 2009).</p>
<p>Regarding the aim of building human capital through education, studies show that CCTs are effective at increasing school enrollment (Schultz 2004; Sadoulet et al. 2004; Behrman et al. 2005; Cardoso and Souza 2003; Dammert 2009; Attanasio et al. 2010). As is the case with health service usage, there is some variability related to gender, age, ethnicity, and location, but overall the evidence indicates a positive </p>
</section>
<section class="chapter" data-type="chapter" contenteditable="true">
<header>
<div class="cn">1</div>
<h1 class="ct">Of the Bookshelf <br> Long title might look like</h1>
<div class="running-chapter">Of the Bookshelf</div>
<div class="cst">A few of my own</div>
</header>
<p>At the most general level, comparison is not a special method, or in any way unique to anthropology. Comparison is implicit in any method of deriving understanding through <em>explanation.</em></p>
</section>
</body>
</html>
......@@ -8,41 +8,35 @@
<script>
var Hyphenopoly = {
require: {
"en-us": "Supercalifragilisticexpialidocious"
"en-us": "FORCEHYPHENOPOLY"
},
paths: {
patterndir: "./js/hyphens/patterns/",
maindir: "./js/hyphens/"
},
setup: {
classnames: {
"hyphenate": {
// hyphen: "•"
}
}
},
handleEvent: {
hyphenopolyEnd: function (e) {
window.PagedPolyfill.preview();
}
}
};
</script>
<script src="js/hyphens/Hyphenopoly_Loader.js"></script>
<script>
function pagedjs() {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "js/paged.polyfill.js";
document.getElementsByTagName("head")[0].appendChild(script);
}
window.PagedConfig = {
auto: false
};
</script>
<style>
#render {
position: fixed;
right: 3em;
top: 3em;
background: black;
color: red;
font-weight: bold;
border: 3px solid red;
padding: 0.45em 1em 0.5em;
text-transform: uppercase;
}
#render:hover {
box-shadow: 0 0 0 4px black;
}
</style>
<script src="js/paged.polyfill.js"></script>
<body class="hyphenate" lang="en-US">
<button id="render">render</button>
<div id="cover"> </div>
<section data-type="chapter">
<div class="running-chapter">Running chapter</div>
......@@ -61,12 +55,5 @@
</header>
<p>At the most general level, comparison is not a special method, or in any way unique to anthropology. Comparison is implicit in any method of deriving understanding through <em>explanation.</em></p>
</section>
<script>
function show() {
pagedjs();
document.querySelector("#render").style.display = "none";
}
document.querySelector('#render').addEventListener('click', show);
</script>
</body>
</html>
\ No newline at end of file
</html>
(function(l, i, v, e) { v = l.createElement(i); v.async = 1; v.src = '//' + (location.host || 'localhost').split(':')[0] + ':35729/livereload.js?snipver=1'; e = l.getElementsByTagName(i)[0]; e.parentNode.insertBefore(v, e)})(document, 'script');
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
......@@ -45,6 +44,14 @@
}
}
 
function isElement(node) {
return node && node.nodeType === 1;
}
function isText(node) {
return node && node.nodeType === 3;
}
function *walk(start, limiter) {
let node = start;
 
......@@ -112,19 +119,6 @@
return after;
}
 
function stackChildren(currentNode, stacked) {
let stack = stacked || [];
stack.unshift(currentNode);
let children = currentNode.children;
for (var i = 0, length = children.length; i < length; i++) {
stackChildren(children[i], stack);
}
return stack;
}
function rebuildAncestors(node) {
let parent, ancestor;
let ancestors = [];
......@@ -174,6 +168,55 @@
return fragment;
}
 
/*
export function split(bound, cutElement, breakAfter) {
let needsRemoval = [];
let index = indexOf(cutElement);
if (!breakAfter && index === 0) {
return;
}
if (breakAfter && index === (cutElement.parentNode.children.length - 1)) {
return;
}
// Create a fragment with rebuilt ancestors
let fragment = rebuildAncestors(cutElement);
// Clone cut
if (!breakAfter) {
let clone = cutElement.cloneNode(true);
let ref = cutElement.parentNode.getAttribute('data-ref');
let parent = fragment.querySelector("[data-ref='" + ref + "']");
parent.appendChild(clone);
needsRemoval.push(cutElement);
}
// Remove all after cut
let next = nodeAfter(cutElement, bound);
while (next) {
let clone = next.cloneNode(true);
let ref = next.parentNode.getAttribute('data-ref');
let parent = fragment.querySelector("[data-ref='" + ref + "']");
parent.appendChild(clone);
needsRemoval.push(next);
next = nodeAfter(next, bound);
}
// Remove originals
needsRemoval.forEach((node) => {
if (node) {
node.remove();
}
});
// Insert after bounds
bound.parentNode.insertBefore(fragment, bound.nextSibling);
return [bound, bound.nextSibling];
}
*/
function needsBreakBefore(node) {
if( typeof node !== "undefined" &&
typeof node.dataset !== "undefined" &&
......@@ -219,6 +262,195 @@
return false;
}
 
function *words(node) {
let currentText = node.nodeValue;
let max = currentText.length;
let currentOffset = 0;
let currentLetter;
let range;
while(currentOffset < max) {
currentLetter = currentText[currentOffset];
if (/^\S$/.test(currentLetter)) {
if (!range) {
range = document.createRange();
range.setStart(node, currentOffset);
}
} else {
if (range) {
range.setEnd(node, currentOffset);
yield range;
range = undefined;
}
}
currentOffset += 1;
}
if (range) {
range.setEnd(node, currentOffset);
yield range;
range = undefined;
}
}
function *letters(wordRange) {
let currentText = wordRange.startContainer;
let max = currentText.length;
let currentOffset = wordRange.startOffset;
let currentLetter;
let range;
while(currentOffset < max) {
currentLetter = currentText[currentOffset];
range = document.createRange();
range.setStart(currentText, currentOffset);
range.setEnd(currentText, currentOffset+1);
yield range;
currentOffset += 1;
}
}
function isContainer(node) {
let container;
if (typeof node.tagName === "undefined") {
return true;
}
if (node.style.display === "none") {
return false;
}
switch (node.tagName) {
// Inline
case "A":
case "ABBR":
case "ACRONYM":
case "B":
case "BDO":
case "BIG":
case "BR":
case "BUTTON":
case "CITE":
case "CODE":
case "DFN":
case "EM":
case "I":
case "IMG":
case "INPUT":
case "KBD":
case "LABEL":
case "MAP":
case "OBJECT":
case "Q":
case "SAMP":
case "SCRIPT":
case "SELECT":
case "SMALL":
case "SPAN":
case "STRONG":
case "SUB":
case "SUP":
case "TEXTAREA":
case "TIME":
case "TT":
case "VAR":
// Content
case "P":
case "H1":
case "H2":
case "H3":
case "H4":
case "H5":
case "H6":
case "FIGCAPTION":
case "BLOCKQUOTE":
case "PRE":
case "LI":
case "TR":
case "DT":
case "DD":
case "VIDEO":
case "CANVAS":
container = false;
break;
default:
container = true;
}
return container;
}
function cloneNode(n, deep=false) {
return n.cloneNode(deep);
}
function findElement(node, doc) {
const ref = node.getAttribute("data-ref");
return findRef(ref, doc);
}
function findRef(ref, doc) {
return doc.querySelector(`[data-ref='${ref}']`);
}
function validNode(node) {
if (isText(node)) {
return true;
}
if (isElement(node) && node.dataset.ref) {
return true;
}
return false;
}
function prevValidNode(node) {
while (!validNode(node)) {
if (node.previousSibling) {
node = node.previousSibling;
} else {
node = node.parentNode;
}
if (!node) {
break;
}
}
return node;
}
function indexOf(node) {
let parent = node.parentNode;
if (!parent) {
return 0;
}
return Array.prototype.indexOf.call(parent.childNodes, node);
}
function child(node, index) {
return node.childNodes[index];
}
function isVisible(node) {
if (isElement(node) && window.getComputedStyle(node).display !== "none") {
return true;
} else if (isText(node) &&
node.textContent.trim().length &&
window.getComputedStyle(node.parentNode).display !== "none") {
return true;
}
return false;
}
function createCommonjsModule(fn, module) {
return module = { exports: {} }, fn(module, module.exports), module.exports;
}
......@@ -317,10 +549,10 @@
return (str.contains("dwa") === true) && (str.contains("foo") === false);
};
 
var indexOf = String.prototype.indexOf;
var indexOf$1 = String.prototype.indexOf;
 
var shim$2 = function (searchString/*, position*/) {
return indexOf.call(this, searchString, arguments[1]) > -1;
return indexOf$1.call(this, searchString, arguments[1]) > -1;
};
 
var contains = isImplemented$2()
......@@ -588,8 +820,6 @@
}
}
 
const _requestIdleCallback = 'requestIdleCallback' in window ? requestIdleCallback : requestAnimationFrame;
const PER_PAGE_CHECK = 4;
 
/**
......@@ -598,250 +828,142 @@
*/
class Layout {
 
constructor(element, wrapper, hooks) {
constructor(element, hooks) {
this.element = element;
this.wrapper = wrapper;
 
let space = this.element.getBoundingClientRect();
this.width = Math.round(space.width);
this.bounds = this.element.getBoundingClientRect();
 
if (hooks) {
this.hooks = hooks;
} else {
this.hooks = {};
this.hooks.layout = new Hook();
this.hooks.renderNode = new Hook();
this.hooks.layoutNode = new Hook();
this.hooks.overflow = new Hook();
}
}
getStart(content, breakToken) {
let start = content;
let node = breakToken.node;
if (node) {
start = node;
}
 
return start;
}
 
isContainer(node) {
let container;
if (typeof node.tagName === "undefined") {
return true;
}
if (node.style.display === "none") {
return false;
}
switch (node.tagName) {
// Inline
case "A":
case "ABBR":
case "ACRONYM":
case "B":
case "BDO":
case "BIG":
case "BR":
case "BUTTON":
case "CITE":
case "CODE":
case "DFN":
case "EM":
case "I":
case "IMG":
case "INPUT":
case "KBD":
case "LABEL":
case "MAP":
case "OBJECT":
case "Q":
case "SAMP":
case "SCRIPT":
case "SELECT":
case "SMALL":
case "SPAN":
case "STRONG":
case "SUB":
case "SUP":
case "TEXTAREA":
case "TIME":
case "TT":
case "VAR":
// Content
case "P":
case "H1":
case "H2":
case "H3":
case "H4":
case "H5":
case "H6":
case "FIGCAPTION":
case "BLOCKQUOTE":
case "PRE":
case "LI":
case "TR":
case "DT":
case "DD":
case "VIDEO":
case "CANVAS":
container = false;
break;
default:
container = true;
}
return container;
}
layout(space, content, styleMap, edges, breakToken) {
let start = content;
if (breakToken.node) {
start = this.getStart(content, breakToken);
}
let walker = walk(start, content);
renderTo(wrapper, source, breakToken, bounds=this.bounds) {
let start = this.getStart(source, breakToken);
let walker = walk(start, source);
 
let node;
let done;
let next;
let hasOverflow = false;
let hasContent = false;
let newBreakToken;
let after;
 
let check = 0;
 
let dest = document.createDocumentFragment();
let rendered;
let shallow = true;
while (!done && !hasOverflow) {
while (!done && !newBreakToken) {
next = walker.next();
node = next.value;
done = next.done;
 
if (node) {
this.hooks.layoutNode.trigger(node);
// Check if the rendered element has a breakBefore set
if (hasContent && (needsBreakBefore(node) || needsPreviousBreakAfter(node) || needsPageBreak(node))) {
// Check for overflow
hasOverflow = this.hasOverflow();
if (hasOverflow) {
let overflow = this.overflow(this.element);
if (!node) {
newBreakToken = this.findBreakToken(wrapper, source, bounds);
return newBreakToken;
}
 
if (overflow) {
/*
let exists;
if (isElement(node)) {
exists = findElement(node, wrapper);
} else {
exists = false;
}
 
newBreakToken = this.findBreakToken(overflow, content);
if (exists) {
console.log("found", exists);
break;
}
*/
 
if (newBreakToken && newBreakToken.node) {
this.removeOverflow(overflow);
}
this.hooks && this.hooks.layoutNode.trigger(node);
 
break;
// Check if the rendered element has a break set
if (hasContent && this.shouldBreak(node)) {
newBreakToken = this.findBreakToken(wrapper, source, bounds);
 
}
} else {
// Break layout with current node
newBreakToken = {
node: node,
offset: 0
};
break;
}
if (!newBreakToken) {
newBreakToken = this.breakAt(node);
}
 
shallow = this.isContainer(node);
break;
}
 
rendered = this.render(node, this.wrapper, breakToken, shallow);
// Should the Node be a shallow or deep clone
let shallow = isContainer(node);
 
if (!hasContent) {
// Only register visible content
if (rendered.nodeType === 1 && window.getComputedStyle(rendered).display !== "none") {
hasContent = true;
} else if (rendered.nodeType === 3 &&
rendered.textContent.trim().length &&
window.getComputedStyle(rendered.parentNode).display !== "none") {
hasContent = true;
}
}
if (!shallow) {
after = nodeAfter(node, content);
walker = walk(after, content);
}
let rendered = this.append(node, wrapper, breakToken, shallow);
 
// Check if layout has content yet
if (!hasContent) {
hasContent = isVisible(node);