1355 lines
62 KiB
Handlebars
1355 lines
62 KiB
Handlebars
<!DOCTYPE html>
|
|
{{>copyright }}
|
|
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
<script src="/js/axios.min.js"></script>
|
|
<script src="/js/fontawesome.all.min.js"></script>
|
|
<script src="/js/Sortable.min.js"></script>
|
|
<script src="/js/socket.io.js"></script>
|
|
<script src="/js/vanilla-js-tooltip.js"></script>
|
|
<script src="/js/spx_controllerImportFunctions.js"></script>
|
|
<script src="/js/anime.min.js"></script>
|
|
<script src="/js/lib/vanilla-picker.csp.min.js"></script> <!-- added in 1.1.1 -->
|
|
<script>
|
|
var socket = io();
|
|
</script>
|
|
<script src="/js/spx_gc.js"></script>
|
|
|
|
<script>
|
|
// Make the DIV element draggable:
|
|
document.addEventListener("DOMContentLoaded", function() {
|
|
dragElement(document.getElementById("dialog"));
|
|
});
|
|
</script>
|
|
|
|
|
|
|
|
<title>SPX | {{lang 'pagetitle.controller'}}</title>
|
|
<link rel="icon" type="image/png" href="/img/spx-gc.ico">
|
|
<link rel="stylesheet" type="text/css" href="/css/spx_fonts.css">
|
|
<link rel="stylesheet" type="text/css" href="/css/spx_layout.css">
|
|
<link rel="stylesheet" type="text/css" href="/css/spx_forms.css">
|
|
<link rel="stylesheet" type="text/css" href="/css/spx_colors.css">
|
|
<link rel="stylesheet" type="text/css" href="/css/spx_modal.css">
|
|
<link rel="stylesheet" type="text/css" href="/css/spx_accents.css">
|
|
<link rel="stylesheet" type="text/css" href="/css/vanilla-js-tooltip.css" />
|
|
<link rel="stylesheet" type="text/css" href="/css/vanilla-picker.csp.css" >
|
|
<link rel="stylesheet" type="text/css" href="/css/toggle2.css">
|
|
<link rel="stylesheet" type="text/css" href="/css/toggle.css">
|
|
|
|
<style>
|
|
|
|
#previewIF {
|
|
border: 0px solid yellow;
|
|
}
|
|
|
|
#previewBG {
|
|
border: 0px dashed orange;
|
|
}
|
|
|
|
#colorPopup {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100px;
|
|
height: 100px;
|
|
background: rgba(0, 0, 0, 0.5);
|
|
z-index: 9999;
|
|
display: none;
|
|
}
|
|
|
|
.stripedMessage {
|
|
--darkCol: rgba(0, 0, 0, 0.1);
|
|
--liteCol: rgba(0, 0, 0, 0.2);
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
display: none; /* flex / controlled by JS logic */
|
|
z-index: 10;
|
|
padding: 0.5em;
|
|
font-size: 0.7em;
|
|
position: relative;
|
|
align-items: center;
|
|
border-radius: 0.0em;
|
|
margin-bottom: 0.4em;
|
|
justify-content: center;
|
|
background-size: 3vw 3vw;
|
|
color: rgb(181, 181, 181);
|
|
text-shadow: 1px 1px 1px rgb(0, 0, 0);
|
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.4);
|
|
border-bottom: 1px solid rgba(0, 0, 0, 0.5);
|
|
background-image: linear-gradient(
|
|
135deg,
|
|
var(--darkCol) 25%,
|
|
var(--liteCol) 25%,
|
|
var(--liteCol) 50%,
|
|
var(--darkCol) 50%,
|
|
var(--darkCol) 75%,
|
|
var(--liteCol) 75%,
|
|
var(--liteCol) 100%);
|
|
}
|
|
|
|
.stripedMessage a {
|
|
color: rgb(161, 161, 161);
|
|
}
|
|
|
|
.stripedMessage a:hover {
|
|
color: rgb(255, 255, 255);
|
|
cursor: help;
|
|
}
|
|
|
|
.ListHeaderButtons {
|
|
width: 100%;
|
|
margin-bottom: 1em;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 0.7em;
|
|
border-left: 10px solid blue;
|
|
background-color: rgba(255, 255, 255, 0.1);
|
|
box-shadow: ;
|
|
}
|
|
|
|
#rundownInfoMessage {
|
|
display: none; /* flex / controlled by JS logic */
|
|
width: 100%;
|
|
padding: 0.2em;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 0.6em;
|
|
background-color: rgba(0, 0, 0, 0.5);
|
|
margin-bottom: 0.2em;
|
|
}
|
|
|
|
.utilityOverlay {
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
z-index: 50;
|
|
display: flex;
|
|
position: absolute;
|
|
align-items: center;
|
|
justify-content: flex-start;
|
|
backdrop-filter: blur(4px);
|
|
color: rgba(225, 225, 225, 0.752);
|
|
text-shadow: 1px 1px 1px rgb(0, 0, 0);
|
|
{{!-- background-color: rgba(52, 60, 68, 0.841); --}}
|
|
background-color: inherit;
|
|
}
|
|
|
|
.utilityOverlay:hover {
|
|
cursor: pointer;
|
|
background-color: rgba(0,0,0,0.5);
|
|
}
|
|
|
|
.utilitySection {
|
|
display: flex;
|
|
flex-direction: column;
|
|
padding: 0.5em 0.8em;
|
|
border-radius: 0.5em;
|
|
}
|
|
.utilitySection:nth-child(2) {
|
|
min-width: 12em;
|
|
}
|
|
|
|
.hoverable:hover {
|
|
transition: all 0.2s ease-in-out;
|
|
color: white;
|
|
background-color: rgba(255, 255, 255, 0.15);
|
|
}
|
|
|
|
.utilityTitle {
|
|
font-size: 0.7em;
|
|
}
|
|
|
|
.utiliteValue {
|
|
font-size: 0.9em;
|
|
font-family: 'UI-Regular';
|
|
}
|
|
|
|
.utiliteValueBold {
|
|
font-size: 0.9em;
|
|
font-family: 'UI-Bold';
|
|
}
|
|
|
|
.utiliteValueLarge {
|
|
font-size: 1.5em;
|
|
font-family: 'UI-Light';
|
|
padding-right: 0.8em;
|
|
border-right: rgb(207, 207, 207) 1px solid;
|
|
}
|
|
|
|
.deleteItem {
|
|
top: 0.4em;
|
|
right: 0.4em;
|
|
opacity: 0.5;
|
|
z-index: 200;
|
|
{{!-- font-size: 0.5rem; --}}
|
|
position: absolute;
|
|
padding: 0.1rem;
|
|
border-radius: 0.2em;
|
|
width: 0.9rem !important;
|
|
height: 0.9rem !important;
|
|
border: 1px solid transparent;
|
|
transition: background-color opacity 0.2s ease-in-out;
|
|
}
|
|
|
|
.deleteItem:hover {
|
|
opacity: 1;
|
|
cursor: pointer;
|
|
background-color: black;
|
|
border: 1px solid transparent;
|
|
transition: background-color opacity 0.2s ease-in-out;
|
|
}
|
|
|
|
#loaderHolder {
|
|
width: 100%;
|
|
height: 100%;
|
|
display: flex;
|
|
z-index: 1000;
|
|
position: absolute;
|
|
align-items: flex-end;
|
|
justify-content: flex-start;
|
|
background-color: transparent;
|
|
border: 0px dotted white;
|
|
}
|
|
|
|
#loader {
|
|
width: 50%;
|
|
height: 1.0%;
|
|
left: -100%;
|
|
position: absolute;
|
|
background-color: rgba(40, 146, 19, 0.8);
|
|
animation: moveAcross 1s infinite linear;
|
|
}
|
|
@keyframes moveAcross {
|
|
0% {
|
|
transform: translateX(0vw);
|
|
}
|
|
|
|
100% {
|
|
transform: translateX(100vw);
|
|
}
|
|
}
|
|
|
|
.optionsButton {
|
|
color: rgba(255, 255, 255, 0.2);
|
|
}
|
|
|
|
.optionsButton:active,
|
|
.optionsButton:hover {
|
|
color: white;
|
|
}
|
|
|
|
|
|
/* notification styles */
|
|
/* see colors in :root */
|
|
|
|
:root {
|
|
--info: rgb(0, 100, 0);
|
|
--warn: rgb(160, 0, 0);
|
|
}
|
|
|
|
#rundownNotification {
|
|
display: flex;
|
|
padding: 0.6em;
|
|
font-size: 0.7rem;
|
|
flex-direction: row;
|
|
border-radius: 0.3em;
|
|
margin-bottom: 0.5em;
|
|
pointer-events: no-none;
|
|
color: rgba(0, 0, 0, 0.8);
|
|
background-color: rgba(255, 255, 255, 0.527);
|
|
border-left: 10px solid rgba(128, 128, 128, 0.8);
|
|
}
|
|
|
|
.notifFGinfo { color: var(--info); }
|
|
.notifFGwarn { color: var(--warn); }
|
|
.notifBGinfo { background-color: var(--info); }
|
|
.notifBGwarn { background-color: var(--warn); }
|
|
|
|
|
|
#rundownNotification #notifLeft {
|
|
gap: 0.4em;
|
|
flex-grow: 1;
|
|
display: flex;
|
|
padding: 0.4em;
|
|
flex-direction: column;
|
|
}
|
|
|
|
#rundownNotification #notifLeft .notifHead {
|
|
font-size: 1.0em;
|
|
font-family: 'UI-Bold';
|
|
}
|
|
|
|
#rundownNotification #notifRight {
|
|
display: flex;
|
|
flex-shrink: 0;
|
|
flex-basis: 25%;
|
|
overflow: hidden;
|
|
border-radius: 0.5em;
|
|
background-size: contain;
|
|
background-position: center;
|
|
background-repeat: no-repeat;
|
|
/* img set in hbs template */
|
|
}
|
|
|
|
.rundownNotificationinfo {
|
|
border-left-color: var(--info) !important;
|
|
}
|
|
|
|
.rundownNotificationwarn {
|
|
border-left-color: var(--warn) !important;
|
|
}
|
|
|
|
.notifLink a,
|
|
.notifLink a:visited,
|
|
.notifLink {
|
|
margin-top: 0.1em;
|
|
font-size: 1em;
|
|
color: rgb(0, 0, 0);
|
|
text-decoration: none;
|
|
padding-left: 0px;
|
|
transition: padding-left 0.2s ease-in-out,
|
|
color 0.2s ease-in-out;
|
|
}
|
|
|
|
.notifLink a:hover {
|
|
color: var(--info);
|
|
padding-left: 4px;
|
|
}
|
|
|
|
.notifLink::before {
|
|
content: "►";
|
|
padding-right: 0.2em;
|
|
}
|
|
|
|
.notifArrinfo {
|
|
color: var(--info);
|
|
}
|
|
|
|
.notifArrwarn {
|
|
color: var(--warn);
|
|
}
|
|
|
|
#dialogHeaderBar {
|
|
cursor: move;
|
|
}
|
|
|
|
#easter {
|
|
right: 0;
|
|
bottom: 9px;
|
|
z-index: 100;
|
|
width: 250px;
|
|
aspect-ratio: 2/1;
|
|
position: absolute;
|
|
pointer-events: none;
|
|
border: 0px dotted yellow;
|
|
background-size: 100% auto;
|
|
background-position: center;
|
|
background-repeat: no-repeat;
|
|
background-image: url('/img/easter/{{easteregg}}');
|
|
}
|
|
|
|
</style>
|
|
|
|
{{{ hookLoadControllerPlugins }}}
|
|
|
|
<script>
|
|
// See: js/spx_gc.js
|
|
</script>
|
|
</head>
|
|
|
|
<body onresize="resizePreview();" class="bg_body">
|
|
|
|
<input type="hidden" id="foldername" value="{{folder}}"> <!-- just the foldername "showname" -->
|
|
<input type="hidden" id="filebasename" value="{{filebasename}}"> <!-- just the filename "listname" -->
|
|
<input type="hidden" id="datafile" value="{{datafile}}"> <!-- full file path "C:/dataroot/showname/listname.json" -->
|
|
<input type="hidden" id="profiledata" value="{{profiledata}}"> <!-- full contents of the "gc_list.json" profilefile as stringified json -->
|
|
<input type="hidden" id="background" value="{{background}}"> <!-- background.png -->
|
|
<input type="hidden" id="csvlist" value="{{csvFileList}}"> <!-- tree data from ASSETS/csv -->
|
|
<input type="hidden" id="previewMode" value="{{previewMode}}"> <!-- previewMode (next/selected) -->
|
|
<input type="hidden" id="assetsroot" value="{{assetsFolder}}"> <!-- used by file browser -->
|
|
<input type="hidden" id="templaterootmassage" value="{{lang 'error.preventBrowseUp'}}">
|
|
<input type="hidden" id="identifier" value="controller"> <!-- used by JS logic to identify view -->
|
|
|
|
<div class="overlay" id="overlayTemplatePicker">
|
|
<!-- This is the file browser modal overlay -->
|
|
<div class="modal wrapper" id="dialog">
|
|
<div class="modal_top height2" id="dialogHeaderBar">
|
|
<table class="wide" style="height:50%; border: 0px solid white; border-spacing: 0px;">
|
|
<tr style="background-color: rgba(255,255,255,0.2);">
|
|
<td valign="middle" style="font-size: 0.8em; border: 0px solid white">
|
|
{{lang 'pagetitle.picktemplate'}} <a href="/show/{{folder}}/config"><i class="fas fa-cog"></i></a></small>
|
|
</td>
|
|
<td valign="middle" class="aright">
|
|
<i style="font-size: 1.5em; cursor: pointer;" class="fas fa-window-close" onClick="ModalOff('overlayTemplatePicker');"></i>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="content scroller">
|
|
<div id="treeview" class="filebrowser" style="padding: 2em;">
|
|
|
|
|
|
{{{ generateTemplateList folder }}}
|
|
|
|
<br>
|
|
|
|
<div class="addTemplateItem row_accent0">
|
|
<button type="button" class="addbtn bg_blue ripple" onClick="addAllTemplatesToRundown();" style="float:right;">{{lang 'general.all'}}</button>
|
|
<span class="templateName">{{lang 'pagetitle.pickAllTemplates'}}</span><BR>
|
|
<span class="templateDesc">Add all project templates to rundown with a single click</span>
|
|
</div>
|
|
|
|
<div onClick="openImportDialog();" class="addTemplateItem row_accent0">
|
|
<button type="button" class="addbtn bg_blue ripple" onClick="openImportDialog();" style="float:right; padding:0.2em 0.4em;"><i class="fas fa-file-import"></i></button>
|
|
<span class="templateName">CSV-file import</span><BR>
|
|
<span class="templateDesc">Generate multiple rundown items from a CSV file <span class="tableheaderHelp2" title="{{lang 'general.help'}}" onClick="help('csv');"><i class="far fa-question-circle"></i> </span></span>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div><!-- overlay ended-->
|
|
|
|
{{>partial-genericfilebrowsermodal}}
|
|
|
|
<div class="overlay" id="overlayHelp">
|
|
<!-- This is the keyboard shortcuts modal overlay -->
|
|
<div class="modal wrapper">
|
|
<div class="modal_top height2">
|
|
<table class="wide" style="height:50%; border: 0px solid white; border-spacing: 0px;">
|
|
<tr style="background-color: rgba(255,255,255,0.2);">
|
|
<td valign="middle" style="font-size: 0.8em;">
|
|
{{lang 'pagetitle.shortcuts'}}</small>
|
|
</td>
|
|
<td valign="middle" class="aright">
|
|
<i style="font-size: 1.5em; cursor: pointer;" class="fas fa-window-close" onClick="ModalOff('overlayHelp');"></i>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="modal_content content scroller" style="padding:2em;">
|
|
<h3>{{lang 'pagetitle.shortcuts'}}</h3><BR>
|
|
<p>
|
|
SPX controller has some basic keyboard shortcuts for fast operation. For more information about the software, visit
|
|
<A href="#" onClick="help('controller')" style="text-decoration: underline;">SPX Knowledge Base</A>.
|
|
</p>
|
|
<BR>
|
|
<table class="wide KBHelptable">
|
|
<TR>
|
|
<th width="30%"><B>Key</B></th><th><B>Function</B></th>
|
|
</TR>
|
|
<TR><td>F1</td> <td>{{lang 'pagetitle.f1ShortcutTip'}}</td></TR>
|
|
<TR><td>Up / Down</td> <td>{{lang 'pagetitle.upDownShortcutTip'}}</td></TR>
|
|
<TR><td>Enter</td> <td>{{lang 'pagetitle.enterShortcutTip'}}</td></TR>
|
|
<TR><td>Space</td> <td>{{lang 'pagetitle.spaceShortcutTip'}}<BR><small>{{lang 'pagetitle.tipContinue'}}</small></td></TR>
|
|
<TR><td>Ctrl + D</td> <td>{{lang 'pagetitle.ctrlDShortcutTip'}}</td></TR>
|
|
<TR><td>Shift + Space</td><td>{{lang 'pagetitle.shiftSpaceShortcutTip'}}</td></TR>
|
|
<TR><td>F5</td> <td>{{lang 'pagetitle.f5ShortcutTip'}}<BR><small>{{lang 'pagetitle.supportUpdateCommandTip'}}</small></td></TR>
|
|
<TR><td>Esc</td> <td>{{lang 'pagetitle.escShortcutTip'}}</td></TR>
|
|
<TR><td>CapsLock</td> <td>{{lang 'pagetitle.capsShortcutTip'}}</td></TR>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div><!-- help overlay ended-->
|
|
|
|
|
|
|
|
<div class="wrapper" onmouseover="tip('');">
|
|
|
|
<div id="severalDetected" class="stripedMessage">
|
|
{{lang 'warning.severalControllers'}}
|
|
<a title="{{lang 'general.help'}}"
|
|
onClick="help('several');"
|
|
class="hoverWhite"
|
|
onmouseover="tip('{{lang 'hover.help'}}');">
|
|
<i class="far fa-question-circle"></i>
|
|
</a>
|
|
</div>
|
|
|
|
<div class="header">
|
|
{{>header page="controller" }}
|
|
</div><!-- header end -->
|
|
|
|
|
|
<div class="content">
|
|
|
|
<div class="left pM wrapper">
|
|
|
|
<div id="rdOptions">
|
|
{{>rundownOptions comment=filedata.comment }}
|
|
</div>
|
|
|
|
|
|
<div id="itemList" class="content pM itemlist scroller" style="user-select: none; opacity:0.2; border-radius: 0.4em;">
|
|
|
|
{{#if filedata.notification}}
|
|
<div id="rundownNotification" class="rundownNotification{{filedata.notification.type}}">
|
|
<div id="notifLeft">
|
|
{{#if filedata.notification.head}}
|
|
<div class="notifHead notifFG{{filedata.notification.type}}">{{filedata.notification.head}}</div>
|
|
{{/if}}
|
|
<div class="notifBody">{{filedata.notification.body}}</div>
|
|
{{#if filedata.notification.link}}
|
|
<div class="notifLink notifArr{{filedata.notification.type}}">
|
|
<a target="_blank"
|
|
href={{filedata.notification.link}}
|
|
title="{{filedata.notification.link}}"
|
|
>{{filedata.notification.text}}</a>
|
|
</div>
|
|
{{/if}}
|
|
</div>
|
|
{{#if filedata.notification.pict}}
|
|
<div id="notifRight" style="background-image: url({{filedata.notification.pict}});"></div>
|
|
{{/if}}
|
|
</div>
|
|
{{/if}}
|
|
|
|
{{#if filedata.templates}}
|
|
<!-- // -->
|
|
{{else}}
|
|
<div style="margin: 3%; padding: 2%; font-size: 0.7em; background-color: rgba(0,0,0,0.2); border-radius: 1em; text-align: center; opacity: 0.5;" >
|
|
<h2>Empty rundown</h2><BR>
|
|
<P>
|
|
Add templates to this rundown from + button below.<br>
|
|
<small style="opacity: 0.3;">Press 'F1' to open a list of useful keyboard shortcuts.</small>
|
|
</P>
|
|
</div>
|
|
{{/if}}
|
|
|
|
<!-- <div id="rundownInfoMessage" style="display:none;">CapsLock is on - showing item overlays.</div> -->
|
|
|
|
<!-- RUNDOWN ITEMS aka TEMPLATES -->
|
|
{{#each filedata.templates}}
|
|
|
|
{{#if DataFields}}
|
|
|
|
<div id="playlistitem{{@index}}"
|
|
class = "itemrow row_accent{{uicolor}}"
|
|
data-spx-epoch = {{itemID}}
|
|
data-spx-index = {{@index}}
|
|
data-spx-changed = "false"
|
|
data-spx-onair = "{{onair}}"
|
|
data-spx-timerid = ""
|
|
data-spx-stepsleft = "{{steps}}"
|
|
onClick = "focusRow(this);"
|
|
ondblclick = "ToggleExpand(this);"
|
|
old-ondblclick = "ToggleExpand({{@index}});"
|
|
onmouseover = "tip('{{lang 'hover.item'}}');">
|
|
|
|
<form name="templates[{{@index}}]" id="form{{@index}}" method="post" action="/gc/saveItemChanges">
|
|
<input type="hidden" name="foldername" value="{{../folder}}">
|
|
<input type="hidden" name="listname" value="{{../filebasename}}">
|
|
<input type="hidden" name="rundownfile" value="{{../datafile}}">
|
|
<input type="hidden" name="TemplIndex" value="{{@index}}">
|
|
|
|
<div class="handle wide" id="item{{@index}}" style="padding: 0px; margin-bottom:0px; padding-left:0px; padding-bottom:0px;">
|
|
<!-- COLLAPSED to small line-->
|
|
<div id="Collapsed" style="position:relative; padding: 10px;">
|
|
|
|
<i id="deleteSmall{{@index}}" data-spx-name="deletesmall" class="deleteItem fas fa-times" onClick="removeItemFromRundown(this.closest('.itemrow'));" onmouseover="tip('{{lang 'hover.delete'}}');"></i>
|
|
|
|
<!-- UTILITY OVERLAY -->
|
|
<div class="utilityOverlay hidden">
|
|
|
|
<div class="utilitySection "
|
|
onClick="copyItemID('{{itemID}}');"
|
|
onmouseover="tip('Copy play API command for ItemID: {{itemID}}');">
|
|
<span class="utiliteValueLarge">{{{max5 webplayout}}}</span>
|
|
</div>
|
|
|
|
<div class="utilitySection hoverable"
|
|
onClick="copyItemID('{{itemID}}', '');"
|
|
onmouseover="tip('Copy ItemID [{{itemID}}]');">
|
|
<span class="utilityTitle">ItemID</span>
|
|
<span class="utiliteValueBold">{{itemID}}</span>
|
|
</div>
|
|
|
|
<div class="utilitySection hoverable"
|
|
onClick="copyItemID('{{itemID}}', 'play');"
|
|
onmouseover="tip('Copy API command [item/play/{{itemID}}]');">
|
|
<span class="utilityTitle"> </span>
|
|
<span class="utiliteValue">PLAY</span>
|
|
</div>
|
|
|
|
<div class="utilitySection hoverable"
|
|
onClick="copyItemID('{{itemID}}', 'stop');"
|
|
onmouseover="tip('Copy API command [item/stop/{{itemID}}]');">
|
|
<span class="utilityTitle"> </span>
|
|
<span class="utiliteValue">STOP</span>
|
|
</div>
|
|
|
|
{{#ifGreater steps 1}}
|
|
<div class="utilitySection hoverable"
|
|
onClick="copyItemID('{{itemID}}', 'continue');"
|
|
onmouseover="tip('Copy API command [item/continue/{{itemID}}]');">
|
|
<span class="utilityTitle"> </span>
|
|
<span class="utiliteValue">CONTINUE</span>
|
|
</div>
|
|
{{/ifGreater}}
|
|
|
|
</div>
|
|
|
|
<div style="position:absolute;right:10px; z-index:50; font-size:1.5em; top:0.6em;">
|
|
|
|
<i id="playIcon{{@index}}" data-spx-name="icon" class="fas fa-play {{{playIconClass onair}}}"></i>
|
|
<!-- Normal play="fas fa-play", Auto play="far fa-play-circle" -->
|
|
</div>
|
|
<table class="wide" style="border-spacing: 2px; margin-top: 2px;">
|
|
<TR>
|
|
<TD colspan="2" class="vmid spxTableHeadsmall" style="height: 1.6em; text-transform:uppercase;">
|
|
<span><!--item {{@index}} · -->{{{ nameFromTemplatePath relpath }}}
|
|
{{#if description}}
|
|
<span class="delim"></span> <span style="opacity:0.5;">{{description}}</span>
|
|
{{/if}}
|
|
</span>
|
|
</TD>
|
|
<!--
|
|
<TD class="vtop aright spxTableHeadsmall">
|
|
<i id="deleteSmall{{@index}}" data-spx-name="deletesmall" class="fas fa-times" onClick="removeItemFromRundown(this.closest('.itemrow'));" onmouseover="tip('{{lang 'hover.delete'}}');"></i>
|
|
</TD>
|
|
-->
|
|
</TR>
|
|
</table>
|
|
<div style="width:100%; " class="truncate">
|
|
|
|
{{{ generateCollapsedHeadline DataFields }}}
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<!-- EXPANDED to an editor -->
|
|
<div id="Expanded" style="display: none; padding: 0px 8px 2px 8px;">
|
|
<table class="wide" style="border-spacing: 2px; margin-top:2px;">
|
|
<TR>
|
|
<TD colspan="3" class="vmid spxTableHeadsmall" style="height: 1.6em; text-transform:uppercase;">
|
|
<span>{{{nameFromTemplatePath relpath}}}</span>
|
|
|
|
<!-- disabled by default, enable with config -->
|
|
<i class="l-icon fas fa-edit {{{allowOpeningFolder}}}" onClick="openRelpathFolder(this.closest('.itemrow'));" onmouseover="tip('{{lang 'button.edit'}}');"></i>
|
|
</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD width="65%" class="vtop">
|
|
|
|
{{#each DataFields}}
|
|
|
|
<!-- COMMON FIELD DATA -->
|
|
<div class="wide HIDE">
|
|
<table class="wide spxTableHeadsmall">
|
|
<tr><td class="aright">field</td> <td><input type="text" class="wide" name="RundownItem[DataFields][{{@index}}][field]" value="{{field}}" ></td></tr>
|
|
<tr><td class="aright">title</td> <td><input type="text" class="wide" name="RundownItem[DataFields][{{@index}}][title]" value="{{title}}" ></td></tr>
|
|
</table>
|
|
</div>
|
|
|
|
{{#ifValue ftype "spacer"}}
|
|
<br><br>
|
|
{{/ifValue}}
|
|
|
|
{{#ifValue ftype "number"}}
|
|
<!-- "NUMBER" TYPE OF TEMPLATE FIELD (added in 1.0.7) -->
|
|
<div class="wide HIDE">
|
|
<table class="wide spxTableHeadsmall">
|
|
<tr><td class="aright">ftype</td> <td><input type="text" class="wide" name="RundownItem[DataFields][{{@index}}][ftype]" value="number"></td></tr>
|
|
</table>
|
|
</div>
|
|
<input type="number" data-tooltip="{{title}}" data-position="right center" name="RundownItem[DataFields][{{@index}}][value]" data-update="{{field}}" data-role="userEditable" value="{{value}}" placeholder="{{title}}" ondblclick="event.stopPropagation();" onkeypress="javascript:applyTextEditChanges(event,this);" class="gcinput"><BR>
|
|
{{/ifValue}}
|
|
|
|
|
|
{{#ifValue ftype "instruction"}}
|
|
<!-- "INSTRUCTION" TYPE OF TEMPLATE FIELD -->
|
|
<div class="wide HIDE">
|
|
<table class="wide spxTableHeadsmall">
|
|
<tr><td class="aright">ftype</td> <td><input type="text" class="wide" name="RundownItem[DataFields][{{@index}}][ftype]" value="instruction"></td></tr>
|
|
</table>
|
|
</div>
|
|
<div class="instruction">{{value}}</div>
|
|
<input type="hidden" name="RundownItem[DataFields][{{@index}}][value]" value="{{value}}">
|
|
{{/ifValue}}
|
|
|
|
|
|
{{#ifValue ftype "caption"}}
|
|
<!-- "CAPTION" TYPE OF TEMPLATE FIELD -->
|
|
<div class="wide HIDE">
|
|
<table class="wide spxTableHeadsmall">
|
|
<tr><td class="aright">ftype</td> <td><input type="text" class="wide" name="RundownItem[DataFields][{{@index}}][ftype]" value="caption"></td></tr>
|
|
</table>
|
|
</div>
|
|
<span class="caption">{{value}}</span><BR>
|
|
<input type="hidden" name="RundownItem[DataFields][{{@index}}][value]" value="{{value}}">
|
|
{{/ifValue}}
|
|
|
|
|
|
{{#ifValue ftype "hidden"}}
|
|
<!-- "HIDDEN" TYPE OF TEMPLATE FIELD -->
|
|
<div class="wide HIDE">
|
|
<table class="wide spxTableHeadsmall">
|
|
<tr><td class="aright">ftype</td> <td><input type="text" class="wide" name="RundownItem[DataFields][{{@index}}][ftype]" value="hidden"></td></tr>
|
|
</table>
|
|
</div>
|
|
<span class="caption">{{title}}<BR><BR>{{field}} value:<BR>{{value}}</span><BR>
|
|
<input type="hidden" name="RundownItem[DataFields][{{@index}}][value]" value="{{value}}">
|
|
{{/ifValue}}
|
|
|
|
|
|
{{#ifValue ftype "textfield"}}
|
|
<!-- "TEXTFIELD" TYPE OF TEMPLATE FIELD -->
|
|
<div class="wide HIDE">
|
|
<table class="wide spxTableHeadsmall">
|
|
<tr><td class="aright">ftype</td> <td><input type="text" class="wide" name="RundownItem[DataFields][{{@index}}][ftype]" value="textfield"></td></tr>
|
|
</table>
|
|
</div>
|
|
<input type="text" data-tooltip="{{title}}" data-position="right center" name="RundownItem[DataFields][{{@index}}][value]" data-update="{{field}}" data-role="userEditable" value="{{value}}" placeholder="{{title}}" ondblclick="event.stopPropagation();" onkeypress="javascript:applyTextEditChanges(event,this);" class="gcinput"><BR>
|
|
{{/ifValue}}
|
|
|
|
|
|
{{#ifValue ftype "checkbox"}}
|
|
<!-- "CHECKBOX" TYPE OF TEMPLATE FIELD (added in 1.0.10) -->
|
|
<div class="wide HIDE">
|
|
<table class="wide spxTableHeadsmall">
|
|
<tr><td class="aright">ftype</td> <td><input type="text" class="wide" name="RundownItem[DataFields][{{@index}}][ftype]" value="checkbox"></td></tr>
|
|
</table>
|
|
</div>
|
|
<div class="gccheckboxdiv" style="white-space: nowrap;">
|
|
|
|
|
|
|
|
<label class="gccheckcontainer">{{title}}
|
|
<BR>
|
|
{{#ifValue value "1"}}
|
|
<input type="checkbox" name="RundownItem[DataFields][{{@index}}][value]" data-update="{{field}}" data-role="userEditable" class="gccheckbox" checked>
|
|
{{else}}
|
|
<input type="checkbox" name="RundownItem[DataFields][{{@index}}][value]" data-update="{{field}}" data-role="userEditable" class="gccheckbox">
|
|
{{/ifValue}}
|
|
<span class="gccheckmark"></span>
|
|
</label>
|
|
</div>
|
|
<!--<div style="white-space: nowrap;">
|
|
<label for="checkbox{{@index}}">{{title}}</label><br>
|
|
</div> -->
|
|
|
|
{{/ifValue}}
|
|
|
|
|
|
{{#ifValue ftype "button"}}
|
|
<!-- "BUTTON" TYPE OF TEMPLATE FIELD (added in 1.0.11) -->
|
|
<div class="wide HIDE">
|
|
<table class="wide spxTableHeadsmall">
|
|
<tr><td class="aright">ftype</td> <td><input type="text" class="wide" name="RundownItem[DataFields][{{@index}}][ftype]" value="button"></td></tr>
|
|
<tr><td class="aright">fcall</td> <td><input type="text" class="wide" name="RundownItem[DataFields][{{@index}}][fcall]" value="{{fcall}}"></td></tr>
|
|
<tr><td class="aright">title</td> <td><input type="text" class="wide" name="RundownItem[DataFields][{{@index}}][title]" value="{{title}}"></td></tr>
|
|
<tr><td class="aright">descr</td> <td><input type="text" class="wide" name="RundownItem[DataFields][{{@index}}][descr]" value="{{descr}}"></td></tr>
|
|
</table>
|
|
</div>
|
|
<div class="gcpluginbuttondiv" style="white-space: nowrap;">
|
|
<button type="button"
|
|
onClick="{{fcall}}"
|
|
class="btnsmall ripple bg_grey15"
|
|
>{{title}}</button> <span class="gcplugindescription">{{descr}}</span>
|
|
</div>
|
|
{{/ifValue}}
|
|
|
|
{{#ifValue ftype "filebrowser"}}
|
|
<!-- "FILEBROWSER" TYPE OF TEMPLATE FIELD (added in 1.1.1) -->
|
|
<div class="wide HIDE" >
|
|
<table class="wide spxTableHeadsmall">
|
|
<tr><td class="aright">ftype</td> <td><input type="text" class="wide" name="RundownItem[DataFields][{{@index}}][ftype]" value="filebrowser"></td></tr>
|
|
<tr><td class="aright">title</td> <td><input type="text" class="wide" name="RundownItem[DataFields][{{@index}}][title]" value="{{title}}"></td></tr>
|
|
<tr><td class="aright">assetfolder</td> <td><input type="text" class="wide" name="RundownItem[DataFields][{{@index}}][assetfolder]" value="{{assetfolder}}"></td></tr>
|
|
<tr><td class="aright">extension</td> <td><input type="text" class="wide" name="RundownItem[DataFields][{{@index}}][extension]" value="{{extension}}"></td></tr>
|
|
</table>
|
|
</div>
|
|
<div class="gcpluginbuttondiv" style="white-space: nowrap;">
|
|
{{title}}
|
|
<input type="text" data-position="right center" name="RundownItem[DataFields][{{@index}}][value]" data-update="{{field}}" data-role="userEditable" value="{{value}}" placeholder="{{title}}" ondblclick="event.stopPropagation();" onkeypress="javascript:applyTextEditChanges(event,this);" class="gcinput"><BR>
|
|
<button type="button"
|
|
onClick="alert('{{assetfolder}} {{extension}} {{value}}')";
|
|
class="btnsmall ripple bg_grey15"
|
|
>Browse</button>
|
|
</div>
|
|
{{/ifValue}}
|
|
|
|
|
|
{{#ifValue ftype "textarea"}}
|
|
<!-- "TEXTAREA" TYPE OF TEMPLATE FIELD -->
|
|
<div class="wide HIDE">
|
|
<table class="wide spxTableHeadsmall">
|
|
<tr><td class="aright">ftype</td> <td><input type="text" class="wide" name="RundownItem[DataFields][{{@index}}][ftype]" value="textarea"></td></tr>
|
|
</table>
|
|
</div>
|
|
<textarea rows="8" data-tooltip="{{title}}" data-position="right center" name="RundownItem[DataFields][{{@index}}][value]" data-update="{{field}}" data-role="userEditable" ondblclick="event.stopPropagation();" class="gcinput">{{injectNewlines value}}</textarea><BR>
|
|
{{/ifValue}}
|
|
|
|
|
|
{{#ifValue ftype "dropdown"}}
|
|
<!-- "DROPDOWN" TYPE OF TEMPLATE FIELD -->
|
|
<!-- first, hidden fields -->
|
|
<table class="HIDE wide brd spxTableHeadsmall">
|
|
<tr><td class="aright">fType</td> <td><input type="text" class="wide" name="RundownItem[DataFields][{{@index}}][ftype]" value="dropdown"><BR><BR></td></tr>
|
|
</table>
|
|
<!-- then visible DOM elements -->
|
|
<select data-update="{{field}}" data-role="userEditable" class="gcinput select" name="DropdownValues[{{field}}]" data-tooltip="{{title}}" data-position="right center">
|
|
<option disabled>{{title}}:</option>
|
|
{{#each items}}
|
|
{{#ifValue value ../value}}
|
|
<option selected value="{{value}}">{{text}}</option>
|
|
{{else}}
|
|
<option value="{{value}}">{{text}}</option>
|
|
{{/ifValue}}
|
|
{{/each}}
|
|
</select>
|
|
{{/ifValue}}
|
|
|
|
|
|
{{#ifValue ftype "filelist"}}
|
|
<!-- "FILELIST" TYPE OF TEMPLATE FIELD -->
|
|
<div class="wide HIDE">
|
|
<table class="wide spxTableHeadsmall">
|
|
<tr><td class="aright">ftype</td> <td><input type="text" class="wide" name="RundownItem[DataFields][{{@index}}][ftype]" value="textfield"></td></tr>
|
|
<tr><td class="aright">assetfolder</td> <td><input type="text" class="wide" name="RundownItem[DataFields][{{@index}}][assetfolder]" value="{{assetfolder}}"></td></tr>
|
|
<tr><td class="aright">extension</td> <td><input type="text" class="wide" name="RundownItem[DataFields][{{@index}}][extension]" value="{{extension}}"></td></tr>
|
|
</table>
|
|
</div>
|
|
<!-- then render visible DOM elements with a helper-->
|
|
<!-- value set as fField value {{value}} -->
|
|
<select data-update="{{field}}" data-role="userEditable" class="gcinput select" name="FilelistValues[{{field}}]" data-tooltip="{{title}} {{lang 'general.fromFolder'}}: {{assetfolder}}" data-position="right center">
|
|
<option disabled>{{title}} {{lang 'general.fromFolder'}}:</option>
|
|
<option disabled>{{assetfolder}}</option>
|
|
<option disabled></option>
|
|
<option value="none">-</option>
|
|
{{{ PopulateFilelistOptions assetfolder extension value ../relpath }}}
|
|
</select>
|
|
{{/ifValue}}
|
|
|
|
|
|
{{#ifValue ftype "divider"}}
|
|
<!-- "DIVIDER" TYPE OF TEMPLATE FIELD -->
|
|
<div class="wide HIDE">
|
|
<table class="wide spxTableHeadsmall">
|
|
<tr><td class="aright">ftype</td> <td><input type="text" class="wide" name="RundownItem[DataFields][{{@index}}][ftype]" value="divider"></td></tr>
|
|
</table>
|
|
</div>
|
|
<div class="divider">{{title}}</div>
|
|
{{/ifValue}}
|
|
|
|
|
|
{{#ifValue ftype "color"}}
|
|
<!-- "COLOR PICKER" TYPE OF TEMPLATE FIELD -->
|
|
<div class="colorRoot">
|
|
<div class="wide HIDE">
|
|
<table class="wide spxTableHeadsmall">
|
|
<tr><td class="aright">ftype</td> <td><input type="text" class="wide" name="RundownItem[DataFields][{{@index}}][ftype]" value="color"></td></tr>
|
|
<tr><td class="aright">value</td> <td><input type="text" class="wide" name="RundownItem[DataFields][{{@index}}][value]" id="colorvalue" value="{{value}}" data-role="userEditable" data-update="{{field}}"></td></tr>
|
|
</table>
|
|
</div>
|
|
<div class="gcpluginbuttondiv wide" style="white-space: nowrap; position:relative;">
|
|
<span class="gcplugindescription">{{title}}</span>
|
|
<!--see handler at the bottom of file -->
|
|
<button type="button"
|
|
onClick="colorPicker(this,'{{value}}')";
|
|
class="colorbtnsmall ripple"
|
|
style="background-color: {{value}}; right:0;">{{value}}</button>
|
|
</div>
|
|
</div>
|
|
{{/ifValue}}
|
|
|
|
|
|
{{#> PRO--types ftype=ftype}}
|
|
{{!-- Extended, proprietary ftypes --}}
|
|
{{/PRO--types}}
|
|
|
|
{{/each}} <!-- ftype check ended -->
|
|
</TD>
|
|
|
|
|
|
|
|
<TD class="vtop">
|
|
<table class="wide" style="border-spacing: 5px; margin-top:0px;">
|
|
<tr>
|
|
<td colspan="2" class="vtop">
|
|
<!-- SAVE CHANGES BUTTON -->
|
|
<!-- onClick="saveTemplateItemChanges({{@index}});" -->
|
|
|
|
<button type="button"
|
|
onClick="saveTemplateItemChangesByElement(this.closest('.itemrow'));"
|
|
class="wide spxFlexItem btnsmall bg_grey15 ripple"
|
|
onmouseover="tip('{{lang 'hover.submitthis'}}');"
|
|
>{{lang 'button.save'}} </button><!-- FORM SUBMIT MODEL -->
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<!-- PLAY BUTTON -->
|
|
<button type="button"
|
|
style="display: none;"
|
|
onClick="playItem(this.closest('.itemrow'));"
|
|
id="tplay{{@index}}"
|
|
class="wide spxFlexItem btnsmall ripple {{{playButtonClass onair}}}"
|
|
data-spx-stoptext="{{lang 'button.stop'}}"
|
|
data-spx-playtext="{{lang 'button.play'}}"
|
|
data-spx-name="playbutton"
|
|
onmouseover="tip('{{lang 'hover.playthis'}}');"
|
|
>{{{playButtonText onair}}}</button>
|
|
</td>
|
|
<td>
|
|
<!-- UPDATE BUTTON -->
|
|
<button type="button"
|
|
onClick="updateItem(this.closest('.itemrow'));"
|
|
class="wide spxFlexItem btnsmall bg_blue ripple disabled"
|
|
data-spx-name="updatebutton"
|
|
onmouseover="tip('{{lang 'hover.updatethis'}}');"
|
|
>{{lang 'button.update'}}</button>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</TD>
|
|
<TD class="vtop center">
|
|
<i id="deleteLarge{{@index}}" class="l-icon far fa-trash-alt" data-spx-name="deletelarge" onClick="removeItemFromRundown(this.closest('.itemrow'));" onmouseover="tip('{{lang 'hover.deletethis'}}');"></i><BR>
|
|
<i id="duplicLarge{{@index}}" class="l-icon far fa-clone" onClick="duplicateRundownItem(this.closest('.itemrow'));" onmouseover="tip('{{lang 'hover.duplicateitem'}}');"></i><BR>
|
|
|
|
<!-- export CSV button -->
|
|
<i id="exportCSV{{@index}}" class="l-icon fas fa-file-export" onClick="exportItemAsCSV(this.closest('.itemrow'));" onmouseover="tip('{{lang 'hover.exportitem'}}');"></i><BR>
|
|
|
|
<!-- import CSV button (moved to add template view) -->
|
|
<!--
|
|
<i id="importCSV{{@index}}" class="l-icon fas fa-file-import" onClick="appendItemsFromCSV();" onmouseover="tip('{{lang 'hover.importitems'}}');"></i>
|
|
-->
|
|
</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD colspan="2" class="aright spxTableHeadsmall">
|
|
{{{GeneratePlayoutInfo playserver playchannel playlayer webplayout out itemID}}}
|
|
</TD>
|
|
<TD>
|
|
|
|
</TD>
|
|
</TR>
|
|
</table>
|
|
<div class="wide HIDE">
|
|
<table class="wide spxTableHeadsmall">
|
|
<tr><td class="aright">relpath</td> <td><input style="width: 100%;" type="text" id="relpath{{@index}}" name="RundownItem[relpath]" value="{{relpath}}"></td></tr>
|
|
<tr><td class="aright">description</td> <td><input style="width: 100%;" type="text" id="description{{@index}}" name="RundownItem[description]" value="{{description}}"></td></tr>
|
|
<tr><td class="aright">playserver</td> <td><input style="width: 100%;" type="text" id="playserver{{@index}}" name="RundownItem[playserver]" value="{{playserver}}"></td></tr>
|
|
<tr><td class="aright">playchannel</td> <td><input style="width: 100%;" type="text" id="playchannel{{@index}}" name="RundownItem[playchannel]" value="{{playchannel}}"></td></tr>
|
|
<tr><td class="aright">playlayer</td> <td><input style="width: 100%;" type="text" id="playlayer{{@index}}" name="RundownItem[playlayer]" value="{{playlayer}}"></td></tr>
|
|
<tr><td class="aright">dataformat</td> <td><input style="width: 100%;" type="text" id="dataformat{{@index}}" name="RundownItem[dataformat]" value="{{dataformat}}"></td></tr>
|
|
<tr><td class="aright">webplayout</td> <td><input style="width: 100%;" type="text" id="webplayout{{@index}}" name="RundownItem[webplayout]" value="{{{max5 webplayout}}}"></td></tr>
|
|
<tr><td class="aright">onair</td> <td><input style="width: 100%;" type="text" id="onair{{@index}}" name="RundownItem[onair]" value="{{onair}}"></td></tr>
|
|
<tr><td class="aright">out</td> <td><input style="width: 100%;" type="text" id="out{{@index}}" name="RundownItem[out]" value="{{out}}"></td></tr>
|
|
<tr><td class="aright">uicolor</td> <td><input style="width: 100%;" type="text" id="uicolor{{@index}}" name="RundownItem[uicolor]" value="{{uicolor}}"></td></tr>
|
|
<tr><td class="aright">steps</td> <td><input style="width: 100%;" type="text" id="steps{{@index}}" name="RundownItem[steps]" value="{{steps}}"></td></tr>
|
|
<tr><td class="aright">imported</td> <td><input style="width: 100%;" type="text" id="imported{{@index}}" name="RundownItem[imported]" value="{{imported}}"></td></tr>
|
|
|
|
<!-- special event triggers -->
|
|
<tr><td class="aright">onPlay</td> <td><input style="width: 100%;" type="text" id="onPlay{{@index}}" name="RundownItem[function_onPlay]" value="{{function_onPlay}}"></td></tr>
|
|
<tr><td class="aright">onNext</td> <td><input style="width: 100%;" type="text" id="onNext{{@index}}" name="RundownItem[function_onNext]" value="{{function_onNext}}"></td></tr>
|
|
<tr><td class="aright">onStop</td> <td><input style="width: 100%;" type="text" id="onStop{{@index}}" name="RundownItem[function_onStop]" value="{{function_onStop}}"></td></tr>
|
|
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</form>
|
|
</div>
|
|
{{else}}
|
|
<!-- object had no DataFields, so it as skipped. NULL item? -->
|
|
{{/if}}
|
|
{{/each}}
|
|
<!-- GC ITEMS ENDED -->
|
|
|
|
|
|
<div class="wide" style="text-align: center; padding: 0.5em 1.0em;">
|
|
<button type="button"
|
|
data-tooltip="{{lang 'hover.addrundownitem'}}"
|
|
data-position="right center"
|
|
class="addbtn bg_blue ripple"
|
|
onClick="ModalOn('overlayTemplatePicker');"
|
|
style="padding: 0.05em 0.75em; border-radius: 0.2em;"
|
|
onmouseover="tip('{{lang 'hover.addrundownitem'}}');">+</button> <!-- + Add Template To Rundown -->
|
|
</div>
|
|
</div>
|
|
|
|
<div style="padding-top: 10px;">
|
|
|
|
|
|
{{!-- MASTER STOP / PLAY / UPDATE --}}
|
|
<div class="wide center" style="margin: 0; padding: 0;">
|
|
<button
|
|
id="MasterTOGGLE"
|
|
class="btn bg_green ripple disabled"
|
|
style="width:45%;"
|
|
data-spx-graphic="name_left"
|
|
data-spx-playtext="{{lang 'button.playmaster'}}"
|
|
data-spx-stoptext="{{lang 'button.stopmaster'}}"
|
|
onClick="playItem();"
|
|
onmouseover="tip('{{lang 'hover.masterplay'}}');"
|
|
>{{lang 'button.playmaster'}}</button>
|
|
|
|
<button
|
|
id="MasterCONTINUE"
|
|
class="btn bg_green ripple disabled"
|
|
style="width:45%;"
|
|
onClick="nextItem();"
|
|
onmouseover="tip('{{lang 'hover.mastercontinue'}}');"
|
|
>{{lang 'button.continue'}}</button>
|
|
|
|
<!-- *** hidden **** it was confusing there -->
|
|
<button
|
|
id="MasterUPDATE"
|
|
class="btn bg_blue ripple disabled"
|
|
style="width:33%; display:none;"
|
|
onClick="updateItem();"
|
|
onmouseover="tip('{{lang 'hover.masterupdate'}}');"
|
|
>{{lang 'button.update'}}</button> </div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
<div class="right pM scroller">
|
|
|
|
<!-- background: {{background}} -->
|
|
|
|
<div id="previewBG"
|
|
style="background-color: rgb(0, 0, 0);
|
|
width:100%;
|
|
height:27%;
|
|
overflow: hidden;
|
|
position: relative;
|
|
{{#ifValue renderer "popup"}}
|
|
display: none;
|
|
{{else}}
|
|
display: block;
|
|
{{/ifValue}}
|
|
opacity:0.1;">
|
|
<div id="LocalRendererDisabledNotification"
|
|
style="width: 100%;
|
|
{{#ifValue disableLRender "true"}}
|
|
opacity: 1;
|
|
{{else}}
|
|
opacity: 0;
|
|
{{/ifValue}}
|
|
position: absolute;
|
|
top: 0; left: 0;
|
|
height: 100%;
|
|
z-index:10;
|
|
text-align: center;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items:center;
|
|
background: transparent;
|
|
color: rgb(54, 54, 54);">Local SPX Renderer<br>DISABLED</div>
|
|
|
|
<div id="loaderHolder">
|
|
<div id="loader"></div>
|
|
</div>
|
|
|
|
<iframe
|
|
width="{{{localPreviewSize width}}}"
|
|
height="{{{localPreviewSize height}}}"
|
|
id="previewIF"
|
|
name="LOCAL"
|
|
data-comment: "Here we had width: {{width}} and height {{height}}"
|
|
|
|
{{#ifValue disableLRender "true"}}
|
|
src="/templates/empty.html"
|
|
{{else}}
|
|
src="/renderer"
|
|
{{/ifValue}}
|
|
class="renderer"
|
|
{{#if background}}
|
|
style="background-image: url('/{{background}}'); background-size: 100% 100%; position: absolute; top: 0; left: 0;"
|
|
{{/if}}
|
|
onLoad="localRendererLoaded();"
|
|
></iframe>
|
|
|
|
</div>
|
|
|
|
<div id="controllerFunctionsZone" style="opacity:0;">
|
|
<div id="renderOptionsFoldable" style="position: relative;">
|
|
|
|
<button id="localRendererCollapsiple"
|
|
class="collapsibleZone optionsButton {{{ GenerateLocalRendererOptions 'class' }}}"
|
|
type="button"
|
|
>OPTIONS</button>
|
|
|
|
<div class="collapsiblecontent spxConfigHead" style="box-shadow: inset 0 8px 12px rgba(0, 0, 0, 0.2); padding:0;">
|
|
|
|
<div style="padding:10px;">
|
|
<table style="width:100%;">
|
|
<tr>
|
|
<td width="60%" style="font-size: 0.7em;">{{lang 'config.autoplay'}}</td>
|
|
<td width="20%" ALIGN="center">
|
|
<div class="toggle-container">
|
|
<label class="vc-switch">
|
|
<input id="toggleRendererAutoplay"
|
|
{{#ifValue autoplayLocalRenderer "true"}}
|
|
checked
|
|
{{/ifValue}}
|
|
type="checkbox"
|
|
class="vc-switch-input"
|
|
onClick="toggleAutoplay(this, 'toggleAutoplaySwitch');"/>
|
|
<span id="recSlider" class="vc-switch-label"></span>
|
|
<span class="vc-handle" id="toggleAutoplaySwitch">
|
|
{{#ifValue autoplayLocalRenderer true}}
|
|
YES
|
|
{{else}}
|
|
NO
|
|
{{/ifValue}}
|
|
</span>
|
|
</label>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td width="60%" style="font-size: 0.7em;">Disable local renderer</td>
|
|
<td width="20%" ALIGN="center">
|
|
<div class="toggle-container">
|
|
<label class="vc-switch">
|
|
<input id="toggleRendererWindowProgramMain"
|
|
{{#ifValue disableLRender "true"}}
|
|
checked
|
|
{{/ifValue}}
|
|
type="checkbox"
|
|
class="vc-switch-input"
|
|
onClick="toggleLRendererHandler(this, 'toggleLRender');"/>
|
|
<span id="recSlider" class="vc-switch-label"></span>
|
|
<span class="vc-handle" id="toggleLRender">
|
|
{{#ifValue disableLRender "true"}}
|
|
YES
|
|
{{else}}
|
|
NO
|
|
{{/ifValue}}
|
|
</span>
|
|
</label>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td width="60%" id="toggleInfo1" style="font-size: 0.7em;">
|
|
Popup program renderer
|
|
</td>
|
|
<td width="20%" ALIGN="center">
|
|
<div class="toggle-container">
|
|
<label class="vc-switch">
|
|
<input id="toggleRendererWindowProgram"
|
|
{{#ifValue renderer "popup"}}
|
|
checked
|
|
{{/ifValue}}
|
|
type="checkbox"
|
|
class="vc-switch-input"
|
|
onClick="toggleSwitchHandler(this, 'toggle1', 'program');"/>
|
|
<span id="recSlider" class="vc-switch-label"></span>
|
|
<span class="vc-handle" id="toggle1">
|
|
{{#ifValue renderer "popup"}}
|
|
ON
|
|
{{else}}
|
|
OFF
|
|
{{/ifValue}}
|
|
</span>
|
|
</label>
|
|
</div>
|
|
</td>
|
|
<td width="20%" ALIGN="center" style="padding:0;">
|
|
<button style="font-size: 0.7em; width:90%; font-family:UI-Regular; padding: 0.15em 0; height: 1.7em;"
|
|
class="btn bg_grey ripple"
|
|
data-defaultTip = 'Program in a viewer'
|
|
data-toggleText = 'Copy program output url'
|
|
onmouseover="toggleTip('toggleInfo1', this, 'data-toggleText')"
|
|
onmouseout ="toggleTip('toggleInfo1', this, 'data-defaultTip')"
|
|
onclick = "copyRendererUrl()"
|
|
><i class="fas fa-clipboard"></i> URL</button>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<table style="width:100%;">
|
|
<tr>
|
|
<td width="60%" id="toggleInfo2" style="font-size: 0.7em;">
|
|
Popup preview viewer
|
|
</td>
|
|
<td width="20%" ALIGN="center">
|
|
<div class="toggle-container">
|
|
<label class="vc-switch">
|
|
<input id="toggleRendererWindowPreview" type="checkbox" data-on="LOOP" data-off="OFF" class="vc-switch-input" onClick="toggleSwitchHandler(this, 'toggle2', 'preview');"/>
|
|
<span id="recSlider" class="vc-switch-label"></span>
|
|
<span class="vc-handle" id="toggle2">OFF</span>
|
|
</label>
|
|
</div>
|
|
</td>
|
|
<td width="20%" ALIGN="center" style="padding:0;">
|
|
<button style="font-size: 0.7em; width:90%; font-family:UI-Regular; padding: 0.15em 0; height: 1.7em;"
|
|
class="btn bg_grey ripple"
|
|
data-defaultTip = 'Show preview viewer'
|
|
data-toggleText = 'Copy preview output url'
|
|
onmouseover="toggleTip('toggleInfo2', this, 'data-toggleText')"
|
|
onmouseout ="toggleTip('toggleInfo2', this, 'data-defaultTip')"
|
|
onclick = "copyRendererUrl(true)"
|
|
><i class="fas fa-clipboard"></i> URL</button>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
</div>
|
|
</div>
|
|
</div> <!-- foldable end -->
|
|
</div><!-- zone ended -->
|
|
|
|
<HR id="previewWidthRuler"> <!-- =========================================================== -->
|
|
|
|
<div id="controllerPluginButtons" style="border:0px dashed yellow">
|
|
<!-- plugins zone, see hookLoadControllerPlugins -->
|
|
</div>
|
|
|
|
<!-- showExtras generated here. In future releases this may move to plugins -->
|
|
<script src="{{profiledataObj.showExtras.customscript}}"></script>
|
|
{{{ GenerateCustomControls profiledataObj.showExtras.CustomControls }}}
|
|
<script defer src="{{globalExtras.customscript}}"></script>
|
|
{{{ GenerateCustomControls globalExtras.CustomControls }}}
|
|
|
|
</div>
|
|
</div><!-- content end -->
|
|
|
|
{{#if easteregg}}
|
|
<div id="easter"></div>
|
|
{{/if}}
|
|
|
|
{{>footer}}
|
|
</div><!-- wrapper end -->
|
|
|
|
|
|
<script>
|
|
// See spx_gc.js
|
|
|
|
// console.log('Init tooltip');
|
|
var tooltip = new Tooltip();
|
|
|
|
function localRendererLoaded() {
|
|
// console.log('Local renderer loaded!');
|
|
document.getElementById('loaderHolder').style.display='none';
|
|
let AutoPlayEnabled = {{{autoplayLocalRenderer}}} || false;
|
|
if (AutoPlayEnabled) {
|
|
var items = document.querySelectorAll('[data-spx-onair]');
|
|
items.forEach((item, index) => {
|
|
if (item.getAttribute('data-spx-onair') == 'true') {
|
|
let itemID = item.getAttribute('data-spx-epoch');
|
|
playItemLocal(itemID);
|
|
}
|
|
});
|
|
} else {
|
|
// console.log('Autoplay disabled');
|
|
}
|
|
}
|
|
|
|
function colorPicker(sourceButton, initialColor) {
|
|
// Color picker
|
|
// alert('Picker to ' + initialColor)
|
|
sourceButton.textContent = '...';
|
|
var picker = new Picker({
|
|
color: initialColor,
|
|
parent: sourceButton,
|
|
popup: 'bottom',
|
|
editorFormat: 'rgb'
|
|
});
|
|
picker.onChange = function(color) {
|
|
sourceButton.style.backgroundColor = color.rgbaString;
|
|
sourceButton.closest('.colorRoot').querySelector('#colorvalue').value=String(color.rgbaString);
|
|
}
|
|
|
|
picker.onDone = function(color) {
|
|
sourceButton.textContent = color.rgbaString;
|
|
sourceButton.style.backgroundColor = color.rgbaString;
|
|
sourceButton.closest('.colorRoot').querySelector('#colorvalue').value=String(color.rgbaString);
|
|
};
|
|
}
|
|
|
|
function pageInit() {
|
|
|
|
// COLLAPSIPLE HANDLERS
|
|
var coll = document.getElementsByClassName("collapsibleZone");
|
|
var i;
|
|
for (i = 0; i < coll.length; i++) {
|
|
coll[i].addEventListener("click", function() {
|
|
this.classList.toggle("activeZone");
|
|
var content = this.nextElementSibling;
|
|
if (content.style.maxHeight){
|
|
content.style.maxHeight = null;
|
|
} else {
|
|
content.style.maxHeight = content.scrollHeight + "px";
|
|
}
|
|
});
|
|
}
|
|
|
|
// Check msg from URL
|
|
var url = new URL(window.location.href);
|
|
var msg = url.searchParams.get("msg");
|
|
if (msg) {
|
|
showMessageSlider(msg) // msg, info|warn|error
|
|
}
|
|
|
|
RenderFolder(JSON.parse(document.getElementById('csvlist').value));
|
|
resizePreview();
|
|
heartbeat(210); // page identifier
|
|
spxInit('');
|
|
|
|
} // pageInit
|
|
|
|
function forceWM() {
|
|
// Force watermark when version is double clicked
|
|
var data = {};
|
|
data.spxcmd = 'forceWM';
|
|
socket.emit('SPXWebRendererMessage', data);
|
|
}
|
|
|
|
function resizePreview() {
|
|
// Controller preview resize
|
|
|
|
let DefaultX = '{{width}}'; // 1920 by default;
|
|
let DefaultY = '{{height}}'; // 1080 by default;
|
|
|
|
if (DefaultX.includes('vw')) {
|
|
// Responsive settings, use window size! Added in v1.3.0
|
|
// console.log('Responsive settings, but forcing 16:9 in Controller');
|
|
DefaultX = '1920px';
|
|
DefaultY = '1080px';
|
|
}
|
|
|
|
let Wpx = document.getElementById('previewWidthRuler').offsetWidth;
|
|
let Sca = Wpx/parseInt(DefaultX);
|
|
let Hpx = parseInt(parseInt(DefaultY) * Sca);
|
|
document.getElementById('previewBG').style.width=Wpx+'px';
|
|
document.getElementById('previewBG').style.height=Hpx+'px';
|
|
document.getElementById('previewIF').style.transform="scale("+Sca+")";
|
|
document.getElementById('previewBG').style.opacity=1;
|
|
document.getElementById('controllerFunctionsZone').style.opacity=1;
|
|
// console.log('Resized to ' + Wpx + ' x ' + Hpx + ' px, scale multiplier: ' + Sca);
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
// added in 1.1.1 - UX is greatly improve with this change
|
|
// compared to previously used onload event
|
|
pageInit();
|
|
})
|
|
|
|
socket.on('connect', function () {
|
|
data={};
|
|
data.spxcmd = 'identifyClient';
|
|
data.name = 'SPX_CONTROLLER'; // <---- Name of this socket connection
|
|
socket.emit('SPXMessage2Server', data);
|
|
});
|
|
|
|
</script>
|
|
</body>
|
|
|
|
</html> |