cinera: Improve keyboard controls and scrolling
This commit adds keyboard navigation of the indices, documented in the "Help" text box. It also improves scrolling of menus to follow progress through the video, with the ability to centre the scrolling around a range of references. Finally in this UI work, it enables the keyboard and mouse to work more cooperatively. Other changes: • Added a "Clear" so the player's initial sizing happens invisibly. • Fixed getBackgroundColourRGB() to handle both rgb() and rgba(). • Deduplicated code, including spurious querySelectorAll() calls. • Moved global variables into the Player object.
This commit is contained in:
parent
c9bf96c7aa
commit
a7694d4c3b
|
@ -23,7 +23,7 @@ typedef struct
|
|||
version CINERA_APP_VERSION = {
|
||||
.Major = 0,
|
||||
.Minor = 10,
|
||||
.Patch = 24
|
||||
.Patch = 25
|
||||
};
|
||||
|
||||
#define __USE_XOPEN2K8 // NOTE(matt): O_NOFOLLOW
|
||||
|
@ -11098,14 +11098,14 @@ ProcessTimestamp(buffers *CollationBuffers, neighbourhood *N, string Filepath, m
|
|||
if(Result == RC_SUCCESS)
|
||||
{
|
||||
CopyStringToBuffer(&MenuBuffers->Quote,
|
||||
" <a target=\"_blank\" class=\"ref\" href=\"https://dev.abaines.me.uk/quotes/%.*s/%d\">\n"
|
||||
" <span data-id=\"&#%d;\">\n"
|
||||
" <a target=\"_blank\" data-id=\"&#%d;\" class=\"ref\" href=\"https://dev.abaines.me.uk/quotes/%.*s/%d\">\n"
|
||||
" <span>\n"
|
||||
" <span class=\"ref_content\">\n"
|
||||
" <div class=\"source\">Quote %d</div>\n"
|
||||
" <div class=\"ref_title\">",
|
||||
*QuoteIdentifier,
|
||||
(int)QuoteUsername.Length, QuoteUsername.Base,
|
||||
Timestamp->quote.id,
|
||||
*QuoteIdentifier,
|
||||
Timestamp->quote.id);
|
||||
|
||||
CopyStringToBufferHTMLSafe(&MenuBuffers->Quote, QuoteInfo.Text);
|
||||
|
@ -11952,14 +11952,30 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF
|
|||
CopyStringToBuffer(&MenuBuffers.Filter,
|
||||
"\"></span>\n"
|
||||
" <div class=\"filter_container\">\n"
|
||||
" <div class=\"filter_mode exclusive\">Filter mode: </div>\n"
|
||||
" <div class=\"filters\">\n");
|
||||
" <div class=\"filter_header\">\n"
|
||||
" <div class=\"filter_mode exclusive\">Filter mode: </div>\n"
|
||||
" <div class=\"filter_titles\">\n");
|
||||
|
||||
if(Topics.ItemCount > 0)
|
||||
{
|
||||
CopyStringToBuffer(&MenuBuffers.Filter,
|
||||
" <div class=\"filter_topics\">\n"
|
||||
" <div class=\"filter_title\">Topics</div>\n");
|
||||
" <div class=\"filter_title\">Topics</div>\n");
|
||||
}
|
||||
if(Media.ItemCount > 0)
|
||||
{
|
||||
CopyStringToBuffer(&MenuBuffers.Filter,
|
||||
" <div class=\"filter_title\">Media</div>\n");
|
||||
}
|
||||
|
||||
CopyStringToBuffer(&MenuBuffers.Filter,
|
||||
" </div>\n"
|
||||
" </div>\n"
|
||||
" <div class=\"filters\">\n");
|
||||
|
||||
if(Topics.ItemCount > 0)
|
||||
{
|
||||
CopyStringToBuffer(&MenuBuffers.Filter,
|
||||
" <div class=\"filter_topics\">\n");
|
||||
for(int i = 0; i < Topics.ItemCount; ++i)
|
||||
{
|
||||
category_info *This = GetPlaceInBook(&Topics, i);
|
||||
|
@ -11988,8 +12004,7 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF
|
|||
if(Media.ItemCount > 0)
|
||||
{
|
||||
CopyStringToBuffer(&MenuBuffers.FilterMedia,
|
||||
" <div class=\"filter_media\">\n"
|
||||
" <div class=\"filter_title\">Media</div>\n");
|
||||
" <div class=\"filter_media\">\n");
|
||||
for(int i = 0; i < Media.ItemCount; ++i)
|
||||
{
|
||||
category_info *This = GetPlaceInBook(&Media, i);
|
||||
|
@ -12056,7 +12071,7 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF
|
|||
"\n"
|
||||
" <h2>Global Keys</h2>\n"
|
||||
" <span class=\"help_key\">[</span>, <span class=\"help_key\"><</span> / <span class=\"help_key\">]</span>, <span class=\"help_key\">></span> <span class=\"help_text\">Jump to previous / next episode</span><br>\n"
|
||||
" <span class=\"help_key\">W</span>, <span class=\"help_key\">K</span>, <span class=\"help_key\">P</span> / <span class=\"help_key\">S</span>, <span class=\"help_key\">J</span>, <span class=\"help_key\">N</span> <span class=\"help_text\">Jump to previous / next marker</span><br>\n"
|
||||
" <span class=\"help_key\">W</span>, <span class=\"help_key\">K</span>, <span class=\"help_key\">P</span> / <span class=\"help_key\">S</span>, <span class=\"help_key\">J</span>, <span class=\"help_key\">N</span> <span class=\"help_text\">Jump to previous / next timestamp</span><br>\n"
|
||||
" <span class=\"help_key\">t</span> / <span class=\"help_key\">T</span> <span class=\"help_text\">Toggle theatre / SUPERtheatre mode</span><br>\n"
|
||||
" <span class=\"help_key%s\">V</span> <span class=\"help_text%s\">Revert filter to original state</span> <span class=\"help_key\">Y</span> <span class=\"help_text\">Select link (requires manual Ctrl-c)</span>\n",
|
||||
|
||||
|
@ -12078,15 +12093,15 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF
|
|||
|
||||
CopyStringToBuffer(&PlayerBuffers.Menus,
|
||||
"\n"
|
||||
" <h2>In-Menu Movement</h2>\n"
|
||||
" <h2>In-Menu and <span class=\"help_title_key help_custom_index\">Index</span> Controls</h2>\n"
|
||||
" <div class=\"help_paragraph\">\n"
|
||||
" <div class=\"key_block\">\n"
|
||||
" <div>\n"
|
||||
" <span class=\"help_key\">a</span>\n"
|
||||
" </div>\n"
|
||||
" <div>\n"
|
||||
" <span class=\"help_key\">w</span><br>\n"
|
||||
" <span class=\"help_key\">s</span>\n"
|
||||
" <span class=\"help_key help_custom_index\">w</span><br>\n"
|
||||
" <span class=\"help_key help_custom_index\">s</span>\n"
|
||||
" </div>\n"
|
||||
" <div>\n"
|
||||
" <span class=\"help_key\">d</span>\n"
|
||||
|
@ -12094,8 +12109,8 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF
|
|||
" </div>\n"
|
||||
" <div class=\"key_block\">\n"
|
||||
" <span class=\"help_key\">h</span>\n"
|
||||
" <span class=\"help_key\">j</span>\n"
|
||||
" <span class=\"help_key\">k</span>\n"
|
||||
" <span class=\"help_key help_custom_index\">j</span>\n"
|
||||
" <span class=\"help_key help_custom_index\">k</span>\n"
|
||||
" <span class=\"help_key\">l</span>\n"
|
||||
" </div>\n"
|
||||
" <div class=\"key_block\">\n"
|
||||
|
@ -12110,25 +12125,29 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF
|
|||
" <span class=\"help_key\">→</span>\n"
|
||||
" </div>\n"
|
||||
" </div>\n"
|
||||
" </div><br>\n"
|
||||
" <div class=\"help_paragraph\">\n"
|
||||
" <span class=\"help_key help_custom_index\">Esc</span> <span class=\"help_text\">Close menu / unfocus timestamp</span>\n"
|
||||
" </div>\n"
|
||||
" <br>\n");
|
||||
|
||||
CopyStringToBuffer(&PlayerBuffers.Menus,
|
||||
" <h2>%sQuotes %sand%s References%s Menus%s</h2>\n"
|
||||
" <span class=\"help_key word%s\">Enter</span> <span class=\"help_text%s\">Jump to timecode</span><br>\n",
|
||||
" <h2>%sQuotes %sand%s References%s Menus and%s Index</h2>\n"
|
||||
" <span class=\"help_key word\">Enter</span> <span class=\"help_text\">Jump to timestamp</span><br>\n",
|
||||
// Q R
|
||||
//
|
||||
// 0 0 <h2><span off>Quotes and References Menus</span></h2>
|
||||
// 0 1 <h2><span off>Quotes and</span> References Menus</h2>
|
||||
// 1 0 <h2>Quotes <span off>and References</span> Menus</h2>
|
||||
// 1 1 <h2>Quotes and References Menus</h2>
|
||||
// 0 0 <h2><span off>Quotes and References Menus and</span> Index</h2>
|
||||
// 0 1 <h2><span off>Quotes and</span> References Menus and Index</h2>
|
||||
// 1 0 <h2>Quotes <span off>and References</span> Menus and Index</h2>
|
||||
// 1 1 <h2>Quotes and References Menus and Index</h2>
|
||||
|
||||
HasQuoteMenu ? "" : "<span class=\"unavailable\">",
|
||||
HasQuoteMenu && !HasReferenceMenu ? "<span class=\"unavailable\">" : "",
|
||||
!HasQuoteMenu && HasReferenceMenu ? "</span>" : "",
|
||||
HasQuoteMenu && !HasReferenceMenu ? "</span>" : "",
|
||||
!HasQuoteMenu && !HasReferenceMenu ? "</span>" : "",
|
||||
HasQuoteMenu || HasReferenceMenu ? "" : " unavailable", HasQuoteMenu || HasReferenceMenu ? "" : " unavailable");
|
||||
!HasQuoteMenu && !HasReferenceMenu ? "</span>" : "");
|
||||
//HasQuoteMenu || HasReferenceMenu ? "" : " unavailable",
|
||||
//HasQuoteMenu || HasReferenceMenu ? "" : " unavailable");
|
||||
|
||||
CopyStringToBuffer(&PlayerBuffers.Menus,
|
||||
"\n"
|
||||
|
@ -12371,6 +12390,19 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF
|
|||
|
||||
CopyStringToBuffer(&CollationBuffers->Player, "<div class=\"cinera\">\n"
|
||||
" ");
|
||||
|
||||
asset *JSClear = GetAsset(Wrap0(BuiltinAssets[ASSET_JS_CLEAR].Filename), ASSET_JS);
|
||||
ConstructResolvedAssetURL(&URL, JSClear, PAGE_PLAYER);
|
||||
CopyStringToBuffer(&CollationBuffers->Player,
|
||||
"<script type=\"text/javascript\" src=\"%s",
|
||||
URL.Location);
|
||||
DeclaimBuffer(&URL);
|
||||
PushAssetLandmark(&CollationBuffers->Player, JSClear, PAGE_PLAYER, 0);
|
||||
CopyStringToBuffer(&CollationBuffers->Player,
|
||||
"\"></script>");
|
||||
|
||||
CopyStringToBuffer(&CollationBuffers->Player, "\n"
|
||||
" ");
|
||||
CopyLandmarkedBuffer(&CollationBuffers->Player, &PlayerBuffers.Menus, 0, PAGE_PLAYER);
|
||||
CopyStringToBuffer(&CollationBuffers->Player, "\n"
|
||||
" ");
|
||||
|
|
|
@ -540,6 +540,16 @@ ul.cineraNavPlain li.current > a {
|
|||
display: block;
|
||||
}
|
||||
|
||||
.cineraHelp .help_container .help_custom_index {
|
||||
background-color: #159 !important;
|
||||
}
|
||||
|
||||
.cineraHelp .help_container h2 .help_title_key {
|
||||
padding: .2em;
|
||||
border: 1px solid;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.cineraHelp .help_container .help_key {
|
||||
box-sizing: content-box;
|
||||
font-family: Inconsolata;
|
||||
|
@ -614,12 +624,11 @@ ul.cineraNavPlain li.current > a {
|
|||
.cineraMenus > .menu .credits_container {
|
||||
border: 1px solid;
|
||||
border-top: none;
|
||||
display: none;
|
||||
z-index: -1; /* NOTE(matt): Using "display: none" to hide them proved problematic for scrolling non-visible menus */
|
||||
overflow-y: auto;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 100%;
|
||||
z-index: 8;
|
||||
}
|
||||
|
||||
.cineraMenus > .menu .refs,
|
||||
|
@ -639,7 +648,7 @@ ul.cineraNavPlain li.current > a {
|
|||
}
|
||||
|
||||
.cineraMenus > .menu .visible {
|
||||
display: block;
|
||||
z-index: 8;
|
||||
}
|
||||
|
||||
.cineraMenus > .menu > .refs .ref {
|
||||
|
@ -737,6 +746,11 @@ ul.cineraNavPlain li.current > a {
|
|||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.cineraMenus > .menu > .filter_container .filter_header {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.cineraMenus > .menu > .filter_container .filter_mode,
|
||||
.cineraMenus > .menu > .link_container #cineraLinkMode {
|
||||
cursor: pointer;
|
||||
|
@ -756,11 +770,13 @@ ul.cineraNavPlain li.current > a {
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
.cineraMenus > .menu > .filter_container .filter_header .filter_titles,
|
||||
.cineraMenus > .menu > .filter_container .filters {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
}
|
||||
|
||||
.cineraMenus > .menu > .filter_container .filter_header .filter_titles > *,
|
||||
.cineraMenus > .menu > .filter_container .filters > * {
|
||||
width: 50%;
|
||||
flex-grow: 1;
|
||||
|
|
|
@ -1,40 +1,5 @@
|
|||
var cinera = document.querySelector(".cinera");
|
||||
var baseURL = location.hash ? (location.toString().substr(0, location.toString().length - location.hash.length)) : location;
|
||||
|
||||
var originalTextContent = {
|
||||
TitleQuotes: null,
|
||||
TitleReferences: null,
|
||||
TitleCredits: null,
|
||||
EpisodePrev: null,
|
||||
EpisodeNext: null,
|
||||
};
|
||||
|
||||
var menuState = [];
|
||||
var titleBar = cinera.querySelector(".cineraMenus");
|
||||
var quotesMenu = null;
|
||||
var referencesMenu = null;
|
||||
var filterMenu = null;
|
||||
var viewsMenu = null;
|
||||
var linkMenu = null;
|
||||
var creditsMenu = null;
|
||||
var sourceMenus = null;
|
||||
var helpButton = null;
|
||||
var helpDocumentation = null;
|
||||
|
||||
// NOTE(matt): One set of markers per page. There is code to support multiple, which we may want to extend everywhere
|
||||
var MarkersContainer = cinera.querySelector(".markers_container");
|
||||
|
||||
var views = {
|
||||
REGULAR: 0,
|
||||
THEATRE: 1,
|
||||
SUPERTHEATRE: 2,
|
||||
};
|
||||
|
||||
var devices = {
|
||||
DESKTOP: 0,
|
||||
MOBILE: 1,
|
||||
};
|
||||
|
||||
var CineraProps = {
|
||||
C: null,
|
||||
V: views.REGULAR,
|
||||
|
@ -57,275 +22,19 @@ var CineraProps = {
|
|||
};
|
||||
CineraProps.O = GetRealOrientation(orientations.LANDSCAPE_LEFT, CineraProps.IsMobile);
|
||||
|
||||
if(titleBar)
|
||||
{
|
||||
quotesMenu = titleBar.querySelector(".quotes_container");
|
||||
if(quotesMenu)
|
||||
{
|
||||
originalTextContent.TitleQuotes = quotesMenu.previousElementSibling.textContent;
|
||||
menuState.push(quotesMenu);
|
||||
var quoteItems = quotesMenu.querySelectorAll(".ref");
|
||||
if(quoteItems)
|
||||
{
|
||||
for(var i = 0; i < quoteItems.length; ++i)
|
||||
{
|
||||
quoteItems[i].addEventListener("mouseenter", function(ev) {
|
||||
mouseOverQuotes(this);
|
||||
})
|
||||
};
|
||||
}
|
||||
var quoteTimecodes = quotesMenu.querySelectorAll(".refs .ref .ref_indices .timecode");
|
||||
for (var i = 0; i < quoteTimecodes.length; ++i) {
|
||||
quoteTimecodes[i].addEventListener("click", function(ev) {
|
||||
if (player) {
|
||||
var time = ev.currentTarget.getAttribute("data-timestamp");
|
||||
mouseSkipToTimecode(player, time, ev);
|
||||
}
|
||||
});
|
||||
}
|
||||
var lastFocusedQuote = null;
|
||||
}
|
||||
|
||||
referencesMenu = titleBar.querySelector(".references_container");
|
||||
if(referencesMenu)
|
||||
{
|
||||
originalTextContent.TitleReferences = referencesMenu.previousElementSibling.textContent;
|
||||
menuState.push(referencesMenu);
|
||||
var referenceItems = referencesMenu.querySelectorAll(".ref");
|
||||
if(referenceItems)
|
||||
{
|
||||
for(var i = 0; i < referenceItems.length; ++i)
|
||||
{
|
||||
referenceItems[i].addEventListener("mouseenter", function(ev) {
|
||||
mouseOverReferences(this);
|
||||
})
|
||||
};
|
||||
var lastFocusedReference = null;
|
||||
var lastFocusedIdentifier = null;
|
||||
}
|
||||
|
||||
var refTimecodes = referencesMenu.querySelectorAll(".refs .ref .ref_indices .timecode");
|
||||
for (var i = 0; i < refTimecodes.length; ++i) {
|
||||
refTimecodes[i].addEventListener("click", function(ev) {
|
||||
if (player) {
|
||||
var time = ev.currentTarget.getAttribute("data-timestamp");
|
||||
mouseSkipToTimecode(player, time, ev);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if(referencesMenu || quotesMenu)
|
||||
{
|
||||
var refSources = titleBar.querySelectorAll(".refs .ref"); // This is for both quotes and refs
|
||||
for (var i = 0; i < refSources.length; ++i) {
|
||||
refSources[i].addEventListener("click", function(ev) {
|
||||
if (player) {
|
||||
player.pause();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
filterMenu = titleBar.querySelector(".filter_container");
|
||||
if(filterMenu)
|
||||
{
|
||||
menuState.push(filterMenu);
|
||||
var lastFocusedCategory = null;
|
||||
var lastFocusedTopic = null;
|
||||
var lastFocusedMedium = null;
|
||||
|
||||
var filter = filterMenu.parentNode;
|
||||
|
||||
var filterModeElement = filter.querySelector(".filter_mode");
|
||||
filterModeElement.addEventListener("click", function(ev) {
|
||||
ev.stopPropagation();
|
||||
toggleFilterMode();
|
||||
});
|
||||
|
||||
var filterMode = filterModeElement.classList[1];
|
||||
var filterItems = filter.querySelectorAll(".filter_content");
|
||||
|
||||
var filterInitState = new Object();
|
||||
var filterState = new Object();
|
||||
for(var i = 0; i < filterItems.length; ++i)
|
||||
{
|
||||
filterItems[i].addEventListener("mouseenter", function(ev) {
|
||||
navigateFilter(this);
|
||||
})
|
||||
|
||||
filterItems[i].addEventListener("click", function(ev) {
|
||||
ev.stopPropagation();
|
||||
filterItemToggle(this);
|
||||
});
|
||||
|
||||
var filterItemName = filterItems[i].classList.item(1);
|
||||
if(filterItems[i].parentNode.classList.contains("filter_topics"))
|
||||
{
|
||||
filterInitState[filterItemName] = { "type" : "topic", "off": (filterItems[i].classList.item(2) == "off") };
|
||||
filterState[filterItemName] = { "type" : "topic", "off": (filterItems[i].classList.item(2) == "off") };
|
||||
}
|
||||
else
|
||||
{
|
||||
filterInitState[filterItemName] = { "type" : "medium", "off": (filterItems[i].classList.item(2) == "off") };
|
||||
filterState[filterItemName] = { "type" : "medium", "off": (filterItems[i].classList.item(2) == "off") };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
viewsMenu = titleBar.querySelector(".views");
|
||||
if(viewsMenu && !CineraProps.IsMobile)
|
||||
{
|
||||
menuState.push(viewsMenu);
|
||||
var viewsContainer = viewsMenu.querySelector(".views_container");
|
||||
viewsMenu.addEventListener("mouseenter", function(ev) {
|
||||
handleMouseOverViewsMenu();
|
||||
});
|
||||
viewsMenu.addEventListener("mouseleave", function(ev) {
|
||||
viewsContainer.style.display = "none";
|
||||
});
|
||||
|
||||
var viewItems = viewsMenu.querySelectorAll(".view");
|
||||
for(var i = 0; i < viewItems.length; ++i)
|
||||
{
|
||||
viewItems[i].addEventListener("click", function(ev) {
|
||||
switch(this.getAttribute("data-id"))
|
||||
{
|
||||
case "regular":
|
||||
case "theatre":
|
||||
{
|
||||
toggleTheatreMode();
|
||||
} break;
|
||||
case "super":
|
||||
{
|
||||
toggleSuperTheatreMode();
|
||||
} break;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
linkMenu = titleBar.querySelector(".link_container");
|
||||
linkTimestamp = true;
|
||||
if(linkMenu)
|
||||
{
|
||||
menuState.push(linkMenu);
|
||||
|
||||
var linkMode = linkMenu.querySelector("#cineraLinkMode");
|
||||
var link = linkMenu.querySelector("#cineraLink");
|
||||
|
||||
linkMode.addEventListener("click", function(ev) {
|
||||
ev.stopPropagation();
|
||||
toggleLinkMode(linkMode, link);
|
||||
});
|
||||
|
||||
link.addEventListener("click", function(ev) {
|
||||
CopyToClipboard(link);
|
||||
toggleMenuVisibility(linkMenu);
|
||||
});
|
||||
}
|
||||
|
||||
creditsMenu = titleBar.querySelector(".credits_container");
|
||||
if(creditsMenu)
|
||||
{
|
||||
originalTextContent.TitleCredits = creditsMenu.previousElementSibling.textContent;
|
||||
menuState.push(creditsMenu);
|
||||
var lastFocusedCreditItem = null;
|
||||
|
||||
var creditItems = creditsMenu.querySelectorAll(".person, .support");
|
||||
for(var i = 0; i < creditItems.length; ++i)
|
||||
{
|
||||
creditItems[i].addEventListener("mouseenter", function(ev) {
|
||||
if(this != lastFocusedCreditItem)
|
||||
{
|
||||
lastFocusedCreditItem.classList.remove("focused");
|
||||
unfocusSprite(lastFocusedCreditItem);
|
||||
if(lastFocusedCreditItem.classList.contains("support"))
|
||||
{
|
||||
setSpriteLightness(lastFocusedCreditItem.firstChild);
|
||||
}
|
||||
lastFocusedCreditItem = this;
|
||||
focusedElement = lastFocusedCreditItem;
|
||||
focusedElement.classList.add("focused");
|
||||
focusSprite(focusedElement);
|
||||
if(focusedElement.classList.contains("support"))
|
||||
{
|
||||
setSpriteLightness(focusedElement.firstChild);
|
||||
}
|
||||
}
|
||||
});
|
||||
if(creditItems[i].tagName == "A")
|
||||
{
|
||||
creditItems[i].addEventListener("click", function(ev) {
|
||||
if(player)
|
||||
{
|
||||
player.pause();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sourceMenus = titleBar.querySelectorAll(".menu");
|
||||
|
||||
helpButton = titleBar.querySelector(".cineraHelp");
|
||||
helpDocumentation = helpButton.querySelector(".help_container");
|
||||
BindHelp(helpButton, helpDocumentation);
|
||||
}
|
||||
|
||||
var focusedElement = null;
|
||||
var focusedIdentifier = null;
|
||||
|
||||
var playerContainer = cinera.querySelector(".cineraPlayerContainer")
|
||||
var prevEpisode = playerContainer.querySelector(".episodeMarker.prev");
|
||||
if(prevEpisode) { originalTextContent.EpisodePrev = prevEpisode.firstChild.textContent; }
|
||||
var nextEpisode = playerContainer.querySelector(".episodeMarker.next");
|
||||
if(nextEpisode) { originalTextContent.EpisodeNext = nextEpisode.firstChild.textContent; }
|
||||
var testMarkers = playerContainer.querySelectorAll(".marker");
|
||||
|
||||
// NOTE(matt): All the originalTextContent values must be set by this point, because the player's construction may need them
|
||||
var MobileCineraContentRuleSelector = ".cinera.mobile .cineraPlayerContainer .markers_container > .markers .marker .cineraContent";
|
||||
var MobileCineraContentRule = GetOrSetRule(MobileCineraContentRuleSelector);
|
||||
|
||||
var MenuContainerRuleSelector = ".cineraMenus > .menu .quotes_container, .cineraMenus > .menu .references_container, .cineraMenus > .menu .filter_container, .cineraMenus > .menu .views_container, .cineraMenus > .menu .link_container, .cineraMenus > .menu .credits_container";
|
||||
var MenuContainerRule = GetOrSetRule(MenuContainerRuleSelector);
|
||||
|
||||
if(CineraProps.IsMobile)
|
||||
{
|
||||
InitMobileStyle();
|
||||
}
|
||||
else
|
||||
{
|
||||
var MenuMaxHeight = cinera.offsetHeight - titleBar.offsetHeight - 4;
|
||||
MenuContainerRule.style.maxHeight = MenuMaxHeight + "px";
|
||||
}
|
||||
|
||||
var player = new Player(playerContainer, onRefChanged);
|
||||
|
||||
if(CineraProps.IsMobile)
|
||||
{
|
||||
ConnectMobileControls(player);
|
||||
}
|
||||
|
||||
var cineraViewStorageItem = "cineraView";
|
||||
|
||||
if(viewsMenu && localStorage.getItem(cineraViewStorageItem))
|
||||
{
|
||||
toggleTheatreMode();
|
||||
}
|
||||
|
||||
InitScrollEventListener(cinera);
|
||||
|
||||
function
|
||||
DelayedUpdateSize()
|
||||
{
|
||||
player.updateSize();
|
||||
}
|
||||
var cinera = document.querySelector(".cinera");
|
||||
var player = new Player(cinera, onRefChanged);
|
||||
|
||||
window.addEventListener("resize", function() {
|
||||
if(CineraProps.IsMobile)
|
||||
{
|
||||
setTimeout(DelayedUpdateSize, 512);
|
||||
setTimeout(DelayedUpdateSize, 512, player);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -336,7 +45,7 @@ window.addEventListener("resize", function() {
|
|||
window.onorientationchange = function() {
|
||||
if(CineraProps.IsMobile)
|
||||
{
|
||||
setTimeout(DelayedUpdateSize, 512);
|
||||
setTimeout(DelayedUpdateSize, 512, player);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -351,43 +60,8 @@ document.addEventListener("keydown", function(ev) {
|
|||
key = "capitalSpace";
|
||||
}
|
||||
|
||||
if(!ev.getModifierState("Control") && handleKey(key) == true && focusedElement)
|
||||
if(!ev.getModifierState("Control") && player.handleKey(key) == true && player.MenusFocused.Item)
|
||||
{
|
||||
ev.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
for(var i = 0; i < sourceMenus.length; ++i)
|
||||
{
|
||||
sourceMenus[i].addEventListener("mouseenter", function(ev) {
|
||||
handleMenuTogglerInteraction(this, ev.type);
|
||||
})
|
||||
sourceMenus[i].addEventListener("mouseleave", function(ev) {
|
||||
handleMenuTogglerInteraction(this, ev.type);
|
||||
})
|
||||
sourceMenus[i].addEventListener("click", function(ev) {
|
||||
handleMenuTogglerInteraction(this, ev.type);
|
||||
})
|
||||
};
|
||||
|
||||
var colouredItems = playerContainer.querySelectorAll(".author, .member, .project");
|
||||
for(i = 0; i < colouredItems.length; ++i)
|
||||
{
|
||||
setTextLightness(colouredItems[i]);
|
||||
}
|
||||
|
||||
var topicDots = cinera.querySelectorAll(".category");
|
||||
for(var i = 0; i < topicDots.length; ++i)
|
||||
{
|
||||
setDotLightness(topicDots[i]);
|
||||
}
|
||||
|
||||
var lastTimestampStorageItem = "cineraTimecode_" + window.location.pathname;
|
||||
var lastTimestamp;
|
||||
if(location.hash) {
|
||||
player.setTimeThenPlay(location.hash.startsWith('#') ? location.hash.substr(1) : location.hash);
|
||||
}
|
||||
else if(lastTimestamp = localStorage.getItem(lastTimestampStorageItem))
|
||||
{
|
||||
player.setTimeThenPlay(lastTimestamp);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -186,14 +186,21 @@ function enableSprite(Element)
|
|||
|
||||
function disableSprite(Element)
|
||||
{
|
||||
if(Element.classList.contains("cineraSprite"))
|
||||
if(Element.classList.contains("focused"))
|
||||
{
|
||||
setSpriteLightness(Element);
|
||||
Element.style.backgroundPositionY = Element.getAttribute("data-y-disabled") + "px";
|
||||
focusSprite(Element);
|
||||
}
|
||||
for(var i = 0; i < Element.childElementCount; ++i)
|
||||
else
|
||||
{
|
||||
disableSprite(Element.children[i]);
|
||||
if(Element.classList.contains("cineraSprite"))
|
||||
{
|
||||
setSpriteLightness(Element);
|
||||
Element.style.backgroundPositionY = Element.getAttribute("data-y-disabled") + "px";
|
||||
}
|
||||
for(var i = 0; i < Element.childElementCount; ++i)
|
||||
{
|
||||
disableSprite(Element.children[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -503,17 +510,29 @@ IsOverflowed(Element)
|
|||
return Element.scrollHeight > Element.clientHeight || Element.scrollWidth > Element.clientWidth;
|
||||
}
|
||||
|
||||
function
|
||||
SetHelpUnfocused(Button)
|
||||
{
|
||||
Button.firstElementChild.innerText = "¿";
|
||||
Button.firstElementChild.title = "Keypresses will not pass through to Cinera because focus is currently elsewhere.\n\nTo regain focus, please press Tab / Shift-Tab (multiple times) or click somewhere related to Cinera other than the video, e.g. this button";
|
||||
}
|
||||
|
||||
function
|
||||
SetHelpFocused(Button)
|
||||
{
|
||||
Button.firstElementChild.innerText = "?";
|
||||
Button.firstElementChild.title = ""
|
||||
}
|
||||
|
||||
function
|
||||
BindHelp(Button, DocumentationContainer)
|
||||
{
|
||||
window.addEventListener("blur", function(){
|
||||
Button.firstElementChild.innerText = "¿";
|
||||
Button.firstElementChild.title = "Keypresses will not pass through to Cinera because focus is currently elsewhere.\n\nTo regain focus, please press Tab / Shift-Tab (multiple times) or click somewhere related to Cinera other than the video, e.g. this button";
|
||||
SetHelpUnfocused(Button);
|
||||
});
|
||||
|
||||
window.addEventListener("focus", function(){
|
||||
Button.firstElementChild.innerText = "?";
|
||||
Button.firstElementChild.title = ""
|
||||
SetHelpFocused(Button);
|
||||
});
|
||||
|
||||
Button.addEventListener("click", function() {
|
||||
|
@ -553,13 +572,13 @@ function RGBtoHSL(colour)
|
|||
function getBackgroundColourRGB(element) {
|
||||
var Colour = getComputedStyle(element).getPropertyValue("background-color");
|
||||
var depth = 0;
|
||||
while((Colour == "transparent" || Colour == "rgba(0, 0, 0, 0)") && depth <= 4)
|
||||
while((Colour == "transparent" || Colour == "rgba(0, 0, 0, 0)") && element.parentElement && depth <= 4)
|
||||
{
|
||||
element = element.parentNode;
|
||||
element = element.parentElement;
|
||||
Colour = getComputedStyle(element).getPropertyValue("background-color");
|
||||
++depth;
|
||||
}
|
||||
var Staging = Colour.slice(4, -1).split(", ");
|
||||
var Staging = Colour.slice(Colour.indexOf("(") + 1, -1).split(", ");
|
||||
var Result = {
|
||||
R: parseInt(Staging[0]),
|
||||
G: parseInt(Staging[1]),
|
||||
|
|
Loading…
Reference in New Issue