2016-11-23 23:48:47 +11:00
|
|
|
/*
|
|
|
|
|
* Copyright 2016 Michael Gratton <mike@vee.net>
|
|
|
|
|
*
|
|
|
|
|
* This software is licensed under the GNU Lesser General Public License
|
|
|
|
|
* (version 2.1 or later). See the COPYING file in this distribution.
|
|
|
|
|
*/
|
|
|
|
|
|
2016-11-24 23:42:28 +11:00
|
|
|
/**
|
|
|
|
|
* Application logic for ClientWebView and subclasses.
|
|
|
|
|
*/
|
|
|
|
|
|
2017-01-04 01:15:08 +11:00
|
|
|
let PageState = function() {
|
2016-11-25 22:00:06 +11:00
|
|
|
this.init.apply(this, arguments);
|
|
|
|
|
};
|
2016-11-25 16:30:50 +11:00
|
|
|
PageState.prototype = {
|
2016-11-25 22:00:06 +11:00
|
|
|
init: function() {
|
|
|
|
|
this.allowRemoteImages = false;
|
2017-01-17 23:40:40 +11:00
|
|
|
this.isLoaded = false;
|
2017-01-19 01:58:26 +11:00
|
|
|
this.hasSelection = false;
|
2017-01-24 19:30:12 +11:00
|
|
|
this.lastPreferredHeight = 0;
|
2016-11-25 22:00:06 +11:00
|
|
|
|
2017-01-04 01:15:08 +11:00
|
|
|
let state = this;
|
2017-01-24 19:30:12 +11:00
|
|
|
|
|
|
|
|
// Coalesce multiple calls to updatePreferredHeight using a
|
|
|
|
|
// timeout to avoid the overhead of multiple JS messages sent
|
|
|
|
|
// to the app and hence view multiple resizes being queued.
|
|
|
|
|
let queueTimeout = null;
|
|
|
|
|
let queuePreferredHeightUpdate = function() {
|
|
|
|
|
if (queueTimeout != null) {
|
|
|
|
|
clearTimeout(queueTimeout);
|
2016-11-25 22:00:06 +11:00
|
|
|
}
|
2017-01-24 19:30:12 +11:00
|
|
|
queueTimeout = setTimeout(
|
|
|
|
|
function() { state.updatePreferredHeight(); }, 10
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Queues an update after the DOM has been initially loaded
|
|
|
|
|
// and had any changes made to it by derived classes.
|
|
|
|
|
document.addEventListener("DOMContentLoaded", function(e) {
|
|
|
|
|
state.loaded();
|
|
|
|
|
queuePreferredHeightUpdate();
|
|
|
|
|
});
|
2017-02-08 00:28:46 +11:00
|
|
|
|
|
|
|
|
// Queues an update when the complete document is loaded.
|
2017-01-24 19:30:12 +11:00
|
|
|
//
|
2017-02-08 00:28:46 +11:00
|
|
|
// Note also that the delay introduced here by this last call
|
2017-01-24 19:30:12 +11:00
|
|
|
// to queuePreferredHeightUpdate when the complete document is
|
|
|
|
|
// loaded seems to be important to get an acurate idea of the
|
|
|
|
|
// final document size.
|
2017-02-08 00:28:46 +11:00
|
|
|
window.addEventListener("load", function(e) {
|
|
|
|
|
queuePreferredHeightUpdate();
|
|
|
|
|
}, true); // load does not bubble
|
|
|
|
|
|
|
|
|
|
// Queues updates for any STYLE, IMG and other loaded
|
|
|
|
|
// elements, hence handles resizing when the user later
|
|
|
|
|
// requests remote images loading.
|
2017-01-24 19:30:12 +11:00
|
|
|
document.addEventListener("load", function(e) {
|
|
|
|
|
queuePreferredHeightUpdate();
|
2017-02-08 00:28:46 +11:00
|
|
|
}, true); // load does not bubble
|
2018-10-14 11:52:52 +11:00
|
|
|
|
|
|
|
|
// Queues an update if the window changes size, e.g. if the
|
|
|
|
|
// user resized the window
|
|
|
|
|
window.addEventListener("resize", function(e) {
|
|
|
|
|
queuePreferredHeightUpdate();
|
|
|
|
|
}, false); // load does not bubble
|
|
|
|
|
|
|
|
|
|
// Queues an update when a transition has completed, e.g. if the
|
|
|
|
|
// user resized the window
|
|
|
|
|
window.addEventListener("transitionend", function(e) {
|
|
|
|
|
queuePreferredHeightUpdate();
|
|
|
|
|
}, false); // load does not bubble
|
2016-11-25 22:00:06 +11:00
|
|
|
},
|
2017-01-04 01:10:38 +11:00
|
|
|
getPreferredHeight: function() {
|
2018-10-14 11:55:46 +11:00
|
|
|
return window.document.documentElement.scrollHeight;
|
2017-01-04 01:10:38 +11:00
|
|
|
},
|
2016-11-27 21:03:52 +11:00
|
|
|
loaded: function() {
|
2017-01-17 23:40:40 +11:00
|
|
|
this.isLoaded = true;
|
2017-11-16 12:44:57 +11:00
|
|
|
window.webkit.messageHandlers.contentLoaded.postMessage(null);
|
2016-11-27 21:03:52 +11:00
|
|
|
},
|
2016-11-25 16:30:50 +11:00
|
|
|
loadRemoteImages: function() {
|
|
|
|
|
this.allowRemoteImages = true;
|
2017-01-04 01:15:08 +11:00
|
|
|
let images = document.getElementsByTagName("IMG");
|
|
|
|
|
for (let i = 0; i < images.length; i++) {
|
|
|
|
|
let img = images.item(i);
|
|
|
|
|
let src = img.src;
|
2016-11-25 16:30:50 +11:00
|
|
|
img.src = "";
|
|
|
|
|
img.src = src;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
remoteImageLoadBlocked: function() {
|
|
|
|
|
window.webkit.messageHandlers.remoteImageLoadBlocked.postMessage(null);
|
2016-11-25 22:00:06 +11:00
|
|
|
},
|
2017-01-24 19:30:12 +11:00
|
|
|
/**
|
|
|
|
|
* Sends "preferredHeightChanged" message if it has changed.
|
|
|
|
|
*/
|
2017-01-30 01:01:56 +11:00
|
|
|
updatePreferredHeight: function(height) {
|
|
|
|
|
if (height === undefined) {
|
|
|
|
|
height = this.getPreferredHeight();
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-24 19:30:12 +11:00
|
|
|
let updated = false;
|
|
|
|
|
if (height > 0 && height != this.lastPreferredHeight) {
|
|
|
|
|
updated = true;
|
|
|
|
|
this.lastPreferredHeight = height;
|
2016-11-25 22:00:06 +11:00
|
|
|
window.webkit.messageHandlers.preferredHeightChanged.postMessage(
|
|
|
|
|
height
|
|
|
|
|
);
|
|
|
|
|
}
|
2017-01-24 19:30:12 +11:00
|
|
|
return updated;
|
2016-11-27 11:24:09 +11:00
|
|
|
},
|
|
|
|
|
selectionChanged: function() {
|
2017-01-17 23:40:40 +11:00
|
|
|
let hasSelection = !window.getSelection().isCollapsed;
|
2017-01-19 01:58:26 +11:00
|
|
|
if (this.hasSelection != hasSelection) {
|
|
|
|
|
this.hasSelection = hasSelection;
|
|
|
|
|
window.webkit.messageHandlers.selectionChanged.postMessage(hasSelection);
|
|
|
|
|
}
|
2016-11-25 16:30:50 +11:00
|
|
|
}
|
|
|
|
|
};
|