Skip to content

Commit

Permalink
Refactored and added TODOs for future cleanup and improvement
Browse files Browse the repository at this point in the history
  • Loading branch information
stenington committed Dec 3, 2011
1 parent d217458 commit 59dcb33
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 74 deletions.
36 changes: 4 additions & 32 deletions kit.html
Expand Up @@ -281,42 +281,14 @@ <h2>Learning Objectives</h2>
</section>
</section>

<script src="lib/getElementsByClassName-1.0.1.js"></script>
<script src="toc.js"></script>
<script type="text/javascript">

if(document.body.hasChildNodes()) {

var toc_section = document.createElement("section");
var toc = document.createElement("ol");
toc_section.appendChild(toc);

var children = document.body.childNodes;
for(var i = 0; i < children.length; i++) {
var child = children[i];
if( child.nodeType == 1 && child.classList ) {
console.log("ok, in child with className " + child.className);
if( typeof child.id === 'undefined' || !child.id ){
child.id = "child" + i;
}
var text = "foo for now";
/*var titles = child.getElementsByClassName("title");
if( titles.length > 0 ){
text += titles[0].firstChild.nodeValue;
}
var subtitles = child.getElementsByClassName("subtitle");
if( subtitles.length > 0 ){
text += " " + subtitles[0].firstChild.nodeValue;
} */
console.log(text);
var toc_el = document.createElement("li");
var toc_link = document.createElement("a");
toc_link.setAttribute("href", "#" + child.id);
var toc_text = document.createTextNode(text);
toc_link.appendChild(toc_text);
toc_el.appendChild(toc_link);
toc.appendChild(toc_el);
}
}
document.body.insertBefore(toc_section, document.body.firstChild);
var toc = buildTOC(document.body);
document.body.insertBefore(toc, document.body.firstChild);
}
</script>
</body>
Expand Down
78 changes: 78 additions & 0 deletions lib/getElementsByClassName-1.0.1.js
@@ -0,0 +1,78 @@
/*
Developed by Robert Nyman, http://www.robertnyman.com
Code/licensing: http://code.google.com/p/getelementsbyclassname/
*/
var getElementsByClassName = function (className, tag, elm){
if (document.getElementsByClassName) {
getElementsByClassName = function (className, tag, elm) {
elm = elm || document;
var elements = elm.getElementsByClassName(className),
nodeName = (tag)? new RegExp("\\b" + tag + "\\b", "i") : null,
returnElements = [],
current;
for(var i=0, il=elements.length; i<il; i+=1){
current = elements[i];
if(!nodeName || nodeName.test(current.nodeName)) {
returnElements.push(current);
}
}
return returnElements;
};
}
else if (document.evaluate) {
getElementsByClassName = function (className, tag, elm) {
tag = tag || "*";
elm = elm || document;
var classes = className.split(" "),
classesToCheck = "",
xhtmlNamespace = "http://www.w3.org/1999/xhtml",
namespaceResolver = (document.documentElement.namespaceURI === xhtmlNamespace)? xhtmlNamespace : null,
returnElements = [],
elements,
node;
for(var j=0, jl=classes.length; j<jl; j+=1){
classesToCheck += "[contains(concat(' ', @class, ' '), ' " + classes[j] + " ')]";
}
try {
elements = document.evaluate(".//" + tag + classesToCheck, elm, namespaceResolver, 0, null);
}
catch (e) {
elements = document.evaluate(".//" + tag + classesToCheck, elm, null, 0, null);
}
while ((node = elements.iterateNext())) {
returnElements.push(node);
}
return returnElements;
};
}
else {
getElementsByClassName = function (className, tag, elm) {
tag = tag || "*";
elm = elm || document;
var classes = className.split(" "),
classesToCheck = [],
elements = (tag === "*" && elm.all)? elm.all : elm.getElementsByTagName(tag),
current,
returnElements = [],
match;
for(var k=0, kl=classes.length; k<kl; k+=1){
classesToCheck.push(new RegExp("(^|\\s)" + classes[k] + "(\\s|$)"));
}
for(var l=0, ll=elements.length; l<ll; l+=1){
current = elements[l];
match = false;
for(var m=0, ml=classesToCheck.length; m<ml; m+=1){
match = classesToCheck[m].test(current.className);
if (!match) {
break;
}
}
if (match) {
returnElements.push(current);
}
}
return returnElements;
};
}
return getElementsByClassName(className, tag, elm);
};
4 changes: 2 additions & 2 deletions print.css
@@ -1,6 +1,6 @@
/* Pagination */

