diff --git a/public/assets/editor.js b/public/assets/editor.js
index 2a9c269..edac79b 100644
--- a/public/assets/editor.js
+++ b/public/assets/editor.js
@@ -107,7 +107,7 @@ function ytknsEditorPreview(zoneInfo) {
var formElement = document.createElement('form');
formElement.action = '/zones/_preview';
formElement.method = 'post';
- formElement.target = '_blank';
+ formElement.target = ytknsEditorSBS ? 'preview' : '_blank';
formElement.style.display = 'none';
var elements = ytknsZoneInfoSerialise(zoneInfo, function(name, value) {
@@ -154,7 +154,8 @@ var ytknsZoneInfo = null,
ytknsEditorElemMainContainer = null,
ytknsEditorEffects = [],
ytknsEditorIgnoreHashChange = false,
- ytknsEditorCleanExit = true;
+ ytknsEditorCleanExit = true,
+ ytknsEditorSBS = false;
function ytknsEditorChangeHash(hash) {
ytknsEditorIgnoreHashChange = true;
@@ -877,6 +878,9 @@ function ytknsEditorMainSetContainer(child, title) {
ytknsEditorElemMainContainer.innerHTML = '';
ytknsEditorElemMainContainer.appendChild(child);
+
+ if(ytknsEditorSBS)
+ ytknsEditorPreview(ytknsZoneInfo);
}
function ytknsEditorMainClone() {
return {
@@ -1025,7 +1029,7 @@ function ytknsEditorHashChange(ev) {
ytknsEditorIgnoreHashChange = false;
}
-function ytknsEditorMain(container, zoneId, editorToken, uploadToken) {
+function ytknsEditorMain(container, zoneId, editorToken, uploadToken, sideBySide) {
if(navigator.userAgent.match(/mobile/gi) && !confirm("The editor is not designed to be used on phones whatsoever.\r\nHit OK to continue anyway or cancel to whereever you came from.")) {
history.go(-1);
return;
@@ -1035,6 +1039,7 @@ function ytknsEditorMain(container, zoneId, editorToken, uploadToken) {
window.onbeforeunload = ytknsEditorBeforeUnload;
ytknsEditorToken = editorToken;
ytknsEditorUploadToken = uploadToken;
+ ytknsEditorSBS = sideBySide;
container.innerHTML = '';
container.classList.add('ye');
diff --git a/public/index.php b/public/index.php
index 374b34c..c794540 100644
--- a/public/index.php
+++ b/public/index.php
@@ -41,6 +41,7 @@ function html_header(array $vars = []): string {
['text' => 'Home', 'link' => page_url('/')],
['text' => 'Create a Zone', 'link' => page_url('/zones/create')],
['text' => 'Zones', 'link' => page_url('/zones')],
+ ['text' => 'Random', 'link' => page_url('/zones/random')],
]);
$userMenu = [];
@@ -313,6 +314,12 @@ if($reqPath === '/zones') {
return;
}
+if($reqPath === '/zones/random') {
+ $zoneInfo = Zone::byRandom();
+ header('Location: ' . $zoneInfo->getUrl());
+ return;
+}
+
if($reqPath === '/zones/create') {
if(!UserSession::hasInstance()) {
http_response_code(403);
@@ -501,6 +508,14 @@ if(preg_match('#^/zones/([0-9]+)/delete$#', $reqPath, $matches)) {
return;
}
+if(preg_match('#^/zones/([0-9]+)/sbs$#', $reqPath, $matches)) {
+ echo '';
+ echo '
YTKNS Side By Side Editor';
+ echo '';
+ echo '';
+ return;
+}
+
if(preg_match('#^/zones/([0-9]+)$#', $reqPath, $matches)) {
if(!UserSession::hasInstance()) {
http_response_code(403);
@@ -523,15 +538,24 @@ if(preg_match('#^/zones/([0-9]+)$#', $reqPath, $matches)) {
return;
}
+ $isSBS = !empty($_GET['sbs']);
$cssHash = hash_file('sha256', YTKNS_PUB . '/assets/editor.css');
$jsHash = hash_file('sha256', YTKNS_PUB . '/assets/editor.js');
- echo html_header([
- 'title' => 'Editing Zone - YTKNS',
- 'styles' => [
- page_url('/assets/editor.css', ['v' => $cssHash]),
- ],
- ]);
+ if($isSBS) {
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ } else {
+ echo html_header([
+ 'title' => 'Editing Zone - YTKNS',
+ 'styles' => [
+ page_url('/assets/editor.css', ['v' => $cssHash]),
+ ],
+ ]);
+ }
+
Template::render('zones/edit', [
'edit_id' => $zoneInfo->getId(),
'edit_token' => UserSession::instance()->getSmallToken(10),
@@ -539,11 +563,24 @@ if(preg_match('#^/zones/([0-9]+)$#', $reqPath, $matches)) {
'edit_js_ver' => substr($jsHash, 0, 16),
'upload_token' => UserSession::instance()->getSmallToken(6),
]);
- echo html_footer([
- 'scripts' => [
- page_url('/assets/editor.js', ['v' => $jsHash]),
- ],
- ]);
+
+ if($isSBS) {
+ echo '';
+ } else {
+ echo <<
+ window.addEventListener('DOMContentLoaded', function() {
+ if(window.location !== window.parent.location)
+ location.assign(location.toString() + '?sbs=1');
+ });
+
+HTML;
+ echo html_footer([
+ 'scripts' => [
+ page_url('/assets/editor.js', ['v' => $jsHash]),
+ ],
+ ]);
+ }
return;
}
diff --git a/src/Effects/ForegroundImageEffect.php b/src/Effects/ForegroundImageEffect.php
index 7789cc7..ec88407 100644
--- a/src/Effects/ForegroundImageEffect.php
+++ b/src/Effects/ForegroundImageEffect.php
@@ -6,6 +6,7 @@ use YTKNS\HtmlTag;
use YTKNS\HtmlText;
use YTKNS\PageBuilder;
use YTKNS\PageEffectInterface;
+use YTKNS\PageEffectException;
use YTKNS\Upload;
use YTKNS\UploadNotFoundException;
diff --git a/src/Zone.php b/src/Zone.php
index 659b94a..c5d1d5d 100644
--- a/src/Zone.php
+++ b/src/Zone.php
@@ -190,6 +190,19 @@ final class Zone {
return $zone;
}
+ public static function byRandom(): self {
+ $getZone = DB::prepare('
+ SELECT `zone_id`, `user_id`, `zone_name`, `zone_title`, `zone_views`,
+ UNIX_TIMESTAMP(`zone_created`) AS `zone_created`,
+ UNIX_TIMESTAMP(`zone_updated`) AS `zone_updated`
+ FROM `ytkns_zones`
+ ORDER BY RAND()
+ LIMIT 1
+ ');
+ $zone = $getZone->execute() ? $getZone->fetchObject(self::class) : null;
+ return $zone;
+ }
+
public static function byName(string $name): self {
$getZone = DB::prepare('
SELECT `zone_id`, `user_id`, `zone_name`, `zone_title`, `zone_views`,
diff --git a/templates/zones/edit.html b/templates/zones/edit.html
index 7b27fe7..e7d8c79 100644
--- a/templates/zones/edit.html
+++ b/templates/zones/edit.html
@@ -13,7 +13,9 @@