Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

The four different methods of loading component contents.

* A string of HTML.
* A URL.
* A DOM document element.
* An array of DOM elements.

Lots of little things are busted, but broadly this works in Saf, Chrome
and Firefox.
  • Loading branch information...
commit b3b7292a73f7b94ad2bb4203e60d45455ccb7863 1 parent f0132bd
@joseph authored
Showing with 106 additions and 48 deletions.
  1. BIN  favicon.ico
  2. +23 −23 src/book.js
  3. +83 −25 src/component.js
View
BIN  favicon.ico
Binary file not shown
View
46 src/book.js
@@ -214,54 +214,54 @@ Monocle.Book = function (dataSource) {
}
- // Fetches the component HTML from the dataSource. The index argument is
+ // Fetches the component source from the dataSource. The index argument is
// the index of the component in the dataSource.getComponents array.
- // Callback is invoked when the HTML is received. pageDiv is optional,
- // and simply allows communication with the reader object that has requested
- // this component, ONLY if the HTML has not already been received.
+ // Callback is invoked when the source is received. pageDiv is optional,
+ // and simply allows firing events on the reader object that has requested
+ // this component, ONLY if the source has not already been received.
//
function loadComponent(index, callback, pageDiv) {
if (p.components[index]) {
return callback(p.components[index]);
}
+ var cmptId = p.componentIds[index];
if (pageDiv) {
- var evtData = { 'page': pageDiv, 'component': src, 'index': index };
+ var evtData = { 'page': pageDiv, 'component': cmptId, 'index': index };
pageDiv.m.reader.dispatchEvent('monocle:componentloading', evtData);
}
- var src = p.componentIds[index];
- console.log("Loading component HTML: '"+src+"'");
- var fn = function (html) {
+ console.log("Loading component contents: '"+cmptId+"' for pageDiv: " + pageDiv.m.pageIndex);
+ var fn = function (cmptSource) {
if (pageDiv) {
- evtData['html'] = html;
+ evtData['source'] = cmptSource;
pageDiv.m.reader.dispatchEvent('monocle:componentloaded', evtData);
html = evtData['html'];
}
p.components[index] = new Monocle.Component(
API,
- src,
+ cmptId,
index,
- chaptersForComponent(src),
- html
+ chaptersForComponent(cmptId),
+ cmptSource
);
callback(p.components[index]);
}
- var html = p.dataSource.getComponent(src, fn);
- if (html && !p.components[index]) {
- fn(html);
+ var cmptSource = p.dataSource.getComponent(cmptId, fn);
+ if (cmptSource && !p.components[index]) {
+ fn(cmptSource);
}
}
- function chaptersForComponent(src) {
- if (p.chapters[src]) {
- return p.chapters[src];
+ function chaptersForComponent(cmptId) {
+ if (p.chapters[cmptId]) {
+ return p.chapters[cmptId];
}
- p.chapters[src] = [];
- var matcher = new RegExp('^'+src+"(\#(.+)|$)");
+ p.chapters[cmptId] = [];
+ var matcher = new RegExp('^'+cmptId+"(\#(.+)|$)");
var matches;
var recurser = function (chp) {
- if (matches = chp.src.match(matcher)) {
- p.chapters[src].push({
+ if (matches = chp.cmptId.match(matcher)) {
+ p.chapters[cmptId].push({
title: chp.title,
fragment: matches[2] || null
});
@@ -276,7 +276,7 @@ Monocle.Book = function (dataSource) {
for (var i = 0; i < p.contents.length; ++i) {
recurser(p.contents[i]);
}
- return p.chapters[src];
+ return p.chapters[cmptId];
}
View
108 src/component.js
@@ -87,25 +87,98 @@ Monocle.Component = function (book, id, index, chapters, source) {
pageDiv.m.sheafDiv.appendChild(frame);
frame.style.visibility = "hidden";
- frame.m.component = API;
+ // Prevent about:blank overriding imported nodes in Firefox.
+ frame.contentWindow.stop();
+ }
+
+ frame.m.component = API;
+ if (typeof p.source == "string") { // STRING
frame.m.loadCallback = function () {
var f = frame;
frame = null;
- Monocle.removeListener(f, 'load', f.m.loadCallback);
- setupFrame(pageDiv, f);
- if (callback) {
- callback(f);
+ if (f) {
+ Monocle.removeListener(f, 'load', f.m.loadCallback);
+ setupFrame(pageDiv, f);
+ if (callback) {
+ callback(f);
+ }
}
}
+ src = p.source;
+
+ // Compress whitespace.
+ src = src.replace(/\s+/g, ' ');
+
+ // Escape single-quotes.
+ src = src.replace(/\'/g, '\\\'');
+
+ // Remove scripts.
+ var scriptFragment = "<script[^>]*>([\\S\\s]*?)<\/script>";
+ src = src.replace(new RegExp(scriptFragment, 'img'), '');
+
+ // Gecko chokes on the DOCTYPE declaration.
+ var doctypeFragment = "<!DOCTYPE[^>]*>";
+ src = src.replace(new RegExp(doctypeFragment, 'm'), '');
+
+ src = "javascript: '" + src + "';";
+
Monocle.addListener(frame, 'load', frame.m.loadCallback);
- frame.src = p.source.contentWindow.location;
+ frame.src = src;
return 'wait';
- } else {
- frame.m.component = API;
+ } else if (p.source.url) { // URL
+ frame.m.loadCallback = function () {
+ var f = frame;
+ frame = null;
+ if (f) {
+ Monocle.removeListener(f, 'load', f.m.loadCallback);
+ setupFrame(pageDiv, f);
+ if (callback) {
+ callback(f);
+ }
+ }
+ }
+ Monocle.addListener(frame, 'load', frame.m.loadCallback);
+ frame.src = p.source.url;
+ return 'wait';
+ } else if (p.source.nodes) { // NODES
+ var destDoc = frame.contentDocument;
+ var destDocElem = destDoc.documentElement;
+
+ destDoc.body.innerHTML = "";
+ //var origChildrenLength = destDocElem.childNodes.length;
+ for (var i = 0; i < p.source.nodes.length; ++i) {
+ var node = destDoc.importNode(p.source.nodes[i], true);
+ destDoc.body.appendChild(node);
+ }
+ // for (i = 0; i < origChildrenLength; ++i) {
+ // destDocElem.removeChild(destDocElem.firstChild);
+ // }
+
+ // Create the body and move everything inside it if relevant.
+ // if (!destDoc.body) {
+ // var body = destDoc.createElement('body');
+ // var nodes = destDoc.documentElement.childNodes;
+ // for (var i = 0; i < nodes.length; ++i) {
+ // body.appendChild(nodes[i]);
+ // }
+ // destDoc.documentElement.appendChild(body);
+ // }
+
+ // Create the <head> element in the frame if it doesn't exist.
+ if (!destDoc.getElementsByTagName('head')[0]) {
+ var head = destDoc.createElement('head');
+ destDoc.documentElement.insertBefore(head, destDoc.body);
+ }
- var srcDoc = p.source.contentDocument;
+ setupFrame(pageDiv, frame);
+ if (callback) {
+ callback(frame);
+ }
+ return 'ready';
+ } else if (p.source.doc) { // DOCUMENT
+ var srcDoc = p.source.doc;
var srcDocElem = srcDoc.documentElement;
var destDoc = frame.contentDocument;
var destDocElem = destDoc.documentElement;
@@ -137,6 +210,7 @@ Monocle.Component = function (book, id, index, chapters, source) {
if (currentlyApplyingTo(pageDiv)) {
return;
}
+
console.log(id+" -> pageDiv["+pageDiv.m.pageIndex+"]");
p.pageDivs[pageDiv.m.pageIndex] = pageDiv;
@@ -156,22 +230,6 @@ Monocle.Component = function (book, id, index, chapters, source) {
function setupFrame(pageDiv, frame) {
var doc = frame.contentDocument;
- if (!doc.body) {
- var body = doc.createElement('body');
- var nodes = doc.documentElement.childNodes;
- for (var i = 0; i < nodes.length; ++i) {
- body.appendChild(nodes[i]);
- }
- doc.documentElement.appendChild(body);
- }
-
- // Create the <head> element in the frame if it doesn't exist.
- // FIXME: I presume this isn't cross-browser?
- if (!doc.getElementsByTagName('head')[0]) {
- var head = doc.createElement('head');
- doc.documentElement.insertBefore(head, doc.body);
- }
-
// Register iframe to get reapplyStyles notifications from the reader.
pageDiv.m.reader.addListener(
'monocle:styles',
Please sign in to comment.
Something went wrong with that request. Please try again.