mirror of
https://github.com/futurepress/epub.js.git
synced 2025-10-03 14:59:18 +02:00
479 lines
No EOL
11 KiB
JavaScript
479 lines
No EOL
11 KiB
JavaScript
EPUBJS.View = function(section, options) {
|
|
this.settings = options || {};
|
|
|
|
this.id = "epubjs-view:" + EPUBJS.core.uuid();
|
|
this.section = section;
|
|
this.index = section.index;
|
|
|
|
this.element = document.createElement('div');
|
|
this.element.classList.add("epub-view");
|
|
|
|
|
|
// this.element.style.minHeight = "100px";
|
|
this.element.style.height = "0px";
|
|
this.element.style.width = "0px";
|
|
this.element.style.overflow = "hidden";
|
|
|
|
this.displayed = false;
|
|
this.rendered = false;
|
|
|
|
//this.width = 0;
|
|
//this.height = 0;
|
|
|
|
// Blank Cfi for Parsing
|
|
this.epubcfi = new EPUBJS.EpubCFI();
|
|
|
|
if(this.settings.axis && this.settings.axis == "horizontal"){
|
|
this.element.style.display = "inline-block";
|
|
} else {
|
|
this.element.style.display = "block";
|
|
}
|
|
|
|
};
|
|
|
|
EPUBJS.View.prototype.create = function() {
|
|
|
|
if(this.iframe) {
|
|
return this.iframe;
|
|
}
|
|
|
|
this.iframe = document.createElement('iframe');
|
|
this.iframe.id = this.id;
|
|
this.iframe.scrolling = "no";
|
|
this.iframe.seamless = "seamless";
|
|
// Back up if seamless isn't supported
|
|
this.iframe.style.border = "none";
|
|
|
|
this.resizing = true;
|
|
|
|
// this.iframe.style.display = "none";
|
|
this.element.style.visibility = "hidden";
|
|
this.iframe.style.visibility = "hidden";
|
|
|
|
this.element.appendChild(this.iframe);
|
|
this.rendered = true;
|
|
|
|
this.elementBounds = EPUBJS.core.bounds(this.element);
|
|
|
|
// if(width || height){
|
|
// this.resize(width, height);
|
|
// } else if(this.width && this.height){
|
|
// this.resize(this.width, this.height);
|
|
// } else {
|
|
// this.iframeBounds = EPUBJS.core.bounds(this.iframe);
|
|
// }
|
|
|
|
// Firefox has trouble with baseURI and srcdoc
|
|
// Disabled for now
|
|
/*
|
|
if(!!("srcdoc" in this.iframe)) {
|
|
this.supportsSrcdoc = true;
|
|
} else {
|
|
this.supportsSrcdoc = false;
|
|
}
|
|
*/
|
|
this.supportsSrcdoc = false;
|
|
|
|
return this.iframe;
|
|
};
|
|
|
|
|
|
EPUBJS.View.prototype.lock = function(what, width, height) {
|
|
|
|
var elBorders = EPUBJS.core.borders(this.element);
|
|
var iframeBorders;
|
|
|
|
if(this.iframe) {
|
|
iframeBorders = EPUBJS.core.borders(this.iframe);
|
|
} else {
|
|
iframeBorders = {width: 0, height: 0};
|
|
}
|
|
|
|
if(what == "width" && EPUBJS.core.isNumber(width)){
|
|
this.lockedWidth = width - elBorders.width - iframeBorders.width;
|
|
this.resize(this.lockedWidth, width); // width keeps ratio correct
|
|
}
|
|
|
|
if(what == "height" && EPUBJS.core.isNumber(height)){
|
|
this.lockedHeight = height - elBorders.height - iframeBorders.height;
|
|
this.resize(width, this.lockedHeight);
|
|
}
|
|
|
|
if(what === "both" &&
|
|
EPUBJS.core.isNumber(width) &&
|
|
EPUBJS.core.isNumber(height)){
|
|
|
|
this.lockedWidth = width - elBorders.width - iframeBorders.width;
|
|
this.lockedHeight = height - elBorders.height - iframeBorders.height;
|
|
|
|
this.resize(this.lockedWidth, this.lockedHeight);
|
|
}
|
|
|
|
if(this.displayed && this.iframe) {
|
|
|
|
this.layout();
|
|
this.expand();
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
EPUBJS.View.prototype.resize = function(width, height) {
|
|
|
|
if(!this.iframe) return;
|
|
|
|
if(EPUBJS.core.isNumber(width)){
|
|
this.iframe.style.width = width + "px";
|
|
}
|
|
|
|
if(EPUBJS.core.isNumber(height)){
|
|
this.iframe.style.height = height + "px";
|
|
}
|
|
|
|
this.iframeBounds = EPUBJS.core.bounds(this.iframe);
|
|
|
|
this.reframe(this.iframeBounds.width, this.iframeBounds.height);
|
|
|
|
};
|
|
|
|
EPUBJS.View.prototype.reframe = function(width, height) {
|
|
//var prevBounds;
|
|
|
|
if(!this.displayed) return;
|
|
|
|
if(EPUBJS.core.isNumber(width)){
|
|
this.element.style.width = width + "px";
|
|
}
|
|
|
|
if(EPUBJS.core.isNumber(height)){
|
|
this.element.style.height = height + "px";
|
|
}
|
|
|
|
this.prevBounds = this.elementBounds;
|
|
|
|
this.elementBounds = EPUBJS.core.bounds(this.element);
|
|
|
|
this.trigger("resized", {
|
|
width: this.elementBounds.width,
|
|
height: this.elementBounds.height,
|
|
widthDelta: this.elementBounds.width - this.prevBounds.width,
|
|
heightDelta: this.elementBounds.height - this.prevBounds.height,
|
|
});
|
|
|
|
};
|
|
|
|
EPUBJS.View.prototype.resized = function(e) {
|
|
/*
|
|
if (!this.resizing) {
|
|
if(this.iframe) {
|
|
// this.expand();
|
|
}
|
|
} else {
|
|
this.resizing = false;
|
|
}*/
|
|
|
|
};
|
|
|
|
EPUBJS.View.prototype.render = function(_request) {
|
|
|
|
// if(this.rendering){
|
|
// return this.displayed;
|
|
// }
|
|
|
|
this.rendering = true;
|
|
// this.displayingDefer = new RSVP.defer();
|
|
// this.displayedPromise = this.displaying.promise;
|
|
|
|
return this.section.render(_request)
|
|
.then(function(contents){
|
|
return this.load(contents);
|
|
}.bind(this));
|
|
};
|
|
|
|
EPUBJS.View.prototype.load = function(contents) {
|
|
var loading = new RSVP.defer();
|
|
var loaded = loading.promise;
|
|
|
|
this.document = this.iframe.contentDocument;
|
|
|
|
if(!this.document) {
|
|
loading.reject(new Error("No Document Available"));
|
|
return loaded;
|
|
}
|
|
|
|
this.iframe.addEventListener("load", function(event) {
|
|
|
|
this.window = this.iframe.contentWindow;
|
|
this.document = this.iframe.contentDocument;
|
|
this.rendering = false;
|
|
loading.resolve(this);
|
|
|
|
}.bind(this));
|
|
|
|
if(this.supportsSrcdoc){
|
|
this.iframe.srcdoc = contents;
|
|
} else {
|
|
this.document.open();
|
|
this.document.write(contents);
|
|
this.document.close();
|
|
}
|
|
|
|
return loaded;
|
|
};
|
|
|
|
|
|
EPUBJS.View.prototype.layout = function(layoutFunc) {
|
|
|
|
this.iframe.style.display = "inline-block";
|
|
|
|
|
|
// Reset Body Styles
|
|
this.document.body.style.margin = "0";
|
|
//this.document.body.style.display = "inline-block";
|
|
//this.document.documentElement.style.width = "auto";
|
|
|
|
if(layoutFunc){
|
|
layoutFunc(this);
|
|
}
|
|
|
|
this.onLayout(this);
|
|
|
|
};
|
|
|
|
EPUBJS.View.prototype.onLayout = function(view) {
|
|
// stub
|
|
};
|
|
|
|
EPUBJS.View.prototype.listeners = function() {
|
|
/*
|
|
setTimeout(function(){
|
|
this.window.addEventListener("resize", this.resized.bind(this), false);
|
|
}.bind(this), 10); // Wait to listen for resize events
|
|
*/
|
|
|
|
// Wait for fonts to load to finish
|
|
// http://dev.w3.org/csswg/css-font-loading/
|
|
// Not implemented fully
|
|
/*
|
|
if(this.document.fonts && this.document.fonts.status === "loading") {
|
|
console.log("fonts unloaded");
|
|
this.document.fonts.onloadingdone = function(){
|
|
console.log("loaded fonts");
|
|
this.expand();
|
|
}.bind(this);
|
|
}
|
|
*/
|
|
if(this.section.properties.indexOf("scripted") > -1){
|
|
this.observer = this.observe(this.document.body);
|
|
}
|
|
|
|
this.imageLoadListeners();
|
|
|
|
this.mediaQueryListeners();
|
|
|
|
};
|
|
|
|
EPUBJS.View.prototype.expand = function() {
|
|
var width = this.lockedWidth;
|
|
var height = this.lockedHeight;
|
|
|
|
// Resize to the locked width;
|
|
//this.resize(width, height);
|
|
|
|
// Expand Vertically
|
|
if(width && !height) {
|
|
height = this.document.documentElement.scrollHeight;
|
|
this.resize(null, height);
|
|
}
|
|
|
|
// Expand Horizontally
|
|
if(height && !width) {
|
|
width = this.document.body.scrollWidth;
|
|
this.resize(width, null);
|
|
};
|
|
|
|
//this.reframe(width, height);
|
|
|
|
};
|
|
|
|
//https://github.com/tylergaw/media-query-events/blob/master/js/mq-events.js
|
|
EPUBJS.View.prototype.mediaQueryListeners = function() {
|
|
var sheets = this.document.styleSheets;
|
|
var mediaChangeHandler = function(m){
|
|
if(m.matches) {
|
|
this.expand();
|
|
}
|
|
}.bind(this);
|
|
|
|
for (var i = 0; i < sheets.length; i += 1) {
|
|
var rules = sheets[i].cssRules;
|
|
|
|
for (var j = 0; j < rules.length; j += 1) {
|
|
//if (rules[j].constructor === CSSMediaRule) {
|
|
if(rules[j].media){
|
|
var mql = this.window.matchMedia(rules[j].media.mediaText);
|
|
mql.addListener(mediaChangeHandler);
|
|
//mql.onchange = mediaChangeHandler;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
EPUBJS.View.prototype.observe = function(target) {
|
|
var renderer = this;
|
|
|
|
// create an observer instance
|
|
var observer = new MutationObserver(function(mutations) {
|
|
renderer.expand();
|
|
// mutations.forEach(function(mutation) {
|
|
// console.log(mutation);
|
|
// });
|
|
});
|
|
|
|
// configuration of the observer:
|
|
var config = { attributes: true, childList: true, characterData: true, subtree: true };
|
|
|
|
// pass in the target node, as well as the observer options
|
|
observer.observe(target, config);
|
|
|
|
return observer;
|
|
};
|
|
|
|
// EPUBJS.View.prototype.appendTo = function(element) {
|
|
// this.element = element;
|
|
// this.element.appendChild(this.iframe);
|
|
// };
|
|
//
|
|
// EPUBJS.View.prototype.prependTo = function(element) {
|
|
// this.element = element;
|
|
// element.insertBefore(this.iframe, element.firstChild);
|
|
// };
|
|
|
|
EPUBJS.View.prototype.imageLoadListeners = function(target) {
|
|
var images = this.document.body.querySelectorAll("img");
|
|
var img;
|
|
for (var i = 0; i < images.length; i++) {
|
|
img = images[i];
|
|
|
|
if (typeof img.naturalWidth !== "undefined" &&
|
|
img.naturalWidth === 0) {
|
|
img.onload = this.expand.bind(this);
|
|
}
|
|
}
|
|
};
|
|
|
|
EPUBJS.View.prototype.display = function() {
|
|
var displayed = new RSVP.defer();
|
|
|
|
this.displayed = true;
|
|
|
|
this.layout();
|
|
|
|
this.listeners();
|
|
|
|
this.expand();
|
|
|
|
this.trigger("displayed", this);
|
|
this.onDisplayed(this);
|
|
|
|
displayed.resolve(this);
|
|
|
|
return displayed.promise;
|
|
};
|
|
|
|
EPUBJS.View.prototype.show = function() {
|
|
|
|
this.element.style.visibility = "visible";
|
|
|
|
if(this.iframe){
|
|
this.iframe.style.visibility = "visible";
|
|
}
|
|
|
|
this.trigger("shown", this);
|
|
};
|
|
|
|
EPUBJS.View.prototype.hide = function() {
|
|
// this.iframe.style.display = "none";
|
|
this.element.style.visibility = "hidden";
|
|
this.iframe.style.visibility = "hidden";
|
|
|
|
this.stopExpanding = true;
|
|
this.trigger("hidden", this);
|
|
};
|
|
|
|
EPUBJS.View.prototype.position = function() {
|
|
return this.element.getBoundingClientRect();
|
|
};
|
|
|
|
EPUBJS.View.prototype.onDisplayed = function(view) {
|
|
// Stub, override with a custom functions
|
|
};
|
|
|
|
EPUBJS.View.prototype.bounds = function() {
|
|
if(!this.elementBounds) {
|
|
this.elementBounds = EPUBJS.core.bounds(this.element);
|
|
}
|
|
return this.elementBounds;
|
|
};
|
|
|
|
EPUBJS.View.prototype.destroy = function() {
|
|
// Stop observing
|
|
if(this.observer) {
|
|
this.observer.disconnect();
|
|
}
|
|
|
|
if(this.displayed){
|
|
this.stopExpanding = true;
|
|
this.element.removeChild(this.iframe);
|
|
this.displayed = false;
|
|
this.iframe = null;
|
|
}
|
|
|
|
// this.element.style.height = "0px";
|
|
// this.element.style.width = "0px";
|
|
};
|
|
|
|
EPUBJS.View.prototype.root = function() {
|
|
if(!this.document) return null;
|
|
return this.document.documentElement;
|
|
};
|
|
|
|
EPUBJS.View.prototype.locationOf = function(target) {
|
|
|
|
if(!this.document) return;
|
|
|
|
if(this.epubcfi.isCfiString(target)) {
|
|
cfi = this.epubcfi.parse(target);
|
|
|
|
if(typeof document.evaluate === 'undefined') {
|
|
marker = this.epubcfi.addMarker(cfi, this.document);
|
|
if(marker) {
|
|
// Must Clean up Marker before going to page
|
|
this.epubcfi.removeMarker(marker, this.document);
|
|
|
|
return marker.getBoundingClientRect();
|
|
}
|
|
} else {
|
|
range = this.epubcfi.generateRangeFromCfi(cfi, this.document);
|
|
if(range) {
|
|
return range.getBoundingClientRect();
|
|
}
|
|
}
|
|
} else if(typeof target === "string" &&
|
|
target.indexOf("#") > -1) {
|
|
|
|
id = target.substring(target.indexOf("#"));
|
|
el = this.document.getElementById(id);
|
|
|
|
if(el) {
|
|
return el.getBoundingClientRect();
|
|
}
|
|
}
|
|
|
|
return {"left": 0, "top": 0};
|
|
};
|
|
|
|
|
|
RSVP.EventTarget.mixin(EPUBJS.View.prototype); |