Closed scottfr closed 10 years ago
Yes, that makes sense. Happy to take a PR, else I'll add it to my list.
Sorry, no pull request but this is what I came up with my own copy. It's just about 6 lines of code added to two functions marked. The two additions are marked by "// SFR XXX".
API.fitMask = function (link, mask) {
var hrefObject = deconstructHref(link);
var rdr = stencil.properties.reader;
var evtData = { href: hrefObject, link: link, mask: mask }
if (hrefObject.internal) {
mask.setAttribute('href', 'javascript:"Skip to chapter"');
mask.onclick = function (evt) {
if (rdr.dispatchEvent('monocle:link:internal', evtData, true)) {
rdr.skipToChapter(hrefObject.internal);
}
evt.preventDefault();
return false;
}
}else if(hrefObject.passThrough){ //SFR XXX
mask.onclick = function (evt) {
link.click();
evt.preventDefault();
return true;
}
return; // We don't want to override the link click event
}else {
mask.setAttribute('href', hrefObject.external);
mask.setAttribute('target', '_blank');
mask.onclick = function (evt) {
return rdr.dispatchEvent('monocle:link:external', evtData, true);
}
}
link.onclick = function (evt) {
evt.preventDefault();
return false;
}
}
// Returns an object with either:
//
// - an 'external' property -- an absolute URL with a protocol,
// host & etc, which should be treated as an external resource (eg,
// open in new window)
//
// OR
//
// - an 'internal' property -- a relative URL (with optional hash anchor),
// that is treated as a link to component in the book
//
// A weird but useful property of <a> tags is that while
// link.getAttribute('href') will return the actual string value of the
// attribute (eg, 'foo.html'), link.href will return the absolute URL (eg,
// 'http://example.com/monocles/foo.html').
//
function deconstructHref(elem) {
if(elem.getAttribute("href").toLowerCase().indexOf("javascript:") == 0){//SFR XXX
return {passThrough: true};
}
var loc = document.location;
var origin = loc.protocol+'//'+loc.host;
var href = elem.href;
var path = href.substring(origin.length);
var ext = { external: href };
// Anchor tags with 'target' attributes are always external URLs.
if (elem.getAttribute('target')) {
return ext;
}
// URLs with a different protocol or domain are always external.
//console.log("Domain test: %s <=> %s", origin, href);
if (href.indexOf(origin) != 0) {
return ext;
}
// If it is in a sub-path of the current path, it's internal.
var topPath = loc.pathname.replace(/[^\/]*\.[^\/]+$/,'');
if (topPath[topPath.length - 1] != '/') {
topPath += '/';
}
//console.log("Sub-path test: %s <=> %s", topPath, path);
if (path.indexOf(topPath) == 0) {
return { internal: path.substring(topPath.length) }
}
// If it's a root-relative URL and it's in our list of component ids,
// it's internal.
var cmptIds = stencil.properties.reader.getBook().properties.componentIds;
for (var i = 0, ii = cmptIds.length; i < ii; ++i) {
//console.log("Component test: %s <=> %s", cmptIds[i], path);
if (path.indexOf(cmptIds[i]) == 0) {
return { internal: path }
}
}
// Otherwise it's external.
return ext;
}
return API;
}
Thanks for this — I've tweaked your suggestion and committed it to master.
Javascript URL's (test) in links should be handled differently by deconstructHref.
Currently monocle opens a new page and then runs the javascript on that page. This is almost certainly what is not intended.
The javascript should be run within the current component iframe.