Compare commits
10 Commits
83845b6f37
...
ad53ce97ff
Author | SHA1 | Date | |
---|---|---|---|
|
ad53ce97ff | ||
|
ca7cef992a | ||
|
00d1cdfc86 | ||
|
ce236254d2 | ||
|
f3797e0f5f | ||
|
b3f35d1a81 | ||
|
4c4372833e | ||
|
60b0b785fc | ||
|
78acccd0ac | ||
|
abd8c2536a |
7
README.md
Normal file
7
README.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
# SiteFalconIOWidget
|
||||
|
||||
Site Falcon IO was a business ideas that I decided to make open source. It comprises a Web Component widget developed using raw HTML, JS and CSS. This repository is still in testing and not yet publicised.
|
||||
|
||||
The widget is a simple web component that can be embedded into any website and allows users to provide feedback by interacting with it. The feedback can also include screenshots of the website. This has proven to be the most challenging component of the project due to cross-origin content. The W3C spec that most browsers implement prohibits the downloading of content originating outside the origin of the current site-hosting server. Thus, any images on a website that are served from a different origin will taint any HTML canvases that are painted with their content. The work-around is to either use a proxy-server or the `getDisplayMedia` JS API. The latter requires asking for user permission each invocation which is sub-optimal. In summary, this project is still ongoing.
|
||||
|
||||
In its completed form, this widget will save web developers considerable time and hassle when it comes to ascertaining beta/alpha testing feedback from users because such users can provide feedback directly on the site, thus preventing bogged down email chain discussions.
|
BIN
icon_close.png
BIN
icon_close.png
Binary file not shown.
Before Width: | Height: | Size: 7.5 KiB |
File diff suppressed because it is too large
Load Diff
|
@ -1,143 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div>
|
||||
<style>
|
||||
p {
|
||||
font-size: 24;
|
||||
}
|
||||
</style>
|
||||
<div style="height: 50px; width: 10000px; background-color: blue;"></div>
|
||||
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
v
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
</div>
|
||||
|
||||
<div id="widget" style="position: fixed; top: 0px; left: 0px; width: 100px; height: 100px; background-color: red;"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
let widget = document.getElementById("widget");
|
||||
|
||||
let isDown = false;
|
||||
|
||||
function onMouseDown(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
isDown = true;
|
||||
|
||||
this.setPointerCapture(e.pointerId);
|
||||
}
|
||||
|
||||
function setCorner(anchorX, anchorY, element) {
|
||||
let offsets = element.getBoundingClientRect();
|
||||
|
||||
if (anchorX < window.innerWidth / 2){
|
||||
// left half
|
||||
if (anchorY < window.innerHeight / 2) {
|
||||
// top left
|
||||
element.style.left = "0px";
|
||||
element.style.top = "0px";
|
||||
}
|
||||
else {
|
||||
// bottom left
|
||||
element.style.left = "0px";
|
||||
element.style.top = window.innerHeight - offsets.height + "px";
|
||||
}
|
||||
}
|
||||
else {
|
||||
// right half
|
||||
if (anchorY < window.innerHeight / 2) {
|
||||
// top right
|
||||
element.style.left = window.innerWidth - offsets.width + "px";4
|
||||
element.style.top = "0px";
|
||||
}
|
||||
else {
|
||||
// bottom right
|
||||
element.style.left = window.innerWidth - offsets.width + "px";
|
||||
element.style.top = window.innerHeight - offsets.height + "px";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseMove(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if (isDown) {
|
||||
setCorner(e.clientX, e.clientY, this);
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseUp(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
isDown = false;
|
||||
|
||||
this.releasePointerCapture(e.pointerId);
|
||||
}
|
||||
|
||||
function onMouseLeave(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if (isDown) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
widget.addEventListener("pointerdown", onMouseDown);
|
||||
widget.addEventListener("pointermove", onMouseMove);
|
||||
widget.addEventListener("pointerleave", onMouseLeave);
|
||||
widget.addEventListener("pointerup", onMouseUp);
|
||||
|
||||
window.addEventListener("resize", () => {
|
||||
let offsets = widget.getBoundingClientRect();
|
||||
setCorner(offsets.left, offsets.top, widget);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,288 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<script src=
|
||||
"https://cdn.jsdelivr.net/npm/html2canvas@1.0.0-rc.5/dist/html2canvas.min.js">
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div>
|
||||
<style>
|
||||
p {
|
||||
font-size: 24;
|
||||
}
|
||||
</style>
|
||||
|
||||
<img />
|
||||
|
||||
<button id="snapshot-button">Take snapshot</button>
|
||||
|
||||
<div style="height: 50px; width: 10000px; background-color: blue;"></div>
|
||||
<!-- <img width="400px" height="700px" src="alley.jpg" /> -->
|
||||
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
v
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
let canvas = document.createElement("canvas");
|
||||
document.body.appendChild(canvas);
|
||||
canvas.style = "position: fixed; top: 0px; left: 0px; cursor: crosshair;";
|
||||
|
||||
function setCanvasDimensions(canvas) {
|
||||
let bodyMarginLeft = window.getComputedStyle(document.body).getPropertyValue('margin-left');
|
||||
let bodyMarginRight = window.getComputedStyle(document.body).getPropertyValue('margin-right');
|
||||
if (bodyMarginLeft || bodyMarginRight) {
|
||||
canvas.width = document.body.offsetWidth + parseInt(bodyMarginLeft) + parseInt(bodyMarginRight);
|
||||
}
|
||||
else {
|
||||
canvas.width = document.body.offsetWidth;
|
||||
}
|
||||
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
canvas.hidden = true;
|
||||
}
|
||||
|
||||
setCanvasDimensions(canvas);
|
||||
window.addEventListener("resize", () => setCanvasDimensions(canvas))
|
||||
|
||||
let ctx = canvas.getContext("2d");
|
||||
|
||||
let hiddenCanvas = document.createElement("canvas");
|
||||
document.body.appendChild(hiddenCanvas);
|
||||
|
||||
hiddenCanvas.hidden = true;
|
||||
|
||||
let hiddenCtx = hiddenCanvas.getContext("2d");
|
||||
|
||||
let initialX;
|
||||
let initialY;
|
||||
|
||||
let isDown = false;
|
||||
|
||||
function onMouseDown(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
initialX = e.offsetX;
|
||||
initialY = e.offsetY;
|
||||
|
||||
isDown = true;
|
||||
|
||||
this.setPointerCapture(e.pointerId);
|
||||
}
|
||||
|
||||
function onMouseMove(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if (isDown) {
|
||||
let offsetX;
|
||||
let offsetY;
|
||||
|
||||
if (e.offsetX < 0) {
|
||||
offsetX = 0;
|
||||
}
|
||||
else if (e.offsetX > canvas.width - 1) {
|
||||
offsetX = canvas.width - 1;
|
||||
}
|
||||
else {
|
||||
offsetX = e.offsetX;
|
||||
}
|
||||
|
||||
if (e.offsetY < 0) {
|
||||
offsetY = 0;
|
||||
}
|
||||
else if (e.offsetY > canvas.height - 1) {
|
||||
offsetY = canvas.height - 1;
|
||||
}
|
||||
else {
|
||||
offsetY = e.offsetY;
|
||||
}
|
||||
|
||||
let width = offsetX - initialX;
|
||||
let height = offsetY - initialY;
|
||||
|
||||
setCanvas();
|
||||
ctx.beginPath();
|
||||
ctx.clearRect(initialX, initialY, width, height);
|
||||
ctx.rect(initialX, initialY, width, height);
|
||||
ctx.stroke();
|
||||
ctx.closePath();
|
||||
}
|
||||
}
|
||||
|
||||
async function onMouseUp(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if (isDown) {
|
||||
let offsetX;
|
||||
let offsetY;
|
||||
|
||||
if (e.offsetX < 0) {
|
||||
offsetX = 0;
|
||||
}
|
||||
else if (e.offsetX > canvas.width - 1) {
|
||||
offsetX = canvas.width - 1;
|
||||
}
|
||||
else {
|
||||
offsetX = e.offsetX;
|
||||
}
|
||||
|
||||
if (e.offsetY < 0) {
|
||||
offsetY = 0;
|
||||
}
|
||||
else if (e.offsetY > canvas.height - 1) {
|
||||
offsetY = canvas.height - 1;
|
||||
}
|
||||
else {
|
||||
offsetY = e.offsetY;
|
||||
}
|
||||
|
||||
unloadCanvas();
|
||||
this.releasePointerCapture(e.pointerId);
|
||||
|
||||
if (Math.abs(offsetX - initialX) > 10 && Math.abs(offsetY - initialY) > 10) {
|
||||
await takeScreenshot(offsetX, offsetY);
|
||||
}
|
||||
|
||||
initialX = null;
|
||||
initialY = null;
|
||||
isDown = false;
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseLeave(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if (isDown) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
async function takeScreenshot(offsetX, offsetY) {
|
||||
let width = offsetX - initialX;
|
||||
let height = offsetY - initialY;
|
||||
let offsetInitialX = initialX;
|
||||
let offsetInitialY = initialY;
|
||||
|
||||
if (width < 0) {
|
||||
width = width * -1;
|
||||
offsetInitialX = initialX - width;
|
||||
}
|
||||
|
||||
if (height < 0) {
|
||||
height = height * -1;
|
||||
offsetInitialY = initialY - height;
|
||||
}
|
||||
|
||||
let documentCanvas;
|
||||
|
||||
await html2canvas(document.body, {
|
||||
logging: true,
|
||||
letterRendering: 1,
|
||||
allowTaint: true,
|
||||
useCORS: true
|
||||
}).then(
|
||||
function (canvas) {
|
||||
console.log("nice")
|
||||
documentCanvas = canvas;
|
||||
});
|
||||
|
||||
return;
|
||||
|
||||
hiddenCanvas.width = width;
|
||||
hiddenCanvas.height = height;
|
||||
hiddenCtx.drawImage(documentCanvas, offsetInitialX, offsetInitialY, width, height, 0, 0, width, height);
|
||||
|
||||
let base64image = canvas.toDataURL("image/png");
|
||||
console.log(base64image);
|
||||
|
||||
hiddenCtx.clearRect(0, 0, hiddenCanvas.width, hiddenCanvas.height);
|
||||
|
||||
hiddenCanvas.width = 0;
|
||||
hiddenCanvas.height = 0;
|
||||
}
|
||||
|
||||
function setCanvas() {
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
ctx.globalAlpha = 0.5;
|
||||
ctx.fillStyle = "white";
|
||||
ctx.beginPath();
|
||||
ctx.rect(0, 0, canvas.width, canvas.height);
|
||||
ctx.fill();
|
||||
ctx.closePath();
|
||||
|
||||
setBrush();
|
||||
}
|
||||
|
||||
function setBrush() {
|
||||
ctx.globalAlpha = 1;
|
||||
ctx.strokeStyle = 'red';
|
||||
}
|
||||
|
||||
canvas.addEventListener("pointerdown", onMouseDown);
|
||||
canvas.addEventListener("pointermove", onMouseMove);
|
||||
canvas.addEventListener("pointerleave", onMouseLeave);
|
||||
canvas.addEventListener("pointerup", onMouseUp);
|
||||
|
||||
function loadCanvas() {
|
||||
setCanvas();
|
||||
canvas.hidden = false;
|
||||
}
|
||||
|
||||
function unloadCanvas() {
|
||||
setCanvas();
|
||||
canvas.hidden = true;
|
||||
}
|
||||
|
||||
let snapshotButton = document.getElementById("snapshot-button");
|
||||
|
||||
snapshotButton.addEventListener("click", () => { loadCanvas() });
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,27 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<script src=
|
||||
"https://cdn.jsdelivr.net/npm/html2canvas@1.0.0-rc.5/dist/html2canvas.min.js">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="capture" style="padding: 10px; background: #f5da55">
|
||||
<h4 style="color: #000; ">Hello wytorld!</h4>
|
||||
<img width="400px" height="700px" src="alley.jpg" />
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
async function Do() {
|
||||
await html2canvas(document.body)
|
||||
.then(
|
||||
function (canvas) {
|
||||
document.body.appendChild(canvas);
|
||||
});
|
||||
}
|
||||
|
||||
Do();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
197
old/Widget.html
197
old/Widget.html
|
@ -1,197 +0,0 @@
|
|||
<html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div>
|
||||
<style>
|
||||
p {
|
||||
font-size: 24;
|
||||
}
|
||||
</style>
|
||||
|
||||
<img />
|
||||
|
||||
<button id="snapshot-button">Take snapshot</button>
|
||||
|
||||
<div style="height: 50px; width: 10000px; background-color: blue;"></div>
|
||||
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
v
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
</div>
|
||||
|
||||
<x-widget></x-widget>
|
||||
|
||||
<script>
|
||||
class XWidget extends HTMLElement {
|
||||
frame;
|
||||
icon;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
const shadowRoot = this.attachShadow({mode: 'open'});
|
||||
|
||||
let frame = document.createElement("div");
|
||||
frame.style.position = "fixed";
|
||||
frame.style.top = "0px";
|
||||
frame.style.left = "0px";
|
||||
frame.style.right = "0px";
|
||||
frame.style.bottom = "0px";
|
||||
frame.style.border = "5px dotted blue";
|
||||
shadowRoot.append(frame);
|
||||
this.frame = frame;
|
||||
|
||||
let icon = document.createElement("x-widget-icon");
|
||||
this.frame.appendChild(icon);
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
}
|
||||
}
|
||||
|
||||
class XWidgetIcon extends HTMLElement {
|
||||
iconContainer;
|
||||
isPressed;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
const shadowRoot = this.attachShadow({mode: 'open'});
|
||||
|
||||
let iconContainer = document.createElement("div");
|
||||
shadowRoot.append(iconContainer);
|
||||
this.iconContainer = iconContainer;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.#render();
|
||||
|
||||
this.isPressed = false;
|
||||
|
||||
this.iconContainer.addEventListener("pointerdown", (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
this.isPressed = true;
|
||||
|
||||
this.iconContainer.setPointerCapture(e.pointerId);
|
||||
});
|
||||
|
||||
this.iconContainer.addEventListener("pointermove", (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if (this.isPressed) {
|
||||
this.#snapToCorner();
|
||||
}
|
||||
});
|
||||
|
||||
this.iconContainer.addEventListener("pointerleave", (e) => {
|
||||
if (this.isPressed) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
this.iconContainer.addEventListener("pointerup", (e) => {
|
||||
this.isPressed = false;
|
||||
|
||||
this.iconContainer.releasePointerCapture(e.pointerId);
|
||||
});
|
||||
}
|
||||
|
||||
#render() {
|
||||
this.iconContainer.style.position = "fixed";
|
||||
this.iconContainer.style.bottom = "0px";
|
||||
this.iconContainer.style.right = "0px";
|
||||
this.iconContainer.style.width = "50px";
|
||||
this.iconContainer.style.height = "50px";
|
||||
this.iconContainer.style.backgroundColor = "red";
|
||||
}
|
||||
|
||||
#snapToCorner(x, y) {
|
||||
let maxWidth = window.innerWidth;
|
||||
let maxHeight = window.innerHeight;
|
||||
|
||||
if (x < maxWidth / 2){
|
||||
// left half
|
||||
if (y < maxHeight / 2) {
|
||||
// top left
|
||||
this.style.left = "0px";
|
||||
this.style.top = "0px";
|
||||
this.style.bottom = null;
|
||||
this.style.right = null;
|
||||
}
|
||||
else {
|
||||
// bottom left
|
||||
this.style.left = "0px";
|
||||
this.style.top = null;
|
||||
this.style.bottom = "0px";
|
||||
this.style.right = null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// right half
|
||||
if (y < maxHeight / 2) {
|
||||
// top right
|
||||
this.style.left = null;
|
||||
this.style.top = "0px";
|
||||
this.style.bottom = null;
|
||||
this.style.right = "0px";
|
||||
}
|
||||
else {
|
||||
// bottom right
|
||||
this.style.left = null;
|
||||
this.style.top = null;
|
||||
this.style.bottom = "0px";
|
||||
this.style.right = "0px";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("x-widget", XWidget);
|
||||
customElements.define("x-widget-icon", XWidgetIcon);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,131 +0,0 @@
|
|||
<html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div>
|
||||
<style>
|
||||
p {
|
||||
font-size: 24;
|
||||
}
|
||||
</style>
|
||||
|
||||
<img />
|
||||
|
||||
<button id="snapshot-button">Take snapshot</button>
|
||||
|
||||
<div style="height: 50px; width: 10000px; background-color: blue;"></div>
|
||||
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
v
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
</div>
|
||||
|
||||
<x-widget></x-widget>
|
||||
|
||||
<script>
|
||||
class XWidget extends HTMLElement {
|
||||
frame;
|
||||
icon;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
const shadowRoot = this.attachShadow({mode: 'open'});
|
||||
|
||||
let frame = document.createElement("div");
|
||||
frame.style.position = "fixed";
|
||||
frame.style.top = "0px";
|
||||
frame.style.left = "0px";
|
||||
frame.style.right = "0px";
|
||||
frame.style.bottom = "0px";
|
||||
frame.style.border = "5px dotted blue";
|
||||
shadowRoot.append(frame);
|
||||
this.frame = frame;
|
||||
|
||||
let icon = document.createElement("x-widget-icon");
|
||||
this.frame.appendChild(icon);
|
||||
this.icon = icon;
|
||||
|
||||
frame.addEventListener("click", (e) => {
|
||||
if (e.target == icon) {
|
||||
console.log("Clicked on icon");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
}
|
||||
}
|
||||
|
||||
class XWidgetIcon extends HTMLElement {
|
||||
iconContainer;
|
||||
isPressed;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
const shadowRoot = this.attachShadow({mode: 'open'});
|
||||
|
||||
let iconContainer = document.createElement("div");
|
||||
shadowRoot.append(iconContainer);
|
||||
this.iconContainer = iconContainer;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.#render();
|
||||
}
|
||||
|
||||
#render() {
|
||||
this.iconContainer.style.position = "fixed";
|
||||
this.iconContainer.style.bottom = "0px";
|
||||
this.iconContainer.style.right = "0px";
|
||||
this.iconContainer.style.width = "50px";
|
||||
this.iconContainer.style.height = "50px";
|
||||
this.iconContainer.style.backgroundColor = "red";
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("x-widget", XWidget);
|
||||
customElements.define("x-widget-icon", XWidgetIcon);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,406 +0,0 @@
|
|||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<div style="height: 50px; width: 10000px; background-color: blue;"></div>
|
||||
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
v
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
<p>Nice thanks man awesome</p>
|
||||
|
||||
<template>
|
||||
<h1>yeehaw</h1>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
loadExternalStyles();
|
||||
|
||||
function loadExternalStyles() {
|
||||
let gfPreconnectLink = document.createElement("link");
|
||||
gfPreconnectLink.setAttribute("rel", "preconnect");
|
||||
gfPreconnectLink.setAttribute("href", "https://fonts.googleapis.com");
|
||||
document.head.appendChild(gfPreconnectLink);
|
||||
|
||||
let gfPreconnectCOLink = document.createElement("link");
|
||||
gfPreconnectCOLink.setAttribute("rel", "preconnect");
|
||||
gfPreconnectCOLink.setAttribute("href", "https://fonts.gstatic.com");
|
||||
gfPreconnectCOLink.setAttribute("crossorigin", true);
|
||||
document.head.appendChild(gfPreconnectCOLink);
|
||||
|
||||
let gfLink = document.createElement("link");
|
||||
gfLink.setAttribute("rel", "stylesheet");
|
||||
gfLink.setAttribute("href", "https://fonts.googleapis.com/css2?family=Alexandria:wght@300;400;500;600;700&display=swap");
|
||||
document.head.appendChild(gfLink);
|
||||
}
|
||||
|
||||
class XWidget extends HTMLElement {
|
||||
#icon;
|
||||
#form;
|
||||
#location;
|
||||
|
||||
#margin;
|
||||
|
||||
#pointerDown;
|
||||
#moving;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
const shadowRoot = this.attachShadow({mode: 'open'});
|
||||
|
||||
this.#icon = this.#createIcon();
|
||||
shadowRoot.appendChild(this.#icon)
|
||||
|
||||
this.#form = this.#createForm();
|
||||
shadowRoot.appendChild(this.#form);
|
||||
|
||||
this.#margin = "20px";
|
||||
this.#pointerDown = false;
|
||||
this.#moving = false;
|
||||
this.#location = "bottom-right";
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.#render();
|
||||
}
|
||||
|
||||
#render() {
|
||||
if (this.isConnected) {
|
||||
this.#renderIcon({width: "60px", height: "60px", imgSrc: this.#icon.openImgSrc});
|
||||
this.#renderForm({visibility: "hidden"});
|
||||
}
|
||||
}
|
||||
|
||||
#createIcon() {
|
||||
let icon = document.createElement("div");
|
||||
|
||||
icon.openImgSrc = "icon_open.png";
|
||||
icon.closeImgSrc = "icon_close.png";
|
||||
|
||||
icon.addEventListener("pointerdown", (e) => this.#onIconPointerDown(e));
|
||||
icon.addEventListener("pointermove", (e) => this.#onIconPointerMove(e));
|
||||
icon.addEventListener("pointerup", (e) => this.#onIconPointerUp(e));
|
||||
icon.addEventListener("pointerover", (e) => this.#onIconPointerOver(e));
|
||||
icon.addEventListener("pointerout", (e) => this.#onIconPointerOut(e));
|
||||
|
||||
let iconImage = document.createElement("img");
|
||||
iconImage.style.width = "100%";
|
||||
iconImage.style.height = "100%";
|
||||
icon.appendChild(iconImage)
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
#createForm() {
|
||||
let form = document.createElement("div");
|
||||
|
||||
let header = document.createElement("div");
|
||||
header.id = "form-header";
|
||||
form.appendChild(header);
|
||||
|
||||
let title = document.createElement("div");
|
||||
title.id = "form-title";
|
||||
header.appendChild(title);
|
||||
|
||||
// let headerBottom = document.createElement("hr");
|
||||
// headerBottom.id = "form-header-bottom";
|
||||
// form.appendChild(headerBottom);
|
||||
|
||||
// let nameInput = document.createElement("input");
|
||||
// nameInput.id = "name-input";
|
||||
// form.appendChild(nameInput);
|
||||
|
||||
// let commentInput = document.createElement("textarea");
|
||||
// commentInput.id = "comment-input";
|
||||
// form.appendChild(commentInput);
|
||||
|
||||
return form;
|
||||
}
|
||||
|
||||
#renderIcon(parameters={}) {
|
||||
this.#icon.style.position = "fixed";
|
||||
this.#icon.style.transition = "scale 0.2s ease";
|
||||
|
||||
if (parameters["width"]) {
|
||||
this.#icon.style.width = parameters["width"];
|
||||
}
|
||||
|
||||
if (parameters["height"]) {
|
||||
this.#icon.style.height = parameters["height"];
|
||||
}
|
||||
|
||||
if (parameters["scale"]) {
|
||||
this.#icon.style.scale = parameters["scale"];
|
||||
}
|
||||
|
||||
if (parameters["imgSrc"]) {
|
||||
this.#icon.querySelector("img").src = parameters["imgSrc"];
|
||||
}
|
||||
|
||||
if (this.#location == "top-left") {
|
||||
this.#icon.style.left = this.#margin;
|
||||
this.#icon.style.top = this.#margin;
|
||||
this.#icon.style.bottom = "auto";
|
||||
this.#icon.style.right = "auto";
|
||||
} else if (this.#location == "top-right") {
|
||||
this.#icon.style.left = "auto";
|
||||
this.#icon.style.top = this.#margin;
|
||||
this.#icon.style.bottom = "auto";
|
||||
this.#icon.style.right = this.#margin;
|
||||
} else if (this.#location == "bottom-left") {
|
||||
this.#icon.style.left = this.#margin;
|
||||
this.#icon.style.top = "auto";
|
||||
this.#icon.style.bottom = this.#margin;
|
||||
this.#icon.style.right = "auto";
|
||||
} else if (this.#location == "bottom-right") {
|
||||
this.#icon.style.left = "auto";
|
||||
this.#icon.style.top = "auto";
|
||||
this.#icon.style.bottom = this.#margin;
|
||||
this.#icon.style.right = this.#margin;
|
||||
}
|
||||
}
|
||||
|
||||
#renderForm(parameters={}) {
|
||||
this.#form.style.width = "350px";
|
||||
this.#form.style.height = "500px";
|
||||
this.#form.style.backgroundColor = "white";
|
||||
this.#form.style.border = "0px";
|
||||
this.#form.style.borderRadius = "10px 10px 10px 10px"
|
||||
this.#form.style.boxShadow = "0 4px 16px rgb(0 0 0 / 25%)";
|
||||
this.#form.style.borderRadius = "15px";
|
||||
this.#form.style.position = "fixed";
|
||||
this.#form.style.opacity = "0";
|
||||
|
||||
if (this.#location == "top-left") {
|
||||
this.#form.style.left = this.#margin;
|
||||
this.#form.style.top = this.#icon.clientHeight + 50 + "px";
|
||||
this.#form.style.bottom = "auto";
|
||||
this.#form.style.right = "auto";
|
||||
} else if (this.#location == "top-right") {
|
||||
this.#form.style.left = "auto";
|
||||
this.#form.style.top = this.#icon.clientHeight + 50 + "px";
|
||||
this.#form.style.bottom = "auto";
|
||||
this.#form.style.right = this.#margin;
|
||||
} else if (this.#location == "bottom-left") {
|
||||
this.#form.style.left = this.#margin;
|
||||
this.#form.style.top = "auto";
|
||||
this.#form.style.bottom = this.#icon.clientHeight + 50 + "px";
|
||||
this.#form.style.right = "auto";
|
||||
} else if (this.#location == "bottom-right") {
|
||||
this.#form.style.left = "auto";
|
||||
this.#form.style.top = "auto";
|
||||
this.#form.style.bottom = this.#icon.clientHeight + 50 + "px";
|
||||
this.#form.style.right = this.#margin;
|
||||
}
|
||||
|
||||
if (parameters["visibility"]) {
|
||||
// This animation feels messy - especially since opacity is always declared above as 0
|
||||
if (parameters["visibility"] == "visible" && this.#form.style.visibility != "visible") {
|
||||
this.#form.style.visibility = "visible";
|
||||
|
||||
if (parameters["animate"]) {
|
||||
this.#form.style.opacity = "1";
|
||||
this.#form.style.transition = "visibility 0s linear 0.1s, opacity 0.1s linear";
|
||||
this.#form.style.transitionDelay = "0s";
|
||||
}
|
||||
else {
|
||||
this.#form.style.transition = "";
|
||||
}
|
||||
}
|
||||
else if (parameters["visibility"] == "hidden" && this.#form.style.visibility != "hidden") {
|
||||
this.#form.style.visibility = "hidden";
|
||||
|
||||
if (parameters["animate"]) {
|
||||
this.#form.style.opacity = "0";
|
||||
this.#form.style.transition = "visibility 0s linear 0.1s, opacity 0.1s linear";
|
||||
}
|
||||
else {
|
||||
this.#form.style.transition = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let header = this.#form.querySelector("#form-header");
|
||||
header.style.top = "0px";
|
||||
header.style.width = "100%";
|
||||
header.style.height = "60px";
|
||||
header.style.backgroundColor = "#AE55E7";
|
||||
header.style.borderRadius = "15px 15px 0px 0px";
|
||||
header.style.border = "0px";
|
||||
header.style.justifyContent = "center";
|
||||
header.style.alignItems = "center";
|
||||
header.style.display = "flex";
|
||||
|
||||
// let headerBottom = this.#form.querySelector("#form-header-bottom");
|
||||
// headerBottom.style.width = "100%";
|
||||
// headerBottom.style.height = "10px";
|
||||
// headerBottom.style.backgroundColor = "#AE55E7";
|
||||
// headerBottom.style.margin = "0px";
|
||||
// headerBottom.style.border = "0px";
|
||||
// headerBottom.style.boxShadow = "0 0 26px -2px rgba(0, 0, 0, 0.5)";
|
||||
// headerBottom.style.clipPath = "polygon(0% 0%, 100% 0%, 100% 500%, 0% 500%)";
|
||||
|
||||
let title = this.#form.querySelector("#form-title");
|
||||
title.textContent = "New Ticket";
|
||||
title.style.fontFamily = "Alexandria, sans-serif";
|
||||
title.style.fontWeight = "400";
|
||||
title.style.fontSize = "24px";
|
||||
title.style.color = "white";
|
||||
title.style.textAlign = "center";
|
||||
|
||||
// let nameInput = this.#form.querySelector("#name-input");
|
||||
// nameInput.setAttribute("type", "text");
|
||||
// nameInput.setAttribute("placeholder", "Name");
|
||||
// nameInput.style.fontFamily = "Alexandria, sans-serif";
|
||||
// nameInput.style.fontWeight = "300";
|
||||
// nameInput.style.fontSize = "12px";
|
||||
|
||||
// let commentInput = this.#form.querySelector("#comment-input");
|
||||
// commentInput.setAttribute("resize", "none");
|
||||
// commentInput.setAttribute("overflow-y", "scroll");
|
||||
// commentInput.setAttribute("rows", "15");
|
||||
// commentInput.setAttribute("cols", "30");
|
||||
}
|
||||
|
||||
#onIconPointerOver(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
this.#renderIcon({scale: 1.05});
|
||||
}
|
||||
|
||||
#onIconPointerOut(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
this.#renderIcon({scale: 1});
|
||||
}
|
||||
|
||||
#onIconPointerDown(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
this.#pointerDown = true;
|
||||
|
||||
this.#icon.setPointerCapture(e.pointerId);
|
||||
}
|
||||
|
||||
#onIconPointerMove(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
this.#icon.style.cursor = "pointer";
|
||||
|
||||
if (this.#pointerDown) {
|
||||
this.#moving = true;
|
||||
this.#icon.style.cursor = "grabbing";
|
||||
this.#snapToCorner(e.clientX, e.clientY);
|
||||
}
|
||||
}
|
||||
|
||||
#onIconPointerUp(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
this.#icon.style.cursor = "pointer";
|
||||
|
||||
if (!this.#moving) {
|
||||
if (this.#form.style.visibility == "visible") {
|
||||
this.#renderIcon({imgSrc: this.#icon.openImgSrc});
|
||||
this.#renderForm({visibility: "hidden", animate: true});
|
||||
}
|
||||
else {
|
||||
this.#renderIcon({imgSrc: this.#icon.closeImgSrc});
|
||||
this.#renderForm({visibility: "visible", animate: true});
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.#moving = false;
|
||||
}
|
||||
|
||||
this.#pointerDown = false;
|
||||
|
||||
this.#icon.releasePointerCapture(e.pointerId);
|
||||
}
|
||||
|
||||
#toggleDisplayForm() {
|
||||
let visibility =
|
||||
this.#form.style.visibility == "visible" ?
|
||||
"hidden" : "visible";
|
||||
|
||||
this.#renderForm({visibility: visibility})
|
||||
}
|
||||
|
||||
#snapToCorner(anchorX, anchorY) {
|
||||
let locationChanged = false;
|
||||
|
||||
if (anchorX < window.innerWidth / 5) {
|
||||
if (this.#location != "top-left" && anchorY < window.innerHeight / 5) {
|
||||
this.#location = "top-left";
|
||||
locationChanged = true;
|
||||
}
|
||||
else if (this.#location != "bottom-left" && anchorY > window.innerHeight - window.innerHeight / 5) {
|
||||
this.#location = "bottom-left";
|
||||
locationChanged = true;
|
||||
}
|
||||
}
|
||||
else if (anchorX > window.innerWidth - window.innerWidth / 5) {
|
||||
if (this.#location != "top-right" && anchorY < window.innerHeight / 5) {
|
||||
this.#location = "top-right";
|
||||
locationChanged = true;
|
||||
}
|
||||
else if (this.#location != "bottom-right" && anchorY > window.innerHeight - window.innerHeight / 5) {
|
||||
this.#location = "bottom-right";
|
||||
locationChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (locationChanged) {
|
||||
this.#renderIcon({imgSrc: this.#icon.openImgSrc});
|
||||
this.#renderForm({visibility: "hidden"});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("b6d215dc-03ff-4ca5-bc48-879e821a07f0", XWidget);
|
||||
document.body.appendChild(document.createElement("b6d215dc-03ff-4ca5-bc48-879e821a07f0"));
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user