1
0
Fork 0
mirror of https://github.com/futurepress/epub.js.git synced 2025-10-03 14:59:18 +02:00
epub.js/lib/epubjs/view.js
2015-06-05 15:20:45 -04:00

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);