Skip to content
This repository has been archived by the owner on Jan 17, 2023. It is now read-only.

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
dannycoates committed Mar 21, 2017
1 parent 0c94071 commit ce56d0c
Show file tree
Hide file tree
Showing 2 changed files with 201 additions and 71 deletions.
230 changes: 178 additions & 52 deletions addon/webextension/selector/ui.js
Expand Up @@ -48,17 +48,17 @@ window.ui = (function () { // eslint-disable-line no-unused-vars
});

function makeEl(tagName, className) {
if (! iframe.document) {
if (! iframe.document()) {
throw new Error("Attempted makeEl before iframe was initialized");
}
let el = iframe.document.createElement(tagName);
let el = iframe.document().createElement(tagName);
if (className) {
el.className = className;
}
return el;
}

let iframe = exports.iframe = {
let iframeSelection = exports.iframeSelection = {
element: null,
addClassName: "",
sizeTracking: {
Expand All @@ -74,6 +74,7 @@ window.ui = (function () { // eslint-disable-line no-unused-vars
if (! this.element) {
this.element = document.createElement("iframe");
this.element.id = "pageshot-iframe";
this.element.style.display = "none";
this.element.style.zIndex = "99999999999";
this.element.style.border = "none";
this.element.style.position = "absolute";
Expand Down Expand Up @@ -150,7 +151,6 @@ window.ui = (function () { // eslint-disable-line no-unused-vars
if (force) {
this.element.style.display = "";
}
WholePageOverlay.resetPosition();
},

initSizeWatch: function () {
Expand Down Expand Up @@ -197,22 +197,18 @@ window.ui = (function () { // eslint-disable-line no-unused-vars
util.removeNode(this.element);
this.element = this.document = null;
}
};

iframe.onResize = watchFunction(iframe.onResize.bind(iframe));
};

/** Represents the shadow overlay that covers the whole page */
let WholePageOverlay = exports.WholePageOverlay = {
let PreSelectionOverlay = {

el: null,
movingEl: null,
isScrollTracking: false,

display: function (callbacks) {
this.remove();
this.el = makeEl("div", "pageshot-preview-overlay");
this.el.innerHTML = `
<div class="pageshot-moving-element" style="position: absolute; pointer-events: none; display: flex">
<div class="pageshot-moving-element">
<div class="pageshot-preview-instructions"></div>
<div class="pageshot-myshots pageshot-myshots-button">
<div class="pageshot-pre-myshots"></div>
Expand All @@ -221,6 +217,7 @@ window.ui = (function () { // eslint-disable-line no-unused-vars
</div>
<div class="pageshot-overlay-button pageshot-visible"></div>
<div class="pageshot-overlay-button pageshot-full-page"></div>
</div>
`;
this.el.querySelector(".pageshot-preview-instructions").textContent = browser.i18n.getMessage("screenshotInstructions");
this.el.querySelector(".pageshot-myshots-text").textContent = browser.i18n.getMessage("myShotsLink");
Expand All @@ -232,49 +229,179 @@ window.ui = (function () { // eslint-disable-line no-unused-vars
"click", watchFunction(callbacks.onClickVisible), false);
this.el.querySelector(".pageshot-full-page").addEventListener(
"click", watchFunction(callbacks.onClickFullPage), false);
this.movingEl = this.el.querySelector(".pageshot-moving-element");
iframe.document.body.appendChild(this.el);
this.resetPosition();
iframePreSelection.document.body.appendChild(this.el);
window.addEventListener("scroll", this.onScroll, false);
},

resetPosition: function () {
if (! this.movingEl) {
return;
remove: function () {
util.removeNode(this.el);
this.el = null;
}
};

let iframePreSelection = exports.iframePreSelection = {
element: null,
document: null,
sizeTracking: {
windowDelayer: null,
resizeBound: null,
lastHeight: null,
lastWidth: null
},
display: function (installHandlerOnDocument, standardOverlayCallbacks) {
return new Promise((resolve, reject) => {
if (! this.element) {
this.element = document.createElement("iframe");
this.element.id = "pageshot-iframe";
this.element.style.zIndex = "99999999999";
this.element.style.border = "none";
this.element.style.position = "fixed";
this.element.style.top = "0";
this.element.style.left = "0";
this.element.style.margin = "0";
this.element.scrolling = "no";
this.updateElementSize();
this.element.onload = watchFunction(() => {
let parsedDom = (new DOMParser()).parseFromString(`
<html>
<head>
<style>${substitutedCss}</style>
<title></title>
</head>
<body></body>
</html>`,
"text/html"
);
this.document = this.element.contentDocument;
this.document.replaceChild(
this.document.adoptNode(parsedDom.documentElement),
this.document.documentElement
);
installHandlerOnDocument(this.document);
if (this.addClassName) {
this.document.body.className = this.addClassName;
}
PreSelectionOverlay.display(standardOverlayCallbacks);
resolve();
});
document.body.appendChild(this.element);
window.addEventListener("scroll", this.onScroll, false);
} else {
resolve();
}
});
},
updateElementSize: function (force) {
// Note: if someone sizes down the page, then the iframe will keep the
// document from naturally shrinking. We use force to temporarily hide
// the element so that we can tell if the document shrinks
if (force) {
this.element.style.display = "none";
}
let height = Math.max(
document.documentElement.clientHeight,
window.innerHeight);
if (height !== this.sizeTracking.lastHeight) {
this.sizeTracking.lastHeight = height;
this.element.style.height = height + "px";
}
let width = Math.max(
document.documentElement.clientWidth,
window.innerWidth);
if (width !== this.sizeTracking.lastWidth) {
this.sizeTracking.lastWidth = width;
this.element.style.width = width + "px";
}
if (force) {
this.element.style.display = "";
}
let scrollX = window.scrollX;
let scrollY = window.scrollY;
this.movingEl.style.top = scrollY + "px";
this.movingEl.style.left = scrollX + "px";
this.movingEl.style.width = window.innerWidth + "px";
this.movingEl.style.height = window.innerHeight + "px";
},

hide: function () {
this.element.style.display = "none";
},
unhide: function () {
this.element.style.display = "";
},
onResize: function () {
if (this.sizeTracking.windowDelayer) {
clearTimeout(this.sizeTracking.windowDelayer);
}
this.sizeTracking.windowDelayer = setTimeout(watchFunction(() => {
this.updateElementSize(true);
}), 100);
},
onScroll: function () {
this.resetPosition();
/* Note, if we used requestAnimationFrame we'd improve the performance
some, but this creates very visible lag in the positioning: */
/*
if (! this.isScrollTracking) {
window.requestAnimationFrame(() => {
this.resetPosition();
this.isScrollTracking = false;
});
this.isScrollTracking = true;
exports.HoverBox.hide();
},
getElementFromPoint: function (x, y) {
this.element.style.pointerEvents = "none";
let el;
try {
el = document.elementFromPoint(x, y);
} finally {
this.element.style.pointerEvents = "";
}
*/
return el;
},

remove: function () {
util.removeNode(this.el);
this.el = null;
this.movingEl = null;
window.removeEventListener("scroll", this.onScroll, false);
util.removeNode(this.element);
this.element = null;
this.document = null;
}

};

WholePageOverlay.onScroll = watchFunction(WholePageOverlay.onScroll.bind(WholePageOverlay));
let iframe = exports.iframe = {
currentIframe: iframePreSelection,
display: function (installHandlerOnDocument, standardOverlayCallbacks) {
return iframeSelection.display(installHandlerOnDocument)
.then(() => iframePreSelection.display(installHandlerOnDocument, standardOverlayCallbacks))
},
updateElementSize: function (force) {
iframePreSelection.updateElementSize(force);
iframeSelection.updateElementSize(force);
},
initSizeWatch: function () {
iframeSelection.initSizeWatch();
},
stopSizeWatch: function () {
iframeSelection.stopSizeWatch();
},
hide: function () {
this.currentIframe.hide();
},
unhide: function () {
this.currentIframe.unhide();
},
onResize: function () {

},
onScroll: function () {},
getElementFromPoint: function (x, y) {
return this.currentIframe.getElementFromPoint(x, y);
},
remove: function () {
iframeSelection.remove();
iframePreSelection.remove();
},
document: function () {
return this.currentIframe.document;
},
useSelection: function () {
if (this.currentIframe === iframePreSelection) {
this.hide();
}
this.currentIframe = iframeSelection;
this.unhide();
},
usePreSelection: function () {
if (this.currentIframe === iframeSelection) {
this.hide();
}
this.currentIframe = iframePreSelection;
this.unhide();
}
};

let movements = ["topLeft", "top", "topRight", "left", "right", "bottomLeft", "bottom", "bottomRight"];

Expand Down Expand Up @@ -357,7 +484,6 @@ window.ui = (function () { // eslint-disable-line no-unused-vars
this.bgRight.style.height = pos.bottom - pos.top + "px";
this.bgRight.style.left = (pos.right - bodyRect.left) + "px";
this.bgRight.style.width = docWidth - (pos.right - bodyRect.left) + "px";
WholePageOverlay.remove();
},

remove: function () {
Expand Down Expand Up @@ -397,14 +523,14 @@ window.ui = (function () { // eslint-disable-line no-unused-vars
boxEl.appendChild(elTarget);
}
this.bgTop = makeEl("div", "pageshot-bghighlight");
iframe.document.body.appendChild(this.bgTop);
iframe.document().body.appendChild(this.bgTop);
this.bgLeft = makeEl("div", "pageshot-bghighlight");
iframe.document.body.appendChild(this.bgLeft);
iframe.document().body.appendChild(this.bgLeft);
this.bgRight = makeEl("div", "pageshot-bghighlight");
iframe.document.body.appendChild(this.bgRight);
iframe.document().body.appendChild(this.bgRight);
this.bgBottom = makeEl("div", "pageshot-bghighlight");
iframe.document.body.appendChild(this.bgBottom);
iframe.document.body.appendChild(boxEl);
iframe.document().body.appendChild(this.bgBottom);
iframe.document().body.appendChild(boxEl);
this.el = boxEl;
},

Expand Down Expand Up @@ -463,7 +589,7 @@ window.ui = (function () { // eslint-disable-line no-unused-vars
display: function (rect) {
if (! this.el) {
this.el = makeEl("div", "pageshot-hover-highlight");
iframe.document.body.appendChild(this.el);
iframe.document().body.appendChild(this.el);
}
this.el.style.display = "";
this.el.style.top = (rect.top - 1) + "px";
Expand Down Expand Up @@ -495,7 +621,7 @@ window.ui = (function () { // eslint-disable-line no-unused-vars
this.el.appendChild(this.xEl);
this.yEl = makeEl("div");
this.el.appendChild(this.yEl);
iframe.document.body.appendChild(this.el);
iframe.document().body.appendChild(this.el);
}
this.xEl.textContent = x;
this.yEl.textContent = y;
Expand All @@ -511,15 +637,15 @@ window.ui = (function () { // eslint-disable-line no-unused-vars
/** Removes every UI this module creates */
exports.remove = function () {
for (let name in exports) {
if (name == "iframe") {
if (name.startsWith("iframe")) {
continue;
}
if (typeof exports[name] == "object" && exports[name].remove) {
exports[name].remove();
}
}
exports.iframe.remove();
exports.Box.remove();
exports.iframeSelection.remove();
exports.iframePreSelection.remove();
};

exports.triggerDownload = function (dataUrl, filename) {
Expand Down

0 comments on commit ce56d0c

Please sign in to comment.