cinera.web: Fix issues (on mobile) with new layout

Both pages:
    Derive reliable window dimensions ourselves
    Set the orientation from the window dimensions
    Use "box-sizing: content-box" on the help keys, to fix sizing

Search page:
    Support irregular (i.e. non-square) grids
    General sizing fixes
    Fix text fitting when toggling back from List to Grid view
    Fix text fitting when textNode would overflow container
    Correctly compute optimal grid size after orientation change
    Rename .text to .cineraText to avoid CSS selector clash
    Only add click events for the main set of buttons (not its clone)

Player page:
    Size the video and timestamps bar more sensibly
This commit is contained in:
Matt Mascarenhas 2021-02-04 00:13:55 +00:00
parent 2cf8739a60
commit 545938d766
7 changed files with 1161 additions and 828 deletions

View File

@ -23,7 +23,7 @@ typedef struct
version CINERA_APP_VERSION = { version CINERA_APP_VERSION = {
.Major = 0, .Major = 0,
.Minor = 8, .Minor = 8,
.Patch = 1 .Patch = 2
}; };
#include <stdarg.h> // NOTE(matt): varargs #include <stdarg.h> // NOTE(matt): varargs
@ -13507,6 +13507,7 @@ SearchToBuffer(buffers *CollationBuffers, db_header_project *StoredP, project *P
OpenNodeNewLine(B, &IndentationLevel, NODE_DIV, 0); OpenNodeNewLine(B, &IndentationLevel, NODE_DIV, 0);
AppendStringToBuffer(B, Wrap0(" class=\"key_block\">")); AppendStringToBuffer(B, Wrap0(" class=\"key_block\">"));
OpenNodeCNewLine(B, &IndentationLevel, NODE_DIV, 0); OpenNodeCNewLine(B, &IndentationLevel, NODE_DIV, 0);
AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("1"), TRUE); AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("1"), TRUE);
AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("q"), TRUE); AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("q"), TRUE);
@ -13535,6 +13536,7 @@ SearchToBuffer(buffers *CollationBuffers, db_header_project *StoredP, project *P
AppendHelpKeyToBuffer(B, &IndentationLevel, Wrap0("v"), TRUE); AppendHelpKeyToBuffer(B, &IndentationLevel, Wrap0("v"), TRUE);
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); CloseNodeNewLine(B, &IndentationLevel, NODE_DIV);
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); // key_block CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); // key_block
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); // help_paragraph CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); // help_paragraph

View File

