mirror of
https://gitlab.com/octospacc/octospacc.gitlab.io
synced 2025-02-09 00:18:40 +01:00
[FramesBrowser] add multiple windows
This commit is contained in:
parent
3deeb7a122
commit
4d740b1627
@ -6,8 +6,11 @@
|
|||||||
<title>Frames Browser (WIP)</title>
|
<title>Frames Browser (WIP)</title>
|
||||||
<style>
|
<style>
|
||||||
:root {
|
:root {
|
||||||
--BtnHeight: 2em;
|
--BaseMargin: 8px;
|
||||||
--BtnActionHeight: 3em;
|
--BtnHeight: calc(1rem + var(--BaseMargin));
|
||||||
|
--BtnActionHeight: calc(2rem + var(--BaseMargin));
|
||||||
|
--ColorBg: #f0f0f0;
|
||||||
|
--ColorFg: #0f0f0f;
|
||||||
}
|
}
|
||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@ -27,22 +30,45 @@
|
|||||||
height: calc(100vh - var(--BtnActionHeight));
|
height: calc(100vh - var(--BtnActionHeight));
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
#BoxControls {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
#BoxControls table, #BoxControls table td, #BoxControls table td > * {
|
#BoxControls table, #BoxControls table td, #BoxControls table td > * {
|
||||||
height: var(--BtnActionHeight);
|
height: var(--BtnActionHeight);
|
||||||
min-width: var(--BtnActionHeight);
|
min-width: var(--BtnActionHeight);
|
||||||
|
padding-top: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
border-spacing: 0;
|
border-spacing: 0;
|
||||||
}
|
}
|
||||||
.BoxPopup {
|
.BoxPopup {
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
|
.BoxPopup.Container {
|
||||||
|
position: absolute;
|
||||||
|
top: 10vh;
|
||||||
|
z-index: 1;
|
||||||
|
max-height: 80vh;
|
||||||
|
overflow: auto;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.BoxPopup.Content {
|
||||||
|
position: relative;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
width: fit-content;
|
||||||
|
box-shadow: gray 4px 4px 4px 0px;
|
||||||
|
color: var(--ColorFg);
|
||||||
|
background-color: var(--ColorBg);
|
||||||
|
}
|
||||||
|
.BtnAction {
|
||||||
|
height: var(--BtnActionHeight);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
var FrameZoomLevels = [50, 200];
|
var FrameZoomLevels = [50, 200];
|
||||||
var AppInfoString = `
|
var AppInfoString = `
|
||||||
Frames Browser v2023-09-21.3 (WIP).
|
Frames Browser v2023-09-22 (WIP).
|
||||||
`.trim();
|
`.trim();
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
@ -54,42 +80,102 @@ Frames Browser v2023-09-21.3 (WIP).
|
|||||||
<input type="file" hidden="hidden" style="display: none;" onchange="LoadFile(this.files[0])"/>
|
<input type="file" hidden="hidden" style="display: none;" onchange="LoadFile(this.files[0])"/>
|
||||||
</td>
|
</td>
|
||||||
<td><button onclick="ZoomFrame()">🔍️ Zoom</button></td>
|
<td><button onclick="ZoomFrame()">🔍️ Zoom</button></td>
|
||||||
<!--<td><button onclick="ListFrames()">🪟 Frames</button></td>-->
|
<td><button onclick="ListFrames()">🪟 Frames</button></td>
|
||||||
<td style="width: 100%;"><input type="text" style="width: 100%;"/></td>
|
<td style="width: 100%;"><input type="text" style="min-width: 100%;" hint="🔗️ Enter URI..."/></td>
|
||||||
<td><button onclick="LoadFrame()">↩️ Load</button></td>
|
<td><button onclick="LoadFrame()">↩️ Load</button></td>
|
||||||
<td><button onclick="ExciseFrame()">↗️ Excise</button></td>
|
<td><button onclick="ExciseFrame()">↗️ Excise</button></td>
|
||||||
<tr></table></div>
|
<tr></table></div>
|
||||||
|
<noscript><p class="NoScript">
|
||||||
|
This is an actual app, not a badly-made website.
|
||||||
|
<br>
|
||||||
|
It needs JavaScript to work, so you need to enable it.
|
||||||
|
<br>
|
||||||
|
The code is fully open, and you can review it with "View Page Source".
|
||||||
|
</p></noscript>
|
||||||
|
<div id="BoxHandy"></div>
|
||||||
<div><iframe></iframe></div>
|
<div><iframe></iframe></div>
|
||||||
<script>
|
<script>
|
||||||
|
var CurrentFrames = [];
|
||||||
|
var FrameIndexes = [-1];
|
||||||
var FrameZoomIndex = -1;
|
var FrameZoomIndex = -1;
|
||||||
|
|
||||||
//function $rule(prop){
|
function $new(tag, props){
|
||||||
// return getComputedStyle(document.body).getPropertyValue(prop);
|
var el = document.createElement(tag);
|
||||||
//};
|
if (props) {
|
||||||
|
Object.keys(props).forEach(function(key){
|
||||||
function $new(tag){
|
el[key] = props[key];
|
||||||
return document.createElement(tag);
|
});
|
||||||
|
};
|
||||||
|
return el;
|
||||||
};
|
};
|
||||||
|
|
||||||
function ShowAppInfo(){
|
function ShowAppInfo(){
|
||||||
alert(AppInfoString);
|
alert(AppInfoString);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function ShowFrame(index){
|
||||||
|
ListFramesClose();
|
||||||
|
FrameIndexes = [index];
|
||||||
|
SaveCurrentFrames();
|
||||||
|
document.querySelector('iframe').hidden = false;
|
||||||
|
document.querySelector('iframe').style.display = '';
|
||||||
|
document.querySelector('input[type="text"]').value = CurrentFrames[index];
|
||||||
|
document.querySelector('input[type="text"]').disabled = false;
|
||||||
|
document.querySelector('iframe').src = CurrentFrames[index];
|
||||||
|
};
|
||||||
|
|
||||||
|
function ShowRootFrame(){
|
||||||
|
ListFramesClose();
|
||||||
|
FrameIndexes = [-1];
|
||||||
|
SaveCurrentFrames();
|
||||||
|
document.querySelector('iframe').hidden = true;
|
||||||
|
document.querySelector('iframe').style.display = 'none';
|
||||||
|
document.querySelector('input[type="text"]').disabled = true;
|
||||||
|
document.querySelector('input[type="text"]').value = '';
|
||||||
|
document.querySelector('iframe').src = '';
|
||||||
|
};
|
||||||
|
|
||||||
function SaveUrl(){
|
function SaveUrl(){
|
||||||
var url = document.querySelector('input[type="text"]').value;
|
var url = document.querySelector('input[type="text"]').value;
|
||||||
localStorage.setItem('FramesBrowser.url', url);
|
localStorage.setItem('FramesBrowser.url', url);
|
||||||
|
CurrentFrames[FrameIndexes[0]] = url;
|
||||||
|
SaveCurrentFrames();
|
||||||
return url;
|
return url;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
function AddFrame(){
|
||||||
|
CurrentFrames = CurrentFrames.concat(['']);
|
||||||
|
ListFrames(); //ListFrames();
|
||||||
|
ShowFrame(CurrentFrames.length - 1);
|
||||||
|
SaveCurrentFrames();
|
||||||
|
};
|
||||||
|
|
||||||
|
function CloseFrame(index){
|
||||||
|
CurrentFrames.pop(index);
|
||||||
|
if (FrameIndexes[0] === index) {
|
||||||
|
ShowRootFrame();
|
||||||
|
} else if (FrameIndexes[0] > index) {
|
||||||
|
FrameIndexes[0] --;
|
||||||
|
};
|
||||||
|
ListFrames(); ListFrames();
|
||||||
|
SaveCurrentFrames();
|
||||||
|
};
|
||||||
|
|
||||||
|
function SaveCurrentFrames(){
|
||||||
|
localStorage.setItem('FramesBrowser.CurrentFrames', JSON.stringify(CurrentFrames));
|
||||||
|
localStorage.setItem('FramesBrowser.FrameIndexes', JSON.stringify(FrameIndexes));
|
||||||
|
};
|
||||||
|
|
||||||
function LoadFrame(){
|
function LoadFrame(){
|
||||||
document.querySelector('iframe').src = SaveUrl();
|
document.querySelector('iframe').src = SaveUrl();
|
||||||
};
|
};
|
||||||
|
|
||||||
function ExciseFrame(){
|
function ExciseFrame(){
|
||||||
var url = SaveUrl();
|
var uri = SaveUrl();
|
||||||
var extwindow = open(url, '_blank');
|
if (uri.toLowerCase().startsWith('data:')) {
|
||||||
if (url.toLowerCase().startsWith('data:')) {
|
opendatauri(uri);
|
||||||
extwindow.document.write(`<style>body { margin: 0; } iframe { width: 100vw; height: 100vh; border: none; }</style><iframe src="${url}" frameborder="0"></iframe>`);
|
} else {
|
||||||
|
open(uri, '_blank');
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -103,7 +189,7 @@ Frames Browser v2023-09-21.3 (WIP).
|
|||||||
};
|
};
|
||||||
|
|
||||||
function ZoomFrame(){
|
function ZoomFrame(){
|
||||||
if (FrameZoomIndex == FrameZoomLevels.length - 1) {
|
if (FrameZoomIndex === FrameZoomLevels.length - 1) {
|
||||||
FrameZoomIndex = -1;
|
FrameZoomIndex = -1;
|
||||||
} else {
|
} else {
|
||||||
FrameZoomIndex ++;
|
FrameZoomIndex ++;
|
||||||
@ -114,35 +200,76 @@ Frames Browser v2023-09-21.3 (WIP).
|
|||||||
? `right: ${level}vw; bottom: calc(${level}vh - 16px);`
|
? `right: ${level}vw; bottom: calc(${level}vh - 16px);`
|
||||||
: `left: ${levelopp/2}vw; top: calc(${levelopp/2}vh - 8px);`
|
: `left: ${levelopp/2}vw; top: calc(${levelopp/2}vh - 8px);`
|
||||||
);
|
);
|
||||||
document.querySelector('iframe').style = (FrameZoomIndex == -1
|
document.querySelector('iframe').style = (FrameZoomIndex === -1
|
||||||
? ''
|
? ''
|
||||||
: `scale: ${level/100}; width: ${levelopp}vw; height: calc(${levelopp}vh - (var(--BtnActionHeight) * ${levelopp / 100})); ${stylepos}`
|
: `scale: ${level/100}; width: ${levelopp}vw; height: calc(${levelopp}vh - (var(--BtnActionHeight) * ${levelopp / 100})); ${stylepos}`
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
function ListFrames(){
|
function ListFrames(){
|
||||||
var Box = NewBoxPopup();
|
if (!ListFramesClose()){
|
||||||
var BtnAdd = $new('button');
|
var Box = NewBoxPopup('BoxFramesList');
|
||||||
BtnAdd.innerHTML = '➕ Add';
|
var BtnAdd = $new('button', { className: 'BtnAction', innerHTML: '➕ Add', onclick: AddFrame });
|
||||||
Box.appendChild(BtnAdd);
|
Box.Content.appendChild(BtnAdd);
|
||||||
var BtnMain = $new('button');
|
var BoxList = $new('ul');
|
||||||
BtnMain.innerHTML = 'No Frame';
|
Box.Content.appendChild(BoxList);
|
||||||
Box.appendChild(BtnMain);
|
var LiMain = $new('li');
|
||||||
|
BoxList.appendChild(LiMain);
|
||||||
|
var BtnMain = $new('button', { innerHTML: 'Root Window', onclick: ShowRootFrame, disabled: FrameIndexes[0] === -1 });
|
||||||
|
LiMain.appendChild(BtnMain);
|
||||||
|
for (var i=0; i<CurrentFrames.length; i++) {
|
||||||
|
var li = $new('li');
|
||||||
|
li.ItemIndex = i;
|
||||||
|
BoxList.appendChild(li);
|
||||||
|
var open = $new('button', { innerHTML: ` ${CurrentFrames[i].slice(0, 16)} `, onclick: function(){ShowFrame(this.parentElement.ItemIndex)}, disabled: FrameIndexes[0] === i });
|
||||||
|
li.append(open);
|
||||||
|
var close = $new('button', { innerHTML: '✖️', onclick: function(){CloseFrame(this.parentElement.ItemIndex)} });
|
||||||
|
li.append(close);
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
function NewBoxPopup(){
|
function ListFramesClose(){
|
||||||
var Box = $new('div');
|
var exist = document.querySelector('#BoxFramesList');
|
||||||
Box.className = 'BoxPopup';
|
if (exist) {
|
||||||
var BtnClose = $new('button');
|
BoxFramesList.remove();
|
||||||
BtnClose.innerHTML = '❌ Close';
|
};
|
||||||
BtnClose.onclick = function(){ this.parentElement.remove() };
|
return exist;
|
||||||
Box.appendChild(BtnClose);
|
};
|
||||||
document.body.appendChild(Box);
|
|
||||||
return Box;
|
function NewBoxPopup(id){
|
||||||
|
var Container = $new('div', { id: id, className: 'BoxPopup Container' });
|
||||||
|
var Content = $new('div', { className: 'BoxPopup Content' });
|
||||||
|
Container.appendChild(Content);
|
||||||
|
var BtnClose = $new('button', { className: 'BtnAction', innerHTML: '❌ Close', onclick: function(){this.parentElement.parentElement.remove()} });
|
||||||
|
Content.appendChild(BtnClose);
|
||||||
|
BoxHandy.appendChild(Container);
|
||||||
|
return { Container: Container, Content: Content };
|
||||||
|
};
|
||||||
|
|
||||||
|
window.opendatauri = function opendatauri(data){
|
||||||
|
var head = data.split(',')[0].split('data:')[1];
|
||||||
|
var [mime, encoding] = head.split(';');
|
||||||
|
data = data.split(',').slice(1).join(',');
|
||||||
|
if (encoding.toLowerCase() === 'base64') {
|
||||||
|
data = atob(data);
|
||||||
|
};
|
||||||
|
var bytes = new Array(data.length);
|
||||||
|
for (var i = 0; i < data.length; i++) {
|
||||||
|
bytes[i] = data.charCodeAt(i);
|
||||||
|
};
|
||||||
|
window.open(URL.createObjectURL(
|
||||||
|
new Blob([new Uint8Array(bytes)], { type: `${mime};${encoding ? encoding : 'utf8'}` })
|
||||||
|
), '_blank');
|
||||||
};
|
};
|
||||||
|
|
||||||
onload = function(){
|
onload = function(){
|
||||||
|
Array.from(document.querySelectorAll('noscript, .NoScript')).forEach(function(el){ el.remove() });
|
||||||
|
CurrentFrames = (JSON.parse(localStorage.getItem('FramesBrowser.CurrentFrames')) || []);
|
||||||
|
FrameIndexes = (JSON.parse(localStorage.getItem('FramesBrowser.FrameIndexes')) || [-1]);
|
||||||
document.querySelector('input[type="text"]').value = localStorage.getItem('FramesBrowser.url');
|
document.querySelector('input[type="text"]').value = localStorage.getItem('FramesBrowser.url');
|
||||||
|
var frame0 = FrameIndexes[0];
|
||||||
|
frame0 === -1 ? ShowRootFrame() : ShowFrame(frame0);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user