#cover, #toc { page-break-after: always; }
#cover, .toc { page-break-after: always; }

.chapter { page-break-before: always; }

Expand All @@ -15,7 +15,7 @@ h1, h2, h3, h4, h5, h6 { page-break-after: avoid; }

/* TOC */

#toc a[href]:after {
.toc a[href]:after {
content: leader('.') target-counter(attr(href), page);
}

Expand Down
57 changes: 39 additions & 18 deletions test/lib/colorTests.js
Expand Up @@ -4,15 +4,15 @@
Publish results to #overall.
Note: Keep this code prince-safe!
TODO: Is there a requires mechanism prince is ok with? This script
requires getElementsByClassName, but prince can't handle require.js.
*/
(function(){
function normalize(value){
if( value ){
value.replace(/\s+/, '');
}
return value;
}

/* TODO: Rename/rewrite. Will it normalize the children of the node passed in, or accept
a list of children to normalize? Also consider normalizing the whole tree and calling once.
*/
function normalizeChildren(children){
var normalized = [];
for(var i = 0; i < children.length; i++) {
Expand All @@ -30,6 +30,7 @@

function nodeLooksLike(actual, expected) {
if( expected.nodeType !== actual.nodeType ){
/* TODO: extract a utility method or something? */
console.log("expected nodeType: " + expected.nodeType + ", got nodeType: " + actual.nodeType);
return false;
}
Expand All @@ -39,18 +40,22 @@
return false;
}

/* Only check for href's if they're defined on the expected node */
if( expected.hasAttribute && expected.hasAttribute('href') ){
/* href="*" means the actual must have an href, but it can be anything */
if( expected.getAttribute('href') === '*' ){
if( !(actual.hasAttribute && actual.hasAttribute('href')) ){
/* Only check for listed attributes if they're defined on the expected node */
var attrs = ['href', 'class'];
for(var i = 0; i < attrs.length; i++){
var attr = attrs[i];
if( expected.hasAttribute && expected.hasAttribute(attr) ){
/* expected attribute of "*" means the actual must have the attribute, but it can be anything */
if( expected.getAttribute(attr) === '*' ){
if( !(actual.hasAttribute && actual.hasAttribute(attr)) ){
return false;
}
}
else if( !actual.hasAttribute(attr) || expected.getAttribute(attr) !== actual.getAttribute(attr) ){
console.log("expected " + attr + ": [" + expected.getAttribute(attr) + "], got " + attr + ": [" + actual.getAttribute(attr) + "]");
return false;
}
}
else if( !actual.hasAttribute('href') || expected.getAttribute('href') !== actual.getAttribute('href') ){
console.log("expected href: [" + expected.getAttribute('href') + "], got href: [" + actual.getAttribute('href') + "]");
return false;
}
}

return true;
Expand Down Expand Up @@ -82,13 +87,29 @@
return nodeLooksLike(actual, expected);
}

/* TODO: rewrite? This seems janky. Why do we need to introduce this weird clean top-level root?
*/
function contentsLookAlike(actualContainer, expectedContainer){
var actuals = normalizeChildren(actualContainer.childNodes);
var expecteds = normalizeChildren(expectedContainer.childNodes);
var actualsRoot = document.createElement('div');
var expectedsRoot = actualsRoot.cloneNode(false);
for(var i = 0; i < actuals.length; i++){
actualsRoot.appendChild(actuals[i]);
}
for(var i = 0; i < expecteds.length; i++){
expectedsRoot.appendChild(expecteds[i]);
}
return looksLike(actualsRoot, expectedsRoot);
}

console.log("\nColoring the tests...");
var tests = getElementsByClassName("test", "div", document);
var failCount = 0;
tests.forEach(function(test, i, arr){
var expected = getElementsByClassName("expected", null, test)[0];
var actual = getElementsByClassName("actual", null, test)[0];
if( looksLike(actual, expected) ){
var expectedContainer = getElementsByClassName("expected", null, test)[0].cloneNode(true);
var actualContainer = getElementsByClassName("actual", null, test)[0].cloneNode(true);
if( contentsLookAlike(actualContainer, expectedContainer) ){
test.className += " pass";
}
else {
Expand Down
10 changes: 5 additions & 5 deletions test/toc.html
Expand Up @@ -28,7 +28,7 @@ <h1 class="title">Title 2</h1>

<h2>Expected:</h2>
<div class="expected">
<ol>
<ol class="toc">
<li><a href="#id10">Title 1</a></li>
<li><a href="#id11">Title 2</a></li>
</ol>
Expand All @@ -50,7 +50,7 @@ <h2 class="subtitle">Subtitle</h2>

<h2>Expected:</h2>
<div class="expected">
<ol>
<ol class="toc">
<li><a href="#toc2-chapter1">Title Subtitle</a></li>
</ol>
</div>
Expand All @@ -73,7 +73,7 @@ <h2>Root:</h2>

<h2>Expected:</h2>
<div class="expected">
<ol>
<ol class="toc">
<li><a href="*">Title</a></li>
</ol>
</div>
Expand All @@ -88,15 +88,15 @@ <h2>Root:</h2>
<div class="root">
<h1>Title</h1>
<p>Some top-level stuff</p>
<section class="chapter other">
<section class="chapter">
<h1 class="title">Chapter title</h1>
</section>
<p class="notachapter">Some more top-level stuff</p>
</div>

<h2>Expected:</h2>
<div class="expected">
<ol>
<ol class="toc">
<li><a href="*">Chapter title</a></li>
</ol>
</div>
Expand Down
49 changes: 32 additions & 17 deletions toc.js
Expand Up @@ -19,30 +19,45 @@
}
return false;
}

function getTextFrom(className, parentEl) {
var els = getElementsByClassName(className, null, parentEl);
if( els.length > 0 ){
return els[0].firstChild.nodeValue;
}
return "";
}

function makeUniqueId(i) {
return "toc" + tocCount + "-chapter" + i;
}

function buildTocItem(node, i) {
var text = getTextFrom("title", node);
if(getTextFrom("subtitle", node)){
text += " " + getTextFrom("subtitle", node);
}

node.id = node.id || makeUniqueId(i);

var toc_line = document.createElement('li');
var link = document.createElement('a');
link.setAttribute('href', '#' + node.id);
var toc_text = document.createTextNode(text);
toc_line.appendChild(link);
link.appendChild(toc_text);
return toc_line;
}

function buildTOC(root) {
tocCount++;
var toc = document.createElement('ol');
toc.className = "toc";
var children = root.childNodes;
for(var i = 0; i < children.length; i++) {
var child = children[i];
if( includeNode(child) ){
var text = "";
var titles = getElementsByClassName("title", null, child);
if( titles.length > 0 ){
text += titles[0].firstChild.nodeValue;
}
var subtitles = getElementsByClassName("subtitle", null, child);
if( subtitles.length > 0 ){
text += " " + subtitles[0].firstChild.nodeValue;
}
var toc_line = document.createElement('li');
var link = document.createElement('a');
child.id = child.id || "toc" + tocCount + "-chapter" + i;
link.setAttribute('href', '#' + child.id);
var toc_text = document.createTextNode(text);
toc_line.appendChild(link);
link.appendChild(toc_text);
toc.appendChild(toc_line);
toc.appendChild(buildTocItem(child, i));
}
}
return toc;
Expand Down

0 comments on commit 59dcb33

Please sign in to comment.