@ -142,20 +142,6 @@ ul.cineraNavPlain li.current > a {
order: 2; order: 2;
} }
#cineraIndex .cineraTraversal .cineraButton
{
/* TODO(matt): Do the cineraTraversal as a flex box, to auto-size these buttons? */
height: 42px;
width: 42px;
padding: 2px;
margin: 2px;
display: inline-flex;
align-items: center;
justify-content: center;
}
#cineraIndex.anim .cineraTraversal, #cineraIndex.anim .cineraTraversal,
#cineraIndex.anim .cineraTraversal * p #cineraIndex.anim .cineraTraversal * p
{ {
@ -179,6 +165,20 @@ ul.cineraNavPlain li.current > a {
transform: rotate(180deg); transform: rotate(180deg);
} }
#cineraIndex .cineraTraversal .cineraButton
{
box-sizing: border-box;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 2px;
margin: 2px;
height: 42px;
width: 42px;
}
#cineraIndex .cineraTraversal * p #cineraIndex .cineraTraversal * p
{ {
transform: rotate(0deg); transform: rotate(0deg);
@ -274,6 +274,7 @@ ul.cineraNavPlain li.current > a {
} }
.cineraQueryContainer #query { .cineraQueryContainer #query {
width: 0px;
flex-grow: 1; flex-grow: 1;
} }
@ -281,6 +282,7 @@ ul.cineraNavPlain li.current > a {
position: absolute; position: absolute;
top: 2px; top: 2px;
right: 5px; right: 5px;
font-size: small;
color: #000000; color: #000000;
height: 100%; height: 100%;
display: none; display: none;
@ -345,14 +347,23 @@ ul.cineraNavPlain li.current > a {
display: flex; display: flex;
backface-visibility: hidden; backface-visibility: hidden;
-webkit-backface-visibility: hidden; -webkit-backface-visibility: hidden;
overflow: hidden;
} }
#cineraIndex #cineraIndexGrid .cineraButton.subdivision .head-item, #cineraIndex #cineraIndexGrid .cineraButton.subdivision .head-item,
#cineraIndex #cineraIndexGrid .cineraButton.subdivision .tail-item #cineraIndex #cineraIndexGrid .cineraButton.subdivision .tail-item
{ {
display: flex;
width: 100%; width: 100%;
height: 50%; height: 50%;
display: flex; }
#cineraIndex #cineraIndexGrid .cineraButton.subdivision .head-item p,
#cineraIndex #cineraIndexGrid .cineraButton.subdivision .tail-item p
{
border: 0;
margin: 0;
padding: 0;
} }
#cineraIndex #cineraIndexGrid .cineraButton.subdivision.leaf #cineraIndex #cineraIndexGrid .cineraButton.subdivision.leaf
@ -518,7 +529,7 @@ ul.cineraNavPlain li.current > a {
left: 50%; left: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
max-height: 97%; max-height: 97%;
overflow-y: scroll; overflow-y: auto;
} }
.cineraHelp .help_container.visible { .cineraHelp .help_container.visible {
@ -526,14 +537,15 @@ ul.cineraNavPlain li.current > a {
} }
.cineraHelp .help_container .help_key { .cineraHelp .help_container .help_key {
box-sizing: content-box;
font-family: Inconsolata; font-family: Inconsolata;
font-size: 16px; font-size: 16px;
border: 1px solid; border: 1px solid;
display: inline-block; display: inline-block;
background-color: #111111; /* Per project */ background-color: #111111; /* Per project */
border-radius: 4px; border-radius: 4px;
height: 16px; min-height: 1em;
width: 16px; min-width: 1em;
padding: 4px; padding: 4px;
line-height: 16px; line-height: 16px;
margin: 2px; margin: 2px;

View File

@ -21,6 +21,9 @@ var sourceMenus = null;
var helpButton = null; var helpButton = null;
var helpDocumentation = 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 = { var views = {
REGULAR: 0, REGULAR: 0,
THEATRE: 1, THEATRE: 1,
@ -32,7 +35,7 @@ var devices = {
MOBILE: 1, MOBILE: 1,
}; };
var cineraProps = { var CineraProps = {
C: null, C: null,
V: views.REGULAR, V: views.REGULAR,
Z: null, Z: null,
@ -46,11 +49,12 @@ var cineraProps = {
Display: null, Display: null,
FlexDirection: null, FlexDirection: null,
JustifyContent: null, JustifyContent: null,
O: window.orientation, O: null,
D: IsMobile() ? devices.MOBILE : devices.DESKTOP, D: IsMobile() ? devices.MOBILE : devices.DESKTOP,
ScrollX: null, ScrollX: null,
ScrollY: null, ScrollY: null,
}; };
CineraProps.O = GetRealOrientation(CineraProps.IsMobile);
if(titleBar) if(titleBar)
{ {
@ -169,7 +173,7 @@ if(titleBar)
} }
viewsMenu = titleBar.querySelector(".views"); viewsMenu = titleBar.querySelector(".views");
if(viewsMenu && cineraProps.D !== devices.MOBILE) if(viewsMenu && CineraProps.D !== devices.MOBILE)
{ {
menuState.push(viewsMenu); menuState.push(viewsMenu);
var viewsContainer = viewsMenu.querySelector(".views_container"); var viewsContainer = viewsMenu.querySelector(".views_container");
@ -276,7 +280,7 @@ 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 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); var MenuContainerRule = GetOrSetRule(MenuContainerRuleSelector);
if(cineraProps.D == devices.MOBILE) if(CineraProps.D == devices.MOBILE)
{ {
InitMobileStyle(); InitMobileStyle();
} }
@ -288,7 +292,7 @@ else
var player = new Player(playerContainer, onRefChanged); var player = new Player(playerContainer, onRefChanged);
if(cineraProps.D == devices.MOBILE) if(CineraProps.D == devices.MOBILE)
{ {
ConnectMobileControls(player); ConnectMobileControls(player);
} }
@ -302,7 +306,28 @@ if(viewsMenu && localStorage.getItem(cineraViewStorageItem))
InitScrollEventListener(cinera); InitScrollEventListener(cinera);
window.addEventListener("resize", function() { player.updateSize(); }); window.addEventListener("resize", function() {
if(CineraProps.IsMobile)
{
setTimeout(player.updateSize, 512);
}
else
{
player.updateSize();
}
});
window.onorientationchange = function() {
if(CineraProps.IsMobile)
{
setTimeout(player.updateSize, 512);
}
else
{
player.updateSize();
}
};
document.addEventListener("keydown", function(ev) { document.addEventListener("keydown", function(ev) {
var key = ev.key; var key = ev.key;
if(ev.getModifierState("Shift") && key == " ") if(ev.getModifierState("Shift") && key == " ")
@ -350,9 +375,3 @@ else if(lastAnnotation = localStorage.getItem(lastAnnotationStorageItem))
{ {
player.setTime(lastAnnotation); player.setTime(lastAnnotation);
} }
window.onorientationchange = function()
{
cineraProps.O = window.orientation;
player.updateSize();
};

View File

@ -207,7 +207,7 @@ function sizeAndPositionMenuContainer(TitleBar, SizerElement, Menu)
var ContainerDimX = SizerElementDimX; var ContainerDimX = SizerElementDimX;
var ContainerDimY = SizerElementDimY; var ContainerDimY = SizerElementDimY;
switch(cineraProps.O) switch(CineraProps.O)
{ {
case orientations.PORTRAIT: case orientations.PORTRAIT:
{ {
@ -286,14 +286,18 @@ ComputeTallest(Elements, UnhidingClass)
function function
ComputeAndSetTallest(Selector, Elements, UnhidingClass) ComputeAndSetTallest(Selector, Elements, UnhidingClass)
{ {
var Result;
Selector.style.height = "unset"; Selector.style.height = "unset";
Selector.style.height = ComputeTallest(Elements, UnhidingClass) + "px"; Result = ComputeTallest(Elements, UnhidingClass);
Selector.style.height = Result + "px";
return Result;
} }
function ApplyMobileStyle(player) function ApplyMobileStyle(player)
{ {
var MaxWidth = MaxWidthOfElement(cinera); var WindowDim = DeriveReliableWindowDimensions();
var MaxHeight = MaxHeightOfElement(cinera); var MaxWidth = cinera.offsetWidth;
var MaxHeight = MaxHeightOfElement(cinera, WindowDim);
var IndicesBar = playerContainer.querySelector(".markers_container"); var IndicesBar = playerContainer.querySelector(".markers_container");
var Markers = IndicesBar.querySelector(".markers"); var Markers = IndicesBar.querySelector(".markers");
@ -305,7 +309,7 @@ function ApplyMobileStyle(player)
CineraContentWidth -= EpisodeMarkers[i].offsetWidth; CineraContentWidth -= EpisodeMarkers[i].offsetWidth;
} }
switch(cineraProps.O) switch(CineraProps.O)
{ {
case orientations.PORTRAIT: case orientations.PORTRAIT:
{ {
@ -326,28 +330,29 @@ function ApplyMobileStyle(player)
} break; } break;
} }
var HeightOfTallestIndex;
if(MobileCineraContentRule !== undefined) if(MobileCineraContentRule !== undefined)
{ {
MobileCineraContentRule.style.width = CineraContentWidth + "px"; MobileCineraContentRule.style.width = CineraContentWidth + "px";
var MarkerList = Markers.querySelectorAll(".marker"); var MarkerList = Markers.querySelectorAll(".marker");
ComputeAndSetTallest(MobileCineraContentRule, MarkerList, "current"); HeightOfTallestIndex = ComputeAndSetTallest(MobileCineraContentRule, MarkerList, "current");
IndicesBar.style.height = HeightOfTallestIndex + "px";
Markers.style.width = CineraContentWidth + "px";
} }
var VideoMaxDimX = null; var VideoMaxDimX = CineraContentWidth;
var VideoMaxDimY = null; var VideoMaxDimY = MaxHeight - HeightOfTallestIndex;
switch(cineraProps.O) switch(CineraProps.O)
{ {
case orientations.PORTRAIT: case orientations.PORTRAIT:
{ {
VideoMaxDimX = MaxWidth; VideoMaxDimY -= titleBar.offsetHeight;
VideoMaxDimY = MaxHeight - IndicesBar.offsetHeight - titleBar.offsetHeight;
} break; } break;
case orientations.LANDSCAPE_LEFT: case orientations.LANDSCAPE_LEFT:
case orientations.LANDSCAPE_RIGHT: case orientations.LANDSCAPE_RIGHT:
{ {
VideoMaxDimX = MaxWidth - titleBar.offsetWidth; VideoMaxDimX -= titleBar.offsetWidth;
VideoMaxDimY = MaxHeight - IndicesBar.offsetHeight;
} break; } break;
} }
@ -477,7 +482,8 @@ ConnectMobileControls(player)
Player.prototype.updateSize = function() { Player.prototype.updateSize = function() {
var width = 0; var width = 0;
var height = 0; var height = 0;
if(cineraProps.D === devices.DESKTOP) CineraProps.O = GetRealOrientation(orientations.LANDSCAPE_LEFT, CineraProps.IsMobile);
if(CineraProps.D === devices.DESKTOP)
{ {
width = this.videoContainer.offsetWidth; width = this.videoContainer.offsetWidth;
height = width / 16 * 9; // TODO(matt): Get the aspect ratio from the video itself? height = width / 16 * 9; // TODO(matt): Get the aspect ratio from the video itself?
@ -862,7 +868,7 @@ function toggleMenuVisibility(element) {
function handleMouseOverViewsMenu() function handleMouseOverViewsMenu()
{ {
switch(cineraProps.V) switch(CineraProps.V)
{ {
case views.REGULAR: case views.REGULAR:
case views.THEATRE: case views.THEATRE:
@ -904,24 +910,24 @@ function leaveFullScreen_()
} }
function toggleTheatreMode() { function toggleTheatreMode() {
switch(cineraProps.V) switch(CineraProps.V)
{ {
case views.REGULAR: case views.REGULAR:
{ {
cineraProps.C = cinera.style.backgroundColor; CineraProps.C = cinera.style.backgroundColor;
cineraProps.Z = cinera.style.zIndex; CineraProps.Z = cinera.style.zIndex;
cineraProps.X = cinera.style.left; CineraProps.X = cinera.style.left;
cineraProps.Y = cinera.style.top; CineraProps.Y = cinera.style.top;
cineraProps.W = cinera.style.width; CineraProps.W = cinera.style.width;
cineraProps.mW = cinera.style.maxWidth; CineraProps.mW = cinera.style.maxWidth;
cineraProps.H = cinera.style.height; CineraProps.H = cinera.style.height;
cineraProps.mH = cinera.style.maxHeight; CineraProps.mH = cinera.style.maxHeight;
cineraProps.P = cinera.style.position; CineraProps.P = cinera.style.position;
cineraProps.Display = cinera.style.display; CineraProps.Display = cinera.style.display;
cineraProps.FlexDirection = cinera.style.flexDirection; CineraProps.FlexDirection = cinera.style.flexDirection;
cineraProps.JustifyContent = cinera.style.justifyContent; CineraProps.JustifyContent = cinera.style.justifyContent;
cineraProps.ScrollX = window.scrollX; CineraProps.ScrollX = window.scrollX;
cineraProps.ScrollY = window.scrollY; CineraProps.ScrollY = window.scrollY;
cinera.style.backgroundColor = "#000"; cinera.style.backgroundColor = "#000";
cinera.style.zIndex = 64; cinera.style.zIndex = 64;
@ -939,43 +945,43 @@ function toggleTheatreMode() {
viewItems[0].setAttribute("data-id", "regular"); viewItems[0].setAttribute("data-id", "regular");
viewItems[0].setAttribute("title", "Regular mode"); viewItems[0].setAttribute("title", "Regular mode");
viewItems[0].firstChild.nodeValue = "📺"; viewItems[0].firstChild.nodeValue = "📺";
} cineraProps.V = views.THEATRE; localStorage.setItem(cineraViewStorageItem, views.THEATRE); break; } CineraProps.V = views.THEATRE; localStorage.setItem(cineraViewStorageItem, views.THEATRE); break;
case views.SUPERTHEATRE: case views.SUPERTHEATRE:
{ {
leaveFullScreen_(); leaveFullScreen_();
} }
case views.THEATRE: case views.THEATRE:
{ {
cinera.style.backgroundColor = cineraProps.C; cinera.style.backgroundColor = CineraProps.C;
cinera.style.zIndex = cineraProps.Z; cinera.style.zIndex = CineraProps.Z;
cinera.style.left = cineraProps.X; cinera.style.left = CineraProps.X;
cinera.style.top = cineraProps.Y; cinera.style.top = CineraProps.Y;
cinera.style.width = cineraProps.W; cinera.style.width = CineraProps.W;
cinera.style.maxWidth = cineraProps.mW; cinera.style.maxWidth = CineraProps.mW;
cinera.style.height = cineraProps.H; cinera.style.height = CineraProps.H;
cinera.style.maxHeight = cineraProps.mH; cinera.style.maxHeight = CineraProps.mH;
cinera.style.position = cineraProps.P; cinera.style.position = CineraProps.P;
cinera.style.display = cineraProps.Display; cinera.style.display = CineraProps.Display;
cinera.style.flexDirection = cineraProps.FlexDirection; cinera.style.flexDirection = CineraProps.FlexDirection;
cinera.style.justifyContent = cineraProps.JustifyContent; cinera.style.justifyContent = CineraProps.JustifyContent;
window.scroll( window.scroll(
{ {
top: cineraProps.ScrollY, top: CineraProps.ScrollY,
left: cineraProps.ScrollX left: CineraProps.ScrollX
} }
); );
viewItems[0].setAttribute("data-id", "theatre"); viewItems[0].setAttribute("data-id", "theatre");
viewItems[0].setAttribute("title", "Theatre mode"); viewItems[0].setAttribute("title", "Theatre mode");
viewItems[0].firstChild.nodeValue = "🎭"; viewItems[0].firstChild.nodeValue = "🎭";
} cineraProps.V = views.REGULAR; localStorage.removeItem(cineraViewStorageItem); break; } CineraProps.V = views.REGULAR; localStorage.removeItem(cineraViewStorageItem); break;
} }
player.updateSize(); player.updateSize();
} }
function toggleSuperTheatreMode() function toggleSuperTheatreMode()
{ {
switch(cineraProps.V) switch(CineraProps.V)
{ {
case views.REGULAR: case views.REGULAR:
{ {
@ -984,12 +990,12 @@ function toggleSuperTheatreMode()
case views.THEATRE: case views.THEATRE:
{ {
enterFullScreen_(); enterFullScreen_();
} cineraProps.V = views.SUPERTHEATRE; localStorage.setItem(cineraViewStorageItem, views.SUPERTHEATRE); break; } CineraProps.V = views.SUPERTHEATRE; localStorage.setItem(cineraViewStorageItem, views.SUPERTHEATRE); break;
case views.SUPERTHEATRE: case views.SUPERTHEATRE:
{ {
leaveFullScreen_(); leaveFullScreen_();
toggleTheatreMode(); toggleTheatreMode();
} cineraProps.V = views.REGULAR; localStorage.removeItem(cineraViewStorageItem); break; } CineraProps.V = views.REGULAR; localStorage.removeItem(cineraViewStorageItem); break;
} }
player.updateSize(); player.updateSize();
} }

View File

@ -4,6 +4,73 @@ var orientations = {
LANDSCAPE_RIGHT: -90, LANDSCAPE_RIGHT: -90,
}; };
function
DeriveReliableWindowDimensions()
{
// https://www.howtocreate.co.uk/tutorials/javascript/browserwindow
var Result = {
X: null,
Y: null,
};
var DisplaySettings = [];
for(var i = 0; i < document.body.children.length; ++i)
{
var Child = document.body.children[i];
DisplaySettings.push(Child.style.display);
Child.style.display = "none";
}
var Element = document.createElement("div");
Element.style.position = "fixed";
Element.style.top = 0;
Element.style.right = 0;
Element.style.bottom = 0;
Element.style.left = 0;
Element.style.zOffset = -1;
Element.style.opacity = 0;
var ElementInPlace = document.body.appendChild(Element);
Result.X = ElementInPlace.offsetWidth;
Result.Y = ElementInPlace.offsetHeight;
ElementInPlace.remove();
for(var i = 0; i < document.body.children.length; ++i)
{
var Child = document.body.children[i];
Child.style.display = DisplaySettings.shift();
}
return Result;
}
function
GetRealOrientation(PreferredLandscape, IsMobile)
{
var Result = window.orientation;
var WindowDim = {
X: null,
Y: null,
};
if(IsMobile)
{
WindowDim = DeriveReliableWindowDimensions();
}
else
{
WindowDim.X = document.body.clientWidth;
WindowDim.Y = document.body.clientHeight;
}
if(WindowDim.Y > WindowDim.X)
{
Result = orientations.PORTRAIT;
}
else if(Result == undefined || Result == orientations.PORTRAIT)
{
Result = PreferredLandscape;
}
return Result;
}
var DebugConsoleMessageCount = 0; var DebugConsoleMessageCount = 0;
function Say(Message) function Say(Message)
{ {
@ -275,7 +342,7 @@ function getElementYOffsetFromPage(el) {
} }
function function
MaxWidthOfElement(Element) MaxWidthOfElement(Element, WindowDim)
{ {
var Result = 0; var Result = 0;
var OriginalWidth = Element.style.width; var OriginalWidth = Element.style.width;
@ -283,21 +350,31 @@ MaxWidthOfElement(Element)
var Max = parseInt(window.getComputedStyle(Element).width); var Max = parseInt(window.getComputedStyle(Element).width);
Element.style.width = "unset"; Element.style.width = "unset";
var Default = parseInt(window.getComputedStyle(Element).width); var Default = parseInt(window.getComputedStyle(Element).width);
Element.style.width = OriginalWidth;
if(Max > window.innerWidth || Max == Default) var InnerWidth = WindowDim ? WindowDim.X : document.body.clientWidth;
if(Max > InnerWidth || Max == Default)
{ {
Result = window.innerWidth; Result = InnerWidth;
} }
else else
{ {
Result = Max; Result = Max;
} }
Element.style.width = Result + "px";
if(Element.scrollWidth > Element.clientWidth)
{
Result = Element.clientWidth;
}
Element.style.width = OriginalWidth;
return Result; return Result;
} }
function function
MaxHeightOfElement(Element) MaxHeightOfElement(Element, WindowDim)
{ {
var Result = 0; var Result = 0;
var OriginalHeight = Element.style.height; var OriginalHeight = Element.style.height;
@ -305,16 +382,25 @@ MaxHeightOfElement(Element)
var Max = parseInt(window.getComputedStyle(Element).height); var Max = parseInt(window.getComputedStyle(Element).height);
Element.style.height = "unset"; Element.style.height = "unset";
var Default = parseInt(window.getComputedStyle(Element).height); var Default = parseInt(window.getComputedStyle(Element).height);
Element.style.height = OriginalHeight;
if(Max > window.innerHeight || Max == Default) var InnerHeight = WindowDim ? WindowDim.Y : document.body.clientHeight;
if(Max > InnerHeight || Max == Default)
{ {
Result = window.innerHeight; Result = InnerHeight;
} }
else else
{ {
Result = Max; Result = Max;
} }
Element.style.height = Result + "px";
if(Element.scrollHeight > Element.clientHeight)
{
Result = Element.clientHeight;
}
Element.style.height = OriginalHeight;
return Result; return Result;
} }

View File

@ -1,4 +1,5 @@
document.body.style.overflowY = "scroll"; document.body.style.overflowY = "scroll";
CineraProps.Orientation = GetRealOrientation(orientations.LANDSCAPE_LEFT, CineraProps.IsMobile);
// Element Selection // Element Selection
// //
@ -48,10 +49,12 @@ SyncNavState();
// NOTE(matt): Listeners // NOTE(matt): Listeners
// //
BindControlKeys();
BindGridKeys(Nav.GridSize);
BindControls(); BindControls();
InitResizeEventListener(); InitResizeEventListener();
InitOrientationChangeListener(); InitOrientationChangeListener();
InitScrollEventListener(Nav.Nexus); InitScrollEventListener(Nav.Grid);
// //
//// ////

View File

@ -2,8 +2,7 @@
// //
var CineraProps = { var CineraProps = {
IsMobile: IsMobile(), IsMobile: IsMobile(),
Orientation: window.orientation, Orientation: null,
}; };
var Search = { var Search = {
@ -680,8 +679,17 @@ var Nav = {
Nexus: null, Nexus: null,
GridContainer: null, GridContainer: null,
ButtonsContainer: null, ButtonsContainer: null,
GridSize: null, GridSize: {
GridWidth: null, X: null,
Y: null,
},
GridMinCellsPerDimension: 1,
GridMaxCellsPerDimension: 4,
GridDim: {
X: null,
Y: null,
},
MinButtonDim: 100,
ButtonDim: null, ButtonDim: null,
GridColumnGap: null, GridColumnGap: null,
GridRowGap: null, GridRowGap: null,
@ -855,23 +863,74 @@ SetHelpKeyAvailability(GridSize)
Nav.Controls.HelpKeys[i].classList.remove("unavailable"); Nav.Controls.HelpKeys[i].classList.remove("unavailable");
} }
if(GridSize < 4) /* NOTE(matt): Key layout:
0 4 8 12
1 5 9 13
2 6 10 14
3 7 11 15
*/
if(GridSize.X < 4)
{ {
Nav.Controls.HelpKeys[3].classList.add("unavailable");
Nav.Controls.HelpKeys[7].classList.add("unavailable");
Nav.Controls.HelpKeys[11].classList.add("unavailable");
Nav.Controls.HelpKeys[12].classList.add("unavailable"); Nav.Controls.HelpKeys[12].classList.add("unavailable");
Nav.Controls.HelpKeys[13].classList.add("unavailable"); Nav.Controls.HelpKeys[13].classList.add("unavailable");
Nav.Controls.HelpKeys[14].classList.add("unavailable"); Nav.Controls.HelpKeys[14].classList.add("unavailable");
Nav.Controls.HelpKeys[15].classList.add("unavailable"); Nav.Controls.HelpKeys[15].classList.add("unavailable");
if(GridSize < 3) if(GridSize.X < 3)
{ {
Nav.Controls.HelpKeys[2].classList.add("unavailable");
Nav.Controls.HelpKeys[6].classList.add("unavailable");
Nav.Controls.HelpKeys[8].classList.add("unavailable"); Nav.Controls.HelpKeys[8].classList.add("unavailable");
Nav.Controls.HelpKeys[9].classList.add("unavailable"); Nav.Controls.HelpKeys[9].classList.add("unavailable");
Nav.Controls.HelpKeys[10].classList.add("unavailable"); Nav.Controls.HelpKeys[10].classList.add("unavailable");
Nav.Controls.HelpKeys[11].classList.add("unavailable");
if(GridSize.X < 2)
{
Nav.Controls.HelpKeys[4].classList.add("unavailable");
Nav.Controls.HelpKeys[5].classList.add("unavailable");
Nav.Controls.HelpKeys[6].classList.add("unavailable");
Nav.Controls.HelpKeys[7].classList.add("unavailable");
if(GridSize.X < 1)
{
Nav.Controls.HelpKeys[0].classList.add("unavailable");
Nav.Controls.HelpKeys[1].classList.add("unavailable");
Nav.Controls.HelpKeys[2].classList.add("unavailable");
Nav.Controls.HelpKeys[3].classList.add("unavailable");
}
}
}
}
if(GridSize.Y < 4)
{
Nav.Controls.HelpKeys[3].classList.add("unavailable");
Nav.Controls.HelpKeys[7].classList.add("unavailable");
Nav.Controls.HelpKeys[11].classList.add("unavailable");
Nav.Controls.HelpKeys[15].classList.add("unavailable");
if(GridSize.Y < 3)
{
Nav.Controls.HelpKeys[2].classList.add("unavailable");
Nav.Controls.HelpKeys[6].classList.add("unavailable");
Nav.Controls.HelpKeys[10].classList.add("unavailable");
Nav.Controls.HelpKeys[14].classList.add("unavailable");
if(GridSize.Y < 2)
{
Nav.Controls.HelpKeys[1].classList.add("unavailable");
Nav.Controls.HelpKeys[5].classList.add("unavailable");
Nav.Controls.HelpKeys[9].classList.add("unavailable");
Nav.Controls.HelpKeys[13].classList.add("unavailable");
if(GridSize.Y < 1)
{
Nav.Controls.HelpKeys[0].classList.add("unavailable");
Nav.Controls.HelpKeys[4].classList.add("unavailable");
Nav.Controls.HelpKeys[8].classList.add("unavailable");
Nav.Controls.HelpKeys[12].classList.add("unavailable");
}
}
} }
} }
} }
@ -895,17 +954,29 @@ SyncNavState()
if(StateBitIsSet(state_bit.SORT_REVERSED)) { Sort(true); } if(StateBitIsSet(state_bit.SORT_REVERSED)) { Sort(true); }
// Nav.ViewType is initialised to view_type.GRID, so we needn't do anything if the Nav.State is also on Grid // Nav.ViewType is initialised to view_type.GRID, so we needn't do anything if the Nav.State is also on Grid
if(StateBitIsSet(state_bit.VIEW_LIST)) { ToggleView(); } if(StateBitIsSet(state_bit.VIEW_LIST) || !GridSizeIsSupported(Nav.GridSize))
{
ToggleView();
}
} }
else else
{ {
Nav.Controls.Save.textContent = "Save Settings: ✘"; Nav.Controls.Save.textContent = "Save Settings: ✘";
// Nav.ViewType was initialised to view_type.GRID
if(!GridSizeIsSupported(Nav.GridSize))
{
ToggleView();
}
} }
} }
else else
{ {
Nav.State = 0; Nav.State = 0;
SetStateBit(state_bit.VIEW_GRID); // NOTE(matt): Nav.ViewType was initialised to view_type.GRID SetStateBit(state_bit.VIEW_GRID); // NOTE(matt): Nav.ViewType was initialised to view_type.GRID
if(!GridSizeIsSupported(Nav.GridSize))
{
ToggleView();
}
} }
} }
@ -936,7 +1007,6 @@ InitTraversalStack()
} }
Nav.TraversalStack.push(Level); Nav.TraversalStack.push(Level);
console.log(Level);
} }
function function
@ -951,6 +1021,13 @@ EmptyElement(Element)
while(Element.firstChild) { Element.removeChild(Element.firstChild); } while(Element.firstChild) { Element.removeChild(Element.firstChild); }
} }
function
SetDim(Element, X, Y)
{
Element.style.width = X;
Element.style.height = Y;
}
function function
EmptyAndResetButton(Button) EmptyAndResetButton(Button)
{ {
@ -958,17 +1035,7 @@ EmptyAndResetButton(Button)
Button.Element.style.fontSize = null; Button.Element.style.fontSize = null;
Button.Element.style.fontWeight = null; Button.Element.style.fontWeight = null;
Button.Element.style.width = Nav.ButtonDim + "px"; SetDim(Button.Element, null, null);
Button.Element.style.height = Nav.ButtonDim + "px";
for(var i = 0; i < Button.Element.children.length; ++i)
{
Button.Element.children[i].style.fontSize = null;
Button.Element.children[i].style.fontWeight = null;
Button.Element.children[i].style.width = null;
Button.Element.children[i].style.height = null;
}
for(var i = 0; i < Button.Element.classList.length;) for(var i = 0; i < Button.Element.classList.length;)
{ {
@ -1074,8 +1141,11 @@ ComputeItemDistribution(Level)
FullButtonEntryCount: 0, FullButtonEntryCount: 0,
}; };
// NOTE(matt): Assuming a square grid, reserving the top row for projects // NOTE(matt): Reserving the top row for projects
Result.ButtonsForProjects = Math.min(Math.sqrt(Nav.Buttons.length), Result.ProjectsToPlace); if(Result.ProjectsToPlace > 0 && Result.EntriesToPlace > 0)
{
Result.ButtonsForProjects = Math.min(Nav.GridSize.X, Result.ProjectsToPlace);
}
Result.ButtonsForEntries = Nav.Buttons.length - Result.ButtonsForProjects; Result.ButtonsForEntries = Nav.Buttons.length - Result.ButtonsForProjects;
if(Result.EntriesToPlace < Result.ButtonsForEntries) if(Result.EntriesToPlace < Result.ButtonsForEntries)
{ {
@ -1126,8 +1196,6 @@ ResetButtonsContainerClone()
ResetTransform(Nav.Transition.Transforms.ButtonsContainerClone.Initial); ResetTransform(Nav.Transition.Transforms.ButtonsContainerClone.Initial);
ApplyTransform(Nav.Transition.ButtonsContainerCloneElement, Nav.Transition.Transforms.ButtonsContainerClone.Current); ApplyTransform(Nav.Transition.ButtonsContainerCloneElement, Nav.Transition.Transforms.ButtonsContainerClone.Current);
Nav.Transition.ButtonsContainerCloneElement.style.width = Nav.ButtonsContainer.style.width;
Nav.Transition.ButtonsContainerCloneElement.style.height = Nav.ButtonsContainer.style.height;
Nav.Transition.ButtonsContainerCloneElement.style.gridTemplateColumns = Nav.ButtonsContainer.style.gridTemplateColumns; Nav.Transition.ButtonsContainerCloneElement.style.gridTemplateColumns = Nav.ButtonsContainer.style.gridTemplateColumns;
Nav.Transition.ButtonsContainerCloneElement.style.gridTemplateRows = Nav.ButtonsContainer.style.gridTemplateRows; Nav.Transition.ButtonsContainerCloneElement.style.gridTemplateRows = Nav.ButtonsContainer.style.gridTemplateRows;
@ -1146,6 +1214,7 @@ ResetButtonsContainerClone()
Nav.ButtonsContainer.style.zIndex = 1; Nav.ButtonsContainer.style.zIndex = 1;
Nav.ButtonsContainer.style.order = 1; Nav.ButtonsContainer.style.order = 1;
Nav.Transition.ButtonsContainerCloneElement.style.order = 0; Nav.Transition.ButtonsContainerCloneElement.style.order = 0;
Nav.Transition.ButtonsContainerCloneElement.style.display = "none";
} }
function function
@ -1161,6 +1230,7 @@ CloneButtonsContainer()
CopyTransform(Nav.Transition.Transforms.ButtonsContainerClone.Current, Nav.Transition.Transforms.ButtonsContainer.Current); CopyTransform(Nav.Transition.Transforms.ButtonsContainerClone.Current, Nav.Transition.Transforms.ButtonsContainer.Current);
ApplyTransform(Nav.Transition.ButtonsContainerCloneElement, Nav.Transition.Transforms.ButtonsContainerClone.Current); ApplyTransform(Nav.Transition.ButtonsContainerCloneElement, Nav.Transition.Transforms.ButtonsContainerClone.Current);
Nav.Transition.ButtonsContainerCloneElement.style.zIndex = 1; Nav.Transition.ButtonsContainerCloneElement.style.zIndex = 1;
Nav.Transition.ButtonsContainerCloneElement.style.display = "grid";
} }
function function
@ -1556,8 +1626,8 @@ ComputeButtonGeometryRelativeToGrid(Button)
var ButtonStyle = window.getComputedStyle(Button); var ButtonStyle = window.getComputedStyle(Button);
var GridDimX = Nav.GridWidth; var GridDimX = Nav.GridDim.X;
var GridDimY = Nav.GridWidth; var GridDimY = Nav.GridDim.Y;
var ButtonDimX = parseInt(ButtonStyle.width); var ButtonDimX = parseInt(ButtonStyle.width);
var ButtonDimY = parseInt(ButtonStyle.height); var ButtonDimY = parseInt(ButtonStyle.height);
@ -1620,31 +1690,23 @@ GetTraversalLevelBundle()
function function
FitText(Element) FitText(Element)
{ {
if(Element.textContent.includes("Day 068") || Element.textContent.includes("Day 136")) var Paragraph = Element.firstElementChild;
{ var ParagraphStyle = window.getComputedStyle(Paragraph);
if(Element.textContent.includes("Day 068")) var ElementStyle = window.getComputedStyle(Element);
{ var Width = parseInt(ElementStyle.width);
Say("FitText(068)"); var Height = parseInt(ElementStyle.height);
}
else
{
Say("FitText(136)");
}
var Style = window.getComputedStyle(Element);
Say("Height: " + Style.height);
var ParentStyle = window.getComputedStyle(Element.parentElement);
Say("Parent Height: " + ParentStyle.height);
}
Element.style.alignItems = "flex-start"; Element.style.alignItems = "flex-start";
var FontSize = parseInt(window.getComputedStyle(Element).fontSize); var FontSize = parseInt(window.getComputedStyle(Element).fontSize);
while(FontSize > 10 && IsOverflowed(Element)) while(FontSize > 10 && (IsOverflowed(Element) || parseInt(ParagraphStyle.width) > Width || parseInt(ParagraphStyle.height) > Height))
{ {
FontSize -= 0.2; FontSize -= 0.2;
Element.style.fontSize = FontSize + "px"; Element.style.fontSize = FontSize + "px";
ParagraphStyle = window.getComputedStyle(Paragraph);
} }
if(IsOverflowed(Element)) ParagraphStyle = window.getComputedStyle(Paragraph);
if(IsOverflowed(Element) || parseInt(ParagraphStyle.width) > Width || parseInt(ParagraphStyle.height) > Height)
{ {
Element.style.fontWeight = "normal"; Element.style.fontWeight = "normal";
} }
@ -1654,16 +1716,21 @@ FitText(Element)
function function
AppendItemToButton(Button, Text, ItemEnd) AppendItemToButton(Button, Text, ItemEnd)
{ {
var ButtonElementStyle = window.getComputedStyle(Button.Element);
var VerticalBorderAllowance = parseInt(ButtonElementStyle.borderLeftWidth) + parseInt(ButtonElementStyle.borderRightWidth);
var HorizontalBorderAllowance;
var ItemElement = document.createElement("div"); var ItemElement = document.createElement("div");
ItemElement.classList.add("text"); ItemElement.classList.add("cineraText");
switch(ItemEnd) switch(ItemEnd)
{ {
case item_end.HEAD: case item_end.HEAD:
{ {
HorizonalBorderAllowance = parseInt(ButtonElementStyle.borderTopWidth);
ItemElement.classList.add("head-item"); ItemElement.classList.add("head-item");
} break; } break;
case item_end.TAIL: case item_end.TAIL:
{ {
HorizonalBorderAllowance = parseInt(ButtonElementStyle.borderBottomWidth);
ItemElement.classList.add("tail-item"); ItemElement.classList.add("tail-item");
} break; } break;
} }
@ -1673,16 +1740,25 @@ AppendItemToButton(Button, Text, ItemEnd)
ItemElement.style.transform = "rotate3d(0, 0, 1, 180deg)"; ItemElement.style.transform = "rotate3d(0, 0, 1, 180deg)";
} }
var ParagraphNode = document.createElement("p");
ParagraphNode.textContent = Text;
ItemElement.appendChild(ParagraphNode);
var Item = Button.Element.appendChild(ItemElement); var Item = Button.Element.appendChild(ItemElement);
Item.textContent = Text;
Item.style.width = Nav.ButtonDim + "px"; // NOTE(matt): This enables Safari to apply height 50% to the head / tail items
Item.style.height = (Nav.ButtonDim / 2) + "px"; var ButtonWidth = parseInt(ButtonElementStyle.width);
var ButtonHeight = parseInt(ButtonElementStyle.height);
SetDim(Button.Element, ButtonWidth + "px", ButtonHeight + "px");
////
FitText(Item); FitText(Item);
} }
function function
UpdateButtons(TransitionType, RelevantButton, PoppedLevel) UpdateButtons(TransitionType, RelevantButton, PoppedLevel)
{ {
if(GridSizeIsSupported(Nav.GridSize))
{
var LevelBundle = GetTraversalLevelBundle(); var LevelBundle = GetTraversalLevelBundle();
Nav.Controls.GridTraversal.Prev.children[0].textContent = "←"; Nav.Controls.GridTraversal.Prev.children[0].textContent = "←";
@ -1708,7 +1784,7 @@ UpdateButtons(TransitionType, RelevantButton, PoppedLevel)
else if(SiblingIsLeaf(siblings.PREV)) else if(SiblingIsLeaf(siblings.PREV))
{ {
Nav.Controls.GridTraversal.PrevAscends = true; Nav.Controls.GridTraversal.PrevAscends = true;
Nav.Controls.GridTraversal.Prev.children[0].textContent = "↰"; Nav.Controls.GridTraversal.Prev.children[0].textContent = Nav.SortChronological ? "↰" : "↲";
} }
if(!HasNextSibling(LevelBundle.This)) if(!HasNextSibling(LevelBundle.This))
@ -1777,7 +1853,7 @@ UpdateButtons(TransitionType, RelevantButton, PoppedLevel)
{ {
This.Element.classList.add("leaf"); This.Element.classList.add("leaf");
var TextElement = document.createElement("p"); var TextElement = document.createElement("p");
TextElement.classList.add("text"); TextElement.classList.add("cineraText");
if(!Nav.SortChronological) if(!Nav.SortChronological)
{ {
TextElement.style.transform = "rotate3d(0, 0, 1, 180deg)"; TextElement.style.transform = "rotate3d(0, 0, 1, 180deg)";
@ -1822,7 +1898,7 @@ UpdateButtons(TransitionType, RelevantButton, PoppedLevel)
{ {
This.Element.classList.add("leaf"); This.Element.classList.add("leaf");
var ButtonLink = document.createElement("a"); var ButtonLink = document.createElement("a");
ButtonLink.classList.add("text"); ButtonLink.classList.add("cineraText");
if(!Nav.SortChronological) if(!Nav.SortChronological)
{ {
ButtonLink.style.transform = "rotate3d(0, 0, 1, 180deg)"; ButtonLink.style.transform = "rotate3d(0, 0, 1, 180deg)";
@ -1875,7 +1951,7 @@ UpdateButtons(TransitionType, RelevantButton, PoppedLevel)
} }
else else
{ {
TargetA0.ScrollX = Nav.GridWidth + Padding; TargetA0.ScrollX = Nav.GridDim.X + Padding;
} }
Nav.Transition.StageDurations.push(320); Nav.Transition.StageDurations.push(320);
@ -1889,7 +1965,7 @@ UpdateButtons(TransitionType, RelevantButton, PoppedLevel)
{ {
Nav.ButtonsContainer.style.order = 0; Nav.ButtonsContainer.style.order = 0;
Nav.Transition.ButtonsContainerCloneElement.style.order = 1; Nav.Transition.ButtonsContainerCloneElement.style.order = 1;
ScrollX = Nav.GridWidth + Padding; ScrollX = Nav.GridDim.X + Padding;
} }
else else
{ {
@ -1911,7 +1987,7 @@ UpdateButtons(TransitionType, RelevantButton, PoppedLevel)
var Padding = Nav.GridColumnGap; var Padding = Nav.GridColumnGap;
if(Nav.SortChronological) if(Nav.SortChronological)
{ {
TargetA0.ScrollX = Nav.GridWidth + Padding; TargetA0.ScrollX = Nav.GridDim.X + Padding;
} }
else else
{ {
@ -1936,7 +2012,7 @@ UpdateButtons(TransitionType, RelevantButton, PoppedLevel)
{ {
Nav.ButtonsContainer.style.order = 0; Nav.ButtonsContainer.style.order = 0;
Nav.Transition.ButtonsContainerCloneElement.style.order = 1; Nav.Transition.ButtonsContainerCloneElement.style.order = 1;
ScrollX = Nav.GridWidth + Padding; ScrollX = Nav.GridDim.X + Padding;
} }
Nav.Transition.ButtonsContainerCloneElement.style.paddingRight = Padding + "px"; Nav.Transition.ButtonsContainerCloneElement.style.paddingRight = Padding + "px";
@ -2195,6 +2271,7 @@ UpdateButtons(TransitionType, RelevantButton, PoppedLevel)
} }
DoTransition(); DoTransition();
} }
}
} }
function function
@ -2438,7 +2515,7 @@ ShouldFireGridEvents()
} }
function function
ModifyButtonKeybinding(Event) ModifyControlKeybinding(Event)
{ {
// TODO(matt): Settle on the final sets of bindings // TODO(matt): Settle on the final sets of bindings
var Chron = Nav.SortChronological; var Chron = Nav.SortChronological;
@ -2456,79 +2533,102 @@ ModifyButtonKeybinding(Event)
case "k": if(ShouldFireGridEvents()) { EnqueueInteraction(interaction_type.ASCEND); } break; case "k": if(ShouldFireGridEvents()) { EnqueueInteraction(interaction_type.ASCEND); } break;
case "l": if(ShouldFireGridEvents()) { EnqueueInteraction(Chron ? interaction_type.SIBLING_SHIFT_NEXT : interaction_type.SIBLING_SHIFT_PREV); } break; case "l": if(ShouldFireGridEvents()) { EnqueueInteraction(Chron ? interaction_type.SIBLING_SHIFT_NEXT : interaction_type.SIBLING_SHIFT_PREV); } break;
} }
}
if(Nav.GridSize == 2) function
{ BindControlKeys()
switch(Key) {
{ document.addEventListener("keydown", ModifyControlKeybinding);
case "1": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 0 : 3].Element; ID.Button = Nav.Buttons[Chron ? 0 : 3]; EnqueueInteraction(IT, ID); } break; }
case "2": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 1 : 2].Element; ID.Button = Nav.Buttons[Chron ? 1 : 2]; EnqueueInteraction(IT, ID); } break;
case "q": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 2 : 1].Element; ID.Button = Nav.Buttons[Chron ? 2 : 1]; EnqueueInteraction(IT, ID); } break; function
case "w": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 3 : 0].Element; ID.Button = Nav.Buttons[Chron ? 3 : 0]; EnqueueInteraction(IT, ID); } break; UnbindControlKeys()
{
document.removeEventListener("keydown", ModifyControlKeybinding);
}
function
RebindControlKeys()
{
UnbindControlKeys();
BindControlKeys();
}
function
KeyIsInGrid(GridSize, KeyPos)
{
return GridSize.X > KeyPos.X && GridSize.Y > KeyPos.Y;
}
function
ComputeNaturalKeyIndex(GridSize, KeyPos)
{
return KeyPos.Y * GridSize.X + KeyPos.X;
}
function
EnqueueGridInteraction(GridSize, KeyPos)
{
var Chron = Nav.SortChronological;
var LastButtonIndex = Nav.Buttons.length - 1;
var NaturalIndex = ComputeNaturalKeyIndex(GridSize, KeyPos);
var IT = interaction_type.PUSH_BUTTON;
var ID = { Element: null, Button: null, }; // NOTE(matt): InteractionData
ID.Element = Nav.Buttons[Chron ? NaturalIndex : LastButtonIndex - NaturalIndex].Element;
ID.Button = Nav.Buttons[Chron ? NaturalIndex : LastButtonIndex - NaturalIndex];
EnqueueInteraction(IT, ID);
}
function
Get2DPosFromIndex(Layout, Index)
{
var Result = {
X: null,
Y: null,
};
Result.X = Index % Layout.X;
Result.Y = (Index - Result.X) / Layout.Y;
return Result;
}
function
ModifyGridKeybinding(Event)
{
var Key = Event.key;
// TODO(matt): With this, we could probably easily add a setting for keyboard layout: e.g. Dvorak
var PhysicalKeys = [
"1", "2", "3", "4",
"q", "w", "e", "r",
"a", "s", "d", "f",
"z", "x", "c", "v"
];
var KeyLayout = { X: 4, Y: 4 };
for(var i = 0; i < PhysicalKeys.length; ++i)
{
if(Key == PhysicalKeys[i])
{
var KeyPos = Get2DPosFromIndex(KeyLayout, i);
if(KeyIsInGrid(Nav.GridSize, KeyPos) && ShouldFireGridEvents())
{
EnqueueGridInteraction(Nav.GridSize, KeyPos);
} }
} }
else if(Nav.GridSize == 3)
{
switch(Key)
{
case "1": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 0 : 8].Element; ID.Button = Nav.Buttons[Chron ? 0 : 8]; EnqueueInteraction(IT, ID); } break;
case "2": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 1 : 7].Element; ID.Button = Nav.Buttons[Chron ? 1 : 7]; EnqueueInteraction(IT, ID); } break;
case "3": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 2 : 6].Element; ID.Button = Nav.Buttons[Chron ? 2 : 6]; EnqueueInteraction(IT, ID); } break;
case "q": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 3 : 5].Element; ID.Button = Nav.Buttons[Chron ? 3 : 5]; EnqueueInteraction(IT, ID); } break;
case "w": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 4 : 4].Element; ID.Button = Nav.Buttons[Chron ? 4 : 4]; EnqueueInteraction(IT, ID); } break;
case "e": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 5 : 3].Element; ID.Button = Nav.Buttons[Chron ? 5 : 3]; EnqueueInteraction(IT, ID); } break;
case "a": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 6 : 2].Element; ID.Button = Nav.Buttons[Chron ? 6 : 2]; EnqueueInteraction(IT, ID); } break;
case "s": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 7 : 1].Element; ID.Button = Nav.Buttons[Chron ? 7 : 1]; EnqueueInteraction(IT, ID); } break;
case "d": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 8 : 0].Element; ID.Button = Nav.Buttons[Chron ? 8 : 0]; EnqueueInteraction(IT, ID); } break;
}
}
else if(Nav.GridSize == 4)
{
switch(Key)
{
case "1": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 0 : 15].Element; ID.Button = Nav.Buttons[Chron ? 0 : 15]; EnqueueInteraction(IT, ID); } break;
case "2": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 1 : 14].Element; ID.Button = Nav.Buttons[Chron ? 1 : 14]; EnqueueInteraction(IT, ID); } break;
case "3": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 2 : 13].Element; ID.Button = Nav.Buttons[Chron ? 2 : 13]; EnqueueInteraction(IT, ID); } break;
case "4": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 3 : 12].Element; ID.Button = Nav.Buttons[Chron ? 3 : 12]; EnqueueInteraction(IT, ID); } break;
case "q": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 4 : 11].Element; ID.Button = Nav.Buttons[Chron ? 4 : 11]; EnqueueInteraction(IT, ID); } break;
case "w": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 5 : 10].Element; ID.Button = Nav.Buttons[Chron ? 5 : 10]; EnqueueInteraction(IT, ID); } break;
case "e": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 6 : 9].Element; ID.Button = Nav.Buttons[Chron ? 6 : 9]; EnqueueInteraction(IT, ID); } break;
case "r": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 7 : 8].Element; ID.Button = Nav.Buttons[Chron ? 7 : 8]; EnqueueInteraction(IT, ID); } break;
case "a": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 8 : 7].Element; ID.Button = Nav.Buttons[Chron ? 8 : 7]; EnqueueInteraction(IT, ID); } break;
case "s": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 9 : 6].Element; ID.Button = Nav.Buttons[Chron ? 9 : 6]; EnqueueInteraction(IT, ID); } break;
case "d": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 10 : 5].Element; ID.Button = Nav.Buttons[Chron ? 10 : 5]; EnqueueInteraction(IT, ID); } break;
case "f": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 11 : 4].Element; ID.Button = Nav.Buttons[Chron ? 11 : 4]; EnqueueInteraction(IT, ID); } break;
case "z": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 12 : 3].Element; ID.Button = Nav.Buttons[Chron ? 12 : 3]; EnqueueInteraction(IT, ID); } break;
case "x": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 13 : 2].Element; ID.Button = Nav.Buttons[Chron ? 13 : 2]; EnqueueInteraction(IT, ID); } break;
case "c": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 14 : 1].Element; ID.Button = Nav.Buttons[Chron ? 14 : 1]; EnqueueInteraction(IT, ID); } break;
case "v": if(ShouldFireGridEvents()) { ID.Element = Nav.Buttons[Chron ? 15 : 0].Element; ID.Button = Nav.Buttons[Chron ? 15 : 0]; EnqueueInteraction(IT, ID); } break;
}
} }
} }
function function
BindKeys() BindGridKeys()
{ {
document.addEventListener("keydown", ModifyButtonKeybinding); document.addEventListener("keydown", ModifyGridKeybinding);
} }
function function
UnbindKeys() UnbindGridKeys()
{ {
document.removeEventListener("keydown", ModifyButtonKeybinding); document.removeEventListener("keydown", ModifyGridKeybinding);
}
function
RebindKeys()
{
UnbindKeys();
BindKeys();
} }
function function
@ -2564,7 +2664,7 @@ DoRotationStage(Now)
for(var i = 0; i < Nav.ButtonsContainer.children.length; ++i) for(var i = 0; i < Nav.ButtonsContainer.children.length; ++i)
{ {
var This = Nav.ButtonsContainer.children[i]; var This = Nav.ButtonsContainer.children[i];
var ThisTexts = This.querySelectorAll(".text"); var ThisTexts = This.querySelectorAll(".cineraText");
for(var j = 0; j < ThisTexts.length; ++j) for(var j = 0; j < ThisTexts.length; ++j)
{ {
ThisTexts[j].style.transform = "rotate3d(0, 0, 1, " + -Nav.Transition.Transforms.ButtonsContainer.Current.Rotation.Z + "deg)"; ThisTexts[j].style.transform = "rotate3d(0, 0, 1, " + -Nav.Transition.Transforms.ButtonsContainer.Current.Rotation.Z + "deg)";
@ -2589,7 +2689,7 @@ DoRotationStage(Now)
function function
RotateButtons(Initialising) RotateButtons(Initialising)
{ {
// TODO(matt): Consider pushing this through DoTransition(), aware that it'd need to transform ".text" children // TODO(matt): Consider pushing this through DoTransition(), aware that it'd need to transform ".cineraText" children
CopyTransform(Nav.Transition.Transforms.ButtonsContainer.Initial, Nav.Transition.Transforms.ButtonsContainer.Current); CopyTransform(Nav.Transition.Transforms.ButtonsContainer.Initial, Nav.Transition.Transforms.ButtonsContainer.Current);
Nav.Transition.StartTime = undefined; Nav.Transition.StartTime = undefined;
if(!Initialising && Nav.Transition.Enabled) if(!Initialising && Nav.Transition.Enabled)
@ -2654,15 +2754,27 @@ Sort(Initialising)
} }
if(Initialising && Nav.Transition.Enabled) { setTimeout(AddAnimationClass, 320); } if(Initialising && Nav.Transition.Enabled) { setTimeout(AddAnimationClass, 320); }
UnbindKeys(); UnbindGridKeys(Nav.GridSize);
Nav.SortChronological = !Nav.SortChronological; Nav.SortChronological = !Nav.SortChronological;
if(Nav.Controls.GridTraversal.PrevAscends)
{
if(Nav.SortChronological)
{
Nav.Controls.GridTraversal.Prev.children[0].textContent = "↰";
}
else
{
Nav.Controls.GridTraversal.Prev.children[0].textContent = "↲";
}
}
if(MaintainingState()) if(MaintainingState())
{ {
if(Nav.SortChronological) { ClearStateBit(state_bit.SORT_REVERSED); } if(Nav.SortChronological) { ClearStateBit(state_bit.SORT_REVERSED); }
else { SetStateBit(state_bit.SORT_REVERSED); } else { SetStateBit(state_bit.SORT_REVERSED); }
} }
RotateButtons(Initialising); RotateButtons(Initialising);
RebindKeys(); BindGridKeys();
runSearch(true); runSearch(true);
} }
@ -2715,6 +2827,29 @@ EnqueueInteraction(InteractionType, Data)
} }
} }
function
UseOrientation(Orientation)
{
Nav.GridContainer.classList.remove("Portrait", "Landscape", "Left", "Right");
switch(Orientation)
{
case orientations.PORTRAIT:
{
Nav.GridContainer.classList.add("Portrait");
} break;
case orientations.LANDSCAPE_LEFT:
{
Nav.GridContainer.classList.add("Landscape", "Left");
} break;
case orientations.LANDSCAPE_RIGHT:
{
Nav.GridContainer.classList.add("Landscape", "Right");
} break;
}
}
function function
InitNexus() InitNexus()
{ {
@ -2749,91 +2884,151 @@ InitNexus()
ScrollCondition = true; // NOTE(matt): Variable in cinera_pre.js, we init with the Grid which is the view we want to auto-scroll ScrollCondition = true; // NOTE(matt): Variable in cinera_pre.js, we init with the Grid which is the view we want to auto-scroll
if(CineraProps.IsMobile) if(CineraProps.IsMobile)
{ {
switch(CineraProps.Orientation) CineraProps.Orientation = GetRealOrientation(orientations.LANDSCAPE_LEFT, CineraProps.IsMobile);
{ UseOrientation(CineraProps.Orientation);
case orientations.LANDSCAPE_LEFT:
{
Nav.GridContainer.classList.add("Landscape", "Left");
} break;
case orientations.LANDSCAPE_RIGHT:
{
Nav.GridContainer.classList.add("Landscape", "Right");
} break;
case orientations.PORTRAIT:
{
Nav.GridContainer.classList.add("Portrait");
} break;
} }
}
function
ComputePossibleCellsInDimension(AvailableSpaceInPixels, GridGap)
{
var Result = 0;
var SpaceToFill = AvailableSpaceInPixels;
if(SpaceToFill >= Nav.MinButtonDim)
{
SpaceToFill -= Nav.MinButtonDim;
++Result;
} }
for(; SpaceToFill >= (Nav.MinButtonDim + GridGap); )
{
SpaceToFill -= (Nav.MinButtonDim + GridGap);
++Result;
}
return Result;
}
function
GridSizeMeetsMinimumSupported(GridSize)
{
return GridSize.X * GridSize.Y >= 2;
}
function
GridSizeIsSupported(GridSize)
{
return (GridSize.X >= Nav.GridMinCellsPerDimension && GridSize.X <= Nav.GridMaxCellsPerDimension) &&
(GridSize.Y >= Nav.GridMinCellsPerDimension && GridSize.Y <= Nav.GridMaxCellsPerDimension) &&
GridSizeMeetsMinimumSupported(GridSize);
} }
function function
ComputeOptimalGridSize() ComputeOptimalGridSize()
{ {
var Result = null; var Result = {
var DimOffset = { X: null,
Y: null,
};
var WindowDim;
if(CineraProps.IsMobile)
{
WindowDim = DeriveReliableWindowDimensions();
}
else
{
WindowDim.X = document.body.clientWidth;
WindowDim.Y = document.body.clientHeight;
}
var DimReduction = {
X: 0, X: 0,
Y: Nav.Controls.Header.offsetHeight, Y: Nav.Controls.Header.offsetHeight,
}; };
if(CineraProps.Orientation == orientations.LANDSCAPE_LEFT || CineraProps.Orientation == orientations.LANDSCAPE_RIGHT) Nav.Transition.ButtonsTransitionContainerElement.style = null;
Nav.ButtonsContainer.style = null;
Nav.Controls.GridTraversal.Header.style = null;
Nav.Controls.GridTraversal.Ascend.style = null;
Nav.Controls.GridTraversal.Prev.style = null;
Nav.Controls.GridTraversal.Next.style = null;
// TODO(matt): Maybe structure it such that the grid is always not hidden at this point?
var GridWasHidden = Nav.GridContainer.classList.contains("hidden");
if(GridWasHidden)
{ {
DimOffset.X += Nav.Controls.GridTraversal.Header.offsetWidth; Nav.GridContainer.classList.remove("hidden");
}
if(CineraProps.IsMobile && (CineraProps.Orientation == orientations.LANDSCAPE_LEFT || CineraProps.Orientation == orientations.LANDSCAPE_RIGHT))
{
DimReduction.X += Nav.Controls.GridTraversal.Header.offsetWidth;
} }
else else
{ {
DimOffset.Y += Nav.Controls.GridTraversal.Header.offsetHeight; DimReduction.Y += Nav.Controls.GridTraversal.Header.offsetHeight;
}
if(GridWasHidden)
{
Nav.GridContainer.classList.add("hidden");
} }
var MaxWidth = MaxWidthOfElement(Nav.Nexus) - DimOffset.X; var MaxWidth = MaxWidthOfElement(Nav.Nexus, WindowDim) - DimReduction.X;
var MaxHeight = MaxHeightOfElement(Nav.Nexus) - DimOffset.Y; var MaxHeight = MaxHeightOfElement(Nav.Nexus, WindowDim) - DimReduction.Y;
var BodyStyle = window.getComputedStyle(document.body);
if(Nav.Nexus.parentNode == document.body) if(Nav.Nexus.parentNode == document.body)
{ {
// TODO(matt): Robustify this // TODO(matt): Robustify this
var BodyStyle = window.getComputedStyle(document.body);
MaxWidth -= parseInt(BodyStyle.marginRight); MaxWidth -= parseInt(BodyStyle.marginRight);
MaxHeight -= parseInt(BodyStyle.marginBottom); MaxHeight -= parseInt(BodyStyle.marginBottom);
} }
if(MaxWidth > MaxHeight) Result.X = ComputePossibleCellsInDimension(MaxWidth, Nav.GridColumnGap);
Result.Y = ComputePossibleCellsInDimension(MaxHeight, Nav.GridRowGap);
if(GridSizeMeetsMinimumSupported(Result))
{ {
MaxWidth = MaxHeight; Result.X = Clamp(Nav.GridMinCellsPerDimension, Result.X, Nav.GridMaxCellsPerDimension);
} Result.Y = Clamp(Nav.GridMinCellsPerDimension, Result.Y, Nav.GridMaxCellsPerDimension);
else if(MaxHeight > MaxWidth)
{
MaxHeight = MaxWidth;
}
var MinButtonSize = 100; var ButtonDimBasedOnX = Math.floor((MaxWidth - Nav.GridColumnGap * (Result.X - 1)) / Result.X);
var ButtonDimBasedOnY = Math.floor((MaxHeight - Nav.GridRowGap * (Result.Y - 1)) / Result.Y);
var MinGridSize = 2; Nav.ButtonDim = Math.min(ButtonDimBasedOnX, ButtonDimBasedOnY);
var MaxGridSize = 4; Nav.ButtonDim -= Nav.ButtonDim % 2; // NOTE(matt): Even-length helps CSS keep the head & tail's correct size when rotated 180 degrees
Result = Clamp(MinGridSize, Math.floor(MaxWidth / MinButtonSize), MaxGridSize); var GridTemplateColumnsStyle = "repeat(" + Result.X + ", minmax(" + Nav.ButtonDim + "px, " + Nav.ButtonDim + "px))";
Nav.ButtonDim = (MaxWidth - Nav.GridRowGap * (Result - 1)) / Result;
// TODO(matt): If Safari's head-item sizing bug proves to be a problem, use this:
/*
var ButtonStyleRuleSelector = "#cineraIndex #cineraIndexGrid .cineraButton.subdivision";
var ButtonStyleRule = GetOrSetRule(ButtonStyleRuleSelector);
ButtonStyleRule.style.width = Nav.ButtonDim + "px";
ButtonStyleRule.style.height = Nav.ButtonDim + "px";
*/
var GridTemplateColumnsStyle = "repeat(" + Result + ", 1fr)";
Nav.ButtonsContainer.style.gridTemplateColumns = GridTemplateColumnsStyle; Nav.ButtonsContainer.style.gridTemplateColumns = GridTemplateColumnsStyle;
var GridTemplateRowsStyle = "repeat(" + Result + ", " + Nav.ButtonDim + "px)"; var GridTemplateRowsStyle = "repeat(" + Result.Y + ", " + Nav.ButtonDim + "px)";
Nav.ButtonsContainer.style.gridTemplateRows = GridTemplateRowsStyle; Nav.ButtonsContainer.style.gridTemplateRows = GridTemplateRowsStyle;
Nav.ButtonsContainer.style.width = MaxWidth + "px"; Nav.GridDim.X = Nav.ButtonDim * Result.X + Nav.GridColumnGap * (Result.X - 1);
Nav.ButtonsContainer.style.height = MaxHeight + "px"; Nav.GridDim.Y = Nav.ButtonDim * Result.Y + Nav.GridRowGap * (Result.Y - 1);
Nav.Transition.ButtonsTransitionContainerElement.style.width = MaxWidth + "px"; SetDim(Nav.Transition.ButtonsTransitionContainerElement, Nav.GridDim.X + "px", Nav.GridDim.Y + "px");
Nav.Transition.ButtonsTransitionContainerElement.style.height = MaxHeight + "px";
Nav.GridWidth = MaxWidth; Nav.Controls.GridTraversal.Header.style.maxWidth = Nav.GridDim.X + "px";
Nav.Controls.GridTraversal.Header.style.maxHeight = Nav.GridDim.Y + "px";
var TraversalButtonCount = 3;
if(Nav.Controls.GridTraversal.Header.scrollWidth > Nav.Controls.GridTraversal.Header.clientWidth)
{
var TraversalButtonDim = Nav.Controls.GridTraversal.Header.clientWidth / TraversalButtonCount;
SetDim(Nav.Controls.GridTraversal.Ascend, TraversalButtonDim + "px", TraversalButtonDim + "px");
SetDim(Nav.Controls.GridTraversal.Prev, TraversalButtonDim + "px", TraversalButtonDim + "px");
SetDim(Nav.Controls.GridTraversal.Next, TraversalButtonDim + "px", TraversalButtonDim + "px");
}
if(Nav.Controls.GridTraversal.Header.scrollHeight > Nav.Controls.GridTraversal.Header.clientHeight)
{
var TraversalButtonDim = Nav.Controls.GridTraversal.Header.clientHeight / TraversalButtonCount;
SetDim(Nav.Controls.GridTraversal.Ascend, TraversalButtonDim + "px", TraversalButtonDim + "px");
SetDim(Nav.Controls.GridTraversal.Prev, TraversalButtonDim + "px", TraversalButtonDim + "px");
SetDim(Nav.Controls.GridTraversal.Next, TraversalButtonDim + "px", TraversalButtonDim + "px");
}
}
ResetButtonsContainerClone(); // NOTE(matt): This reapplies the sorting Z-rotation
return Result; return Result;
} }
@ -3273,6 +3468,8 @@ ToggleView()
} }
} }
else else
{
if(GridSizeIsSupported(Nav.GridSize))
{ {
Nav.Controls.View.textContent = "View: Grid"; Nav.Controls.View.textContent = "View: Grid";
Nav.ViewType = view_type.GRID; Nav.ViewType = view_type.GRID;
@ -3291,14 +3488,19 @@ ToggleView()
var ProjectsStack = BuildProjectsStack(TargetLevel); var ProjectsStack = BuildProjectsStack(TargetLevel);
DeriveTraversalStack(ProjectsStack, TargetLevel); DeriveTraversalStack(ProjectsStack, TargetLevel);
} }
UpdateButtons();
Nav.List.classList.add("hidden"); Nav.List.classList.add("hidden");
Nav.GridContainer.classList.remove("hidden"); Nav.GridContainer.classList.remove("hidden");
UpdateButtons();
ScrollToWithOffset(Nav.Controls.GridTraversal.Header, Nav.Controls.Header.offsetHeight); ScrollToWithOffset(Nav.Controls.GridTraversal.Header, Nav.Controls.Header.offsetHeight);
} }
} }
else
{
// TODO(matt): Inform user that grid view is unavailable
}
}
ScrollCondition = Nav.ViewType == view_type.GRID; ScrollCondition = Nav.ViewType == view_type.GRID;
} }
@ -3431,14 +3633,16 @@ BindControls()
function function
InitButtons() InitButtons()
{ {
if(GridSizeIsSupported(Nav.GridSize))
{
var ButtonPrototype = document.createElement("div"); var ButtonPrototype = document.createElement("div");
ButtonPrototype.classList.add("cineraButton", "subdivision"); ButtonPrototype.classList.add("cineraButton", "subdivision");
for(var i = 0; i < Math.pow(Nav.GridSize, 2); ++i) for(var i = 0; i < Nav.GridSize.X * Nav.GridSize.Y; ++i)
{ {
Nav.ButtonsContainer.appendChild(ButtonPrototype.cloneNode()); Nav.ButtonsContainer.appendChild(ButtonPrototype.cloneNode());
} }
var Buttons = Nav.Nexus.querySelectorAll(".cineraButton.subdivision"); var Buttons = Nav.ButtonsContainer.querySelectorAll(".cineraButton.subdivision");
for(let j = 0; j < Buttons.length; ++j) for(let j = 0; j < Buttons.length; ++j)
{ {
let Button = { let Button = {
@ -3459,8 +3663,7 @@ InitButtons()
Nav.Buttons.push(Button); Nav.Buttons.push(Button);
} }
}
BindKeys();
} }
function function
@ -3471,9 +3674,7 @@ ReinitButtons()
Nav.Buttons[0].Element.remove(); Nav.Buttons[0].Element.remove();
Nav.Buttons.shift(); Nav.Buttons.shift();
} }
RebindKeys();
InitButtons(); InitButtons();
UpdateButtons();
} }
function function
@ -3600,20 +3801,48 @@ PseudoPushButton(Button)
} }
function function
InitResizeEventListener() ResizeFunction()
{ {
window.addEventListener("resize", function() { CineraProps.Orientation = GetRealOrientation(orientations.LANDSCAPE_LEFT, CineraProps.IsMobile);
if(CineraProps.IsMobile)
{
UseOrientation(CineraProps.Orientation);
}
var NewGridSize = ComputeOptimalGridSize(); var NewGridSize = ComputeOptimalGridSize();
if(Nav.GridSize !== NewGridSize) if(Nav.GridSize !== NewGridSize)
{ {
UnbindGridKeys();
Nav.GridSize = NewGridSize; Nav.GridSize = NewGridSize;
ReinitButtons(); ReinitButtons();
BindGridKeys();
SetHelpKeyAvailability(Nav.GridSize)
if(GridSizeIsSupported(Nav.GridSize))
{
var TargetLevel = Nav.TraversalStack[Nav.TraversalStack.length - 1]; var TargetLevel = Nav.TraversalStack[Nav.TraversalStack.length - 1];
var ProjectsStack = EmptyTraversalStackIntoProjectsStack(); var ProjectsStack = EmptyTraversalStackIntoProjectsStack();
DeriveTraversalStack(ProjectsStack, TargetLevel); DeriveTraversalStack(ProjectsStack, TargetLevel);
SetHelpKeyAvailability(Nav.GridSize) }
else if(Nav.ViewType == view_type.GRID)
{
ToggleView();
// TODO(matt): Inform user that we've switched to the list view
}
ScrollToWithOffset(Nav.Nexus, 0);
} }
UpdateButtons(); UpdateButtons();
}
function
InitResizeEventListener()
{
window.addEventListener("resize", function() {
if(CineraProps.IsMobile)
{
window.setTimeout(ResizeFunction, 512);
}
else
{
ResizeFunction();
}
}); });
} }
@ -3624,35 +3853,11 @@ InitOrientationChangeListener()
{ {
if(CineraProps.IsMobile) if(CineraProps.IsMobile)
{ {
CineraProps.Orientation = window.orientation; window.setTimeout(ResizeFunction, 512);
Nav.GridContainer.classList.remove("Portrait", "Landscape", "Left", "Right");
switch(CineraProps.Orientation)
{
case orientations.LANDSCAPE_LEFT:
{
Nav.GridContainer.classList.add("Landscape", "Left");
} break;
case orientations.LANDSCAPE_RIGHT:
{
Nav.GridContainer.classList.add("Landscape", "Right");
} break;
case orientations.PORTRAIT:
{
Nav.GridContainer.classList.add("Portrait");
} break;
} }
else
var NewGridSize = ComputeOptimalGridSize();
if(Nav.GridSize !== NewGridSize)
{ {
Nav.GridSize = NewGridSize; ResizeFunction();
ReinitButtons();
var TargetLevel = Nav.TraversalStack[Nav.TraversalStack.length - 1];
var ProjectsStack = EmptyTraversalStackIntoProjectsStack();
DeriveTraversalStack(ProjectsStack, TargetLevel);
SetHelpKeyAvailability(Nav.GridSize)
}
UpdateButtons();
} }
}; };
} }