iwmlib/browser/padMinimal.js

1381 lines
48 KiB
JavaScript
Raw Normal View History

const {fileURL} = require('./utils.js')
const path = require('path')
/* A specialization that ignores webview events and thus allows
* webviews to get touch, mouse and wheel events.
*/
class minimalDOMPadContainer extends DOMScatterContainer {
capture(event) {
if (event.target.tagName === 'WEBVIEW' || event.target.classList.contains('interactiveElement'))
return false
return super.capture(event)
}
}
/* A wrapper for a webview that behaves like a virtual tablet browser.
* Uses a DOMScatter to zoom and rotate the virtual browser window.
* The position of buttons and the border size remain constant.
*/
class minimalPad {
constructor(scatterContainer, {
startScale=1.0, minScale=0.25, maxScale=10.5,
autoBringToFront=true,
type = 'minimal',
title="",
tabbedView = true,
hasTtitleBar = false,
// urlList=["https://www.iwm-tuebingen.de/www/index.html"],
padMapKey="key",
url="https://www.iwm-tuebingen.de/www/index.html",
hideOnStart=false,
translatable=true, scalable=true, rotatable=true,
movableX=true,
movableY=true,
rotationDegrees=null,
rotation=null,
onTransform=null,
transformOrigin = 'center center',
// extras which are in part needed
x=0,
y=0,
width=null,
height=null,
resizable=false,
} ={}) {
this.x = x
this.y = y
this.type = type
this.url = url
// this.urlList = urlList
this.padMapKey = padMapKey,
this.title = title,
this.hasTtitleBar = hasTtitleBar
this.tabbedView = tabbedView
this.hideOnStart = hideOnStart
this.width = width
this.height = height
this.minScale = minScale
this.maxScale = maxScale
this.scatterContainer = scatterContainer
this.startScale = startScale
this.scale = startScale
this.scalable = scalable
this.rotatable = rotatable
this.rotationDegrees = this.startRotationDegrees
this.transformOrigin = transformOrigin
this.web = null
this.WebviewCounter = 0
this.id=0
this.pointerCounter = 0
this.webviewMap = new Map()
this.overlayMap = new Map()
this.tabMap = new Map()
this.listMap = new Map()
this.frame = document.createElement('div')
this.frame.classList.add("pad")
this.border = 50 / startScale
Elements.setStyle(this.frame, {
backgroundColor: "#333",
position: "absolute",
display: 'flex',
width: this.width+"px",
height: this.height+"px",
visibility: "visible",
top: 0,
left: 0,
// boxShadow: `10px 10px 10px rgba(0, 0, 0, 0.5)`,
// borderRadius: '10px',
overflow: "visible"})
document.body.appendChild( this.frame)
this.tabs=document.createElement("div")
this.webBackground=document.createElement("div")
this.webviewList=document.createElement("div")
this.titlebar = document.createElement("div")
this.webViewSnapshot=document.createElement("img")
this.tabs.classList.add("interactiveElement")
this.tabs.classList.add("tabs")
// this.tabs.style.display="flex"
// this.tabs.style.flexFlow="row nowrap"
Elements.setStyle(this.tabs, {
position: "absolute",
background: "white",
overflowX: "auto",
overflowY: "hidden",
display: "flex",
flexFlow:"row nowrap",
// justifyContent: "flex-end",
alignItems: "flex-end"
// overflow: "auto",
})
this.titlebar.innerHTML = ""
Elements.setStyle(this.titlebar, {
color: "#fff",
position: "absolute",
overflowX: "hidden"
})
Elements.setStyle(this.webBackground, {
position: "absolute",
overflow: "hidden",
background: "white"
})
this.webviewList.classList.add("interactiveElement")
Elements.setStyle(this.webviewList, {
position: "absolute",
visibility: "hidden",
overflow: "auto",
background: "white",
boxShadow: "5px 5px 10px #bbb"
})
/*Elements.setStyle(this.overlay, {
position: "absolute",
overflow: "auto",
background: "white",
opacity: "0.8"
})*/
Elements.setStyle(this.webViewSnapshot, {
position: "absolute",
overflow: "auto"
})
if(this.hasTtitleBar)this.frame.appendChild(this.titlebar)
this.frame.appendChild(this.webBackground)
// this.frame.appendChild(this.webViewSnapshot)
this.frame.appendChild(this.tabs)
this.frame.appendChild(this.webviewList)
this.webViewSnapshot.style.visibility="hidden"
this.closeButton = this.addButton("../assets/icons/svg/cross.svg", "close")
this.backButton = this.addButton("../assets/icons/svg/left.svg", "go back")
this.forwardButton = this.addButton("../assets/icons/svg/right.svg", "go forward")
this.showWebviewListButton = this.addButton("../assets/icons/svg/flat/ic_list_48px.svg", "show list")
this.addNewWebview(this.url)
this.backButton.style.opacity = 0.5
this.forwardButton.style.opacity = 0.5
/*for (let callback of window.padLoadedHandler) {
callback(this, url)
}*/
// this.pseudoFrame = document.createElement('div')
this.pseudoFrameTop = document.createElement('div')
this.pseudoFrameLeft = document.createElement('div')
this.pseudoFrameRight = document.createElement('div')
/*Elements.setStyle(this.pseudoFrame, {
position: "absolute",
top: "0px",
left: "0px",
width: "100%",
height: "100%",
pointerEvents: "none"
})*/
Elements.setStyle(this.pseudoFrameTop, {
position: "absolute",
// background: "pink",
top: "0px",
left: "0px",
width: "100%"
// height: "50px"
})
Elements.setStyle(this.pseudoFrameLeft, {
position: "absolute",
// background: "pink",
top: "0px",
left: "0px",
// width: "5px",
height: "100%"
})
Elements.setStyle(this.pseudoFrameRight, {
position: "absolute",
// background: "pink",
top: "0px",
right: "0px",
// width: "5px",
height: "100%"
})
this.frame.appendChild(this.pseudoFrameTop)
this.frame.appendChild(this.pseudoFrameLeft)
this.frame.appendChild(this.pseudoFrameRight)
// this.frame.appendChild(this.pseudoFrame)
this.pseudoFrameTop.addEventListener('pointerenter',(e)=>{
this.scatter.scalable=false
this.web.pointerEvents = "none"
e.target.style.cursor = "move"
})
this.pseudoFrameTop.addEventListener('pointerleave',(e)=>{
this.scatter.scalable=true
// this.frame.style.cursor = "initial"
})
this.pseudoFrameLeft.addEventListener('pointerenter',(e)=>{
// e.target.setPointerCapture(e.pointerId)
this.scatter.scalable=false
this.web.pointerEvents = "none"
e.target.style.cursor = "move"
})
this.pseudoFrameLeft.addEventListener('pointerleave',(e)=>{
this.scatter.scalable=true
// this.frame.style.cursor = "initial"
})
this.pseudoFrameRight.addEventListener('pointerenter',(e)=>{
this.scatter.scalable=false
this.web.pointerEvents = "none"
e.target.style.cursor = "move"
})
this.pseudoFrameRight.addEventListener('pointerleave',(e)=>{
this.scatter.scalable=true
// this.frame.style.cursor = "initial"
})
/*this.web.addEventListener('new-window', (e) => {
if(e.url.indexOf("youtube")>-1)return
if (urlPadMap.has(e.url)) {
let childPad = urlPadMap.get(e.url)
childPad.scatter.moveTo(x, y)
return childPad
}
let childPad = new minimalPad(this.scatterContainer, {
x: this.scatter.position.x+100,
y: this.scatter.position.y+100,
url: e.url,
width: this.scatter.width,
height: this.scatter.height,
scalable: true,
rotatable: true})
urlPadMap.set(e.url, childPad)
for(let callback of window.padLoadedHandler) {
callback(childPad, url)
}
})*/
/*this.backButton.addEventListener('click', (e)=>{
if(this.web.canGoBack()){
TweenMax.to(e.target, 0.1, {scale:"1.1", onComplete: ()=>{
TweenMax.to(e.target, 0.1, {scale:"1.0"})
}})
this.web.goBack()
}
})
this.forwardButton.addEventListener('click', (e)=>{
if(this.web.canGoForward()){
TweenMax.to(e.target, 0.1, {scale:"1.1", onComplete: ()=>{
TweenMax.to(e.target, 0.1, {scale:"1.0"})
}})
this.web.goForward()
}
})
this.closeButton.addEventListener('click', (e)=>{
TweenMax.to(e.target, 0.1, {scale:"1.1", onComplete: ()=>{
TweenMax.to(e.target, 0.1, {scale:"1.0"})
}})
this.close()
})*/
InteractionMapper.on('tap',this.backButton, e => {
if(this.web.canGoBack()){
TweenMax.to(e.target, 0.1, {scale:"1.1", onComplete: ()=>{
TweenMax.to(e.target, 0.1, {scale:"1.0"})
}})
this.web.goBack()
}
})
InteractionMapper.on('tap',this.forwardButton, e => {
if(this.web.canGoForward()){
TweenMax.to(e.target, 0.1, {scale:"1.1", onComplete: ()=>{
TweenMax.to(e.target, 0.1, {scale:"1.0"})
}})
this.web.goForward()
}
})
InteractionMapper.on('tap',this.closeButton, e => {
TweenMax.to(e.target, 0.1, {scale:"1.1", onComplete: ()=>{
TweenMax.to(e.target, 0.1, {scale:"1.0"})
}})
this.close()
})
this.showWebviewListButton.addEventListener('click', (e)=>{
/*TweenMax.to(e.target, 0.1, {scale:"1.1", onComplete: ()=>{
TweenMax.to(e.target, 0.1, {scale:"1.0"})
}})*/
this.webviewList.style.visibility=="visible" ? this.webviewList.style.visibility="hidden" : this.webviewList.style.visibility="visible"
})
this.scatter = new DOMScatter(this.frame, scatterContainer, {
x: this.x,
y: this.y,
startScale: this.startScale,
width: this.width,
height: this.height,
minScale: this.minScale,
maxScale: this.maxScale,
scalable: this.scalable,
resizable: true,
rotatable: this.rotatable})
let img=document.createElement("img")
img.style.width = "70%"
img.style.position = "absolute"
img.style.bottom = "20%"
img.style.right = "20%"
img.style.pointerEvents="none"
img.src = "../../assets/icons/png/flat/resize.png"
this.scatter.resizeButton.appendChild(img)
this.scatter.moveTo({x, y})
this.scatter.bringToFront()
this.scatter.addTransformEventCallback((e) => {
let newBorder = 50 / e.scale
if (newBorder !== this.border) {
this.border = newBorder
this.layout()
}
})
/*this.test = document.createElement('div')
Elements.setStyle(this.test, {
position: "absolute",
width: "400px",
height: "400px",
overflow: "auto",
background: "pink"
})
this.frame.appendChild(this.test)
this.test.addEventListener('click',()=>{
// this.frame.style.visibility="hidden"
console.log($( this.webBackground ).children())
$( this.webBackground ).children().css( "visibility", "hidden" )
$( this.frame ).children().css( "visibility", "hidden" )
})*/
this.heinz = document.createElement('div')
Elements.setStyle(this.heinz, {
position: "absolute",
background: "pink",
top: "0px",
left: "0px",
width: "100%",
opacity: "0.5",
display: "inline",
height: "100%"
})
this.heinz.addEventListener('pointerdown',(e)=>{
console.log('pointer down on Heinz')
e.target.style.display="none"
})
this.layout()
// this.webBackground.appendChild(this.heinz)
// this.heinz.classList.add("interactiveElement")
}
addNewWebview(src){
/* if(this.web!=null){
this.web.style.visibility="hidden"
this.web.setAttribute('selected','0')
}*/
let timeTouchStart = 0
let webview=document.createElement("webview")
this.web=webview
// webview.style.pointerEvents="none"
webview.setAttribute('loaded','0')
this.webBackground.appendChild(webview)
this.webviewMap.set(src+this.padMapKey, webview)
// console.log("number of webviews",this.webviewMap.size)
// $("webview").each(function(i, obj) {
// obj.setAttribute('selected','0')
// })
Elements.setStyle(webview, {
position: "absolute",
overflow: "hidden",
width: "100%",
height: "100%",
// border: "1px solid #fff"
})
webview.src=src
webview.preload= path.join(__dirname, './preloadPad.js')
let listItem=document.createElement('div')
listItem.className="interactiveElement"
listItem.classList.add("webviewListItem")
listItem.setAttribute('id',src+this.padMapKey)
// listItem.style.height = "5%"
// // listItem.style.width = "80%"
// listItem.style.marginLeft="10%"
// listItem.style.marginTop="5%"
listItem.style.padding = "10px"
// listItem.style.paddingBottom = "10px"
this.webviewList.appendChild(listItem)
this.listMap.set(src+this.padMapKey,listItem)
webview.setAttribute('id',src+this.padMapKey)
this.setSelectedWebview(src+this.padMapKey)
this.addNewTab(webview,src)
listItem.addEventListener('click',(e)=>{
console.log(e.target.getAttribute('id'))
this.setSelectedWebview(e.target.getAttribute('id'))
this.webviewList.style.visibility = "hidden"
$(this.tabs).animate({scrollLeft: $(".tab[id='"+e.target.getAttribute('id')+"']").prop('offsetLeft') - 10}, "slow")
this.enableButtons()
})
listItem.addEventListener('pointerenter',(e)=>{
e.target.style.background = "#ddd"
let webview=null
this.webviewMap.forEach(function (item, key, mapObj) {
item.style.visibility="hidden"
if(item.getAttribute('id')==e.target.getAttribute("id")){
item.style.visibility="visible"
if(item.getAttribute('selected')=='0')item.style.opacity="0.5"
webview=item
// obj.style.width="50%"
// obj.style.height="50%"
}
})
this.overlayMap.forEach(function (item, key, mapObj) {
item.style.visibility="hidden"
if(item.getAttribute('id')==e.target.getAttribute("id")){
item.style.visibility="visible"
}
})
// webview.getAttribute('loaded')=='0' ? this.overlay.style.visibility='visible' : this.overlay.style.visibility='hidden'
})
listItem.addEventListener('pointerleave',(e)=>{
e.target.style.background = "#fff"
if(e.target.getAttribute('selected')=='1') e.target.style.background = "#999"
this.webviewMap.forEach(function (item, key, mapObj) {
if(item.getAttribute('selected')=='0'){
item.style.visibility="hidden"
}
if(item.getAttribute('selected')=='1'){
item.style.visibility="visible"
item.style.opacity="1"
}
// obj.style.width="100%"
// obj.style.height="100%"
})
})
let overlay = document.createElement('div')
overlay.style.position="absolute"
overlay.style.width="100%"
overlay.style.height="100%"
overlay.style.top="0px"
overlay.style.left="0px"
overlay.style.background="white"
overlay.style.opacity="0.6"
this.overlayMap.set(src,overlay)
let overlayCaptureEvents = document.createElement('div')
overlayCaptureEvents.style.position="absolute"
overlayCaptureEvents.style.background="lime"
overlayCaptureEvents.style.opacity="0.01"
overlayCaptureEvents.style.width="100%"
overlayCaptureEvents.style.height="100%"
overlayCaptureEvents.style.top="0px"
overlayCaptureEvents.style.left="0px"
// overlay.style.background="white"
overlayCaptureEvents.classList.add("interactiveElement")
overlayCaptureEvents.addEventListener('touchmove',(e)=>{
e.preventDefault()
e.stopPropagation()
})
overlayCaptureEvents.addEventListener('pointerup',(e)=>{
e.preventDefault()
e.stopPropagation()
let p = {x:e.clientX, y:e.clientY}
let webviewPosition = Points.fromPageToNode(webview,p)
// oldX = 0
// oldY = 0
let d = new Date()
console.log("delta Time",d.getTime()-timeTouchStart)
// if(d.getTime()-timeTouchStart<150)webview.sendInputEvent({type:'mouseUp', x: (e.clientX-webview.getBoundingClientRect().left)/this.scatter.scale, y: (e.clientY-webview.getBoundingClientRect().top)/this.scatter.scale, button:'left', clickCount: 1})
if(d.getTime()-timeTouchStart<150)webview.sendInputEvent({type:'mouseUp', x: webviewPosition.x, y: webviewPosition.y, button:'left', clickCount: 1})
})
overlayCaptureEvents.addEventListener('pointerdown',(e)=>{
e.preventDefault()
e.stopPropagation()
this.scatter.bringToFront()
let p = {x:e.clientX, y:e.clientY}
let webviewPosition = Points.fromPageToNode(webview,p)
let d = new Date()
timeTouchStart = d.getTime()
// webview.sendInputEvent({type:'mouseDown', x: (e.clientX-webview.getBoundingClientRect().left)/this.scatter.scale, y: (e.clientY-webview.getBoundingClientRect().top)/this.scatter.scale, button:'left', clickCount: 1})
webview.sendInputEvent({type:'mouseDown', x: webviewPosition.x, y: webviewPosition.y, button:'left', clickCount: 1})
})
overlayCaptureEvents.addEventListener('pointermove',(e)=>{
if(e.pointerType!='mouse'){
let rotation = Angle.radian2degree(this.scatter.rotation);
rotation = (rotation + 360) % 360;
let r = Math.sqrt(Math.pow(e.movementX, 2) + Math.pow(e.movementY, 2));
let phi = Angle.radian2degree(Math.atan2(e.movementX, e.movementY));
phi = ((phi) + 630) % 360;
let rot = ((rotation + 90) + 630) % 360;
let diffAngle = ((0 + rot) + 360) % 360;
let phiCorrected = (phi + diffAngle + 360) % 360;
let deltaX = r * Math.cos(Angle.degree2radian(phiCorrected));
let deltaY = -r * Math.sin(Angle.degree2radian(phiCorrected));
// if(oldX!=0)deltaX = (e.clientX-oldX)
// if(oldY!=0)deltaY = (e.clientY-oldY)
// console.log("e.movementY",e.movementY)
// webview.sendInputEvent({type:'mouseWheel', x: 0, y: 0, deltaX: e.movementX, deltaY: e.movementY, canScroll: true })
webview.executeJavaScript("window.scrollTo(scrollX+"+(-1*deltaX)+", scrollY+"+ (-1*deltaY)+")")
// oldX = e.clientX
// oldY = e.clientY
}
})
overlayCaptureEvents.addEventListener('mousewheel',(e)=>{
console.log("mousewheel",e.deltaY)
// webview.sendInputEvent({type:'mouseWheel', x: 0, y: 0, deltaX: e.deltaX, deltaY: -e.deltaY, canScroll: true })
webview.executeJavaScript("window.scrollTo(scrollX+"+e.deltaX+", scrollY+"+ e.deltaY+")")
})
let loadAnim = document.createElement("div")
loadAnim.style.webkitAnimation= "spin 2s linear infinite"
loadAnim.style.animation= "spin 2s linear infinite"
loadAnim.style.position = "absolute"
document.styleSheets[0].insertRule("div.tabs::-webkit-scrollbar {display: none;}");
document.styleSheets[0].insertRule('\
@keyframes spin {\
from { transform: rotateZ(0deg); }\
to { transform: rotateZ(360deg); }\
}'
)
overlay.appendChild(loadAnim)
this.webBackground.appendChild(overlay)
if(remote.getGlobal('multiUserMode'))this.webBackground.appendChild(overlayCaptureEvents)
webview.addEventListener('did-navigate', (e) => {
this.enableButtons()
//this.backButton.style.opacity = (webview.canGoBack()) ? 1 : 0.5
//this.forwardButton.style.opacity = (webview.canGoForward()) ? 1 : 0.5
})
webview.addEventListener('dom-ready',()=>{
// console.log("DOM READY TABBED WEBVIEW!!!!!!!!!!")
listItem.innerHTML=webview.getTitle()+" "+src
$(".tab[id='"+src+this.padMapKey+"']").children()[0].innerHTML=webview.getTitle()
// $(".tab[id='"+src+"']").children()[0].innerHTML="READY LOADED"
$(this.tabs).animate({scrollLeft: $(".tab[id='"+src+"']").prop('offsetLeft') - 10}, "slow")
this.titlebar.innerHTML=this.web.getTitle()
// this.web.openDevTools()
// webview.style.overflow= "auto"
// webview.style.overflowY= "hidden"
})
webview.addEventListener('ipc-message', (e) => {
if(e.channel=='touchStart'){
// console.log("pointer down on webview",e.srcElement)
if(e.srcElement.src==webview.src)this.pointerCounter++
this.scatter.bringToFront()
}
if(e.channel=='touchEnd'){
// console.log("pointer up on webview")
if(e.srcElement.src==webview.src)this.pointerCounter--
}
if(e.channel=='webviewPointerCancel'){
this.heinz.style.display="inline"
}
// console.log("pointerCounter",this.pointerCounter)
})
/* let {ipcRenderer} = require('electron')
ipcRenderer.on('touchStartWebview' ,function(event){
console.log(event)
})*/
webview.addEventListener('did-start-loading', ()=>{
webview.setAttribute('loaded','0')
overlay.style.visibility="visible"
let w = overlay.offsetWidth
let h = overlay.offsetHeight
let animationSize = w<h ? w*0.5 : h*0.5
let animationRingWidth = animationSize*0.1;
loadAnim.style.border=animationRingWidth+"px solid #f3f3f3"
loadAnim.style.borderTop=animationRingWidth+"px solid #ffb18c"
loadAnim.style.borderRadius="50%"
loadAnim.style.height=animationSize-animationRingWidth*2+"px"
loadAnim.style.width=animationSize-animationRingWidth*2+"px"
loadAnim.style.top = h*0.25+"px"
loadAnim.style.left = w*0.25+"px"
w<h ? loadAnim.style.top = 0.5*(h-animationSize)+"px" : loadAnim.style.left = 0.5*(w-animationSize)+"px"
})
// webview.addEventListener('dom-ready', ()=>{
// })
webview.addEventListener('did-stop-loading', ()=>{
webview.setAttribute('loaded','1')
this.layout()
overlay.style.visibility="hidden"
})
webview.addEventListener('new-window', (e) => {
if (!this.webviewMap.has(e.url+this.padMapKey)){
if(this.tabbedView)this.addNewWebview(e.url)
if(!this.tabbedView){
if (urlPadMap.has(e.url)) {
let childPad = urlPadMap.get(e.url)
childPad.scatter.moveTo(x, y)
return childPad
}
let childPad = new minimalPad(this.scatterContainer, {
x: this.scatter.position.x+100,
y: this.scatter.position.y+100,
url: e.url,
tabbedView: false,
hasTtitleBar: this.hasTtitleBar,
width: this.scatter.width,
height: this.scatter.height,
scalable: true,
rotatable: true})
urlPadMap.set(e.url, childPad)
for(let callback of window.padLoadedHandler) {
callback(childPad, url)
}
}
}
})
this.id++
}
setSelectedWebview(id){
let webview=null
this.webviewMap.forEach(function (item, key, mapObj) {
item.setAttribute('selected','0')
item.style.opacity = "0"
item.style.visibility = "hidden"
if(key==id){
webview=item
item.setAttribute('selected','1')
item.style.opacity = "1"
item.style.visibility = "visible"
}
})
this.tabMap.forEach(function (tab, key, mapObj) {
tab.style.border="none"
if(key==id){
tab.style.borderLeft="1px solid black"
tab.style.borderTop="1px solid black"
tab.style.borderRight="1px solid black"
}
})
this.listMap.forEach(function (entry, key, mapObj) {
entry.style.background = "white"
entry.setAttribute('selected','0')
if(key==id){
entry.style.background = "#999"
entry.setAttribute('selected','1')
}
})
this.web = webview
if(webview.getAttribute('loaded')=='1') this.titlebar.innerHTML=this.web.getTitle()
// webview.getAttribute('loaded')=='0' ? this.overlay.style.visibility='visible' : this.overlay.style.visibility='hidden'
}
addNewTab(webview,src){
this.tabMap.forEach(function (tab, key, mapObj) {
tab.style.border="none"
})
let tab=document.createElement('div')
tab.className="tab"
tab.classList.add("interactiveElement")
tab.style.display="flex"
tab.style.flexFlow="row nowrap"
tab.style.textOverflow="ellipsis"
tab.setAttribute('id',src+this.padMapKey)
// tab.innerHTML=" "
tab.style.color="black"
tab.style.background="white"
tab.style.borderLeft="1px solid black"
tab.style.borderTop="1px solid black"
tab.style.borderRight="1px solid black"
tab.style.position="relative"
tab.style.borderRadius="5px 5px 0 0"
tab.style.maxWidth="25%"
tab.style.height="80%"
tab.style.alignItems= "center"
// tab.style.display="inline"
// tab.style.marginLeft="10px"
tab.style.paddingLeft="10px"
this.tabs.appendChild(tab)
this.tabMap.set(src+this.padMapKey,tab)
let newSelectedWebview=null
let title = document.createElement('div')
title.classList.add('tabTitle')
// title.style.display="flex"
// title.style.flexFlow="row nowrap"
title.style.overflow="hidden"
title.style.whiteSpace="nowrap"
title.style.textOverflow="ellipsis"
title.style.pointerEvents="none"
title.innerHTML="New Tab"
tab.appendChild(title)
let close = document.createElement('img')
close.setAttribute('id',src+this.padMapKey)
close.classList.add('tabCloseButton')
close.style.background="#666"
close.style.height="50%"
close.style.marginLeft="10px"
close.style.marginRight="10px"
close.style.borderRadius="100%"
close.style.visibility="hidden"
close.src = "../../assets/icons/svg/cross.svg"
tab.appendChild(close)
close.addEventListener('click',(e)=>{
e.stopPropagation()
e.preventDefault()
let newSelectedItem = false
if(this.webviewMap.size>1){
let next=this.getNextTab(e.target.getAttribute("id"))
let previous=this.getPreviousTab(e.target.getAttribute("id"))
this.webviewMap.forEach(function (item, key, mapObj) {
if(item.getAttribute('id')==e.target.getAttribute("id")){
if(item.getAttribute('selected')=='1'){
newSelectedItem=true
}
mapObj.delete(key)
$(item).remove()
}
})
this.tabMap.forEach(function (tab, key, mapObj) {
if(tab.getAttribute('id')==e.target.getAttribute("id")){
mapObj.delete(key)
$(tab).remove()
}
})
this.listMap.forEach(function (entry, key, mapObj) {
if(entry.getAttribute('id')==e.target.getAttribute("id")){
mapObj.delete(key)
}
})
$(".webviewListItem[id='"+e.target.getAttribute("id")+"']").remove()
$(e.target).remove()
if(newSelectedItem){
next!=null ? this.setSelectedWebview(next.getAttribute('id')) : this.setSelectedWebview(previous.getAttribute('id'))
}
}
this.layout()
})
tab.addEventListener('pointerenter',(e)=>{
if(this.webviewMap.size>1)e.target.childNodes[1].style.visibility="visible"
let z=this.frame.style.zIndex
let webview=null
e.target.style.background="#ddd"
this.webviewMap.forEach(function (item, key, mapObj) {
item.style.visibility="hidden"
if(item.getAttribute('id')==e.target.getAttribute("id")){
item.style.visibility="visible"
if(item.getAttribute('selected')=='0')item.style.opacity="0.5"
webview=item
// obj.style.width="50%"
// obj.style.height="50%"
}
})
this.overlayMap.forEach(function (item, key, mapObj) {
item.style.visibility="hidden"
if(item.getAttribute('id')==e.target.getAttribute("id")){
item.style.visibility="visible"
}
})
// webview.getAttribute('loaded')=='0' ? this.overlay.style.visibility='visible' : this.overlay.style.visibility='hidden'
/*Popup.open({"text":webview.getTitle()},
{x: e.clientX, y: e.clientY},
{ fontSize: "2vh", maxWidth: width*0.2, spacing: '10px', notchPosition: 'topLeft', zIndex: z+100})*/
})
tab.addEventListener('pointerleave',(e)=>{
e.target.childNodes[1].style.visibility="hidden"
e.target.style.background="#fff"
this.webviewMap.forEach(function (item, key, mapObj) {
if(item.getAttribute('selected')=='0'){
item.style.visibility="hidden"
}
if(item.getAttribute('selected')=='1'){
item.style.visibility="visible"
item.style.opacity="1"
}
// obj.style.width="100%"
// obj.style.height="100%"
})
//this.web.style.visibility="visible"
//this.web.style.opacity="1"
})
tab.addEventListener('click',(e)=>{
this.tabMap.forEach(function (item, key, mapObj) {
item.style.border="none"
})
e.target.style.borderLeft="1px solid black"
e.target.style.borderTop="1px solid black"
e.target.style.borderRight="1px solid black"
this.setSelectedWebview(e.target.getAttribute('id'))
if(e.target.offsetLeft+e.target.offsetWidth>this.tabs.offsetWidth+this.tabs.scrollLeft){
$(this.tabs).animate({scrollLeft: e.target.offsetLeft-this.tabs.offsetWidth+e.target.offsetWidth}, "slow")
}
if(e.target.offsetLeft<this.tabs.scrollLeft){
$(this.tabs).animate({scrollLeft: e.target.offsetLeft-10}, "slow")
}
/* $("webview").each(function(i, obj) {
obj.style.visibility="hidden"
obj.setAttribute('selected','0')
if(obj.getAttribute('id')==src){
obj.style.visibility="visible"
obj.style.opacity="1"
newSelectedWebview=obj
obj.setAttribute('selected','1')
}
})*/
//this.web = newSelectedWebview
this.enableButtons()
})
}
getPreviousTab(val){
let obj=null
let returnValue=null
this.webviewMap.forEach(function (item, key, mapObj) {
if(key==val){
returnValue=obj
}
obj=item
})
return returnValue
}
getNextTab(val){
console.log("this.webviewMap",this.webviewMap[0])
let obj=null
let oldKey=null
let returnValue=null
this.webviewMap.forEach(function (item, key, mapObj) {
obj=item
if(oldKey==val){
returnValue=obj
}
oldKey=key
})
return returnValue
}
rad2degree(alpha){
return alpha * 180 / Math.PI;
}
degree2rad(alpha){
return alpha * Math.PI / 180;
}
close() {
// this.frame.style.display="none"
this.frame.parentNode.removeChild(this.frame)
urlPadMap.delete(this.url)
}
enableButtons() {
console.log("enabling buttons")
this.backButton.style.opacity = (this.web.canGoBack()) ? 1 : 0.5
this.forwardButton.style.opacity = (this.web.canGoForward()) ? 1 : 0.5
}
addButton(src, value) {
let button = document.createElement("img")
button.type = "image"
button.className = "frameButton"
button.style.position = "absolute"
button.src = fileURL(src)
button.value="close"
button.draggable = false
button.classList.add("interactiveElement")
this.frame.appendChild(button)
return button
}
layout() {
let b = this.border
let b2 = b * 2
let b8 = b / 8
let b25 = b / 25
let b15 = b / 15
Elements.setStyle(this.frame, {
// borderRadius: b8 + "px",
// boxShadow: `${b25}px ${b15}px ${b8}px rgba(0, 0, 0, 0.5)`
})
this.scatter.resizeButton.style.width=b+"px"
this.scatter.resizeButton.style.height=b+"px"
let size = "calc(100% - " + (2*b) +"px)"
let h = "calc(100% - " + (b) +"px)"
let w = "calc(100% - "+2 +"px)"
let w2 = "calc(100% - " + (b+2) +"px)"
/* Elements.setStyle(this.web, {
width: w,
height: h,
margin: "0px"})*/
$(this.frame).find(".tabCloseButton").css('height',0.5*b+"px")
$(this.frame).find(".tabCloseButton").css('width',0.5*b+"px")
$(this.frame).find(".tabCloseButton").css('borderRadius',b+"px")
$(this.frame).find(".tabTitle").css('fontSize',0.3*b+"px")
// $(this.frame).find(".tab").css('borderLeft',0.01*b+'px solid black')
// $(this.frame).find(".tab").css('borderTop',0.01*b+'px solid black')
// $(this.frame).find(".tab").css('borderRight',0.01*b+'px solid black')
// $(".tabTitle").css('fontSize',0.3*b+"px")
Elements.setStyle(this.titlebar, {
left: (b * 2.75) + "px",
top: "0px",
fontSize: 0.7*b+"px",
display: "none",
// paddingTop: 10+"px",
// textAlign: "center",
height: 0.9*b+"px"})
Elements.setStyle(this.webViewSnapshot, {
width: w,
height: h,
margin: "0px"})
Elements.setStyle(this.tabs, {
width: w2,
height: b+"px",
bottom: b+"px",
margin: "1px"})
Elements.setStyle(this.webBackground, {
width: w,
height: size,
margin: "1px"})
Elements.setStyle(this.webviewList, {
bottom: 2*b+2+"px",
right: b+"px",
width: "50%",
margin: "0px"})
/* Elements.setStyle(this.overlay, {
width: w,
height: h,
margin: "0px"})*/
Elements.setStyle(this.pseudoFrameTop, {
width: w,
height: 0.1*b+"px",
margin: "0px"})
Elements.setStyle(this.pseudoFrameLeft, {
width: 0.1*b+"px",
height: h,
margin: "0px"})
Elements.setStyle(this.pseudoFrameRight, {
width: 0.1*b+"px",
height: h,
margin: "0px"})
Elements.setStyle(this.closeButton, {
right: (b * 0.75) + "px",
bottom: "0px",
width: b+"px",
height: b+"px"})
Elements.setStyle(this.backButton, {
left: (b * 0.1) +"px",
bottom: "0px",
width: b+"px",
height: b+"px"})
Elements.setStyle(this.forwardButton, {
left: (this.border + (b * 0.1)) +"px",
bottom: "0px",
width: b+"px",
height: b+"px"})
Elements.setStyle(this.showWebviewListButton, {
right: "1px",
background: "white",
bottom: b+1+"px",
width: b+"px",
height: b+"px"})
if(this.tabMap.size > 1){
this.tabs.style.display = "flex"
this.showWebviewListButton.style.display = "inline"
if(this.hasTtitleBar){
Elements.setStyle(this.webBackground, {
top: b+"px",
width: w,
height: size-b,
margin: "1px"})
Elements.setStyle(this.titlebar, {
display: "inline"})
}
if(!this.hasTtitleBar){
Elements.setStyle(this.webBackground, {
width: w,
height: size,
margin: "1px"})
}
}
if(this.tabMap.size <= 1){
this.tabs.style.display = "none"
this.showWebviewListButton.style.display = "none"
if(this.hasTtitleBar){
Elements.setStyle(this.webBackground, {
top: b+"px",
width: w,
height: size,
margin: "1px"})
Elements.setStyle(this.titlebar, {
display: "inline"})
}
if(!this.hasTtitleBar){
Elements.setStyle(this.webBackground, {
width: w,
height: h,
margin: "1px"})
}
}
if(!this.tabbedView){
this.tabs.style.display = "none"
this.showWebviewListButton.style.display = "none"
Elements.setStyle(this.webBackground, {
width: w,
height: h,
margin: "1px"})
}
}
}
class minimalPadFromElement {
constructor(element, scatterContainer, {
startScale=1.0, minScale=0.1, maxScale=1.0,
autoBringToFront=true,
translatable=true, scalable=true, rotatable=true,
movableX=true,
movableY=true,
rotationDegrees=null,
rotation=null,
onTransform=null,
transformOrigin = 'center center',
// extras which are in part needed
x=0,
y=0,
width=null,
height=null,
resizable=false,
} ={}) {
this.element = element
this.x = x
this.y = y
this.width = width
this.height = height
this.minScale = minScale
this.maxScale = maxScale
this.scatterContainer = scatterContainer
this.scale = startScale
this.scalable = scalable
this.rotatable = rotatable
this.rotationDegrees = this.startRotationDegrees
this.transformOrigin = transformOrigin
this.frame = document.createElement('div')
Elements.setStyle(this.frame, {
width: this.width+"px",
height: this.height+"px",
backgroundColor: "#333",
position: "fixed",
top: 0,
left: 0,
overflow: "auto"})
this.closeButton = this.addButton("../assets/icons/svg/cross.svg", "close")
document.body.appendChild( this.frame)
this.border = 50
this.frame.appendChild(this.element)
this.title = document.createElement("div")
this.title.innerHTML = ""
this.title.style.color = "white"
// this.frame.appendChild(this.title)
Elements.setStyle(this.title, {
position: "absolute"
})
// this.pseudoFrame = document.createElement('div')
this.pseudoFrameTop = document.createElement('div')
this.pseudoFrameLeft = document.createElement('div')
this.pseudoFrameRight = document.createElement('div')
/*Elements.setStyle(this.pseudoFrame, {
position: "absolute",
top: "0px",
left: "0px",
width: "100%",
height: "100%",
pointerEvents: "none"
})*/
Elements.setStyle(this.pseudoFrameTop, {
position: "absolute",
// background: "pink",
top: "0px",
left: "0px",
width: "100%"
// height: "50px"
})
Elements.setStyle(this.pseudoFrameLeft, {
position: "absolute",
// background: "pink",
top: "0px",
left: "0px",
// width: "5px",
height: "100%"
})
Elements.setStyle(this.pseudoFrameRight, {
position: "absolute",
// background: "pink",
top: "0px",
right: "0px",
// width: "5px",
height: "100%"
})
this.frame.appendChild(this.pseudoFrameTop)
this.frame.appendChild(this.pseudoFrameLeft)
this.frame.appendChild(this.pseudoFrameRight)
// this.frame.appendChild(this.pseudoFrame)
this.pseudoFrameTop.addEventListener('pointerenter',(e)=>{
this.scatter.scalable=false
this.element.pointerEvents = "none"
e.target.style.cursor = "move"
})
this.pseudoFrameTop.addEventListener('pointerleave',(e)=>{
this.scatter.scalable=true
// this.frame.style.cursor = "initial"
})
this.pseudoFrameLeft.addEventListener('pointerenter',(e)=>{
// e.target.setPointerCapture(e.pointerId)
this.scatter.scalable=false
this.element.pointerEvents = "none"
e.target.style.cursor = "move"
})
this.pseudoFrameLeft.addEventListener('pointerleave',(e)=>{
this.scatter.scalable=true
// this.frame.style.cursor = "initial"
})
this.pseudoFrameRight.addEventListener('pointerenter',(e)=>{
this.scatter.scalable=false
this.element.pointerEvents = "none"
e.target.style.cursor = "move"
})
this.pseudoFrameRight.addEventListener('pointerleave',(e)=>{
this.scatter.scalable=true
// this.frame.style.cursor = "initial"
})
// this.element.style.overflow = "auto"
// this.element.style.position = "absolute"
this.layout()
this.closeButton.addEventListener('click', ()=>{
this.frame.style.display="none"
})
this.scatter = new DOMScatter(this.frame, scatterContainer, {
x: this.x,
y: this.y,
startScale: this.startScale,
width: this.width,
height: this.height,
minScale: this.minScale,
maxScale: this.maxScale,
scalable: this.scalable,
resizable: true,
rotatable: this.rotatable})
let img=document.createElement("img")
img.style.width = "70%"
img.style.position = "absolute"
img.style.bottom = "20%"
img.style.right = "20%"
img.style.pointerEvents="none"
img.src = "../../assets/icons/png/flat/resize.png"
this.scatter.resizeButton.appendChild(img)
this.scatter.bringToFront()
this.scatter.addTransformEventCallback((e) => {
let newBorder = 50 / e.scale
if (newBorder !== this.border) {
this.border = newBorder
this.layout()
}
})
this.element.addEventListener('pointerdown', (e) => {
this.scatter.bringToFront()
})
}
close() {
// this.frame.style.display="none"
this.frame.parentNode.removeChild(this.frame)
urlPadMap.delete(this.url)
}
addButton(src, value) {
let button = document.createElement("img")
button.type = "image"
button.className = "frameButton"
button.style.position = "absolute"
button.src = fileURL(src)
button.value="close"
button.draggable = false
this.frame.appendChild(button)
return button
}
layout() {
let b = this.border
let b2 = b * 2
let b8 = b / 8
let b25 = b / 25
let b15 = b / 15
let size = "calc(100% - " + (2*b) +"px)"
let h = "calc(100% - " + (b) +"px)"
let w = "calc(100% - "+2 +"px)"
let w2 = "calc(100% - " + (b+2) +"px)"
this.scatter.resizeButton.style.width=b+"px"
this.scatter.resizeButton.style.height=b+"px"
Elements.setStyle(this.frame, {
// borderRadius: b8 + "px",
// boxShadow: `${b25}px ${b15}px ${b8}px rgba(0, 0, 0, 0.5)`
})
Elements.setStyle(this.element, {
width: w,
height: h,
top: 0+"px",
left: 0+"px"})
Elements.setStyle(this.title, {
left: (b * 1.5) + "px",
fontSize: (b * 0.8) + "px",
top: (0.1)+"0px"})
Elements.setStyle(this.pseudoFrameTop, {
width: w,
height: 0.1*b+"px",
margin: "0px"})
Elements.setStyle(this.pseudoFrameLeft, {
width: 0.1*b+"px",
height: h,
margin: "0px"})
Elements.setStyle(this.pseudoFrameRight, {
width: 0.1*b+"px",
height: h,
margin: "0px"})
Elements.setStyle(this.closeButton, {
right: (b * 0.75) + "px",
bottom: "0px",
width: b+"px",
height: b+"px"})
}
}
module.exports = { minimalPad, minimalDOMPadContainer, minimalPadFromElement}