cinera v0.8.0: Mobile-friendly layout
Major features: Search page: Subdivision grid layout Player page: Device orientation-specific layout Fixes: Strip slashes of the URLs: base_url, etc. Fix SnipeChecksumAndCloseFile() to not null-terminate the checksum string Fix hover background colouration of medium icons of current timestamp Fix DeriveLineageWithoutOriginOfProject() to call InitBookOfPointers() Fix SortAndAbbreviateSpeakers() to use the person's ID if Name is blank More directly display the "unit", if set, in the search results Fix VideoIsPrivate() to find the apparently relocated privacyStatus Make VideoIsPrivate() default to TRUE for non-youtube Output as keywords all topics that do not match "nullTopic" Deleted asset: cinera_search.js New assets: cinera_search_pre.js cinera_search_post.js
This commit is contained in:
parent
6eeb588adf
commit
3945ac883c
595
cinera/cinera.c
595
cinera/cinera.c
|
@ -22,8 +22,8 @@ typedef struct
|
||||||
|
|
||||||
version CINERA_APP_VERSION = {
|
version CINERA_APP_VERSION = {
|
||||||
.Major = 0,
|
.Major = 0,
|
||||||
.Minor = 7,
|
.Minor = 8,
|
||||||
.Patch = 18
|
.Patch = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <stdarg.h> // NOTE(matt): varargs
|
#include <stdarg.h> // NOTE(matt): varargs
|
||||||
|
@ -119,6 +119,9 @@ clock_t TIMING_START;
|
||||||
|
|
||||||
#define MIN(A, B) A < B ? A : B
|
#define MIN(A, B) A < B ? A : B
|
||||||
|
|
||||||
|
typedef int32_t hash32;
|
||||||
|
typedef hash32 asset_hash;
|
||||||
|
|
||||||
void
|
void
|
||||||
Clear(void *V, uint64_t Size)
|
Clear(void *V, uint64_t Size)
|
||||||
{
|
{
|
||||||
|
@ -2442,7 +2445,7 @@ typedef struct
|
||||||
char BaseURL[MAX_BASE_URL_LENGTH];
|
char BaseURL[MAX_BASE_URL_LENGTH];
|
||||||
char SearchLocation[MAX_RELATIVE_PAGE_LOCATION_LENGTH];
|
char SearchLocation[MAX_RELATIVE_PAGE_LOCATION_LENGTH];
|
||||||
char PlayerLocation[MAX_RELATIVE_PAGE_LOCATION_LENGTH];
|
char PlayerLocation[MAX_RELATIVE_PAGE_LOCATION_LENGTH];
|
||||||
char PlayerURLPrefix[MAX_PLAYER_URL_PREFIX_LENGTH]; // TODO(matt): Replace this with the OutputPath, when we add that
|
char PlayerURLPrefix[MAX_PLAYER_URL_PREFIX_LENGTH];
|
||||||
} db_header_entries4;
|
} db_header_entries4;
|
||||||
|
|
||||||
typedef db_entry3 db_entry4;
|
typedef db_entry3 db_entry4;
|
||||||
|
@ -2553,7 +2556,7 @@ typedef struct
|
||||||
{
|
{
|
||||||
char Filename[MAX_ASSET_FILENAME_LENGTH];
|
char Filename[MAX_ASSET_FILENAME_LENGTH];
|
||||||
enum8(asset_type) Type;
|
enum8(asset_type) Type;
|
||||||
int32_t Hash;
|
hash32 Hash;
|
||||||
uint32_t LandmarkCount;
|
uint32_t LandmarkCount;
|
||||||
uint64_t Associated:1;
|
uint64_t Associated:1;
|
||||||
uint64_t Variants:63;
|
uint64_t Variants:63;
|
||||||
|
@ -2639,7 +2642,7 @@ typedef struct asset
|
||||||
{
|
{
|
||||||
asset_type Type;
|
asset_type Type;
|
||||||
char Filename[MAX_ASSET_FILENAME_LENGTH];
|
char Filename[MAX_ASSET_FILENAME_LENGTH];
|
||||||
int32_t Hash;
|
asset_hash Hash;
|
||||||
vec2 Dimensions;
|
vec2 Dimensions;
|
||||||
sprite Sprite;
|
sprite Sprite;
|
||||||
uint64_t Variants:63;
|
uint64_t Variants:63;
|
||||||
|
@ -2659,7 +2662,8 @@ asset BuiltinAssets[] =
|
||||||
{ ASSET_IMG, "cinera_icon_filter.png" },
|
{ ASSET_IMG, "cinera_icon_filter.png" },
|
||||||
{ ASSET_JS, "cinera_pre.js" },
|
{ ASSET_JS, "cinera_pre.js" },
|
||||||
{ ASSET_JS, "cinera_post.js" },
|
{ ASSET_JS, "cinera_post.js" },
|
||||||
{ ASSET_JS, "cinera_search.js" },
|
{ ASSET_JS, "cinera_search_pre.js" },
|
||||||
|
{ ASSET_JS, "cinera_search_post.js" },
|
||||||
{ ASSET_JS, "cinera_player_pre.js" },
|
{ ASSET_JS, "cinera_player_pre.js" },
|
||||||
{ ASSET_JS, "cinera_player_post.js" },
|
{ ASSET_JS, "cinera_player_post.js" },
|
||||||
};
|
};
|
||||||
|
@ -2671,7 +2675,8 @@ typedef enum
|
||||||
ASSET_IMG_FILTER,
|
ASSET_IMG_FILTER,
|
||||||
ASSET_JS_CINERA_PRE,
|
ASSET_JS_CINERA_PRE,
|
||||||
ASSET_JS_CINERA_POST,
|
ASSET_JS_CINERA_POST,
|
||||||
ASSET_JS_SEARCH,
|
ASSET_JS_SEARCH_PRE,
|
||||||
|
ASSET_JS_SEARCH_POST,
|
||||||
ASSET_JS_PLAYER_PRE,
|
ASSET_JS_PLAYER_PRE,
|
||||||
ASSET_JS_PLAYER_POST,
|
ASSET_JS_PLAYER_POST,
|
||||||
BUILTIN_ASSETS_COUNT,
|
BUILTIN_ASSETS_COUNT,
|
||||||
|
@ -3457,6 +3462,22 @@ CopyStringToBufferNoFormat_(int LineNumber, buffer *Dest, string String)
|
||||||
*Dest->Ptr = '\0';
|
*Dest->Ptr = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define CopyStringToBufferNoTerminate(Dest, Src) CopyStringToBufferNoTerminate_(__LINE__, Dest, Src)
|
||||||
|
void
|
||||||
|
CopyStringToBufferNoTerminate_(int LineNumber, buffer *Dest, string Src)
|
||||||
|
{
|
||||||
|
if((Dest->Ptr - Dest->Location + Src.Length) > Dest->Size)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "CopyStringToBufferNoTerminate(%s) call on line %d cannot accommodate %ld-character string:\n"
|
||||||
|
"%.*s\n", BufferIDStrings[Dest->ID], LineNumber, Src.Length, (int)Src.Length, Src.Base);
|
||||||
|
__asm__("int3");
|
||||||
|
}
|
||||||
|
for(int i = 0; i < Src.Length; ++i)
|
||||||
|
{
|
||||||
|
*Dest->Ptr++ = Src.Base[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define CopyStringToBufferNoFormatL(Dest, Length, String) CopyStringToBufferNoFormatL_(__LINE__, Dest, Length, String)
|
#define CopyStringToBufferNoFormatL(Dest, Length, String) CopyStringToBufferNoFormatL_(__LINE__, Dest, Length, String)
|
||||||
void
|
void
|
||||||
CopyStringToBufferNoFormatL_(int LineNumber, buffer *Dest, int Length, char *String)
|
CopyStringToBufferNoFormatL_(int LineNumber, buffer *Dest, int Length, char *String)
|
||||||
|
@ -4569,7 +4590,7 @@ PrintAssetAndLandmarks(db_asset *A, uint16_t *Index)
|
||||||
|
|
||||||
// TODO(matt): Almost definitely redo this using Locate*() functions...
|
// TODO(matt): Almost definitely redo this using Locate*() functions...
|
||||||
void
|
void
|
||||||
SnipeChecksumAndCloseFile(file *HTMLFile, db_asset *Asset, int LandmarksInFile, buffer *Checksum, int64_t *RunningLandmarkIndex)
|
SnipeChecksumAndCloseFile(file *HTMLFile, db_asset *Asset, int LandmarksInFile, asset_hash Checksum, int64_t *RunningLandmarkIndex)
|
||||||
{
|
{
|
||||||
db_landmark *FirstLandmark = LocateFirstLandmark(Asset);
|
db_landmark *FirstLandmark = LocateFirstLandmark(Asset);
|
||||||
for(int j = 0; j < LandmarksInFile; ++j, ++*RunningLandmarkIndex)
|
for(int j = 0; j < LandmarksInFile; ++j, ++*RunningLandmarkIndex)
|
||||||
|
@ -4577,7 +4598,9 @@ SnipeChecksumAndCloseFile(file *HTMLFile, db_asset *Asset, int LandmarksInFile,
|
||||||
db_landmark *Landmark = FirstLandmark + *RunningLandmarkIndex;
|
db_landmark *Landmark = FirstLandmark + *RunningLandmarkIndex;
|
||||||
|
|
||||||
HTMLFile->Buffer.Ptr = HTMLFile->Buffer.Location + Landmark->Position;
|
HTMLFile->Buffer.Ptr = HTMLFile->Buffer.Location + Landmark->Position;
|
||||||
CopyBufferSized(&HTMLFile->Buffer, Checksum, Checksum->Ptr - Checksum->Location);
|
char ChecksumString[16];
|
||||||
|
ClearCopyString(ChecksumString, sizeof(ChecksumString), "%08x", Checksum);
|
||||||
|
CopyStringToBufferNoTerminate(&HTMLFile->Buffer, Wrap0(ChecksumString));
|
||||||
}
|
}
|
||||||
|
|
||||||
HTMLFile->Handle = fopen(HTMLFile->Path, "w");
|
HTMLFile->Handle = fopen(HTMLFile->Path, "w");
|
||||||
|
@ -4996,7 +5019,7 @@ ReadPlayerPageIntoBuffer(file *File, string BaseDir, string PlayerLocation, stri
|
||||||
}
|
}
|
||||||
|
|
||||||
rc
|
rc
|
||||||
SnipeChecksumIntoHTML(db_asset *Asset, buffer *Checksum)
|
SnipeChecksumIntoHTML(db_asset *Asset, asset_hash Checksum)
|
||||||
{
|
{
|
||||||
db_landmark *FirstLandmark = LocateFirstLandmark(Asset);
|
db_landmark *FirstLandmark = LocateFirstLandmark(Asset);
|
||||||
|
|
||||||
|
@ -5564,32 +5587,38 @@ UpdateAssetInDB(asset *Asset)
|
||||||
|
|
||||||
if(StoredAsset->Hash != Asset->Hash)
|
if(StoredAsset->Hash != Asset->Hash)
|
||||||
{
|
{
|
||||||
|
char OldChecksum[16];
|
||||||
|
ClearCopyString(OldChecksum, sizeof(OldChecksum), "%08x", StoredAsset->Hash);
|
||||||
|
|
||||||
|
char NewChecksum[16];
|
||||||
|
ClearCopyString(NewChecksum, sizeof(NewChecksum), "%08x", Asset->Hash);
|
||||||
|
|
||||||
StoredAsset->Hash = Asset->Hash;
|
StoredAsset->Hash = Asset->Hash;
|
||||||
char *Ptr = (char *)Asset;
|
char *Ptr = (char *)Asset;
|
||||||
Ptr += sizeof(*Asset);
|
Ptr += sizeof(*Asset);
|
||||||
|
|
||||||
buffer Checksum = {};
|
|
||||||
ClaimBuffer(&Checksum, BID_CHECKSUM, 16);
|
|
||||||
CopyStringToBuffer(&Checksum, "%08x", StoredAsset->Hash);
|
|
||||||
|
|
||||||
file AssetFile = {};
|
file AssetFile = {};
|
||||||
AssetFile.Path = ConstructAssetPath(&AssetFile, Wrap0i(StoredAsset->Filename, sizeof(StoredAsset->Filename)), StoredAsset->Type);
|
AssetFile.Path = ConstructAssetPath(&AssetFile, Wrap0i(StoredAsset->Filename, sizeof(StoredAsset->Filename)), StoredAsset->Type);
|
||||||
ResolvePath(&AssetFile.Path);
|
ResolvePath(&AssetFile.Path);
|
||||||
|
|
||||||
string ChecksumL = Wrap0i(Checksum.Location, Checksum.Ptr - Checksum.Location);
|
string MessageEditType = MakeString("sss", ColourStrings[CS_ONGOING], "Updating", ColourStrings[CS_END]);
|
||||||
string Message = MakeString("sssslsss",
|
string Message = MakeString("sssssssssss",
|
||||||
ColourStrings[CS_ONGOING], "Updating", ColourStrings[CS_END], " checksum ", &ChecksumL, " of ", AssetFile.Path, " in HTML files");
|
" checksum ",
|
||||||
fprintf(stderr, "%.*s", (int)Message.Length, Message.Base);
|
ColourStrings[CS_BLACK_BOLD], OldChecksum, ColourStrings[CS_END],
|
||||||
uint64_t MessageLength = Message.Length;
|
" → ",
|
||||||
FreeString(&Message);
|
ColourStrings[CS_BLUE_BOLD], NewChecksum, ColourStrings[CS_END],
|
||||||
|
" of ", AssetFile.Path, " in HTML files");
|
||||||
|
fprintf(stderr, "%.*s%.*s", (int)MessageEditType.Length, MessageEditType.Base, (int)Message.Length, Message.Base);
|
||||||
|
uint64_t MessageLength = MessageEditType.Length + Message.Length;
|
||||||
|
|
||||||
if(SnipeChecksumIntoHTML(StoredAsset, &Checksum) == RC_SUCCESS)
|
if(SnipeChecksumIntoHTML(StoredAsset, Asset->Hash) == RC_SUCCESS)
|
||||||
{
|
{
|
||||||
ClearTerminalRow(MessageLength);
|
ClearTerminalRow(MessageLength);
|
||||||
fprintf(stderr, "%sUpdated%s checksum %.*s of %s\n", ColourStrings[CS_REINSERTION], ColourStrings[CS_END], (int)ChecksumL.Length, ChecksumL.Base, AssetFile.Path);
|
PrintC(CS_REINSERTION, "Updated");
|
||||||
|
fprintf(stderr, "%.*s\n", (int)Message.Length, Message.Base);
|
||||||
}
|
}
|
||||||
|
|
||||||
DeclaimBuffer(&Checksum);
|
FreeString(&Message);
|
||||||
|
|
||||||
DB.Metadata.File.Handle = fopen(DB.Metadata.File.Path, "w");
|
DB.Metadata.File.Handle = fopen(DB.Metadata.File.Path, "w");
|
||||||
fwrite(DB.Metadata.File.Buffer.Location, DB.Metadata.File.Buffer.Size, 1, DB.Metadata.File.Handle);
|
fwrite(DB.Metadata.File.Buffer.Location, DB.Metadata.File.Buffer.Size, 1, DB.Metadata.File.Handle);
|
||||||
|
@ -5625,7 +5654,7 @@ UpdateAssetInDB(asset *Asset)
|
||||||
fwrite(&StoredAsset, sizeof(StoredAsset), 1, DB.Metadata.File.Handle);
|
fwrite(&StoredAsset, sizeof(StoredAsset), 1, DB.Metadata.File.Handle);
|
||||||
AccumulateFileEditSize(&DB.Metadata, sizeof(StoredAsset));
|
AccumulateFileEditSize(&DB.Metadata, sizeof(StoredAsset));
|
||||||
|
|
||||||
printf("%sAppended%s %s asset: %s [%08x]\n", ColourStrings[CS_ADDITION], ColourStrings[CS_END], AssetTypeNames[StoredAsset.Type], StoredAsset.Filename, StoredAsset.Hash);
|
fprintf(stderr, "%sAppended%s %s asset: %s [%08x]\n", ColourStrings[CS_ADDITION], ColourStrings[CS_END], AssetTypeNames[StoredAsset.Type], StoredAsset.Filename, StoredAsset.Hash);
|
||||||
|
|
||||||
fwrite(DB.Metadata.File.Buffer.Location + BytesIntoFile, DB.Metadata.File.Buffer.Size - BytesIntoFile, 1, DB.Metadata.File.Handle);
|
fwrite(DB.Metadata.File.Buffer.Location + BytesIntoFile, DB.Metadata.File.Buffer.Size - BytesIntoFile, 1, DB.Metadata.File.Handle);
|
||||||
|
|
||||||
|
@ -5985,8 +6014,6 @@ AbbreviationsClash(memory_book *Speakers)
|
||||||
void
|
void
|
||||||
SortAndAbbreviateSpeakers(speakers *Speakers)
|
SortAndAbbreviateSpeakers(speakers *Speakers)
|
||||||
{
|
{
|
||||||
// TODO(matt): Handle Abbreviation in its new form as a char *, rather than a fixed-sized char[], so probably doing
|
|
||||||
// MakeString0() or ExpandString0() or something
|
|
||||||
for(int i = 0; i < Speakers->Speakers.ItemCount; ++i)
|
for(int i = 0; i < Speakers->Speakers.ItemCount; ++i)
|
||||||
{
|
{
|
||||||
speaker *A = GetPlaceInBook(&Speakers->Speakers, i);
|
speaker *A = GetPlaceInBook(&Speakers->Speakers, i);
|
||||||
|
@ -6006,8 +6033,9 @@ SortAndAbbreviateSpeakers(speakers *Speakers)
|
||||||
for(int i = 0; i < Speakers->Speakers.ItemCount; ++i)
|
for(int i = 0; i < Speakers->Speakers.ItemCount; ++i)
|
||||||
{
|
{
|
||||||
speaker *This = GetPlaceInBook(&Speakers->Speakers, i);
|
speaker *This = GetPlaceInBook(&Speakers->Speakers, i);
|
||||||
|
string Name = This->Person->Name.Length > 0 ? This->Person->Name : This->Person->ID;
|
||||||
StringToColourHash(&This->Colour, This->Person->ID);
|
StringToColourHash(&This->Colour, This->Person->ID);
|
||||||
This->Abbreviation = InitialString(&Speakers->Abbreviations, This->Person->Name);
|
This->Abbreviation = InitialString(&Speakers->Abbreviations, Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Attempt = 0;
|
int Attempt = 0;
|
||||||
|
@ -6016,11 +6044,12 @@ SortAndAbbreviateSpeakers(speakers *Speakers)
|
||||||
for(int i = 0; i < Speakers->Speakers.ItemCount; ++i)
|
for(int i = 0; i < Speakers->Speakers.ItemCount; ++i)
|
||||||
{
|
{
|
||||||
speaker *This = GetPlaceInBook(&Speakers->Speakers, i);
|
speaker *This = GetPlaceInBook(&Speakers->Speakers, i);
|
||||||
|
string Name = This->Person->Name.Length > 0 ? This->Person->Name : This->Person->ID;
|
||||||
switch(Attempt)
|
switch(Attempt)
|
||||||
{
|
{
|
||||||
case 0: This->Abbreviation = GetFirstSubstring(This->Person->Name); break;
|
case 0: This->Abbreviation = GetFirstSubstring(Name); break;
|
||||||
case 1: This->Abbreviation = InitialAndGetFinalString(&Speakers->Abbreviations, This->Person->Name); break;
|
case 1: This->Abbreviation = InitialAndGetFinalString(&Speakers->Abbreviations, Name); break;
|
||||||
case 2: This->Abbreviation = This->Person->Name; break;
|
case 2: This->Abbreviation = Name; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++Attempt;
|
++Attempt;
|
||||||
|
@ -6405,6 +6434,8 @@ PushCredentials(buffer *CreditsMenu, memory_book *Speakers, person *Actor, role
|
||||||
|
|
||||||
CopyStringToBuffer(CreditsMenu,
|
CopyStringToBuffer(CreditsMenu,
|
||||||
" <span class=\"credit\">\n");
|
" <span class=\"credit\">\n");
|
||||||
|
|
||||||
|
string Name = Actor->Name.Length > 0 ? Actor->Name : Actor->ID;
|
||||||
if(Actor->Homepage.Length)
|
if(Actor->Homepage.Length)
|
||||||
{
|
{
|
||||||
CopyStringToBuffer(CreditsMenu,
|
CopyStringToBuffer(CreditsMenu,
|
||||||
|
@ -6414,7 +6445,7 @@ PushCredentials(buffer *CreditsMenu, memory_book *Speakers, person *Actor, role
|
||||||
" </a>\n",
|
" </a>\n",
|
||||||
(int)Actor->Homepage.Length, Actor->Homepage.Base,
|
(int)Actor->Homepage.Length, Actor->Homepage.Base,
|
||||||
RoleStrings[Role],
|
RoleStrings[Role],
|
||||||
(int)Actor->Name.Length, Actor->Name.Base);
|
(int)Name.Length, Name.Base);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -6424,7 +6455,7 @@ PushCredentials(buffer *CreditsMenu, memory_book *Speakers, person *Actor, role
|
||||||
" <div class=\"name\">%.*s</div>\n"
|
" <div class=\"name\">%.*s</div>\n"
|
||||||
" </div>\n",
|
" </div>\n",
|
||||||
RoleStrings[Role],
|
RoleStrings[Role],
|
||||||
(int)Actor->Name.Length, Actor->Name.Base);
|
(int)Name.Length, Name.Base);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(matt): Handle multiple support platforms!
|
// TODO(matt): Handle multiple support platforms!
|
||||||
|
@ -6462,9 +6493,9 @@ ErrorCredentials(string HMMLFilepath, string Actor, role Role)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
BuildCredits(string HMMLFilepath, buffer *CreditsMenu, HMML_VideoMetaData *Metadata, speakers *Speakers, bool *RequiresCineraJS)
|
BuildCredits(string HMMLFilepath, buffer *CreditsMenu, HMML_VideoMetaData *Metadata, person *Host, speakers *Speakers, bool *RequiresCineraJS)
|
||||||
{
|
{
|
||||||
person *Host = GetPersonFromConfig(Wrap0(Metadata->member));
|
//person *Host = GetPersonFromConfig(Wrap0(Metadata->member));
|
||||||
if(Host)
|
if(Host)
|
||||||
{
|
{
|
||||||
PushCredentials(CreditsMenu, &Speakers->Speakers, Host, R_HOST, RequiresCineraJS);
|
PushCredentials(CreditsMenu, &Speakers->Speakers, Host, R_HOST, RequiresCineraJS);
|
||||||
|
@ -8709,61 +8740,73 @@ ExamineDB(void)
|
||||||
DeclaimMenuBuffers(&MenuBuffers)
|
DeclaimMenuBuffers(&MenuBuffers)
|
||||||
|
|
||||||
bool
|
bool
|
||||||
VideoIsPrivate(char *VideoID)
|
VideoIsPrivate(string VODPlatform, char *VideoID)
|
||||||
{
|
{
|
||||||
|
// TODO(matt): Redo this to only return once, at the end
|
||||||
|
|
||||||
// NOTE(matt): Currently only supports YouTube
|
// NOTE(matt): Currently only supports YouTube
|
||||||
// NOTE(matt): Stack-string
|
// NOTE(matt): Stack-string
|
||||||
char Message[128];
|
if(StringsMatch(Wrap0("youtube"), VODPlatform))
|
||||||
CopyString(Message, sizeof(Message), "%sChecking%s privacy status of: https://youtube.com/watch?v=%s", ColourStrings[CS_ONGOING], ColourStrings[CS_END], VideoID);
|
{
|
||||||
fprintf(stderr, "%s", Message);
|
char Message[128];
|
||||||
int MessageLength = StringLength(Message);
|
CopyString(Message, sizeof(Message), "%sChecking%s privacy status of: https://youtube.com/watch?v=%s", ColourStrings[CS_ONGOING], ColourStrings[CS_END], VideoID);
|
||||||
buffer VideoAPIResponse;
|
fprintf(stderr, "%s", Message);
|
||||||
ClaimBuffer(&VideoAPIResponse, BID_VIDEO_API_RESPONSE, Kilobytes(1));
|
int MessageLength = StringLength(Message);
|
||||||
|
buffer VideoAPIResponse;
|
||||||
|
ClaimBuffer(&VideoAPIResponse, BID_VIDEO_API_RESPONSE, Kilobytes(1));
|
||||||
|
|
||||||
CURL *curl = curl_easy_init();
|
CURL *curl = curl_easy_init();
|
||||||
if(curl) {
|
if(curl) {
|
||||||
LastPrivacyCheck = time(0);
|
LastPrivacyCheck = time(0);
|
||||||
#define APIKey "AIzaSyAdV2U8ivPk8PHMaPMId0gynksw_gdzr9k"
|
#define APIKey "AIzaSyAdV2U8ivPk8PHMaPMId0gynksw_gdzr9k"
|
||||||
// NOTE(matt): Stack-string
|
// NOTE(matt): Stack-string
|
||||||
char URL[1024] = {0};
|
char URL[1024] = {0};
|
||||||
CopyString(URL, sizeof(URL), "https://www.googleapis.com/youtube/v3/videos?key=%s&part=status&id=%s", APIKey, VideoID);
|
CopyString(URL, sizeof(URL), "https://www.googleapis.com/youtube/v3/videos?key=%s&part=status&id=%s", APIKey, VideoID);
|
||||||
CURLcode CurlReturnCode;
|
CURLcode CurlReturnCode;
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &VideoAPIResponse.Ptr);
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &VideoAPIResponse.Ptr);
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlIntoBuffer);
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlIntoBuffer);
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, URL);
|
curl_easy_setopt(curl, CURLOPT_URL, URL);
|
||||||
if((CurlReturnCode = curl_easy_perform(curl)))
|
// TODO(matt): Handle the case when our API quota has depleted / expired
|
||||||
{
|
if((CurlReturnCode = curl_easy_perform(curl)))
|
||||||
fprintf(stderr, "%s\n", curl_easy_strerror(CurlReturnCode));
|
{
|
||||||
}
|
fprintf(stderr, "%s\n", curl_easy_strerror(CurlReturnCode));
|
||||||
curl_easy_cleanup(curl);
|
}
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
|
||||||
VideoAPIResponse.Ptr = VideoAPIResponse.Location;
|
VideoAPIResponse.Ptr = VideoAPIResponse.Location;
|
||||||
// TODO(matt): Parse this JSON
|
// TODO(matt): Parse this JSON
|
||||||
SeekBufferForString(&VideoAPIResponse, "{", C_SEEK_FORWARDS, C_SEEK_AFTER);
|
SeekBufferForString(&VideoAPIResponse, "{", C_SEEK_FORWARDS, C_SEEK_AFTER);
|
||||||
SeekBufferForString(&VideoAPIResponse, "\"totalResults\": ", C_SEEK_FORWARDS, C_SEEK_AFTER);
|
SeekBufferForString(&VideoAPIResponse, "\"totalResults\": ", C_SEEK_FORWARDS, C_SEEK_AFTER);
|
||||||
if(*VideoAPIResponse.Ptr == '0')
|
if(*VideoAPIResponse.Ptr == '0')
|
||||||
{
|
{
|
||||||
DeclaimBuffer(&VideoAPIResponse);
|
DeclaimBuffer(&VideoAPIResponse);
|
||||||
// printf("Private video: https://youtube.com/watch?v=%s\n", VideoID);
|
// printf("Private video: https://youtube.com/watch?v=%s\n", VideoID);
|
||||||
ClearTerminalRow(MessageLength);
|
ClearTerminalRow(MessageLength);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
SeekBufferForString(&VideoAPIResponse, "{", C_SEEK_FORWARDS, C_SEEK_AFTER);
|
|
||||||
SeekBufferForString(&VideoAPIResponse, "\"privacyStatus\": \"", C_SEEK_FORWARDS, C_SEEK_AFTER);
|
VideoAPIResponse.Ptr = VideoAPIResponse.Location;
|
||||||
// NOTE(matt): Stack-string
|
SeekBufferForString(&VideoAPIResponse, "{", C_SEEK_FORWARDS, C_SEEK_AFTER);
|
||||||
char Status[16];
|
SeekBufferForString(&VideoAPIResponse, "\"privacyStatus\": \"", C_SEEK_FORWARDS, C_SEEK_AFTER);
|
||||||
CopyStringNoFormatT(Status, sizeof(Status), VideoAPIResponse.Ptr, '\"');
|
// NOTE(matt): Stack-string
|
||||||
if(!StringsDiffer0(Status, "public"))
|
char Status[16];
|
||||||
{
|
CopyStringNoFormatT(Status, sizeof(Status), VideoAPIResponse.Ptr, '\"');
|
||||||
DeclaimBuffer(&VideoAPIResponse);
|
if(!StringsDiffer0(Status, "public"))
|
||||||
ClearTerminalRow(MessageLength);
|
{
|
||||||
return FALSE;
|
DeclaimBuffer(&VideoAPIResponse);
|
||||||
|
ClearTerminalRow(MessageLength);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
DeclaimBuffer(&VideoAPIResponse);
|
||||||
|
// printf("Unlisted video: https://youtube.com/watch?v=%s\n", VideoID);
|
||||||
|
ClearTerminalRow(MessageLength);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
DeclaimBuffer(&VideoAPIResponse);
|
|
||||||
// printf("Unlisted video: https://youtube.com/watch?v=%s\n", VideoID);
|
|
||||||
ClearTerminalRow(MessageLength);
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
speaker *
|
speaker *
|
||||||
|
@ -9210,7 +9253,7 @@ FreeReferences(_memory_book(ref_info) *References)
|
||||||
rc
|
rc
|
||||||
ProcessTimecode(buffers *CollationBuffers, neighbourhood *N, string Filepath, memory_book *Strings,
|
ProcessTimecode(buffers *CollationBuffers, neighbourhood *N, string Filepath, memory_book *Strings,
|
||||||
menu_buffers *MenuBuffers, index_buffers *IndexBuffers, player_buffers *PlayerBuffers,
|
menu_buffers *MenuBuffers, index_buffers *IndexBuffers, player_buffers *PlayerBuffers,
|
||||||
medium *DefaultMedium, speakers *Speakers, string Author,
|
medium *DefaultMedium, speakers *Speakers, person *Host, string Author,
|
||||||
_memory_book(ref_info) *ReferencesArray,
|
_memory_book(ref_info) *ReferencesArray,
|
||||||
bool *HasQuoteMenu, bool *HasReferenceMenu, bool *HasFilterMenu, bool *RequiresCineraJS,
|
bool *HasQuoteMenu, bool *HasReferenceMenu, bool *HasFilterMenu, bool *RequiresCineraJS,
|
||||||
int *QuoteIdentifier, int *RefIdentifier,
|
int *QuoteIdentifier, int *RefIdentifier,
|
||||||
|
@ -9247,7 +9290,7 @@ ProcessTimecode(buffers *CollationBuffers, neighbourhood *N, string Filepath, me
|
||||||
CopyStringToBuffer(&IndexBuffers->Class,
|
CopyStringToBuffer(&IndexBuffers->Class,
|
||||||
" class=\"marker");
|
" class=\"marker");
|
||||||
|
|
||||||
speaker *Speaker = GetSpeaker(&Speakers->Speakers, Anno->author ? Wrap0(Anno->author) : CurrentProject->StreamUsername.Length > 0 ? CurrentProject->StreamUsername : CurrentProject->Owner->ID);
|
speaker *Speaker = GetSpeaker(&Speakers->Speakers, Anno->author ? Wrap0(Anno->author) : CurrentProject->StreamUsername.Length > 0 ? CurrentProject->StreamUsername : Host->ID);
|
||||||
if(!IsCategorisedAFK(Anno))
|
if(!IsCategorisedAFK(Anno))
|
||||||
{
|
{
|
||||||
if(Speakers->Speakers.ItemCount > 1 && Speaker && !IsCategorisedAuthored(Anno))
|
if(Speakers->Speakers.ItemCount > 1 && Speaker && !IsCategorisedAuthored(Anno))
|
||||||
|
@ -9617,12 +9660,46 @@ ProcessTimecode(buffers *CollationBuffers, neighbourhood *N, string Filepath, me
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
GetNumberFromHMMLBaseFilename(string ProjectID, string HMMLBaseFilename)
|
||||||
|
{
|
||||||
|
// TODO(matt): That rigorous notion of numbering, goddammit?!
|
||||||
|
string Result = {};
|
||||||
|
if(HMMLBaseFilename.Length > ProjectID.Length)
|
||||||
|
{
|
||||||
|
Result = TrimString(HMMLBaseFilename, ProjectID.Length, 0);
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
rc
|
rc
|
||||||
HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseFilename, neighbourhood *N)
|
HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseFilename, neighbourhood *N)
|
||||||
{
|
{
|
||||||
MEM_TEST_TOP("HMMLToBuffers");
|
MEM_TEST_TOP("HMMLToBuffers");
|
||||||
rc Result = RC_SUCCESS;
|
rc Result = RC_SUCCESS;
|
||||||
|
|
||||||
|
RewindCollationBuffers(CollationBuffers);
|
||||||
|
Clear(CollationBuffers->Custom0, sizeof(CollationBuffers->Custom0));
|
||||||
|
Clear(CollationBuffers->Custom1, sizeof(CollationBuffers->Custom1));
|
||||||
|
Clear(CollationBuffers->Custom2, sizeof(CollationBuffers->Custom2));
|
||||||
|
Clear(CollationBuffers->Custom3, sizeof(CollationBuffers->Custom3));
|
||||||
|
Clear(CollationBuffers->Custom4, sizeof(CollationBuffers->Custom4));
|
||||||
|
Clear(CollationBuffers->Custom5, sizeof(CollationBuffers->Custom5));
|
||||||
|
Clear(CollationBuffers->Custom6, sizeof(CollationBuffers->Custom6));
|
||||||
|
Clear(CollationBuffers->Custom7, sizeof(CollationBuffers->Custom7));
|
||||||
|
Clear(CollationBuffers->Custom8, sizeof(CollationBuffers->Custom8));
|
||||||
|
Clear(CollationBuffers->Custom9, sizeof(CollationBuffers->Custom9));
|
||||||
|
Clear(CollationBuffers->Custom10, sizeof(CollationBuffers->Custom10));
|
||||||
|
Clear(CollationBuffers->Custom11, sizeof(CollationBuffers->Custom11));
|
||||||
|
Clear(CollationBuffers->Custom12, sizeof(CollationBuffers->Custom12));
|
||||||
|
Clear(CollationBuffers->Custom13, sizeof(CollationBuffers->Custom13));
|
||||||
|
Clear(CollationBuffers->Custom14, sizeof(CollationBuffers->Custom14));
|
||||||
|
Clear(CollationBuffers->Custom15, sizeof(CollationBuffers->Custom15));
|
||||||
|
Clear(CollationBuffers->Title, sizeof(CollationBuffers->Title));
|
||||||
|
Clear(CollationBuffers->URLPlayer, sizeof(CollationBuffers->URLPlayer));
|
||||||
|
Clear(CollationBuffers->URLSearch, sizeof(CollationBuffers->URLSearch));
|
||||||
|
Clear(CollationBuffers->VODPlatform, sizeof(CollationBuffers->VODPlatform));
|
||||||
|
|
||||||
// TODO(matt): A "MakeString0OnStack()" sort of function?
|
// TODO(matt): A "MakeString0OnStack()" sort of function?
|
||||||
// NOTE(matt): Stack-string
|
// NOTE(matt): Stack-string
|
||||||
int NullTerminationBytes = 1;
|
int NullTerminationBytes = 1;
|
||||||
|
@ -9656,30 +9733,11 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF
|
||||||
// NOTE(matt): WorkingThis.Size > 0 means that this entry was previously processed as non-private. Would we rather
|
// NOTE(matt): WorkingThis.Size > 0 means that this entry was previously processed as non-private. Would we rather
|
||||||
// reregister such an entry as newly private? This test lets us avoid calling VideoIsPrivate() for all
|
// reregister such an entry as newly private? This test lets us avoid calling VideoIsPrivate() for all
|
||||||
// entries, on every cinera invocation, when !CurrentProject->IgnorePrivacy
|
// entries, on every cinera invocation, when !CurrentProject->IgnorePrivacy
|
||||||
if(N->WorkingThis.Size > 0 || CurrentProject->IgnorePrivacy || !VideoIsPrivate(HMML.metadata.id))
|
|
||||||
{
|
|
||||||
RewindCollationBuffers(CollationBuffers);
|
|
||||||
Clear(CollationBuffers->Custom0, sizeof(CollationBuffers->Custom0));
|
|
||||||
Clear(CollationBuffers->Custom1, sizeof(CollationBuffers->Custom1));
|
|
||||||
Clear(CollationBuffers->Custom2, sizeof(CollationBuffers->Custom2));
|
|
||||||
Clear(CollationBuffers->Custom3, sizeof(CollationBuffers->Custom3));
|
|
||||||
Clear(CollationBuffers->Custom4, sizeof(CollationBuffers->Custom4));
|
|
||||||
Clear(CollationBuffers->Custom5, sizeof(CollationBuffers->Custom5));
|
|
||||||
Clear(CollationBuffers->Custom6, sizeof(CollationBuffers->Custom6));
|
|
||||||
Clear(CollationBuffers->Custom7, sizeof(CollationBuffers->Custom7));
|
|
||||||
Clear(CollationBuffers->Custom8, sizeof(CollationBuffers->Custom8));
|
|
||||||
Clear(CollationBuffers->Custom9, sizeof(CollationBuffers->Custom9));
|
|
||||||
Clear(CollationBuffers->Custom10, sizeof(CollationBuffers->Custom10));
|
|
||||||
Clear(CollationBuffers->Custom11, sizeof(CollationBuffers->Custom11));
|
|
||||||
Clear(CollationBuffers->Custom12, sizeof(CollationBuffers->Custom12));
|
|
||||||
Clear(CollationBuffers->Custom13, sizeof(CollationBuffers->Custom13));
|
|
||||||
Clear(CollationBuffers->Custom14, sizeof(CollationBuffers->Custom14));
|
|
||||||
Clear(CollationBuffers->Custom15, sizeof(CollationBuffers->Custom15));
|
|
||||||
Clear(CollationBuffers->Title, sizeof(CollationBuffers->Title));
|
|
||||||
Clear(CollationBuffers->URLPlayer, sizeof(CollationBuffers->URLPlayer));
|
|
||||||
Clear(CollationBuffers->URLSearch, sizeof(CollationBuffers->URLSearch));
|
|
||||||
Clear(CollationBuffers->VODPlatform, sizeof(CollationBuffers->VODPlatform));
|
|
||||||
|
|
||||||
|
if(N->WorkingThis.Size > 0 || CurrentProject->IgnorePrivacy || !VideoIsPrivate(CurrentProject->VODPlatform, HMML.metadata.id))
|
||||||
|
{
|
||||||
|
// TODO(matt): Do a catch-all function that checks for missing info at the head, such as everything from here
|
||||||
|
// to the loop and additionally an indexer
|
||||||
if(BaseFilename.Length > MAX_BASE_FILENAME_LENGTH)
|
if(BaseFilename.Length > MAX_BASE_FILENAME_LENGTH)
|
||||||
{
|
{
|
||||||
IndexingErrorSizing(&FilepathL, 0, "Base filename", BaseFilename, MAX_BASE_FILENAME_LENGTH);
|
IndexingErrorSizing(&FilepathL, 0, "Base filename", BaseFilename, MAX_BASE_FILENAME_LENGTH);
|
||||||
|
@ -9702,15 +9760,24 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF
|
||||||
Title = Wrap0(HMML.metadata.title);
|
Title = Wrap0(HMML.metadata.title);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!HMML.metadata.member)
|
person *Host = CurrentProject->Owner;
|
||||||
|
if(HMML.metadata.member)
|
||||||
{
|
{
|
||||||
IndexingError(&FilepathL, 0, S_ERROR, "The [video] node lacks a \"member\"", 0);
|
Host = GetPersonFromConfig(Wrap0(HMML.metadata.member));
|
||||||
Result = RC_ERROR_HMML;
|
if(!Host && CurrentProject->Owner)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Falling back to the owner set in the config: ");
|
||||||
|
PrintStringCN(CS_MAGENTA_BOLD, CurrentProject->Owner->ID, FALSE, TRUE);
|
||||||
|
Host = CurrentProject->Owner;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if(!GetPersonFromConfig(Wrap0(HMML.metadata.member)))
|
|
||||||
|
if(!Host)
|
||||||
{
|
{
|
||||||
ErrorCredentials(FilepathL, Wrap0(HMML.metadata.member), R_HOST);
|
IndexingError(&FilepathL, 0, S_ERROR, "No known owner set in the config, or member in the [video] node", 0);
|
||||||
Result = RC_ERROR_HMML;
|
Result = RC_ERROR_HMML;
|
||||||
|
//ErrorCredentials(FilepathL, Wrap0(HMML.metadata.member), R_HOST);
|
||||||
|
//Result = RC_ERROR_HMML;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!HMML.metadata.id)
|
if(!HMML.metadata.id)
|
||||||
|
@ -9928,14 +9995,14 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF
|
||||||
" <div class=\"markers\">\n");
|
" <div class=\"markers\">\n");
|
||||||
|
|
||||||
bool RequiresCineraJS = FALSE;
|
bool RequiresCineraJS = FALSE;
|
||||||
Result = BuildCredits(FilepathL, &MenuBuffers.Credits, &HMML.metadata, &Speakers, &RequiresCineraJS);
|
Result = BuildCredits(FilepathL, &MenuBuffers.Credits, &HMML.metadata, Host, &Speakers, &RequiresCineraJS);
|
||||||
if(Result == RC_SUCCESS)
|
if(Result == RC_SUCCESS)
|
||||||
{
|
{
|
||||||
CopyStringToBuffer(&CollationBuffers->SearchEntry, "name: \"");
|
CopyStringToBuffer(&CollationBuffers->SearchEntry, "location: \"%.*s\"\n", (int)OutputLocation.Length, OutputLocation.Base);
|
||||||
CopyStringToBuffer(&CollationBuffers->SearchEntry, "%.*s", (int)OutputLocation.Length, OutputLocation.Base);
|
string Number = GetNumberFromHMMLBaseFilename(Wrap0i(N->Project->ID, sizeof(N->Project->ID)), BaseFilename);
|
||||||
|
CopyStringToBuffer(&CollationBuffers->SearchEntry, "number: \"%.*s\"\n", (int)Number.Length, Number.Base);
|
||||||
|
|
||||||
CopyStringToBuffer(&CollationBuffers->SearchEntry, "\"\n"
|
CopyStringToBuffer(&CollationBuffers->SearchEntry, "title: \"");
|
||||||
"title: \"");
|
|
||||||
CopyStringToBufferNoFormat(&CollationBuffers->SearchEntry, Wrap0(HMML.metadata.title));
|
CopyStringToBufferNoFormat(&CollationBuffers->SearchEntry, Wrap0(HMML.metadata.title));
|
||||||
CopyStringToBuffer(&CollationBuffers->SearchEntry, "\"\n"
|
CopyStringToBuffer(&CollationBuffers->SearchEntry, "\"\n"
|
||||||
"markers:\n");
|
"markers:\n");
|
||||||
|
@ -9964,12 +10031,12 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF
|
||||||
if(Anno->quote.author) { Author = Wrap0(Anno->quote.author); }
|
if(Anno->quote.author) { Author = Wrap0(Anno->quote.author); }
|
||||||
else if(HMML.metadata.stream_username) { Author = Wrap0(HMML.metadata.stream_username); }
|
else if(HMML.metadata.stream_username) { Author = Wrap0(HMML.metadata.stream_username); }
|
||||||
else if(CurrentProject->StreamUsername.Length > 0) { Author = CurrentProject->StreamUsername; }
|
else if(CurrentProject->StreamUsername.Length > 0) { Author = CurrentProject->StreamUsername; }
|
||||||
else { Author = CurrentProject->Owner->ID; }
|
else { Author = Host->ID; }
|
||||||
|
|
||||||
/* */ MEM_TEST_MID("HMMLToBuffers");
|
/* */ MEM_TEST_MID("HMMLToBuffers");
|
||||||
/* +MEM */ Result = ProcessTimecode(CollationBuffers, N, Wrap0(Filepath), &Strings,
|
/* +MEM */ Result = ProcessTimecode(CollationBuffers, N, Wrap0(Filepath), &Strings,
|
||||||
/* */ &MenuBuffers, &IndexBuffers, &PlayerBuffers,
|
/* */ &MenuBuffers, &IndexBuffers, &PlayerBuffers,
|
||||||
/* */ DefaultMedium, &Speakers, Author, &ReferencesArray,
|
/* */ DefaultMedium, &Speakers, Host, Author, &ReferencesArray,
|
||||||
/* */ &HasQuoteMenu, &HasReferenceMenu, &HasFilterMenu, &RequiresCineraJS,
|
/* */ &HasQuoteMenu, &HasReferenceMenu, &HasFilterMenu, &RequiresCineraJS,
|
||||||
/* */ &QuoteIdentifier, &RefIdentifier,
|
/* */ &QuoteIdentifier, &RefIdentifier,
|
||||||
/* */ &Topics, &Media,
|
/* */ &Topics, &Media,
|
||||||
|
@ -10167,7 +10234,7 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF
|
||||||
}
|
}
|
||||||
|
|
||||||
CopyStringToBuffer(&PlayerBuffers.Menus,
|
CopyStringToBuffer(&PlayerBuffers.Menus,
|
||||||
" <div class=\"help\">\n"
|
" <div class=\"cineraHelp\">\n"
|
||||||
" <span>?</span>\n"
|
" <span>?</span>\n"
|
||||||
" <div class=\"help_container\">\n"
|
" <div class=\"help_container\">\n"
|
||||||
" <span class=\"help_key\">?</span><h1>Keyboard Navigation</h1>\n"
|
" <span class=\"help_key\">?</span><h1>Keyboard Navigation</h1>\n"
|
||||||
|
@ -10347,7 +10414,8 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF
|
||||||
|
|
||||||
CopyStringToBuffer(&CollationBuffers->IncludesPlayer,
|
CopyStringToBuffer(&CollationBuffers->IncludesPlayer,
|
||||||
"<meta charset=\"UTF-8\">\n"
|
"<meta charset=\"UTF-8\">\n"
|
||||||
" <meta name=\"generator\" content=\"Cinera %d.%d.%d\">\n",
|
" <meta name=\"generator\" content=\"Cinera %d.%d.%d\">\n"
|
||||||
|
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n",
|
||||||
CINERA_APP_VERSION.Major,
|
CINERA_APP_VERSION.Major,
|
||||||
CINERA_APP_VERSION.Minor,
|
CINERA_APP_VERSION.Minor,
|
||||||
CINERA_APP_VERSION.Patch);
|
CINERA_APP_VERSION.Patch);
|
||||||
|
@ -10362,7 +10430,7 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF
|
||||||
for(int i = 0; i < Topics.ItemCount; ++i)
|
for(int i = 0; i < Topics.ItemCount; ++i)
|
||||||
{
|
{
|
||||||
category_info *This = GetPlaceInBook(&Topics, i);
|
category_info *This = GetPlaceInBook(&Topics, i);
|
||||||
if(StringsMatch(This->Marker, Wrap0("nullTopic")))
|
if(!StringsMatch(This->Marker, Wrap0("nullTopic")))
|
||||||
{
|
{
|
||||||
CopyStringToBuffer(&CollationBuffers->IncludesPlayer, "%.*s, ", (int)This->Marker.Length, This->Marker.Base);
|
CopyStringToBuffer(&CollationBuffers->IncludesPlayer, "%.*s, ", (int)This->Marker.Length, This->Marker.Base);
|
||||||
}
|
}
|
||||||
|
@ -10477,7 +10545,7 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF
|
||||||
CopyStringToBuffer(&PlayerBuffers.Script,
|
CopyStringToBuffer(&PlayerBuffers.Script,
|
||||||
"\"></script>");
|
"\"></script>");
|
||||||
|
|
||||||
CopyStringToBuffer(&CollationBuffers->Player, "<div>\n"
|
CopyStringToBuffer(&CollationBuffers->Player, "<div class=\"cinera\">\n"
|
||||||
" ");
|
" ");
|
||||||
CopyLandmarkedBuffer(&CollationBuffers->Player, &PlayerBuffers.Menus, 0, PAGE_PLAYER);
|
CopyLandmarkedBuffer(&CollationBuffers->Player, &PlayerBuffers.Menus, 0, PAGE_PLAYER);
|
||||||
CopyStringToBuffer(&CollationBuffers->Player, "\n"
|
CopyStringToBuffer(&CollationBuffers->Player, "\n"
|
||||||
|
@ -10555,12 +10623,16 @@ typedef struct
|
||||||
html_element HTMLElements[] =
|
html_element HTMLElements[] =
|
||||||
{
|
{
|
||||||
{ "a", FALSE },
|
{ "a", FALSE },
|
||||||
|
{ "br", TRUE },
|
||||||
{ "div", FALSE },
|
{ "div", FALSE },
|
||||||
|
{ "h1", FALSE },
|
||||||
|
{ "h2", FALSE },
|
||||||
{ "img", TRUE },
|
{ "img", TRUE },
|
||||||
{ "input", TRUE },
|
{ "input", TRUE },
|
||||||
{ "label", FALSE },
|
{ "label", FALSE },
|
||||||
{ "li", FALSE },
|
{ "li", FALSE },
|
||||||
{ "nav", FALSE },
|
{ "nav", FALSE },
|
||||||
|
{ "p", FALSE },
|
||||||
{ "script", FALSE },
|
{ "script", FALSE },
|
||||||
{ "span", FALSE },
|
{ "span", FALSE },
|
||||||
{ "ul", FALSE },
|
{ "ul", FALSE },
|
||||||
|
@ -10569,12 +10641,16 @@ html_element HTMLElements[] =
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
NODE_A,
|
NODE_A,
|
||||||
|
NODE_BR,
|
||||||
NODE_DIV,
|
NODE_DIV,
|
||||||
|
NODE_H1,
|
||||||
|
NODE_H2,
|
||||||
NODE_IMG,
|
NODE_IMG,
|
||||||
NODE_INPUT,
|
NODE_INPUT,
|
||||||
NODE_LABEL,
|
NODE_LABEL,
|
||||||
NODE_LI,
|
NODE_LI,
|
||||||
NODE_NAV,
|
NODE_NAV,
|
||||||
|
NODE_P,
|
||||||
NODE_SCRIPT,
|
NODE_SCRIPT,
|
||||||
NODE_SPAN,
|
NODE_SPAN,
|
||||||
NODE_UL,
|
NODE_UL,
|
||||||
|
@ -11619,10 +11695,9 @@ InsertIntoDB(neighbourhood *N, buffers *CollationBuffers, template *BespokeTempl
|
||||||
CycleFile(&DB.File);
|
CycleFile(&DB.File);
|
||||||
}
|
}
|
||||||
|
|
||||||
string EntryTitle = Wrap0(CollationBuffers->Title);
|
|
||||||
|
|
||||||
if(!VideoIsPrivate || !RecheckingPrivacy)
|
if(!VideoIsPrivate || !RecheckingPrivacy)
|
||||||
{
|
{
|
||||||
|
string EntryTitle = Wrap0(CollationBuffers->Title);
|
||||||
LogEdit(EditType, CurrentProject->Lineage, BaseFilename, &EntryTitle, VideoIsPrivate);
|
LogEdit(EditType, CurrentProject->Lineage, BaseFilename, &EntryTitle, VideoIsPrivate);
|
||||||
PrintEdit(EditType, CurrentProject->Lineage, BaseFilename, &EntryTitle, VideoIsPrivate, TRUE);
|
PrintEdit(EditType, CurrentProject->Lineage, BaseFilename, &EntryTitle, VideoIsPrivate, TRUE);
|
||||||
}
|
}
|
||||||
|
@ -12825,7 +12900,7 @@ GenerateFilterOfProjectAndChildren(buffer *Filter, db_header_project *StoredP, p
|
||||||
if(!TopLevel || StoredP->EntryCount > 0)
|
if(!TopLevel || StoredP->EntryCount > 0)
|
||||||
{
|
{
|
||||||
OpenNodeNewLine(Filter, &Filter->IndentLevel, NODE_DIV, 0);
|
OpenNodeNewLine(Filter, &Filter->IndentLevel, NODE_DIV, 0);
|
||||||
AppendStringToBuffer(Filter, Wrap0(" class=\"cineraFilterProject\" data-baseURL=\""));
|
AppendStringToBuffer(Filter, Wrap0(" class=\"cineraMenuItem cineraFilterProject\" data-baseURL=\""));
|
||||||
AppendStringToBuffer(Filter, P->BaseURL);
|
AppendStringToBuffer(Filter, P->BaseURL);
|
||||||
AppendStringToBuffer(Filter, Wrap0("\" data-searchLocation=\""));
|
AppendStringToBuffer(Filter, Wrap0("\" data-searchLocation=\""));
|
||||||
AppendStringToBuffer(Filter, P->SearchLocation);
|
AppendStringToBuffer(Filter, P->SearchLocation);
|
||||||
|
@ -12872,6 +12947,8 @@ GenerateIndexOfProjectAndChildren(buffer *Index, db_header_project *StoredP, pro
|
||||||
AppendStringToBuffer(Index, P->SearchLocation);
|
AppendStringToBuffer(Index, P->SearchLocation);
|
||||||
AppendStringToBuffer(Index, Wrap0("\" data-playerLocation=\""));
|
AppendStringToBuffer(Index, Wrap0("\" data-playerLocation=\""));
|
||||||
AppendStringToBuffer(Index, P->PlayerLocation);
|
AppendStringToBuffer(Index, P->PlayerLocation);
|
||||||
|
AppendStringToBuffer(Index, Wrap0("\" data-unit=\""));
|
||||||
|
AppendStringToBuffer(Index, P->Unit);
|
||||||
AppendStringToBuffer(Index, Wrap0("\">"));
|
AppendStringToBuffer(Index, Wrap0("\">"));
|
||||||
|
|
||||||
OpenNodeNewLine(Index, &Index->IndentLevel, NODE_DIV, 0);
|
OpenNodeNewLine(Index, &Index->IndentLevel, NODE_DIV, 0);
|
||||||
|
@ -12905,27 +12982,28 @@ GenerateIndexOfProjectAndChildren(buffer *Index, db_header_project *StoredP, pro
|
||||||
|
|
||||||
if(*StoredP->Unit)
|
if(*StoredP->Unit)
|
||||||
{
|
{
|
||||||
// TODO(matt): That rigorous notion of numbering, goddammit?!
|
string NumberL = GetNumberFromHMMLBaseFilename(P->ID, Wrap0i(Entry->HMMLBaseFilename, sizeof(Entry->HMMLBaseFilename)));
|
||||||
string NumberL = TrimString(Wrap0i(Entry->HMMLBaseFilename, sizeof(Entry->HMMLBaseFilename)),
|
if(NumberL.Length > 0)
|
||||||
P->ID.Length, 0);
|
|
||||||
char Number[NumberL.Length + 1];
|
|
||||||
ClearCopyStringNoFormat(Number, sizeof(Number), NumberL);
|
|
||||||
|
|
||||||
if(CurrentProject->NumberingScheme == NS_LINEAR)
|
|
||||||
{
|
{
|
||||||
for(int i = 0; Number[i]; ++i)
|
char Number[NumberL.Length + 1];
|
||||||
|
ClearCopyStringNoFormat(Number, sizeof(Number), NumberL);
|
||||||
|
|
||||||
|
if(CurrentProject->NumberingScheme == NS_LINEAR)
|
||||||
{
|
{
|
||||||
if(Number[i] == '_')
|
for(int i = 0; Number[i]; ++i)
|
||||||
{
|
{
|
||||||
Number[i] = '.';
|
if(Number[i] == '_')
|
||||||
|
{
|
||||||
|
Number[i] = '.';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
AppendStringToBuffer(Index, P->Unit);
|
AppendStringToBuffer(Index, P->Unit);
|
||||||
AppendStringToBuffer(Index, Wrap0(" "));
|
AppendStringToBuffer(Index, Wrap0(" "));
|
||||||
AppendStringToBuffer(Index, Wrap0i(Number, sizeof(Number)));
|
AppendStringToBuffer(Index, Wrap0i(Number, sizeof(Number)));
|
||||||
AppendStringToBuffer(Index, Wrap0(": "));
|
AppendStringToBuffer(Index, Wrap0(": "));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// HERE
|
// HERE
|
||||||
|
@ -13097,6 +13175,45 @@ GenerateThemeLinks(buffer *IncludesSearch, project *P)
|
||||||
FreeBook(&UniqueThemes);
|
FreeBook(&UniqueThemes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AppendHelpKeyToBuffer(buffer *B, uint32_t *IndentationLevel, string Key, bool Available)
|
||||||
|
{
|
||||||
|
OpenNodeNewLine(B, IndentationLevel, NODE_SPAN, 0);
|
||||||
|
AppendStringToBuffer(B, Wrap0(" class=\"help_key"));
|
||||||
|
if(!Available)
|
||||||
|
{
|
||||||
|
AppendStringToBuffer(B, Wrap0(" unavailable"));
|
||||||
|
}
|
||||||
|
AppendStringToBuffer(B, Wrap0("\">"));
|
||||||
|
AppendStringToBuffer(B, Key);
|
||||||
|
CloseNode(B, IndentationLevel, NODE_SPAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AppendHelpKeyToBufferNewLine(buffer *B, uint32_t *IndentationLevel, string Key, bool Available)
|
||||||
|
{
|
||||||
|
AppendHelpKeyToBuffer(B, IndentationLevel, Key, Available);
|
||||||
|
OpenNodeC(B, IndentationLevel, NODE_BR, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AppendHelpKeyAndTextToBuffer(buffer *B, uint32_t *IndentationLevel, string Key, string Text, bool Available)
|
||||||
|
{
|
||||||
|
AppendHelpKeyToBuffer(B, IndentationLevel, Key, Available);
|
||||||
|
AppendStringToBuffer(B, Wrap0(" "));
|
||||||
|
|
||||||
|
OpenNodeNewLine(B, IndentationLevel, NODE_SPAN, 0);
|
||||||
|
AppendStringToBuffer(B, Wrap0(" class=\"help_text"));
|
||||||
|
if(!Available)
|
||||||
|
{
|
||||||
|
AppendStringToBuffer(B, Wrap0(" unavailable"));
|
||||||
|
}
|
||||||
|
AppendStringToBuffer(B, Wrap0("\">"));
|
||||||
|
AppendStringToBuffer(B, Text);
|
||||||
|
CloseNode(B, IndentationLevel, NODE_SPAN);
|
||||||
|
AppendStringToBuffer(B, Wrap0("\n"));
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
SearchToBuffer(buffers *CollationBuffers, db_header_project *StoredP, project *P, string Theme, bool RequiresCineraJS) // NOTE(matt): This guy malloc's CollationBuffers->Search
|
SearchToBuffer(buffers *CollationBuffers, db_header_project *StoredP, project *P, string Theme, bool RequiresCineraJS) // NOTE(matt): This guy malloc's CollationBuffers->Search
|
||||||
{
|
{
|
||||||
|
@ -13134,6 +13251,7 @@ SearchToBuffer(buffers *CollationBuffers, db_header_project *StoredP, project *P
|
||||||
CopyStringToBuffer(&CollationBuffers->IncludesSearch,
|
CopyStringToBuffer(&CollationBuffers->IncludesSearch,
|
||||||
"<meta charset=\"UTF-8\">\n"
|
"<meta charset=\"UTF-8\">\n"
|
||||||
" <meta name=\"generator\" content=\"Cinera %d.%d.%d\">\n"
|
" <meta name=\"generator\" content=\"Cinera %d.%d.%d\">\n"
|
||||||
|
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n"
|
||||||
"\n"
|
"\n"
|
||||||
" <link rel=\"stylesheet\" type=\"text/css\" href=\"%.*s",
|
" <link rel=\"stylesheet\" type=\"text/css\" href=\"%.*s",
|
||||||
CINERA_APP_VERSION.Major,
|
CINERA_APP_VERSION.Major,
|
||||||
|
@ -13159,38 +13277,54 @@ SearchToBuffer(buffers *CollationBuffers, db_header_project *StoredP, project *P
|
||||||
CopyStringToBuffer(&CollationBuffers->IncludesSearch,
|
CopyStringToBuffer(&CollationBuffers->IncludesSearch,
|
||||||
"\">");
|
"\">");
|
||||||
|
|
||||||
asset *JSSearch = GetAsset(Wrap0(BuiltinAssets[ASSET_JS_SEARCH].Filename), ASSET_JS);
|
|
||||||
ConstructResolvedAssetURL(&URL, JSSearch, PAGE_SEARCH);
|
|
||||||
|
|
||||||
uint32_t IndentationLevel = 1;
|
uint32_t IndentationLevel = 1;
|
||||||
++IndentationLevel;
|
++IndentationLevel;
|
||||||
|
|
||||||
buffer Script = {};
|
|
||||||
Script.ID = BID_SCRIPT;
|
|
||||||
OpenNodeNewLine(&Script, &IndentationLevel, NODE_SCRIPT, 0);
|
|
||||||
AppendStringToBuffer(&Script, Wrap0(" type=\"text/javascript\" src=\""));
|
|
||||||
AppendStringToBuffer(&Script, Wrap0i(URL.Location, URL.Ptr - URL.Location));
|
|
||||||
DeclaimBuffer(&URL);
|
|
||||||
PushAssetLandmark(&Script, JSSearch, PAGE_SEARCH, TRUE);
|
|
||||||
AppendStringToBuffer(&Script, Wrap0("\">"));
|
|
||||||
CloseNode(&Script, &IndentationLevel, NODE_SCRIPT);
|
|
||||||
|
|
||||||
bool SearchRequired = FALSE;
|
bool SearchRequired = FALSE;
|
||||||
|
|
||||||
//IndentBuffer(&CollationBuffers->Search, ++IndentationLevel);
|
//IndentBuffer(&CollationBuffers->Search, ++IndentationLevel);
|
||||||
|
|
||||||
buffer *B = &CollationBuffers->Search;
|
buffer *B = &CollationBuffers->Search;
|
||||||
OpenNode(B, &IndentationLevel, NODE_DIV, "cineraIndexControl");
|
OpenNodeNewLine(B, &IndentationLevel, NODE_DIV, "cineraIndex");
|
||||||
AppendStringToBuffer(B, Wrap0(" class=\""));
|
AppendStringToBuffer(B, Wrap0(" class=\""));
|
||||||
AppendStringToBuffer(B, Theme);
|
AppendStringToBuffer(B, Theme);
|
||||||
AppendStringToBuffer(B, Wrap0("\">"));
|
AppendStringToBuffer(B, Wrap0("\">"));
|
||||||
|
OpenNodeC(B, &IndentationLevel, NODE_DIV, "cineraIndexControl");
|
||||||
|
|
||||||
OpenNodeCNewLine(B, &IndentationLevel, NODE_DIV, "cineraIndexSort");
|
OpenNodeNewLine(B, &IndentationLevel, NODE_DIV, 0);
|
||||||
|
AppendStringToBuffer(B, Wrap0(" class=\"cineraMenu cineraMenuTitle ViewSettings\">"));
|
||||||
|
|
||||||
|
OpenNodeCNewLine(B, &IndentationLevel, NODE_SPAN, 0);
|
||||||
|
AppendStringToBuffer(B, Wrap0("Settings"));
|
||||||
|
CloseNodeNewLine(B, &IndentationLevel, NODE_SPAN);
|
||||||
|
|
||||||
|
OpenNodeNewLine(B, &IndentationLevel, NODE_DIV, 0);
|
||||||
|
AppendStringToBuffer(B, Wrap0(" class=\"cineraMenuContainer\">"));
|
||||||
|
|
||||||
|
OpenNodeNewLine(B, &IndentationLevel, NODE_DIV, 0);
|
||||||
|
AppendStringToBuffer(B, Wrap0(" class=\"cineraMenuItem sort\">"));
|
||||||
AppendStringToBuffer(B, Wrap0("Sort: Old to New ⏶"));
|
AppendStringToBuffer(B, Wrap0("Sort: Old to New ⏶"));
|
||||||
|
|
||||||
CloseNode(B, &IndentationLevel, NODE_DIV);
|
CloseNode(B, &IndentationLevel, NODE_DIV);
|
||||||
|
|
||||||
|
OpenNodeNewLine(B, &IndentationLevel, NODE_DIV, 0);
|
||||||
|
AppendStringToBuffer(B, Wrap0(" class=\"cineraMenuItem view\">"));
|
||||||
|
AppendStringToBuffer(B, Wrap0("View: Grid"));
|
||||||
|
CloseNode(B, &IndentationLevel, NODE_DIV);
|
||||||
|
|
||||||
|
OpenNodeNewLine(B, &IndentationLevel, NODE_DIV, 0);
|
||||||
|
AppendStringToBuffer(B, Wrap0(" class=\"cineraMenuItem anim\">"));
|
||||||
|
AppendStringToBuffer(B, Wrap0("Animations: ✔"));
|
||||||
|
CloseNode(B, &IndentationLevel, NODE_DIV);
|
||||||
|
|
||||||
|
OpenNodeNewLine(B, &IndentationLevel, NODE_DIV, 0);
|
||||||
|
AppendStringToBuffer(B, Wrap0(" class=\"cineraMenuItem save\">"));
|
||||||
|
AppendStringToBuffer(B, Wrap0("Save Settings: ✔"));
|
||||||
|
CloseNode(B, &IndentationLevel, NODE_DIV);
|
||||||
|
|
||||||
|
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); // cineraMenuContainer
|
||||||
|
|
||||||
|
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); // cineraMenu ViewSettings
|
||||||
|
|
||||||
bool FilterRequired = FALSE;
|
bool FilterRequired = FALSE;
|
||||||
if(StoredP)
|
if(StoredP)
|
||||||
{
|
{
|
||||||
|
@ -13221,7 +13355,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=\"cineraIndexFilter\">"));
|
AppendStringToBuffer(B, Wrap0(" class=\"cineraMenu cineraMenuTitle IndexFilter\">"));
|
||||||
|
|
||||||
OpenNodeCNewLine(B, &IndentationLevel, NODE_SPAN, 0);
|
OpenNodeCNewLine(B, &IndentationLevel, NODE_SPAN, 0);
|
||||||
|
|
||||||
|
@ -13237,7 +13371,7 @@ SearchToBuffer(buffers *CollationBuffers, db_header_project *StoredP, project *P
|
||||||
CloseNode(B, &IndentationLevel, NODE_SPAN);
|
CloseNode(B, &IndentationLevel, NODE_SPAN);
|
||||||
|
|
||||||
OpenNodeNewLine(B, &IndentationLevel, NODE_DIV, 0);
|
OpenNodeNewLine(B, &IndentationLevel, NODE_DIV, 0);
|
||||||
AppendStringToBuffer(B, Wrap0(" class=\"filter_container\">"));
|
AppendStringToBuffer(B, Wrap0(" class=\"cineraMenuContainer\">"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(matt): What I think the rules should be are:
|
// NOTE(matt): What I think the rules should be are:
|
||||||
|
@ -13271,8 +13405,8 @@ SearchToBuffer(buffers *CollationBuffers, db_header_project *StoredP, project *P
|
||||||
{
|
{
|
||||||
AppendLandmarkedBuffer(B, &Filter, PAGE_SEARCH);
|
AppendLandmarkedBuffer(B, &Filter, PAGE_SEARCH);
|
||||||
FreeBuffer(&Filter);
|
FreeBuffer(&Filter);
|
||||||
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV);
|
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); // cineraMenuContainer
|
||||||
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV);
|
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); // cineraMenu IndexFilter
|
||||||
}
|
}
|
||||||
|
|
||||||
asset *JSCineraPre = GetAsset(Wrap0(BuiltinAssets[ASSET_JS_CINERA_PRE].Filename), ASSET_JS);
|
asset *JSCineraPre = GetAsset(Wrap0(BuiltinAssets[ASSET_JS_CINERA_PRE].Filename), ASSET_JS);
|
||||||
|
@ -13298,6 +13432,26 @@ SearchToBuffer(buffers *CollationBuffers, db_header_project *StoredP, project *P
|
||||||
"\" defer></script>");
|
"\" defer></script>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
asset *JSSearchPre = GetAsset(Wrap0(BuiltinAssets[ASSET_JS_SEARCH_PRE].Filename), ASSET_JS);
|
||||||
|
ConstructResolvedAssetURL(&URL, JSSearchPre, PAGE_SEARCH);
|
||||||
|
CopyStringToBuffer(&CollationBuffers->IncludesSearch,
|
||||||
|
"\n <script type=\"text/javascript\" src=\"%s",
|
||||||
|
URL.Location);
|
||||||
|
DeclaimBuffer(&URL);
|
||||||
|
PushAssetLandmark(&CollationBuffers->IncludesSearch, JSSearchPre, PAGE_SEARCH, 0);
|
||||||
|
CopyStringToBuffer(&CollationBuffers->IncludesSearch,
|
||||||
|
"\"></script>");
|
||||||
|
|
||||||
|
asset *JSSearchPost = GetAsset(Wrap0(BuiltinAssets[ASSET_JS_SEARCH_POST].Filename), ASSET_JS);
|
||||||
|
ConstructResolvedAssetURL(&URL, JSSearchPost, PAGE_SEARCH);
|
||||||
|
CopyStringToBuffer(&CollationBuffers->IncludesSearch,
|
||||||
|
"\n <script type=\"text/javascript\" src=\"%s",
|
||||||
|
URL.Location);
|
||||||
|
DeclaimBuffer(&URL);
|
||||||
|
PushAssetLandmark(&CollationBuffers->IncludesSearch, JSSearchPost, PAGE_SEARCH, 0);
|
||||||
|
CopyStringToBuffer(&CollationBuffers->IncludesSearch,
|
||||||
|
"\" defer></script>");
|
||||||
|
|
||||||
OpenNodeNewLine(B, &IndentationLevel, NODE_DIV, 0);
|
OpenNodeNewLine(B, &IndentationLevel, NODE_DIV, 0);
|
||||||
AppendStringToBuffer(B, Wrap0(" class=\"cineraQueryContainer\">"));
|
AppendStringToBuffer(B, Wrap0(" class=\"cineraQueryContainer\">"));
|
||||||
|
|
||||||
|
@ -13320,10 +13474,82 @@ SearchToBuffer(buffers *CollationBuffers, db_header_project *StoredP, project *P
|
||||||
IndentBuffer(B, IndentationLevel);
|
IndentBuffer(B, IndentationLevel);
|
||||||
AppendStringToBuffer(B, Wrap0("Downloading data..."));
|
AppendStringToBuffer(B, Wrap0("Downloading data..."));
|
||||||
|
|
||||||
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV);
|
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); // spinner
|
||||||
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV);
|
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); // inputContainer
|
||||||
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV);
|
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); // cineraQueryContainer
|
||||||
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV);
|
|
||||||
|
OpenNodeNewLine(B, &IndentationLevel, NODE_DIV, 0);
|
||||||
|
AppendStringToBuffer(B, Wrap0(" class=\"cineraHelp\">"));
|
||||||
|
OpenNodeCNewLine(B, &IndentationLevel, NODE_SPAN, 0);
|
||||||
|
AppendStringToBuffer(B, Wrap0("?"));
|
||||||
|
CloseNode(B, &IndentationLevel, NODE_SPAN);
|
||||||
|
|
||||||
|
OpenNodeNewLine(B, &IndentationLevel, NODE_DIV, 0);
|
||||||
|
AppendStringToBuffer(B, Wrap0(" class=\"help_container\">"));
|
||||||
|
|
||||||
|
AppendHelpKeyToBuffer(B, &IndentationLevel, Wrap0("?"), TRUE);
|
||||||
|
OpenNodeC(B, &IndentationLevel, NODE_H1, 0);
|
||||||
|
AppendStringToBuffer(B, Wrap0("Keyboard Navigation"));
|
||||||
|
CloseNode(B, &IndentationLevel, NODE_H1);
|
||||||
|
|
||||||
|
OpenNodeC(B, &IndentationLevel, NODE_H2, 0);
|
||||||
|
AppendStringToBuffer(B, Wrap0("Grid Traversal"));
|
||||||
|
CloseNode(B, &IndentationLevel, NODE_H2);
|
||||||
|
AppendHelpKeyAndTextToBuffer(B, &IndentationLevel, Wrap0("h"), Wrap0("Shift leftwards"), TRUE);
|
||||||
|
AppendHelpKeyAndTextToBuffer(B, &IndentationLevel, Wrap0("k"), Wrap0("Ascend (zoom out)"), TRUE);
|
||||||
|
AppendHelpKeyAndTextToBuffer(B, &IndentationLevel, Wrap0("l"), Wrap0("Shift rightwards"), TRUE);
|
||||||
|
|
||||||
|
OpenNodeCNewLine(B, &IndentationLevel, NODE_BR, 0);
|
||||||
|
|
||||||
|
OpenNodeNewLine(B, &IndentationLevel, NODE_DIV, 0);
|
||||||
|
AppendStringToBuffer(B, Wrap0(" class=\"help_paragraph\">"));
|
||||||
|
|
||||||
|
OpenNodeNewLine(B, &IndentationLevel, NODE_DIV, 0);
|
||||||
|
AppendStringToBuffer(B, Wrap0(" class=\"key_block\">"));
|
||||||
|
|
||||||
|
OpenNodeCNewLine(B, &IndentationLevel, NODE_DIV, 0);
|
||||||
|
AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("1"), TRUE);
|
||||||
|
AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("q"), TRUE);
|
||||||
|
AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("a"), TRUE);
|
||||||
|
AppendHelpKeyToBuffer(B, &IndentationLevel, Wrap0("z"), TRUE);
|
||||||
|
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV);
|
||||||
|
|
||||||
|
OpenNodeCNewLine(B, &IndentationLevel, NODE_DIV, 0);
|
||||||
|
AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("2"), TRUE);
|
||||||
|
AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("w"), TRUE);
|
||||||
|
AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("s"), TRUE);
|
||||||
|
AppendHelpKeyToBuffer(B, &IndentationLevel, Wrap0("x"), TRUE);
|
||||||
|
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV);
|
||||||
|
|
||||||
|
OpenNodeCNewLine(B, &IndentationLevel, NODE_DIV, 0);
|
||||||
|
AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("3"), TRUE);
|
||||||
|
AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("e"), TRUE);
|
||||||
|
AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("d"), TRUE);
|
||||||
|
AppendHelpKeyToBuffer(B, &IndentationLevel, Wrap0("c"), TRUE);
|
||||||
|
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV);
|
||||||
|
|
||||||
|
OpenNodeCNewLine(B, &IndentationLevel, NODE_DIV, 0);
|
||||||
|
AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("4"), TRUE);
|
||||||
|
AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("r"), TRUE);
|
||||||
|
AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("f"), TRUE);
|
||||||
|
AppendHelpKeyToBuffer(B, &IndentationLevel, Wrap0("v"), TRUE);
|
||||||
|
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV);
|
||||||
|
|
||||||
|
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); // key_block
|
||||||
|
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); // help_paragraph
|
||||||
|
|
||||||
|
OpenNodeC(B, &IndentationLevel, NODE_H2, 0);
|
||||||
|
AppendStringToBuffer(B, Wrap0("Settings"));
|
||||||
|
CloseNode(B, &IndentationLevel, NODE_H2);
|
||||||
|
AppendHelpKeyAndTextToBuffer(B, &IndentationLevel, Wrap0("t"), Wrap0("Toggle sort order"), TRUE);
|
||||||
|
AppendHelpKeyAndTextToBuffer(B, &IndentationLevel, Wrap0("y"), Wrap0("Toggle view style"), TRUE);
|
||||||
|
AppendHelpKeyAndTextToBuffer(B, &IndentationLevel, Wrap0("m"), Wrap0("Toggle animations"), TRUE);
|
||||||
|
|
||||||
|
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); // help_container
|
||||||
|
|
||||||
|
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); // cineraHelp
|
||||||
|
|
||||||
|
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); // cineraIndexControl
|
||||||
|
|
||||||
OpenNodeCNewLine(B, &IndentationLevel, NODE_DIV, "cineraResultsSummary");
|
OpenNodeCNewLine(B, &IndentationLevel, NODE_DIV, "cineraResultsSummary");
|
||||||
|
|
||||||
|
@ -13340,17 +13566,50 @@ SearchToBuffer(buffers *CollationBuffers, db_header_project *StoredP, project *P
|
||||||
|
|
||||||
AppendStringToBuffer(B, Wrap0("\n"));
|
AppendStringToBuffer(B, Wrap0("\n"));
|
||||||
|
|
||||||
OpenNodeCNewLine(B, &IndentationLevel, NODE_DIV, "cineraIndex");
|
OpenNodeCNewLine(B, &IndentationLevel, NODE_DIV, "cineraIndexList");
|
||||||
|
|
||||||
|
|
||||||
AppendLandmarkedBuffer(B, &Index, PAGE_SEARCH);
|
AppendLandmarkedBuffer(B, &Index, PAGE_SEARCH);
|
||||||
FreeBuffer(&Index);
|
FreeBuffer(&Index);
|
||||||
|
|
||||||
|
|
||||||
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV);
|
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); // cineraIndexList
|
||||||
|
|
||||||
AppendLandmarkedBuffer(B, &Script, PAGE_SEARCH);
|
OpenNodeNewLine(B, &IndentationLevel, NODE_DIV, 0);
|
||||||
FreeBuffer(&Script);
|
AppendStringToBuffer(B, Wrap0(" class=\"cineraIndexGridContainer\">"));
|
||||||
|
|
||||||
|
OpenNodeNewLine(B, &IndentationLevel, NODE_DIV, 0);
|
||||||
|
AppendStringToBuffer(B, Wrap0(" class=\"cineraTraversalContainer\">"));
|
||||||
|
|
||||||
|
OpenNodeNewLine(B, &IndentationLevel, NODE_DIV, 0);
|
||||||
|
AppendStringToBuffer(B, Wrap0(" class=\"cineraTraversal\">"));
|
||||||
|
|
||||||
|
OpenNodeNewLine(B, &IndentationLevel, NODE_DIV, 0);
|
||||||
|
AppendStringToBuffer(B, Wrap0(" class=\"cineraButton prev\">"));
|
||||||
|
OpenNodeC(B, &IndentationLevel, NODE_P, 0);
|
||||||
|
AppendStringToBuffer(B, Wrap0("←"));
|
||||||
|
CloseNode(B, &IndentationLevel, NODE_P);
|
||||||
|
CloseNode(B, &IndentationLevel, NODE_DIV);
|
||||||
|
|
||||||
|
OpenNodeNewLine(B, &IndentationLevel, NODE_DIV, 0);
|
||||||
|
AppendStringToBuffer(B, Wrap0(" class=\"cineraButton ascension\">"));
|
||||||
|
OpenNodeC(B, &IndentationLevel, NODE_P, 0);
|
||||||
|
AppendStringToBuffer(B, Wrap0("↑"));
|
||||||
|
CloseNode(B, &IndentationLevel, NODE_P);
|
||||||
|
CloseNode(B, &IndentationLevel, NODE_DIV);
|
||||||
|
|
||||||
|
OpenNodeNewLine(B, &IndentationLevel, NODE_DIV, 0);
|
||||||
|
AppendStringToBuffer(B, Wrap0(" class=\"cineraButton next\">"));
|
||||||
|
OpenNodeC(B, &IndentationLevel, NODE_P, 0);
|
||||||
|
AppendStringToBuffer(B, Wrap0("→"));
|
||||||
|
CloseNode(B, &IndentationLevel, NODE_P);
|
||||||
|
CloseNode(B, &IndentationLevel, NODE_DIV);
|
||||||
|
|
||||||
|
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); // cineraTraversal
|
||||||
|
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); // cineraTraversalContainer
|
||||||
|
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); // cineraIndexGridContainer
|
||||||
|
|
||||||
|
CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); // cineraIndex
|
||||||
|
|
||||||
if(!SearchRequired) { return RC_NOOP; }
|
if(!SearchRequired) { return RC_NOOP; }
|
||||||
else { return RC_SUCCESS; }
|
else { return RC_SUCCESS; }
|
||||||
|
|
|
@ -58,7 +58,7 @@ nav.cineraNavDropdown .cineraNavTitle {
|
||||||
nav.cineraNavDropdown ul.cineraNavHorizontal {
|
nav.cineraNavDropdown ul.cineraNavHorizontal {
|
||||||
display: none;
|
display: none;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
z-index: 8;
|
z-index: 4096;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,12 +85,124 @@ ul.cineraNavPlain li.current > a {
|
||||||
|
|
||||||
/* Index */
|
/* Index */
|
||||||
|
|
||||||
#cineraIndexControl {
|
#cineraIndex
|
||||||
|
{
|
||||||
display: flex;
|
display: flex;
|
||||||
margin: 16px auto;
|
flex-direction: column;
|
||||||
max-width: 1024px;
|
}
|
||||||
|
|
||||||
|
#cineraIndex #cineraIndexControl
|
||||||
|
{
|
||||||
|
display: flex;
|
||||||
|
position: -webkit-sticky;
|
||||||
|
position: sticky;
|
||||||
|
top: 0px;
|
||||||
|
z-index: 64;
|
||||||
|
|
||||||
|
user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cineraIndex .cineraIndexGridContainer
|
||||||
|
{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 8px;
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cineraIndex .cineraIndexGridContainer.Portrait
|
||||||
|
{
|
||||||
|
flex-direction: column-reverse;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cineraIndex .cineraIndexGridContainer.Landscape.Left
|
||||||
|
{
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cineraIndex .cineraIndexGridContainer.Landscape.Right
|
||||||
|
{
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cineraIndex .cineraIndexGridContainer.Landscape .cineraTraversal
|
||||||
|
{
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cineraIndex .cineraIndexGridContainer.Landscape .cineraTraversal .cineraButton.prev
|
||||||
|
{
|
||||||
|
order: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cineraIndex .cineraIndexGridContainer.Landscape .cineraTraversal .cineraButton.next
|
||||||
|
{
|
||||||
|
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 * p
|
||||||
|
{
|
||||||
|
transition: transform .32s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cineraIndex .cineraTraversalContainer
|
||||||
|
{
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cineraIndex .cineraTraversal
|
||||||
|
{
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#cineraIndex.reversed .cineraTraversal
|
||||||
|
{
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#cineraIndex .cineraTraversal * p
|
||||||
|
{
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#cineraIndex.reversed .cineraTraversal .ascension p
|
||||||
|
{
|
||||||
|
transform: rotate(-180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#cineraIndex.reversed .cineraTraversal .prev p,
|
||||||
|
#cineraIndex.reversed .cineraTraversal .next p
|
||||||
|
{
|
||||||
|
transform: rotate(-360deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#cineraIndex .cineraTraversal .next.ascension p
|
||||||
|
{
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#cineraIndex.reversed .cineraTraversal .next.ascension p
|
||||||
|
{
|
||||||
|
transform: rotate(-315deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.cineraFilterProject .cineraText,
|
.cineraFilterProject .cineraText,
|
||||||
|
@ -99,15 +211,30 @@ ul.cineraNavPlain li.current > a {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cineraIndexFilter {
|
.cineraMenu.cineraMenuTitle {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cineraIndexFilter .filter_container
|
.cineraMenuContainer
|
||||||
{
|
{
|
||||||
display: none;
|
display: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
z-index: 64;
|
z-index: 64;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
|
||||||
|
border: 1px solid;
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cineraMenuContainer.visible
|
||||||
|
{
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cineraFilterProject,
|
.cineraFilterProject,
|
||||||
|
@ -120,7 +247,7 @@ ul.cineraNavPlain li.current > a {
|
||||||
}
|
}
|
||||||
|
|
||||||
.cineraIndexProject .cineraProjectTitle,
|
.cineraIndexProject .cineraProjectTitle,
|
||||||
.cineraFilterProject
|
.cineraMenuItem
|
||||||
{
|
{
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
@ -130,7 +257,6 @@ ul.cineraNavPlain li.current > a {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
padding-left: 16px;
|
padding-left: 16px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: horizontal;
|
|
||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,19 +267,21 @@ ul.cineraNavPlain li.current > a {
|
||||||
}
|
}
|
||||||
|
|
||||||
.cineraQueryContainer .inputContainer {
|
.cineraQueryContainer .inputContainer {
|
||||||
|
display: flex;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
padding: .5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cineraQueryContainer #query {
|
.cineraQueryContainer #query {
|
||||||
width: 100%;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cineraQueryContainer .inputContainer .spinner {
|
.cineraQueryContainer .inputContainer .spinner {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 2px;
|
top: 2px;
|
||||||
right: 5px;
|
right: 5px;
|
||||||
color: black;
|
color: #000000;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
@ -163,7 +291,7 @@ ul.cineraNavPlain li.current > a {
|
||||||
}
|
}
|
||||||
|
|
||||||
#cineraResults,
|
#cineraResults,
|
||||||
#cineraIndex {
|
#cineraIndexList {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
}
|
}
|
||||||
|
@ -173,22 +301,94 @@ ul.cineraNavPlain li.current > a {
|
||||||
flex-flow: column;
|
flex-flow: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
#cineraIndexControl #cineraIndexSort {
|
#cineraIndexList .cineraIndexEntries {
|
||||||
padding: 4px;
|
display: flex;
|
||||||
|
flex-flow: column;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#cineraIndexControl #cineraIndexSort,
|
#cineraIndex #cineraIndexGrid
|
||||||
#cineraIndexControl .cineraIndexFilter .filter_container {
|
{
|
||||||
cursor: pointer;
|
display: flex;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
perspective-origin: center;
|
||||||
|
-webkit-perspective-origin: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cineraIndex #cineraIndexGrid .cineraButtons
|
||||||
|
{
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: grid;
|
||||||
|
grid-gap: 2px;
|
||||||
|
backface-visibility: hidden;
|
||||||
|
-webkit-backface-visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cineraIndex .cineraButton
|
||||||
|
{
|
||||||
|
border: 1px solid;
|
||||||
|
|
||||||
|
text-align: center;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
flex-direction: column;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
-moz-user-select: none;
|
-moz-user-select: none;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#cineraIndex .cineraIndexEntries {
|
#cineraIndex #cineraIndexGrid .cineraButton.subdivision
|
||||||
|
{
|
||||||
|
box-sizing: border-box;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: column;
|
backface-visibility: hidden;
|
||||||
|
-webkit-backface-visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cineraIndex #cineraIndexGrid .cineraButton.subdivision .head-item,
|
||||||
|
#cineraIndex #cineraIndexGrid .cineraButton.subdivision .tail-item
|
||||||
|
{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height: 50%;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cineraIndex #cineraIndexGrid .cineraButton.subdivision.leaf
|
||||||
|
{
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cineraIndex #cineraIndexGrid .cineraButton.subdivision.leaf a
|
||||||
|
{
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cineraIndex #cineraIndexGrid .cineraButton.subdivision.leaf a:hover {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cineraIndex #cineraIndexGrid .cineraButton.subdivision .head-item,
|
||||||
|
#cineraIndex.reversed #cineraIndexGrid .cineraButton.subdivision .tail-item
|
||||||
|
{
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cineraIndex #cineraIndexGrid .cineraButton.subdivision .tail-item,
|
||||||
|
#cineraIndex.reversed #cineraIndexGrid .cineraButton.subdivision .head-item
|
||||||
|
{
|
||||||
|
align-items: flex-end;
|
||||||
|
justify-content: flex-end;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cineraIndexList.hidden,
|
||||||
|
#cineraIndex .cineraIndexGridContainer.hidden
|
||||||
|
{
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#cineraResults .dayContainer {
|
#cineraResults .dayContainer {
|
||||||
|
@ -203,7 +403,7 @@ ul.cineraNavPlain li.current > a {
|
||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
width: 200px;
|
max-width: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cineraIndexEntries div a {
|
.cineraIndexEntries div a {
|
||||||
|
@ -243,36 +443,6 @@ ul.cineraNavPlain li.current > a {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 720px), (max-height: 512px)
|
|
||||||
{
|
|
||||||
#cineraIndexControl {
|
|
||||||
margin: 4px auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#cineraIndexControl,
|
|
||||||
#cineraResultsSummary {
|
|
||||||
font-size: 64%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#cineraResults .dayContainer {
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
#cineraResults .dayContainer .dayName {
|
|
||||||
font-weight: bold;
|
|
||||||
text-align: center;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#cineraResults .dayContainer .markerList {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cineraIndexEntries div a {
|
|
||||||
font-size: 80%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Player */
|
/* Player */
|
||||||
|
|
||||||
/* Player / Structure */
|
/* Player / Structure */
|
||||||
|
@ -285,7 +455,7 @@ ul.cineraNavPlain li.current > a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cineraMenus > *:not(.views),
|
.cineraMenus > *:not(.views, .cineraHelp),
|
||||||
.cineraMenus > .menu > .refs .ref,
|
.cineraMenus > .menu > .refs .ref,
|
||||||
.cineraMenus > .menu > .view,
|
.cineraMenus > .menu > .view,
|
||||||
.cineraMenus > .menu > .views_container .view,
|
.cineraMenus > .menu > .views_container .view,
|
||||||
|
@ -299,7 +469,14 @@ ul.cineraNavPlain li.current > a {
|
||||||
|
|
||||||
.cineraMenus > .menu {
|
.cineraMenus > .menu {
|
||||||
position: relative;
|
position: relative;
|
||||||
align-self: center;
|
min-height: 1em;
|
||||||
|
min-width: 1em;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cineraMenus > .menu.filter.responsible,
|
.cineraMenus > .menu.filter.responsible,
|
||||||
|
@ -312,67 +489,7 @@ ul.cineraNavPlain li.current > a {
|
||||||
animation-iteration-count: 1;
|
animation-iteration-count: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cineraMenus .help .help_container .help_key {
|
.cineraHelp {
|
||||||
font-family: Inconsolata;
|
|
||||||
font-size: 16px;
|
|
||||||
border: 1px solid;
|
|
||||||
display: inline-block;
|
|
||||||
background-color: #111; /* Per project */
|
|
||||||
border-radius: 4px;
|
|
||||||
height: 16px;
|
|
||||||
width: 16px;
|
|
||||||
padding: 4px;
|
|
||||||
line-height: 16px;
|
|
||||||
margin: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cineraMenus .help .help_container .help_key.word {
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cineraMenus .help .help_container .help_key.modifer {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cineraMenus .help .help_container .help_key.unavailable,
|
|
||||||
.cineraMenus .help .help_container .help_text.unavailable,
|
|
||||||
.cineraMenus .help .help_container h2 .unavailable {
|
|
||||||
opacity: 0.32;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cineraMenus .help .help_container .key_block {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: flex-end;
|
|
||||||
flex-direction: row;
|
|
||||||
margin: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cineraMenus .help .help_container .help_text {
|
|
||||||
margin: 0 8px 0 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.cineraMenus .help .help_container h1 {
|
|
||||||
display: inline;
|
|
||||||
margin-left: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cineraMenus .help .help_container h1:after {
|
|
||||||
content: "\a";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.cineraMenus .help .help_container h2 {
|
|
||||||
font-size: 16px;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cineraMenus .help .help_container .help_paragraph {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cineraMenus > .help {
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border: 1px solid;
|
border: 1px solid;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
@ -387,32 +504,87 @@ ul.cineraNavPlain li.current > a {
|
||||||
z-index: 64;
|
z-index: 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cineraMenus .help .help_container .help_grid {
|
.cineraHelp .help_container {
|
||||||
display: inline-flex;
|
background-color: #000000; /* Per project */
|
||||||
flex-direction: column;
|
color: #EEEEEE; /* Per project */
|
||||||
}
|
|
||||||
|
|
||||||
.cineraMenus .help .help_container {
|
|
||||||
background-color: black; /* Per project */
|
|
||||||
color: #EEE; /* Per project */
|
|
||||||
display: none;
|
display: none;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
line-height: 12px;
|
line-height: 12px;
|
||||||
opacity: 0.9;
|
opacity: 0.9;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
right: 612px;
|
top: 50%;
|
||||||
top: 42px;
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.cineraMenus .help .help_container.visible {
|
.cineraHelp .help_container.visible {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
#cineraIndexControl .cineraIndexFilter .filter_container
|
.cineraHelp .help_container .help_key {
|
||||||
{
|
font-family: Inconsolata;
|
||||||
|
font-size: 16px;
|
||||||
border: 1px solid;
|
border: 1px solid;
|
||||||
border-top: none;
|
display: inline-block;
|
||||||
|
background-color: #111111; /* Per project */
|
||||||
|
border-radius: 4px;
|
||||||
|
height: 16px;
|
||||||
|
width: 16px;
|
||||||
|
padding: 4px;
|
||||||
|
line-height: 16px;
|
||||||
|
margin: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cineraHelp .help_container .help_key.word {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cineraHelp .help_container .help_key.modifer {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cineraHelp .help_container .help_key.unavailable,
|
||||||
|
.cineraHelp .help_container .help_text.unavailable,
|
||||||
|
.cineraHelp .help_container h2 .unavailable {
|
||||||
|
opacity: 0.32;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cineraHelp .help_container .key_block {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
flex-direction: row;
|
||||||
|
margin: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cineraHelp .help_container .help_text {
|
||||||
|
margin: 0 8px 0 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.cineraHelp .help_container h1 {
|
||||||
|
display: inline;
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cineraHelp .help_container h1:after {
|
||||||
|
content: "\a";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.cineraHelp .help_container h2 {
|
||||||
|
font-size: 16px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cineraHelp .help_container .help_paragraph {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cineraHelp .help_container .help_grid {
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cineraMenus > .menu .quotes_container,
|
.cineraMenus > .menu .quotes_container,
|
||||||
|
@ -430,11 +602,13 @@ ul.cineraNavPlain li.current > a {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
top: 100%;
|
top: 100%;
|
||||||
z-index: 1;
|
z-index: 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cineraMenus > .menu .refs,
|
.cineraMenus > .menu .refs,
|
||||||
.cineraMenus > .menu .link_container {
|
.cineraMenus > .menu .filter_container,
|
||||||
|
.cineraMenus > .menu .link_container,
|
||||||
|
.cineraMenus > .menu .credits_container {
|
||||||
width: 350px;
|
width: 350px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -442,12 +616,9 @@ ul.cineraNavPlain li.current > a {
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cineraMenus > .menu .filter_container {
|
.cineraMenus > .menu .sizing {
|
||||||
min-width: 350px;
|
z-index: -1;
|
||||||
}
|
display: block;
|
||||||
|
|
||||||
.cineraMenus > .menu .credits_container {
|
|
||||||
min-width: 240px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.cineraMenus > .menu .visible {
|
.cineraMenus > .menu .visible {
|
||||||
|
@ -639,7 +810,7 @@ ul.cineraNavPlain li.current > a {
|
||||||
}
|
}
|
||||||
|
|
||||||
.cineraPlayerContainer .markers_container {
|
.cineraPlayerContainer .markers_container {
|
||||||
flex-shrink: 0;
|
flex-shrink: 1;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
@ -651,6 +822,16 @@ ul.cineraNavPlain li.current > a {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cineraPlayerContainer {
|
||||||
|
background-color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cineraPlayerContainer .video_container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
.cineraPlayerContainer .markers_container > a.episodeMarker {
|
.cineraPlayerContainer .markers_container > a.episodeMarker {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
@ -683,7 +864,7 @@ ul.cineraNavPlain li.current > a {
|
||||||
border-bottom: 1px solid;
|
border-bottom: 1px solid;
|
||||||
position: relative;
|
position: relative;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
max-height: 320px;
|
max-height: 320px; /* NOTE(matt): Required for the transition */
|
||||||
transition: max-height .32s;
|
transition: max-height .32s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -709,7 +890,7 @@ ul.cineraNavPlain li.current > a {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cineraPlayerContainer .markers_container > .markers .marker.skip {
|
.cinera:not(.mobile) .cineraPlayerContainer .markers_container > .markers .marker.skip {
|
||||||
max-height: 0;
|
max-height: 0;
|
||||||
transition: max-height .32s;
|
transition: max-height .32s;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -781,97 +962,109 @@ ul.cineraNavPlain li.current > a {
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 720px), (max-height: 512px)
|
/* NOTE(matt): Mobile Style */
|
||||||
{
|
|
||||||
.cineraMenus .episode_name,
|
|
||||||
.cineraMenus > .menu > .view,
|
|
||||||
.cineraMenus > .menu > .views_container .view,
|
|
||||||
.cineraMenus > .help,
|
|
||||||
.markers_container > .episodeMarker div:nth-child(2),
|
|
||||||
.markers_container > .episodeMarker div:nth-child(3),
|
|
||||||
.markers_container > .markers .marker:not(.current) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cineraMenus {
|
#cineraIndex.mobile #cineraResults .dayContainer {
|
||||||
justify-content: center;
|
flex-direction: column;
|
||||||
}
|
|
||||||
|
|
||||||
.cineraMenus .menu .quotes_container,
|
|
||||||
.cineraMenus .menu .references_container,
|
|
||||||
.cineraMenus .menu .filter_container,
|
|
||||||
.cineraMenus .menu .link_container,
|
|
||||||
.cineraMenus .menu .credits_container {
|
|
||||||
position: fixed;
|
|
||||||
left: 0;
|
|
||||||
margin: auto;
|
|
||||||
max-height: 80%;
|
|
||||||
max-width: 97%;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.cineraPlayerContainer {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cineraPlayerContainer .markers_container {
|
|
||||||
display: flex;
|
|
||||||
flex-flow: row;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cineraPlayerContainer .markers_container > .episodeMarker {
|
|
||||||
user-select: none;
|
|
||||||
-moz-user-select: none;
|
|
||||||
-webkit-user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cineraPlayerContainer .markers_container > .markers .marker .cineraContent {
|
|
||||||
width: 456px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 580px)
|
|
||||||
{
|
|
||||||
.cineraPlayerContainer .markers_container > .markers .marker .cineraContent {
|
|
||||||
width: 320px;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@media (max-width: 450px)
|
|
||||||
{
|
|
||||||
.cineraPlayerContainer .markers_container > .markers .marker .cineraContent {
|
|
||||||
width: 256px;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@media (max-width: 375px)
|
|
||||||
{
|
|
||||||
.cineraPlayerContainer .markers_container > .markers .marker .cineraContent {
|
|
||||||
width: 180px;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.cineraPlayerContainer .markers_container > .episodeMarker.first,
|
|
||||||
.cineraPlayerContainer .markers_container > .episodeMarker.prev,
|
|
||||||
.cineraPlayerContainer .markers_container > .markers .marker,
|
|
||||||
.cineraPlayerContainer .markers_container > .episodeMarker.last,
|
|
||||||
.cineraPlayerContainer .markers_container > .episodeMarker.next {
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cineraPlayerContainer .markers_container > .episodeMarker.first,
|
|
||||||
.cineraPlayerContainer .markers_container > .episodeMarker.prev {
|
|
||||||
border-right: 3px double;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cineraPlayerContainer .markers_container > .episodeMarker.last,
|
|
||||||
.cineraPlayerContainer .markers_container > .episodeMarker.next {
|
|
||||||
border-left: 3px double;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#cineraIndex.mobile #cineraResults .dayContainer .dayName {
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cineraIndex.mobile #cineraResults .dayContainer .markerList {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cinera.mobile
|
||||||
|
{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-grow: 0;
|
||||||
|
-webkit-text-size-adjust: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cinera.mobile .cineraMenus {
|
||||||
|
justify-content: center;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
position: relative;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cinera.mobile .cineraMenus,
|
||||||
|
.cinera.mobile .player_container {
|
||||||
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cinera.mobile .cineraMenus .episode_name,
|
||||||
|
.cinera.mobile .cineraMenus > .menu > .view,
|
||||||
|
.cinera.mobile .cineraMenus > .menu > .views_container .view,
|
||||||
|
.cinera.mobile .cineraHelp,
|
||||||
|
#cineraIndex.mobile .cineraHelp,
|
||||||
|
.cinera.mobile .markers_container > .episodeMarker div:nth-child(2),
|
||||||
|
.cinera.mobile .markers_container > .episodeMarker div:nth-child(3),
|
||||||
|
.cinera.mobile .markers_container > .markers .marker:not(.current) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cinera.mobile .cineraMenus .menu {
|
||||||
|
position: static;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cinera.mobile .cineraMenus .menu .quotes_container,
|
||||||
|
.cinera.mobile .cineraMenus .menu .references_container,
|
||||||
|
.cinera.mobile .cineraMenus .menu .filter_container,
|
||||||
|
.cinera.mobile .cineraMenus .menu .link_container,
|
||||||
|
.cinera.mobile .cineraMenus .menu .credits_container {
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.cinera.mobile .cineraPlayerContainer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cinera.mobile .cineraPlayerContainer .markers_container {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row;
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cinera.mobile .cineraPlayerContainer .markers_container > .episodeMarker {
|
||||||
|
width: 32px;
|
||||||
|
user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cinera.mobile .cineraPlayerContainer .markers_container > .markers {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cinera.mobile .cineraPlayerContainer .markers_container > .episodeMarker.first,
|
||||||
|
.cinera.mobile .cineraPlayerContainer .markers_container > .episodeMarker.prev,
|
||||||
|
.cinera.mobile .cineraPlayerContainer .markers_container > .markers .marker,
|
||||||
|
.cinera.mobile .cineraPlayerContainer .markers_container > .episodeMarker.last,
|
||||||
|
.cinera.mobile .cineraPlayerContainer .markers_container > .episodeMarker.next {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cinera.mobile .cineraPlayerContainer .markers_container > .episodeMarker.first,
|
||||||
|
.cinera.mobile .cineraPlayerContainer .markers_container > .episodeMarker.prev {
|
||||||
|
border-right: 3px double;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cinera.mobile .cineraPlayerContainer .markers_container > .episodeMarker.last,
|
||||||
|
.cinera.mobile .cineraPlayerContainer .markers_container > .episodeMarker.next {
|
||||||
|
border-left: 3px double;
|
||||||
|
}
|
||||||
|
/* Mobile Style End */
|
||||||
|
|
||||||
/* CUSTOM PAGE STYLE */
|
/* CUSTOM PAGE STYLE */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -889,4 +1082,4 @@ Open menu: ▾ ▾
|
||||||
Open link in new tab: ⤻ or &10559; or &8599; or ⭷
|
Open link in new tab: ⤻ or &10559; or &8599; or ⭷
|
||||||
Play from timecode: ⏵ (or, if ↓ ▸)
|
Play from timecode: ⏵ (or, if ↓ ▸)
|
||||||
Playable from timecode: ▹
|
Playable from timecode: ▹
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -516,7 +516,7 @@ typedef struct project
|
||||||
asset *IconAsset;
|
asset *IconAsset;
|
||||||
|
|
||||||
string StreamUsername;
|
string StreamUsername;
|
||||||
string VODPlatform;
|
string VODPlatform; // TODO(matt): Make this an enum
|
||||||
|
|
||||||
bool DenyBespokeTemplates;
|
bool DenyBespokeTemplates;
|
||||||
bool SingleBrowserTab;
|
bool SingleBrowserTab;
|
||||||
|
@ -2615,7 +2615,7 @@ string
|
||||||
DeriveLineageWithoutOriginOfProject(config *C, scope_tree *Project)
|
DeriveLineageWithoutOriginOfProject(config *C, scope_tree *Project)
|
||||||
{
|
{
|
||||||
string Result = {};
|
string Result = {};
|
||||||
memory_book StringList = {};
|
memory_book StringList = InitBookOfPointers(MBT_STRING_PTR, 4);
|
||||||
if(Project->Parent && Project->Parent->ID.Key == IDENT_PROJECT)
|
if(Project->Parent && Project->Parent->ID.Key == IDENT_PROJECT)
|
||||||
{
|
{
|
||||||
string **Writer = MakeSpaceInBook(&StringList);
|
string **Writer = MakeSpaceInBook(&StringList);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -54,7 +54,8 @@ function Player(htmlContainer, refsCallback) {
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
Player.initializeYoutube(this.onYoutubeReady.bind(this));
|
Player.initializeYoutube(this.onYoutubeReady.bind(this));
|
||||||
this.updateSize();
|
var PendingMobileStyleInitialisation = true;
|
||||||
|
this.updateSize(PendingMobileStyleInitialisation);
|
||||||
this.resume();
|
this.resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,6 +100,11 @@ Player.prototype.setTime = function(time) {
|
||||||
Player.prototype.jumpToNextMarker = function() {
|
Player.prototype.jumpToNextMarker = function() {
|
||||||
var targetMarkerIdx = Math.min((this.currentMarkerIdx === null ? 0 : this.currentMarkerIdx + 1), this.markers.length-1);
|
var targetMarkerIdx = Math.min((this.currentMarkerIdx === null ? 0 : this.currentMarkerIdx + 1), this.markers.length-1);
|
||||||
var targetTime = this.markers[targetMarkerIdx].timestamp;
|
var targetTime = this.markers[targetMarkerIdx].timestamp;
|
||||||
|
while(targetMarkerIdx < this.markers.length && this.markers[targetMarkerIdx].el.classList.contains("skip"))
|
||||||
|
{
|
||||||
|
++targetMarkerIdx;
|
||||||
|
targetTime = this.markers[targetMarkerIdx].timestamp;
|
||||||
|
}
|
||||||
this.setTime(targetTime);
|
this.setTime(targetTime);
|
||||||
this.play();
|
this.play();
|
||||||
};
|
};
|
||||||
|
@ -106,35 +112,310 @@ Player.prototype.jumpToNextMarker = function() {
|
||||||
Player.prototype.jumpToPrevMarker = function() {
|
Player.prototype.jumpToPrevMarker = function() {
|
||||||
var targetMarkerIdx = Math.max(0, (this.currentMarkerIdx === null ? 0 : this.currentMarkerIdx - 1));
|
var targetMarkerIdx = Math.max(0, (this.currentMarkerIdx === null ? 0 : this.currentMarkerIdx - 1));
|
||||||
var targetTime = this.markers[targetMarkerIdx].timestamp;
|
var targetTime = this.markers[targetMarkerIdx].timestamp;
|
||||||
|
while(targetMarkerIdx >= 0 && this.markers[targetMarkerIdx].el.classList.contains("skip"))
|
||||||
|
{
|
||||||
|
--targetMarkerIdx;
|
||||||
|
targetTime = this.markers[targetMarkerIdx].timestamp;
|
||||||
|
}
|
||||||
this.setTime(targetTime);
|
this.setTime(targetTime);
|
||||||
this.play();
|
this.play();
|
||||||
};
|
};
|
||||||
|
|
||||||
function switchToMobileView(player)
|
function
|
||||||
|
GetHeightOfHideableElement(Element, UnhidingClass)
|
||||||
|
{
|
||||||
|
var Result = 0;
|
||||||
|
if(Element.classList.contains(UnhidingClass))
|
||||||
|
{
|
||||||
|
Result = Element.offsetHeight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var ZOffset = Element.style.zOffset;
|
||||||
|
Element.style.zOffset = -1;
|
||||||
|
Element.classList.add(UnhidingClass);
|
||||||
|
|
||||||
|
Result = Element.offsetHeight;
|
||||||
|
|
||||||
|
Element.classList.remove(UnhidingClass);
|
||||||
|
Element.style.zOffset = ZOffset;
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function
|
||||||
|
GetWidthOfHideableElement(Element, UnhidingClass)
|
||||||
|
{
|
||||||
|
var Result = 0;
|
||||||
|
if(Element.classList.contains(UnhidingClass))
|
||||||
|
{
|
||||||
|
Result = Element.offsetWidth;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var ZOffset = Element.style.zOffset;
|
||||||
|
Element.style.zOffset = -1;
|
||||||
|
Element.classList.add(UnhidingClass);
|
||||||
|
|
||||||
|
Result = Element.offsetWidth;
|
||||||
|
|
||||||
|
Element.classList.remove(UnhidingClass);
|
||||||
|
Element.style.zOffset = ZOffset;
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function
|
||||||
|
ComputeVerticalOffsetForMenu(Menu, Toggler, VideoContainerDimY)
|
||||||
|
{
|
||||||
|
console.log("ComputeVerticalOffsetForMenu()");
|
||||||
|
var Result = 0;
|
||||||
|
var MenuHeight = GetHeightOfHideableElement(Menu, "visible");
|
||||||
|
var TogglerHeight = Toggler.offsetHeight;
|
||||||
|
|
||||||
|
var TogglerOffset = Toggler.offsetTop;
|
||||||
|
var Result = TogglerOffset + (TogglerHeight / 2) - (MenuHeight / 2);
|
||||||
|
|
||||||
|
console.log("Lower Point (0): " + (Result + MenuHeight));
|
||||||
|
console.log("VideoContainerDimY (0): " + VideoContainerDimY);
|
||||||
|
var LowerProtrusion = MenuHeight + Result - VideoContainerDimY;
|
||||||
|
if(LowerProtrusion > 0)
|
||||||
|
{
|
||||||
|
Result -= LowerProtrusion;
|
||||||
|
}
|
||||||
|
console.log("Lower Point (1): " + (Result + MenuHeight));
|
||||||
|
console.log("VideoContainerDimY (1): " + VideoContainerDimY);
|
||||||
|
|
||||||
|
if(Result < 0)
|
||||||
|
{
|
||||||
|
Result = 0;
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sizeAndPositionMenuContainer(TitleBar, SizerElement, Menu)
|
||||||
|
{
|
||||||
|
if(Menu)
|
||||||
|
{
|
||||||
|
var Toggler = Menu.parentElement;
|
||||||
|
|
||||||
|
var TitleBarDimX = TitleBar.offsetWidth;
|
||||||
|
var TitleBarDimY = TitleBar.offsetHeight;
|
||||||
|
var SizerElementDimX = SizerElement.offsetWidth;
|
||||||
|
var SizerElementDimY = SizerElement.offsetHeight;
|
||||||
|
|
||||||
|
var ContainerDimX = SizerElementDimX;
|
||||||
|
var ContainerDimY = SizerElementDimY;
|
||||||
|
|
||||||
|
switch(cineraProps.O)
|
||||||
|
{
|
||||||
|
case orientations.PORTRAIT:
|
||||||
|
{
|
||||||
|
Menu.style.borderTopWidth = 0;
|
||||||
|
Menu.style.borderTopStyle = "none";
|
||||||
|
Menu.style.borderRightWidth = "1px";
|
||||||
|
Menu.style.borderRightStyle = "solid";
|
||||||
|
Menu.style.borderLeftWidth = "1px";
|
||||||
|
Menu.style.borderLeftStyle = "solid";
|
||||||
|
|
||||||
|
Menu.style.maxWidth = ContainerDimX + "px";
|
||||||
|
ContainerDimY -= TitleBarDimY;
|
||||||
|
Menu.style.maxHeight = ContainerDimY + "px";
|
||||||
|
|
||||||
|
Menu.style.top = TitleBarDimY + "px";
|
||||||
|
Menu.style.left = 0 + "px";
|
||||||
|
} break;
|
||||||
|
case orientations.LANDSCAPE_LEFT:
|
||||||
|
{
|
||||||
|
Menu.style.borderTopWidth = "1px";
|
||||||
|
Menu.style.borderTopStyle = "solid";
|
||||||
|
Menu.style.borderRightWidth = "1px";
|
||||||
|
Menu.style.borderRightStyle = "solid";
|
||||||
|
Menu.style.borderLeftWidth = 0;
|
||||||
|
Menu.style.borderLeftStyle = "none";
|
||||||
|
|
||||||
|
ContainerDimX -= TitleBarDimX;
|
||||||
|
Menu.style.maxWidth = ContainerDimX + "px";
|
||||||
|
Menu.style.maxHeight = ContainerDimY + "px";
|
||||||
|
|
||||||
|
var MenuVerticalOffset = ComputeVerticalOffsetForMenu(Menu, Toggler, SizerElementDimY);
|
||||||
|
|
||||||
|
Menu.style.top = MenuVerticalOffset + "px";
|
||||||
|
Menu.style.left = TitleBarDimX + "px";
|
||||||
|
} break;
|
||||||
|
case orientations.LANDSCAPE_RIGHT:
|
||||||
|
{
|
||||||
|
Menu.style.borderTopWidth = "1px";
|
||||||
|
Menu.style.borderTopStyle = "solid";
|
||||||
|
Menu.style.borderRightWidth = 0;
|
||||||
|
Menu.style.borderRightStyle = "none";
|
||||||
|
Menu.style.borderLeftWidth = "1px";
|
||||||
|
Menu.style.borderLeftStyle = "solid";
|
||||||
|
|
||||||
|
ContainerDimX -= TitleBarDimX;
|
||||||
|
Menu.style.maxWidth = ContainerDimX + "px";
|
||||||
|
Menu.style.maxHeight = ContainerDimY + "px";
|
||||||
|
|
||||||
|
var MenuVerticalOffset = ComputeVerticalOffsetForMenu(Menu, Toggler, SizerElementDimY);
|
||||||
|
|
||||||
|
Menu.style.top = MenuVerticalOffset + "px";
|
||||||
|
var MenuWidth = GetWidthOfHideableElement(Menu, "visible");
|
||||||
|
Menu.style.left = -MenuWidth + "px";
|
||||||
|
} break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function
|
||||||
|
ComputeTallest(Elements, UnhidingClass)
|
||||||
|
{
|
||||||
|
var Result = null;
|
||||||
|
for(var i = 0; i < Elements.length; ++i)
|
||||||
|
{
|
||||||
|
var This = Elements[i];
|
||||||
|
var Height = UnhidingClass ? GetHeightOfHideableElement(This, UnhidingClass) : This.offsetHeight;
|
||||||
|
if(Height > Result)
|
||||||
|
{
|
||||||
|
Result = Height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function
|
||||||
|
ComputeAndSetTallest(Selector, Elements, UnhidingClass)
|
||||||
|
{
|
||||||
|
Selector.style.height = "unset";
|
||||||
|
Selector.style.height = ComputeTallest(Elements, UnhidingClass) + "px";
|
||||||
|
}
|
||||||
|
|
||||||
|
function ApplyMobileStyle(player)
|
||||||
|
{
|
||||||
|
var MaxWidth = MaxWidthOfElement(cinera);
|
||||||
|
var MaxHeight = MaxHeightOfElement(cinera);
|
||||||
|
|
||||||
|
var IndicesBar = playerContainer.querySelector(".markers_container");
|
||||||
|
var Markers = IndicesBar.querySelector(".markers");
|
||||||
|
var CineraContentWidth = MaxWidth;
|
||||||
|
|
||||||
|
var EpisodeMarkers = IndicesBar.querySelectorAll(".episodeMarker");
|
||||||
|
for(var i = 0; i < EpisodeMarkers.length; ++i)
|
||||||
|
{
|
||||||
|
CineraContentWidth -= EpisodeMarkers[i].offsetWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(cineraProps.O)
|
||||||
|
{
|
||||||
|
case orientations.PORTRAIT:
|
||||||
|
{
|
||||||
|
cinera.style.flexDirection = "column";
|
||||||
|
titleBar.style.flexDirection = "row";
|
||||||
|
} break;
|
||||||
|
case orientations.LANDSCAPE_LEFT:
|
||||||
|
{
|
||||||
|
cinera.style.flexDirection = "row";
|
||||||
|
titleBar.style.flexDirection = "column-reverse";
|
||||||
|
CineraContentWidth -= titleBar.offsetWidth;
|
||||||
|
} break;
|
||||||
|
case orientations.LANDSCAPE_RIGHT:
|
||||||
|
{
|
||||||
|
cinera.style.flexDirection = "row-reverse";
|
||||||
|
titleBar.style.flexDirection = "column";
|
||||||
|
CineraContentWidth -= titleBar.offsetWidth;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(MobileCineraContentRule !== undefined)
|
||||||
|
{
|
||||||
|
MobileCineraContentRule.style.width = CineraContentWidth + "px";
|
||||||
|
var MarkerList = Markers.querySelectorAll(".marker");
|
||||||
|
ComputeAndSetTallest(MobileCineraContentRule, MarkerList, "current");
|
||||||
|
}
|
||||||
|
|
||||||
|
var VideoMaxDimX = null;
|
||||||
|
var VideoMaxDimY = null;
|
||||||
|
|
||||||
|
switch(cineraProps.O)
|
||||||
|
{
|
||||||
|
case orientations.PORTRAIT:
|
||||||
|
{
|
||||||
|
VideoMaxDimX = MaxWidth;
|
||||||
|
VideoMaxDimY = MaxHeight - IndicesBar.offsetHeight - titleBar.offsetHeight;
|
||||||
|
} break;
|
||||||
|
case orientations.LANDSCAPE_LEFT:
|
||||||
|
case orientations.LANDSCAPE_RIGHT:
|
||||||
|
{
|
||||||
|
VideoMaxDimX = MaxWidth - titleBar.offsetWidth;
|
||||||
|
VideoMaxDimY = MaxHeight - IndicesBar.offsetHeight;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var VideoDimYFromMaxX = VideoMaxDimX * 9 / 16;
|
||||||
|
var VideoDimXFromMaxY = VideoMaxDimY * 16 / 9;
|
||||||
|
|
||||||
|
var VideoDimX = 0;
|
||||||
|
var VideoDimY = 0;
|
||||||
|
if(VideoDimXFromMaxY > VideoMaxDimX)
|
||||||
|
{
|
||||||
|
VideoDimX = Math.floor(VideoMaxDimX);
|
||||||
|
VideoDimY = Math.floor(VideoDimYFromMaxX);
|
||||||
|
}
|
||||||
|
else if(VideoDimYFromMaxX > VideoMaxDimY)
|
||||||
|
{
|
||||||
|
VideoDimY = Math.floor(VideoMaxDimY);
|
||||||
|
VideoDimX = Math.floor(VideoDimXFromMaxY);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VideoDimX = Math.floor(VideoMaxDimX);
|
||||||
|
VideoDimY = Math.floor(VideoDimYFromMaxX);
|
||||||
|
}
|
||||||
|
|
||||||
|
var VideoContainer = cinera.querySelector(".video_container");
|
||||||
|
|
||||||
|
VideoContainer.style.width = VideoDimX + "px";
|
||||||
|
VideoContainer.style.height = VideoDimY + "px";
|
||||||
|
|
||||||
|
sizeAndPositionMenuContainer(titleBar, cinera, quotesMenu);
|
||||||
|
sizeAndPositionMenuContainer(titleBar, cinera, referencesMenu);
|
||||||
|
sizeAndPositionMenuContainer(titleBar, cinera, filterMenu);
|
||||||
|
sizeAndPositionMenuContainer(titleBar, cinera, linkMenu);
|
||||||
|
sizeAndPositionMenuContainer(titleBar, cinera, creditsMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
function
|
||||||
|
IconifyMenuTogglers()
|
||||||
{
|
{
|
||||||
var menuContainerOffset = getElementYOffsetFromPage(titleBar) + parseInt(window.getComputedStyle(titleBar).height);
|
|
||||||
if(quotesMenu)
|
if(quotesMenu)
|
||||||
{
|
{
|
||||||
quotesMenu.previousElementSibling.textContent = '\u{1F5E9}';
|
quotesMenu.previousElementSibling.textContent = '\u{1F5E9}';
|
||||||
quotesMenu.style.top = menuContainerOffset + "px";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(referencesMenu)
|
if(referencesMenu)
|
||||||
{
|
{
|
||||||
referencesMenu.previousElementSibling.textContent = '\u{1F4D6}';
|
referencesMenu.previousElementSibling.textContent = '\u{1F4D6}';
|
||||||
referencesMenu.style.top = menuContainerOffset + "px";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(filterMenu) { filterMenu.style.top = menuContainerOffset + "px"; }
|
if(creditsMenu)
|
||||||
if(linkMenu) { linkMenu.style.top = menuContainerOffset + "px"; }
|
{
|
||||||
|
|
||||||
if(creditsMenu) {
|
|
||||||
creditsMenu.previousElementSibling.textContent = '\u{1F46A}';
|
creditsMenu.previousElementSibling.textContent = '\u{1F46A}';
|
||||||
creditsMenu.style.top = menuContainerOffset + "px";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(viewsMenu)
|
||||||
|
{
|
||||||
|
viewsMenu.remove();
|
||||||
|
viewsMenu = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function
|
||||||
|
InitMobileControls()
|
||||||
|
{
|
||||||
var rightmost = {};
|
var rightmost = {};
|
||||||
var markersContainer = player.markersContainer;
|
var markersContainer = cinera.querySelector(".markers_container");
|
||||||
markersContainer.style.height = "auto";
|
markersContainer.style.height = "auto";
|
||||||
|
var episodeMarkerFirst = markersContainer.querySelector(".episodeMarker.first");
|
||||||
var episodeMarkerPrev = markersContainer.querySelector(".episodeMarker.prev");
|
var episodeMarkerPrev = markersContainer.querySelector(".episodeMarker.prev");
|
||||||
var episodeMarkerNext = markersContainer.querySelector(".episodeMarker.next");
|
var episodeMarkerNext = markersContainer.querySelector(".episodeMarker.next");
|
||||||
var episodeMarkerLast = markersContainer.querySelector(".episodeMarker.last");
|
var episodeMarkerLast = markersContainer.querySelector(".episodeMarker.last");
|
||||||
|
@ -143,94 +424,70 @@ function switchToMobileView(player)
|
||||||
if(episodeMarkerNext) { episodeMarkerNext.firstChild.textContent = '\u{23ED}'; rightmost = episodeMarkerNext; }
|
if(episodeMarkerNext) { episodeMarkerNext.firstChild.textContent = '\u{23ED}'; rightmost = episodeMarkerNext; }
|
||||||
else if (episodeMarkerLast) { rightmost = episodeMarkerLast; }
|
else if (episodeMarkerLast) { rightmost = episodeMarkerLast; }
|
||||||
|
|
||||||
|
var controlPrevTimestamp = document.createElement("a");
|
||||||
|
controlPrevTimestamp.classList.add("episodeMarker");
|
||||||
|
controlPrevTimestamp.classList.add("prevTimestamp");
|
||||||
|
var controlPrevTimestampContent = document.createElement("div");
|
||||||
|
controlPrevTimestampContent.appendChild(document.createTextNode('\u{25C0}'));
|
||||||
|
controlPrevTimestamp.appendChild(controlPrevTimestampContent);
|
||||||
|
|
||||||
var markers = markersContainer.querySelector(".markers");
|
var markers = markersContainer.querySelector(".markers");
|
||||||
|
markersContainer.insertBefore(controlPrevTimestamp, markers);
|
||||||
|
|
||||||
var controlPrevAnnotation = document.createElement("a");
|
var controlNextTimestamp = document.createElement("a");
|
||||||
controlPrevAnnotation.classList.add("episodeMarker");
|
controlNextTimestamp.classList.add("episodeMarker");
|
||||||
controlPrevAnnotation.classList.add("prevAnnotation");
|
controlNextTimestamp.classList.add("nextTimestamp");
|
||||||
controlPrevAnnotation.addEventListener("click", function(ev) {
|
var controlNextTimestampContent = document.createElement("div");
|
||||||
player.jumpToPrevMarker();
|
controlNextTimestampContent.appendChild(document.createTextNode('\u{25B6}'));
|
||||||
});
|
controlNextTimestamp.appendChild(controlNextTimestampContent);
|
||||||
var controlPrevAnnotationContent = document.createElement("div");
|
|
||||||
controlPrevAnnotationContent.appendChild(document.createTextNode('\u{23F4}'));
|
|
||||||
controlPrevAnnotation.appendChild(controlPrevAnnotationContent);
|
|
||||||
|
|
||||||
markersContainer.insertBefore(controlPrevAnnotation, markers);
|
|
||||||
|
|
||||||
var controlNextAnnotation = document.createElement("a");
|
|
||||||
controlNextAnnotation.classList.add("episodeMarker");
|
|
||||||
controlNextAnnotation.classList.add("nextAnnotation");
|
|
||||||
controlNextAnnotation.addEventListener("click", function(ev) {
|
|
||||||
player.jumpToNextMarker();
|
|
||||||
});
|
|
||||||
var controlNextAnnotationContent = document.createElement("div");
|
|
||||||
controlNextAnnotationContent.appendChild(document.createTextNode('\u{23F5}'));
|
|
||||||
controlNextAnnotation.appendChild(controlNextAnnotationContent);
|
|
||||||
|
|
||||||
if(rightmost)
|
if(rightmost)
|
||||||
{
|
{
|
||||||
markersContainer.insertBefore(controlNextAnnotation, rightmost);
|
markersContainer.insertBefore(controlNextTimestamp, rightmost);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
markersContainer.appendChild(controlNextAnnotation);
|
markersContainer.appendChild(controlNextTimestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
cineraProps.D = devices.MOBILE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function switchToDesktopView(player)
|
function InitMobileStyle()
|
||||||
{
|
{
|
||||||
if(quotesMenu)
|
cinera.classList.add("mobile");
|
||||||
{
|
IconifyMenuTogglers();
|
||||||
quotesMenu.previousElementSibling.textContent = originalTextContent.TitleQuotes;
|
InitMobileControls();
|
||||||
quotesMenu.style.top = "100%";
|
ApplyMobileStyle();
|
||||||
}
|
}
|
||||||
if(referencesMenu)
|
|
||||||
{
|
|
||||||
referencesMenu.previousElementSibling.textContent = originalTextContent.TitleReferences;
|
|
||||||
referencesMenu.style.top = "100%";
|
|
||||||
}
|
|
||||||
if(filterMenu) { filterMenu.style.top = "100%"; }
|
|
||||||
if(linkMenu) { linkMenu.style.top = "100%"; }
|
|
||||||
if(creditsMenu)
|
|
||||||
{
|
|
||||||
creditsMenu.previousElementSibling.textContent = originalTextContent.TitleCredits;
|
|
||||||
creditsMenu.style.top = "100%";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
function
|
||||||
|
ConnectMobileControls(player)
|
||||||
|
{
|
||||||
var markersContainer = player.markersContainer;
|
var markersContainer = player.markersContainer;
|
||||||
|
var ControlPrevTimestamp = markersContainer.querySelector(".episodeMarker.prevTimestamp");
|
||||||
var episodeMarkerPrev = markersContainer.querySelector(".episodeMarker.prev");
|
ControlPrevTimestamp.addEventListener("click", function(ev) {
|
||||||
if(episodeMarkerPrev) { episodeMarkerPrev.firstChild.textContent = originalTextContent.EpisodePrev; }
|
player.jumpToPrevMarker();
|
||||||
var episodeMarkerNext = markersContainer.querySelector(".episodeMarker.next");
|
});
|
||||||
if(episodeMarkerNext) { episodeMarkerNext.firstChild.textContent = originalTextContent.EpisodeNext; }
|
var ControlNextTimestamp = markersContainer.querySelector(".episodeMarker.nextTimestamp");
|
||||||
|
ControlNextTimestamp.addEventListener("click", function(ev) {
|
||||||
var prevAnnotation = markersContainer.querySelector(".episodeMarker.prevAnnotation");
|
player.jumpToNextMarker();
|
||||||
markersContainer.removeChild(prevAnnotation);
|
});
|
||||||
var nextAnnotation = markersContainer.querySelector(".episodeMarker.nextAnnotation");
|
|
||||||
markersContainer.removeChild(nextAnnotation);
|
|
||||||
cineraProps.D = devices.DESKTOP;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call this after changing the size of the video container in order to update the youtube player.
|
// Call this after changing the size of the video container in order to update the youtube player.
|
||||||
Player.prototype.updateSize = function() {
|
Player.prototype.updateSize = function() {
|
||||||
var width = this.videoContainer.offsetWidth;
|
var width = 0;
|
||||||
var height = width / 16 * 9;
|
var height = 0;
|
||||||
if(window.innerHeight > 512 && window.innerWidth > 720)
|
if(cineraProps.D === devices.DESKTOP)
|
||||||
{
|
{
|
||||||
if(cineraProps.D == devices.MOBILE)
|
width = this.videoContainer.offsetWidth;
|
||||||
{
|
height = width / 16 * 9; // TODO(matt): Get the aspect ratio from the video itself?
|
||||||
switchToDesktopView(this);
|
this.markersContainer.style.height = height + "px";
|
||||||
}
|
|
||||||
this.markersContainer.style.height = height + "px"; // NOTE(matt): This was the original line here
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(cineraProps.D == devices.DESKTOP)
|
ApplyMobileStyle();
|
||||||
{
|
width = this.videoContainer.offsetWidth;
|
||||||
switchToMobileView(this);
|
height = this.videoContainer.offsetHeight;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.youtubePlayerReady) {
|
if (this.youtubePlayerReady) {
|
||||||
|
@ -288,25 +545,10 @@ Player.prototype.onMarkerClick = function(marker, ev) {
|
||||||
this.play();
|
this.play();
|
||||||
};
|
};
|
||||||
|
|
||||||
function getElementXOffsetFromPage(el) {
|
|
||||||
var left = 0;
|
|
||||||
do {
|
|
||||||
left += el.offsetLeft;
|
|
||||||
} while (el = el.offsetParent);
|
|
||||||
return left;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getElementYOffsetFromPage(el) {
|
|
||||||
var top = 0;
|
|
||||||
do {
|
|
||||||
top += el.offsetTop;
|
|
||||||
} while (el = el.offsetParent);
|
|
||||||
return top;
|
|
||||||
}
|
|
||||||
|
|
||||||
Player.prototype.onMarkerMouseMove = function(marker, ev) {
|
Player.prototype.onMarkerMouseMove = function(marker, ev) {
|
||||||
if (this.currentMarker == marker) {
|
if (this.currentMarker == marker) {
|
||||||
marker.hoverx = (ev.pageX - getElementXOffsetFromPage(marker.el)) / marker.el.offsetWidth;
|
var CineraContent = this.currentMarker.el.querySelector(".cineraContent");
|
||||||
|
marker.hoverx = (ev.pageX - getElementXOffsetFromPage(CineraContent)) / CineraContent.offsetWidth;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -329,7 +571,8 @@ Player.prototype.updateProgress = function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.currentMarker) {
|
if (this.currentMarker) {
|
||||||
var totalWidth = this.currentMarker.el.offsetWidth;
|
var CineraContent = this.currentMarker.el.querySelector(".cineraContent");
|
||||||
|
var totalWidth = CineraContent.offsetWidth;
|
||||||
var progress = (this.currentTime - this.currentMarker.timestamp) / (this.currentMarker.endTime - this.currentMarker.timestamp);
|
var progress = (this.currentTime - this.currentMarker.timestamp) / (this.currentMarker.endTime - this.currentMarker.timestamp);
|
||||||
if (this.currentMarker.hoverx === null) {
|
if (this.currentMarker.hoverx === null) {
|
||||||
var pixelWidth = progress * totalWidth;
|
var pixelWidth = progress * totalWidth;
|
||||||
|
@ -364,9 +607,6 @@ Player.prototype.updateProgress = function() {
|
||||||
this.currentMarker.el.classList.add("current");
|
this.currentMarker.el.classList.add("current");
|
||||||
this.scrollTo = this.currentMarker.el.offsetTop + this.currentMarker.el.offsetHeight/2.0;
|
this.scrollTo = this.currentMarker.el.offsetTop + this.currentMarker.el.offsetHeight/2.0;
|
||||||
this.scrollPosition = this.markersContainer.scrollTop;
|
this.scrollPosition = this.markersContainer.scrollTop;
|
||||||
}
|
|
||||||
|
|
||||||
if (this.currentMarker) {
|
|
||||||
this.refsCallback(this.currentMarker.ref, this.currentMarker.el, this);
|
this.refsCallback(this.currentMarker.ref, this.currentMarker.el, this);
|
||||||
} else if (prevMarker && prevMarker.ref) {
|
} else if (prevMarker && prevMarker.ref) {
|
||||||
this.refsCallback(null);
|
this.refsCallback(null);
|
||||||
|
@ -445,6 +685,7 @@ Player.prototype.onYoutubeReady = function() {
|
||||||
videoId: this.videoContainer.getAttribute("data-videoId"),
|
videoId: this.videoContainer.getAttribute("data-videoId"),
|
||||||
width: this.videoContainer.offsetWidth,
|
width: this.videoContainer.offsetWidth,
|
||||||
height: this.videoContainer.offsetWidth / 16 * 9,
|
height: this.videoContainer.offsetWidth / 16 * 9,
|
||||||
|
playerVars: { 'playsinline': 1 },
|
||||||
//playerVars: { disablekb: 1 },
|
//playerVars: { disablekb: 1 },
|
||||||
events: {
|
events: {
|
||||||
"onReady": this.onYoutubePlayerReady.bind(this),
|
"onReady": this.onYoutubePlayerReady.bind(this),
|
||||||
|
@ -636,13 +877,13 @@ function enterFullScreen_()
|
||||||
{
|
{
|
||||||
if(!document.mozFullScreen && !document.webkitFullScreen)
|
if(!document.mozFullScreen && !document.webkitFullScreen)
|
||||||
{
|
{
|
||||||
if(cinera.mozRequestFullScreen)
|
if(document.mozRequestFullScreen)
|
||||||
{
|
{
|
||||||
cinera.mozRequestFullScreen();
|
document.mozRequestFullScreen();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cinera.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
|
document.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -673,6 +914,11 @@ function toggleTheatreMode() {
|
||||||
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.FlexDirection = cinera.style.flexDirection;
|
||||||
|
cineraProps.JustifyContent = cinera.style.justifyContent;
|
||||||
|
cineraProps.ScrollX = window.scrollX;
|
||||||
|
cineraProps.ScrollY = window.scrollY;
|
||||||
|
|
||||||
cinera.style.backgroundColor = "#000";
|
cinera.style.backgroundColor = "#000";
|
||||||
cinera.style.zIndex = 64;
|
cinera.style.zIndex = 64;
|
||||||
|
@ -683,6 +929,9 @@ function toggleTheatreMode() {
|
||||||
cinera.style.height = "100%";
|
cinera.style.height = "100%";
|
||||||
cinera.style.maxHeight = "100%";
|
cinera.style.maxHeight = "100%";
|
||||||
cinera.style.position = "fixed";
|
cinera.style.position = "fixed";
|
||||||
|
cinera.style.display = "flex";
|
||||||
|
cinera.style.flexDirection = "column";
|
||||||
|
cinera.style.justifyContent = "center";
|
||||||
|
|
||||||
viewItems[0].setAttribute("data-id", "regular");
|
viewItems[0].setAttribute("data-id", "regular");
|
||||||
viewItems[0].setAttribute("title", "Regular mode");
|
viewItems[0].setAttribute("title", "Regular mode");
|
||||||
|
@ -703,6 +952,15 @@ function toggleTheatreMode() {
|
||||||
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.flexDirection = cineraProps.FlexDirection;
|
||||||
|
cinera.style.justifyContent = cineraProps.JustifyContent;
|
||||||
|
window.scroll(
|
||||||
|
{
|
||||||
|
top: cineraProps.ScrollY,
|
||||||
|
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");
|
||||||
|
@ -859,10 +1117,12 @@ function handleKey(key) {
|
||||||
if(focusedElement.previousElementSibling)
|
if(focusedElement.previousElementSibling)
|
||||||
{
|
{
|
||||||
focusedElement.classList.remove("focused");
|
focusedElement.classList.remove("focused");
|
||||||
|
unfocusSprite(focusedElement);
|
||||||
|
|
||||||
lastFocusedQuote = focusedElement.previousElementSibling;
|
lastFocusedQuote = focusedElement.previousElementSibling;
|
||||||
focusedElement = lastFocusedQuote;
|
focusedElement = lastFocusedQuote;
|
||||||
focusedElement.classList.add("focused");
|
focusedElement.classList.add("focused");
|
||||||
|
focusSprite(focusedElement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(focusedElement.parentNode.classList.contains("references_container"))
|
else if(focusedElement.parentNode.classList.contains("references_container"))
|
||||||
|
@ -870,15 +1130,19 @@ function handleKey(key) {
|
||||||
if(focusedElement.previousElementSibling)
|
if(focusedElement.previousElementSibling)
|
||||||
{
|
{
|
||||||
focusedElement.classList.remove("focused");
|
focusedElement.classList.remove("focused");
|
||||||
|
unfocusSprite(focusedElement);
|
||||||
focusedIdentifier.classList.remove("focused");
|
focusedIdentifier.classList.remove("focused");
|
||||||
|
unfocusSprite(focusedIdentifier);
|
||||||
|
|
||||||
lastFocusedReference = focusedElement.previousElementSibling;
|
lastFocusedReference = focusedElement.previousElementSibling;
|
||||||
focusedElement = lastFocusedReference;
|
focusedElement = lastFocusedReference;
|
||||||
focusedElement.classList.add("focused");
|
focusedElement.classList.add("focused");
|
||||||
|
focusSprite(focusedElement);
|
||||||
|
|
||||||
lastFocusedIdentifier = focusedElement.querySelector(".ref_indices").firstElementChild;
|
lastFocusedIdentifier = focusedElement.querySelector(".ref_indices").firstElementChild;
|
||||||
focusedIdentifier = lastFocusedIdentifier;
|
focusedIdentifier = lastFocusedIdentifier;
|
||||||
focusedIdentifier.classList.add("focused");
|
focusedIdentifier.classList.add("focused");
|
||||||
|
focusSprite(focusedIdentifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(focusedElement.parentNode.parentNode.classList.contains("filters"))
|
else if(focusedElement.parentNode.parentNode.classList.contains("filters"))
|
||||||
|
@ -887,10 +1151,12 @@ function handleKey(key) {
|
||||||
focusedElement.previousElementSibling.classList.contains("filter_content"))
|
focusedElement.previousElementSibling.classList.contains("filter_content"))
|
||||||
{
|
{
|
||||||
focusedElement.classList.remove("focused");
|
focusedElement.classList.remove("focused");
|
||||||
|
unfocusSprite(focusedElement);
|
||||||
|
|
||||||
lastFocusedCategory = focusedElement.previousElementSibling;
|
lastFocusedCategory = focusedElement.previousElementSibling;
|
||||||
focusedElement = lastFocusedCategory;
|
focusedElement = lastFocusedCategory;
|
||||||
focusedElement.classList.add("focused");
|
focusedElement.classList.add("focused");
|
||||||
|
focusSprite(focusedElement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(focusedElement.parentNode.classList.contains("credit"))
|
else if(focusedElement.parentNode.classList.contains("credit"))
|
||||||
|
@ -898,6 +1164,7 @@ function handleKey(key) {
|
||||||
if(focusedElement.parentNode.previousElementSibling)
|
if(focusedElement.parentNode.previousElementSibling)
|
||||||
{
|
{
|
||||||
focusedElement.classList.remove("focused");
|
focusedElement.classList.remove("focused");
|
||||||
|
unfocusSprite(focusedElement);
|
||||||
if(focusedElement.parentNode.previousElementSibling.querySelector(".support") &&
|
if(focusedElement.parentNode.previousElementSibling.querySelector(".support") &&
|
||||||
focusedElement.classList.contains("support"))
|
focusedElement.classList.contains("support"))
|
||||||
{
|
{
|
||||||
|
@ -905,13 +1172,14 @@ function handleKey(key) {
|
||||||
lastFocusedCreditItem = focusedElement.parentNode.previousElementSibling.querySelector(".support");
|
lastFocusedCreditItem = focusedElement.parentNode.previousElementSibling.querySelector(".support");
|
||||||
focusedElement = lastFocusedCreditItem;
|
focusedElement = lastFocusedCreditItem;
|
||||||
focusedElement.classList.add("focused");
|
focusedElement.classList.add("focused");
|
||||||
setSpriteLightness(focusedElement.firstChild);
|
focusSprite(focusedElement);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lastFocusedCreditItem = focusedElement.parentNode.previousElementSibling.querySelector(".person");
|
lastFocusedCreditItem = focusedElement.parentNode.previousElementSibling.querySelector(".person");
|
||||||
focusedElement = lastFocusedCreditItem;
|
focusedElement = lastFocusedCreditItem;
|
||||||
focusedElement.classList.add("focused");
|
focusedElement.classList.add("focused");
|
||||||
|
focusSprite(focusedElement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -926,10 +1194,12 @@ function handleKey(key) {
|
||||||
if(focusedElement.nextElementSibling)
|
if(focusedElement.nextElementSibling)
|
||||||
{
|
{
|
||||||
focusedElement.classList.remove("focused");
|
focusedElement.classList.remove("focused");
|
||||||
|
unfocusSprite(focusedElement);
|
||||||
|
|
||||||
lastFocusedQuote = focusedElement.nextElementSibling;
|
lastFocusedQuote = focusedElement.nextElementSibling;
|
||||||
focusedElement = lastFocusedQuote;
|
focusedElement = lastFocusedQuote;
|
||||||
focusedElement.classList.add("focused");
|
focusedElement.classList.add("focused");
|
||||||
|
focusSprite(focusedElement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(focusedElement.parentNode.classList.contains("references_container"))
|
else if(focusedElement.parentNode.classList.contains("references_container"))
|
||||||
|
@ -937,15 +1207,19 @@ function handleKey(key) {
|
||||||
if(focusedElement.nextElementSibling)
|
if(focusedElement.nextElementSibling)
|
||||||
{
|
{
|
||||||
focusedElement.classList.remove("focused");
|
focusedElement.classList.remove("focused");
|
||||||
|
unfocusSprite(focusedElement);
|
||||||
focusedIdentifier.classList.remove("focused");
|
focusedIdentifier.classList.remove("focused");
|
||||||
|
unfocusSprite(focusedIdentifier);
|
||||||
|
|
||||||
lastFocusedReference = focusedElement.nextElementSibling;
|
lastFocusedReference = focusedElement.nextElementSibling;
|
||||||
focusedElement = lastFocusedReference;
|
focusedElement = lastFocusedReference;
|
||||||
focusedElement.classList.add("focused");
|
focusedElement.classList.add("focused");
|
||||||
|
focusSprite(focusedElement);
|
||||||
|
|
||||||
lastFocusedIdentifier = focusedElement.querySelector(".ref_indices").firstElementChild;
|
lastFocusedIdentifier = focusedElement.querySelector(".ref_indices").firstElementChild;
|
||||||
focusedIdentifier = lastFocusedIdentifier;
|
focusedIdentifier = lastFocusedIdentifier;
|
||||||
focusedIdentifier.classList.add("focused");
|
focusedIdentifier.classList.add("focused");
|
||||||
|
focusSprite(focusedIdentifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(focusedElement.parentNode.parentNode.classList.contains("filters"))
|
else if(focusedElement.parentNode.parentNode.classList.contains("filters"))
|
||||||
|
@ -954,10 +1228,12 @@ function handleKey(key) {
|
||||||
focusedElement.nextElementSibling.classList.contains("filter_content"))
|
focusedElement.nextElementSibling.classList.contains("filter_content"))
|
||||||
{
|
{
|
||||||
focusedElement.classList.remove("focused");
|
focusedElement.classList.remove("focused");
|
||||||
|
unfocusSprite(focusedElement);
|
||||||
|
|
||||||
lastFocusedCategory = focusedElement.nextElementSibling;
|
lastFocusedCategory = focusedElement.nextElementSibling;
|
||||||
focusedElement = lastFocusedCategory;
|
focusedElement = lastFocusedCategory;
|
||||||
focusedElement.classList.add("focused");
|
focusedElement.classList.add("focused");
|
||||||
|
focusSprite(focusedElement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(focusedElement.parentNode.classList.contains("credit"))
|
else if(focusedElement.parentNode.classList.contains("credit"))
|
||||||
|
@ -965,6 +1241,7 @@ function handleKey(key) {
|
||||||
if(focusedElement.parentNode.nextElementSibling)
|
if(focusedElement.parentNode.nextElementSibling)
|
||||||
{
|
{
|
||||||
focusedElement.classList.remove("focused");
|
focusedElement.classList.remove("focused");
|
||||||
|
unfocusSprite(focusedElement);
|
||||||
if(focusedElement.parentNode.nextElementSibling.querySelector(".support") &&
|
if(focusedElement.parentNode.nextElementSibling.querySelector(".support") &&
|
||||||
focusedElement.classList.contains("support"))
|
focusedElement.classList.contains("support"))
|
||||||
{
|
{
|
||||||
|
@ -972,13 +1249,14 @@ function handleKey(key) {
|
||||||
lastFocusedCreditItem = focusedElement.parentNode.nextElementSibling.querySelector(".support");
|
lastFocusedCreditItem = focusedElement.parentNode.nextElementSibling.querySelector(".support");
|
||||||
focusedElement = lastFocusedCreditItem;
|
focusedElement = lastFocusedCreditItem;
|
||||||
focusedElement.classList.add("focused");
|
focusedElement.classList.add("focused");
|
||||||
setSpriteLightness(focusedElement.firstChild);
|
focusSprite(focusedElement);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lastFocusedCreditItem = focusedElement.parentNode.nextElementSibling.querySelector(".person");
|
lastFocusedCreditItem = focusedElement.parentNode.nextElementSibling.querySelector(".person");
|
||||||
focusedElement = lastFocusedCreditItem;
|
focusedElement = lastFocusedCreditItem;
|
||||||
focusedElement.classList.add("focused");
|
focusedElement.classList.add("focused");
|
||||||
|
focusSprite(focusedElement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -993,16 +1271,20 @@ function handleKey(key) {
|
||||||
if(focusedIdentifier.previousElementSibling)
|
if(focusedIdentifier.previousElementSibling)
|
||||||
{
|
{
|
||||||
focusedIdentifier.classList.remove("focused");
|
focusedIdentifier.classList.remove("focused");
|
||||||
|
unfocusSprite(focusedIdentifier);
|
||||||
lastFocusedIdentifier = focusedIdentifier.previousElementSibling;
|
lastFocusedIdentifier = focusedIdentifier.previousElementSibling;
|
||||||
focusedIdentifier = lastFocusedIdentifier;
|
focusedIdentifier = lastFocusedIdentifier;
|
||||||
focusedIdentifier.classList.add("focused");
|
focusedIdentifier.classList.add("focused");
|
||||||
|
focusSprite(focusedIdentifier);
|
||||||
}
|
}
|
||||||
else if(focusedIdentifier.parentNode.previousElementSibling.classList.contains("ref_indices"))
|
else if(focusedIdentifier.parentNode.previousElementSibling.classList.contains("ref_indices"))
|
||||||
{
|
{
|
||||||
focusedIdentifier.classList.remove("focused");
|
focusedIdentifier.classList.remove("focused");
|
||||||
|
unfocusSprite(focusedIdentifier);
|
||||||
lastFocusedIdentifier = focusedIdentifier.parentNode.previousElementSibling.lastElementChild;
|
lastFocusedIdentifier = focusedIdentifier.parentNode.previousElementSibling.lastElementChild;
|
||||||
focusedIdentifier = lastFocusedIdentifier;
|
focusedIdentifier = lastFocusedIdentifier;
|
||||||
focusedIdentifier.classList.add("focused");
|
focusedIdentifier.classList.add("focused");
|
||||||
|
focusSprite(focusedIdentifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(focusedElement.classList.contains("filter_content"))
|
else if(focusedElement.classList.contains("filter_content"))
|
||||||
|
@ -1011,6 +1293,7 @@ function handleKey(key) {
|
||||||
focusedElement.parentNode.previousElementSibling)
|
focusedElement.parentNode.previousElementSibling)
|
||||||
{
|
{
|
||||||
focusedElement.classList.remove("focused");
|
focusedElement.classList.remove("focused");
|
||||||
|
unfocusSprite(focusedElement);
|
||||||
lastFocusedMedium = focusedElement;
|
lastFocusedMedium = focusedElement;
|
||||||
|
|
||||||
if(!lastFocusedTopic)
|
if(!lastFocusedTopic)
|
||||||
|
@ -1020,6 +1303,7 @@ function handleKey(key) {
|
||||||
lastFocusedCategory = lastFocusedTopic;
|
lastFocusedCategory = lastFocusedTopic;
|
||||||
focusedElement = lastFocusedCategory;
|
focusedElement = lastFocusedCategory;
|
||||||
focusedElement.classList.add("focused");
|
focusedElement.classList.add("focused");
|
||||||
|
focusSprite(focusedElement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(focusedElement.parentNode.classList.contains("credit"))
|
else if(focusedElement.parentNode.classList.contains("credit"))
|
||||||
|
@ -1027,14 +1311,14 @@ function handleKey(key) {
|
||||||
if(focusedElement.classList.contains("support"))
|
if(focusedElement.classList.contains("support"))
|
||||||
{
|
{
|
||||||
focusedElement.classList.remove("focused");
|
focusedElement.classList.remove("focused");
|
||||||
|
console.log(focusedElement);
|
||||||
|
unfocusSprite(focusedElement);
|
||||||
|
|
||||||
lastFocusedCreditItem = focusedElement.previousElementSibling;
|
lastFocusedCreditItem = focusedElement.previousElementSibling;
|
||||||
if(focusedElement.firstChild.classList.contains("cineraSprite"))
|
setSpriteLightness(focusedElement.firstChild);
|
||||||
{
|
|
||||||
setSpriteLightness(focusedElement.firstChild);
|
|
||||||
}
|
|
||||||
focusedElement = lastFocusedCreditItem;
|
focusedElement = lastFocusedCreditItem;
|
||||||
focusedElement.classList.add("focused");
|
focusedElement.classList.add("focused");
|
||||||
|
focusSprite(focusedElement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1048,17 +1332,21 @@ function handleKey(key) {
|
||||||
if(focusedIdentifier.nextElementSibling)
|
if(focusedIdentifier.nextElementSibling)
|
||||||
{
|
{
|
||||||
focusedIdentifier.classList.remove("focused");
|
focusedIdentifier.classList.remove("focused");
|
||||||
|
unfocusSprite(focusedIdentifier);
|
||||||
|
|
||||||
lastFocusedIdentifier = focusedIdentifier.nextElementSibling;
|
lastFocusedIdentifier = focusedIdentifier.nextElementSibling;
|
||||||
focusedIdentifier = lastFocusedIdentifier;
|
focusedIdentifier = lastFocusedIdentifier;
|
||||||
focusedIdentifier.classList.add("focused");
|
focusedIdentifier.classList.add("focused");
|
||||||
|
focusSprite(focusedIdentifier);
|
||||||
}
|
}
|
||||||
else if(focusedIdentifier.parentNode.nextElementSibling)
|
else if(focusedIdentifier.parentNode.nextElementSibling)
|
||||||
{
|
{
|
||||||
focusedIdentifier.classList.remove("focused");
|
focusedIdentifier.classList.remove("focused");
|
||||||
|
unfocusSprite(focusedIdentifier);
|
||||||
lastFocusedIdentifier = focusedIdentifier.parentNode.nextElementSibling.firstElementChild;
|
lastFocusedIdentifier = focusedIdentifier.parentNode.nextElementSibling.firstElementChild;
|
||||||
focusedIdentifier = lastFocusedIdentifier;
|
focusedIdentifier = lastFocusedIdentifier;
|
||||||
focusedIdentifier.classList.add("focused");
|
focusedIdentifier.classList.add("focused");
|
||||||
|
focusSprite(focusedIdentifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(focusedElement.classList.contains("filter_content"))
|
else if(focusedElement.classList.contains("filter_content"))
|
||||||
|
@ -1067,6 +1355,7 @@ function handleKey(key) {
|
||||||
focusedElement.parentNode.nextElementSibling)
|
focusedElement.parentNode.nextElementSibling)
|
||||||
{
|
{
|
||||||
focusedElement.classList.remove("focused");
|
focusedElement.classList.remove("focused");
|
||||||
|
unfocusSprite(focusedElement);
|
||||||
lastFocusedTopic = focusedElement;
|
lastFocusedTopic = focusedElement;
|
||||||
|
|
||||||
if(!lastFocusedMedium)
|
if(!lastFocusedMedium)
|
||||||
|
@ -1076,6 +1365,7 @@ function handleKey(key) {
|
||||||
lastFocusedCategory = lastFocusedMedium;
|
lastFocusedCategory = lastFocusedMedium;
|
||||||
focusedElement = lastFocusedCategory;
|
focusedElement = lastFocusedCategory;
|
||||||
focusedElement.classList.add("focused");
|
focusedElement.classList.add("focused");
|
||||||
|
focusSprite(focusedElement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(focusedElement.parentNode.classList.contains("credit"))
|
else if(focusedElement.parentNode.classList.contains("credit"))
|
||||||
|
@ -1084,14 +1374,12 @@ function handleKey(key) {
|
||||||
focusedElement.nextElementSibling)
|
focusedElement.nextElementSibling)
|
||||||
{
|
{
|
||||||
focusedElement.classList.remove("focused");
|
focusedElement.classList.remove("focused");
|
||||||
|
unfocusSprite(focusedElement);
|
||||||
|
|
||||||
lastFocusedCreditItem = focusedElement.nextElementSibling;
|
lastFocusedCreditItem = focusedElement.nextElementSibling;
|
||||||
focusedElement = lastFocusedCreditItem;
|
focusedElement = lastFocusedCreditItem;
|
||||||
focusedElement.classList.add("focused");
|
focusedElement.classList.add("focused");
|
||||||
if(focusedElement.firstChild.classList.contains("cineraSprite"))
|
focusSprite(focusedElement);
|
||||||
{
|
|
||||||
setSpriteLightness(focusedElement.firstChild);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1105,6 +1393,7 @@ function handleKey(key) {
|
||||||
focusedElement.nextElementSibling.classList.contains("filter_content"))
|
focusedElement.nextElementSibling.classList.contains("filter_content"))
|
||||||
{
|
{
|
||||||
focusedElement.classList.remove("focused");
|
focusedElement.classList.remove("focused");
|
||||||
|
unfocusSprite(focusedElement);
|
||||||
if(focusedElement.parentNode.classList.contains("filter_topics"))
|
if(focusedElement.parentNode.classList.contains("filter_topics"))
|
||||||
{
|
{
|
||||||
lastFocusedTopic = focusedElement.nextElementSibling;
|
lastFocusedTopic = focusedElement.nextElementSibling;
|
||||||
|
@ -1118,6 +1407,7 @@ function handleKey(key) {
|
||||||
lastFocusedElement = lastFocusedCategory;
|
lastFocusedElement = lastFocusedCategory;
|
||||||
focusedElement = lastFocusedElement;
|
focusedElement = lastFocusedElement;
|
||||||
focusedElement.classList.add("focused");
|
focusedElement.classList.add("focused");
|
||||||
|
focusSprite(focusedElement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
@ -1130,6 +1420,7 @@ function handleKey(key) {
|
||||||
focusedElement.previousElementSibling.classList.contains("filter_content"))
|
focusedElement.previousElementSibling.classList.contains("filter_content"))
|
||||||
{
|
{
|
||||||
focusedElement.classList.remove("focused");
|
focusedElement.classList.remove("focused");
|
||||||
|
unfocusSprite(focusedElement);
|
||||||
if(focusedElement.parentNode.classList.contains("filter_topics"))
|
if(focusedElement.parentNode.classList.contains("filter_topics"))
|
||||||
{
|
{
|
||||||
lastFocusedTopic = focusedElement.previousElementSibling;
|
lastFocusedTopic = focusedElement.previousElementSibling;
|
||||||
|
@ -1143,6 +1434,7 @@ function handleKey(key) {
|
||||||
lastFocusedElement = lastFocusedCategory;
|
lastFocusedElement = lastFocusedCategory;
|
||||||
focusedElement = lastFocusedElement;
|
focusedElement = lastFocusedElement;
|
||||||
focusedElement.classList.add("focused");
|
focusedElement.classList.add("focused");
|
||||||
|
focusSprite(focusedElement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
@ -1163,7 +1455,10 @@ function handleKey(key) {
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case "?": {
|
case "?": {
|
||||||
helpDocumentation.classList.toggle("visible");
|
if(helpDocumentation)
|
||||||
|
{
|
||||||
|
helpDocumentation.classList.toggle("visible");
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case 'N':
|
case 'N':
|
||||||
|
@ -1319,7 +1614,7 @@ function filterItemToggle(filterItem) {
|
||||||
filterItem.querySelector(".icon").style.backgroundColor = getComputedStyle(filterItem.querySelector(".icon")).getPropertyValue("border-color");
|
filterItem.querySelector(".icon").style.backgroundColor = getComputedStyle(filterItem.querySelector(".icon")).getPropertyValue("border-color");
|
||||||
}
|
}
|
||||||
setDotLightness(filterItem.querySelector(".icon"));
|
setDotLightness(filterItem.querySelector(".icon"));
|
||||||
var testMarkers = document.querySelectorAll(".marker.off_" + selectedCategory);
|
var testMarkers = cinera.querySelectorAll(".marker.off_" + selectedCategory);
|
||||||
for(var j = 0; j < testMarkers.length; ++j)
|
for(var j = 0; j < testMarkers.length; ++j)
|
||||||
{
|
{
|
||||||
if(filterState[selectedCategory].type == "topic")
|
if(filterState[selectedCategory].type == "topic")
|
||||||
|
@ -1461,35 +1756,36 @@ function onRefChanged(ref, element, player) {
|
||||||
{
|
{
|
||||||
player.jumpToNextMarker();
|
player.jumpToNextMarker();
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
for (var MenuIndex = 0; MenuIndex < sourceMenus.length; ++MenuIndex)
|
|
||||||
{
|
{
|
||||||
var SetMenu = 0;
|
for (var MenuIndex = 0; MenuIndex < sourceMenus.length; ++MenuIndex)
|
||||||
if (ref !== undefined && ref !== null) {
|
{
|
||||||
var refElements = sourceMenus[MenuIndex].querySelectorAll(".refs .ref");
|
var SetMenu = 0;
|
||||||
var refs = ref.split(",");
|
if (ref !== undefined && ref !== null) {
|
||||||
|
var refElements = sourceMenus[MenuIndex].querySelectorAll(".refs .ref");
|
||||||
|
var refs = ref.split(",");
|
||||||
|
|
||||||
for (var i = 0; i < refElements.length; ++i) {
|
for (var i = 0; i < refElements.length; ++i) {
|
||||||
if (refs.includes(refElements[i].getAttribute("data-id"))) {
|
if (refs.includes(refElements[i].getAttribute("data-id"))) {
|
||||||
refElements[i].classList.add("current");
|
refElements[i].classList.add("current");
|
||||||
SetMenu = 1;
|
SetMenu = 1;
|
||||||
} else {
|
} else {
|
||||||
refElements[i].classList.remove("current");
|
refElements[i].classList.remove("current");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
if(SetMenu) {
|
||||||
if(SetMenu) {
|
sourceMenus[MenuIndex].classList.add("current");
|
||||||
sourceMenus[MenuIndex].classList.add("current");
|
} else {
|
||||||
|
sourceMenus[MenuIndex].classList.remove("current");
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
sourceMenus[MenuIndex].classList.remove("current");
|
sourceMenus[MenuIndex].classList.remove("current");
|
||||||
}
|
var refs = sourceMenus[MenuIndex].querySelectorAll(".refs .ref");
|
||||||
|
for (var i = 0; i < refs.length; ++i) {
|
||||||
} else {
|
refs[i].classList.remove("current");
|
||||||
sourceMenus[MenuIndex].classList.remove("current");
|
}
|
||||||
var refs = sourceMenus[MenuIndex].querySelectorAll(".refs .ref");
|
|
||||||
for (var i = 0; i < refs.length; ++i) {
|
|
||||||
refs[i].classList.remove("current");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1574,10 +1870,11 @@ function mouseSkipToTimecode(player, time, ev)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMouseOverMenu(menu, eventType)
|
function handleMenuTogglerInteraction(menu, eventType)
|
||||||
{
|
{
|
||||||
if(!(menu.classList.contains("visible")) && eventType == "mouseenter" ||
|
if(!(menu.classList.contains("visible")) && eventType == "mouseenter" ||
|
||||||
menu.classList.contains("visible") && eventType == "mouseleave")
|
menu.classList.contains("visible") && eventType == "mouseleave" ||
|
||||||
|
(eventType == "click" && !menu.classList.contains("cineraHelp")))
|
||||||
{
|
{
|
||||||
if(menu.classList.contains("quotes"))
|
if(menu.classList.contains("quotes"))
|
||||||
{
|
{
|
||||||
|
@ -1600,10 +1897,6 @@ function handleMouseOverMenu(menu, eventType)
|
||||||
toggleMenuVisibility(creditsMenu);
|
toggleMenuVisibility(creditsMenu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(eventType == "click" && menu.classList.contains("help"))
|
|
||||||
{
|
|
||||||
helpDocumentation.classList.toggle("visible");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function RGBtoHSL(colour)
|
function RGBtoHSL(colour)
|
||||||
|
@ -1648,7 +1941,6 @@ function getBackgroundBrightness(element) {
|
||||||
var result = Math.sqrt(rgb[0] * rgb[0] * .241 +
|
var result = Math.sqrt(rgb[0] * rgb[0] * .241 +
|
||||||
rgb[1] * rgb[1] * .691 +
|
rgb[1] * rgb[1] * .691 +
|
||||||
rgb[2] * rgb[2] * .068);
|
rgb[2] * rgb[2] * .068);
|
||||||
console.log(result);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,24 @@
|
||||||
|
var orientations = {
|
||||||
|
PORTRAIT: 0,
|
||||||
|
LANDSCAPE_LEFT: 90,
|
||||||
|
LANDSCAPE_RIGHT: -90,
|
||||||
|
};
|
||||||
|
|
||||||
|
var DebugConsoleMessageCount = 0;
|
||||||
|
function Say(Message)
|
||||||
|
{
|
||||||
|
var DebugConsole = document.getElementById("debug-console");
|
||||||
|
if(DebugConsole)
|
||||||
|
{
|
||||||
|
DebugConsole.textContent += DebugConsoleMessageCount++ + ": " + Message + "\n";
|
||||||
|
DebugConsole.scrollTo(
|
||||||
|
{
|
||||||
|
top: DebugConsole.scrollHeight,
|
||||||
|
behavior: "smooth"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getBackgroundBrightness(element) {
|
function getBackgroundBrightness(element) {
|
||||||
var colour = getComputedStyle(element).getPropertyValue("background-color");
|
var colour = getComputedStyle(element).getPropertyValue("background-color");
|
||||||
var depth = 0;
|
var depth = 0;
|
||||||
|
@ -110,3 +131,233 @@ function unfocusSprite(Element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function IsMobile() {
|
||||||
|
// NOTE(matt): From https://medium.com/simplejs/detect-the-users-device-type-with-a-simple-javascript-check-4fc656b735e1
|
||||||
|
var Identifier = navigator.userAgent||navigator.vendor||window.opera;
|
||||||
|
var Result = (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(Identifier)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(Identifier.substr(0,4)));
|
||||||
|
return Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
function GetRule(SelectorText)
|
||||||
|
{
|
||||||
|
// NOTE(matt): Modifying CSS style
|
||||||
|
// from https://stackoverflow.com/a/566445
|
||||||
|
// https://usefulangle.com/post/39/adding-css-to-stylesheet-with-javascript
|
||||||
|
var Result = undefined;
|
||||||
|
|
||||||
|
var StyleSheets = document.styleSheets;
|
||||||
|
var cssRuleCode = document.all ? 'rules' : 'cssRules'; // account for IE and FF
|
||||||
|
for(var StyleSheetIndex = StyleSheets.length - 1; StyleSheetIndex >= 0; --StyleSheetIndex)
|
||||||
|
{
|
||||||
|
var ThisSheet = StyleSheets[StyleSheetIndex];
|
||||||
|
var Rules = ThisSheet[cssRuleCode];
|
||||||
|
for(var RuleIndex = Rules.length - 1; RuleIndex >= 0; --RuleIndex)
|
||||||
|
{
|
||||||
|
var ThisRule = Rules[RuleIndex];
|
||||||
|
if(SelectorText === ThisRule.selectorText)
|
||||||
|
{
|
||||||
|
Result = ThisRule;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(Result !== undefined) { break; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function
|
||||||
|
GetRulesOfStyleSheetIndex(Index)
|
||||||
|
{
|
||||||
|
var Result = undefined;
|
||||||
|
var StyleSheets = document.styleSheets;
|
||||||
|
var cssRuleCode = document.all ? 'rules' : 'cssRules'; // account for IE and FF
|
||||||
|
var StyleSheet = StyleSheets[Index];
|
||||||
|
if(StyleSheet)
|
||||||
|
{
|
||||||
|
Result = StyleSheet[cssRuleCode];
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function
|
||||||
|
GetOrSetRule(SelectorText)
|
||||||
|
{
|
||||||
|
var Result = GetRule(SelectorText);
|
||||||
|
if(Result === undefined)
|
||||||
|
{
|
||||||
|
var StyleSheet = document.styleSheets[0];
|
||||||
|
var RuleIndex = StyleSheet.insertRule(SelectorText + "{}", StyleSheet.length - 1);
|
||||||
|
var Rules = GetRulesOfStyleSheetIndex(0);
|
||||||
|
Result = Rules[RuleIndex];
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Auto-scrolling */
|
||||||
|
var LastScrollYPos = 0;
|
||||||
|
var ScrollTicking = false;
|
||||||
|
var ScrollerFunction;
|
||||||
|
var ScrollCondition;
|
||||||
|
|
||||||
|
function ScrollTo(Element, ScrollPos) {
|
||||||
|
var BoundingRect = Element.getBoundingClientRect();
|
||||||
|
var Height = BoundingRect.height;
|
||||||
|
var PercentageOfInView = 89;
|
||||||
|
var GatherableHeight = Height * (1 - PercentageOfInView / 100);
|
||||||
|
var ScrollY = BoundingRect.top;
|
||||||
|
var YOffsetFromPage = getElementYOffsetFromPage(Element);
|
||||||
|
var DesiredScroll = null;
|
||||||
|
|
||||||
|
if(ScrollY < 0)
|
||||||
|
{
|
||||||
|
ScrollY = ~ScrollY;
|
||||||
|
if(ScrollY <= GatherableHeight)
|
||||||
|
{
|
||||||
|
DesiredScroll = YOffsetFromPage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var LowerProtrusion = ScrollY - (window.innerHeight - Height);
|
||||||
|
if(LowerProtrusion > 0 && LowerProtrusion <= GatherableHeight)
|
||||||
|
{
|
||||||
|
DesiredScroll = ScrollPos + LowerProtrusion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(DesiredScroll !== null)
|
||||||
|
{
|
||||||
|
window.scrollTo({
|
||||||
|
top: DesiredScroll,
|
||||||
|
behavior: "smooth"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function
|
||||||
|
InitScrollEventListener(Element)
|
||||||
|
{
|
||||||
|
window.addEventListener('scroll', function() {
|
||||||
|
if(ScrollCondition == undefined || ScrollCondition == true)
|
||||||
|
{
|
||||||
|
LastScrollYPos = window.scrollY;
|
||||||
|
|
||||||
|
if (!ScrollTicking) {
|
||||||
|
window.requestAnimationFrame(function() {
|
||||||
|
clearTimeout(ScrollerFunction);
|
||||||
|
ScrollerFunction = setTimeout(ScrollTo, 2000, Element, LastScrollYPos);
|
||||||
|
ScrollTicking = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
ScrollTicking = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/* /Auto-scrolling */
|
||||||
|
|
||||||
|
function getElementXOffsetFromPage(el) {
|
||||||
|
var left = 0;
|
||||||
|
do {
|
||||||
|
left += el.offsetLeft;
|
||||||
|
} while (el = el.offsetParent);
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getElementYOffsetFromPage(el) {
|
||||||
|
var top = 0;
|
||||||
|
do {
|
||||||
|
top += el.offsetTop;
|
||||||
|
} while (el = el.offsetParent);
|
||||||
|
return top;
|
||||||
|
}
|
||||||
|
|
||||||
|
function
|
||||||
|
MaxWidthOfElement(Element)
|
||||||
|
{
|
||||||
|
var Result = 0;
|
||||||
|
var OriginalWidth = Element.style.width;
|
||||||
|
Element.style.width = "100%";
|
||||||
|
var Max = parseInt(window.getComputedStyle(Element).width);
|
||||||
|
Element.style.width = "unset";
|
||||||
|
var Default = parseInt(window.getComputedStyle(Element).width);
|
||||||
|
Element.style.width = OriginalWidth;
|
||||||
|
|
||||||
|
if(Max > window.innerWidth || Max == Default)
|
||||||
|
{
|
||||||
|
Result = window.innerWidth;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Result = Max;
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function
|
||||||
|
MaxHeightOfElement(Element)
|
||||||
|
{
|
||||||
|
var Result = 0;
|
||||||
|
var OriginalHeight = Element.style.height;
|
||||||
|
Element.style.height = "100%";
|
||||||
|
var Max = parseInt(window.getComputedStyle(Element).height);
|
||||||
|
Element.style.height = "unset";
|
||||||
|
var Default = parseInt(window.getComputedStyle(Element).height);
|
||||||
|
Element.style.height = OriginalHeight;
|
||||||
|
|
||||||
|
if(Max > window.innerHeight || Max == Default)
|
||||||
|
{
|
||||||
|
Result = window.innerHeight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Result = Max;
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function
|
||||||
|
Clamp(EndA, N, EndB)
|
||||||
|
{
|
||||||
|
var Min = EndA < EndB ? EndA : EndB;
|
||||||
|
var Max = EndA > EndB ? EndA : EndB;
|
||||||
|
return N < Min ? Min : N > Max ? Max : N;
|
||||||
|
}
|
||||||
|
|
||||||
|
function
|
||||||
|
Clamp01(N)
|
||||||
|
{
|
||||||
|
return N < 0 ? 0 : N > 1 ? 1 : N;
|
||||||
|
}
|
||||||
|
|
||||||
|
function
|
||||||
|
Lerp(A, t, B)
|
||||||
|
{
|
||||||
|
return (1-t)*A + t*B;
|
||||||
|
}
|
||||||
|
|
||||||
|
function
|
||||||
|
IsOverflowed(Element)
|
||||||
|
{
|
||||||
|
return Element.scrollHeight > Element.clientHeight || Element.scrollWidth > Element.clientWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
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";
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener("focus", function(){
|
||||||
|
Button.firstElementChild.innerText = "?";
|
||||||
|
Button.firstElementChild.title = ""
|
||||||
|
});
|
||||||
|
|
||||||
|
Button.addEventListener("click", function() {
|
||||||
|
DocumentationContainer.classList.toggle("visible");
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -1,642 +0,0 @@
|
||||||
document.body.style.overflowY = "scroll";
|
|
||||||
|
|
||||||
if (location.hash && location.hash.length > 0) {
|
|
||||||
var initialQuery = location.hash;
|
|
||||||
if (initialQuery[0] == "#") {
|
|
||||||
initialQuery = initialQuery.slice(1);
|
|
||||||
}
|
|
||||||
document.getElementById("query").value = decodeURIComponent(initialQuery);
|
|
||||||
}
|
|
||||||
|
|
||||||
var indexControl = document.getElementById("cineraIndexControl");
|
|
||||||
var indexSort = indexControl.querySelector("#cineraIndexSort");
|
|
||||||
var indexSortChronological = true;
|
|
||||||
|
|
||||||
var filterMenu = indexControl.querySelector(".cineraIndexFilter");
|
|
||||||
if(filterMenu)
|
|
||||||
{
|
|
||||||
var filterContainer = filterMenu.querySelector(".filter_container");
|
|
||||||
//menuState.push(linkMenu);
|
|
||||||
|
|
||||||
filterMenu.addEventListener("mouseenter", function(ev) {
|
|
||||||
filterContainer.style.display = "block";
|
|
||||||
});
|
|
||||||
|
|
||||||
filterMenu.addEventListener("mouseleave", function(ev) {
|
|
||||||
filterContainer.style.display = "none";
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function hideEntriesOfProject(ProjectElement)
|
|
||||||
{
|
|
||||||
if(!ProjectElement.classList.contains("off"))
|
|
||||||
{
|
|
||||||
ProjectElement.classList.add("off");
|
|
||||||
}
|
|
||||||
var baseURL = ProjectElement.attributes.getNamedItem("data-baseURL").value;
|
|
||||||
var searchLocation = ProjectElement.attributes.getNamedItem("data-searchLocation").value;
|
|
||||||
var playerLocation = ProjectElement.attributes.getNamedItem("data-playerLocation").value;
|
|
||||||
for(var i = 0; i < projects.length; ++i)
|
|
||||||
{
|
|
||||||
var ThisProject = projects[i];
|
|
||||||
if(baseURL === ThisProject.baseURL && searchLocation === ThisProject.searchLocation && playerLocation === ThisProject.playerLocation)
|
|
||||||
{
|
|
||||||
ThisProject.filteredOut = true;
|
|
||||||
if(ThisProject.entriesContainer != null)
|
|
||||||
{
|
|
||||||
ThisProject.entriesContainer.style.display = "none";
|
|
||||||
disableSprite(ThisProject.entriesContainer.parentElement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function showEntriesOfProject(ProjectElement)
|
|
||||||
{
|
|
||||||
if(ProjectElement.classList.contains("off"))
|
|
||||||
{
|
|
||||||
ProjectElement.classList.remove("off");
|
|
||||||
}
|
|
||||||
var baseURL = ProjectElement.attributes.getNamedItem("data-baseURL").value;
|
|
||||||
var searchLocation = ProjectElement.attributes.getNamedItem("data-searchLocation").value;
|
|
||||||
var playerLocation = ProjectElement.attributes.getNamedItem("data-playerLocation").value;
|
|
||||||
for(var i = 0; i < projects.length; ++i)
|
|
||||||
{
|
|
||||||
var ThisProject = projects[i];
|
|
||||||
if(baseURL === ThisProject.baseURL && searchLocation === ThisProject.searchLocation && playerLocation === ThisProject.playerLocation)
|
|
||||||
{
|
|
||||||
ThisProject.filteredOut = false;
|
|
||||||
if(ThisProject.entriesContainer != null)
|
|
||||||
{
|
|
||||||
ThisProject.entriesContainer.style.display = "flex";
|
|
||||||
enableSprite(ThisProject.entriesContainer.parentElement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function hideProjectSearchResults(baseURL, searchLocation, playerLocation)
|
|
||||||
{
|
|
||||||
var cineraResults = document.getElementById("cineraResults");
|
|
||||||
if(cineraResults)
|
|
||||||
{
|
|
||||||
var cineraResultsProjects = cineraResults.querySelectorAll(".projectContainer");
|
|
||||||
for(var i = 0; i < cineraResultsProjects.length; ++i)
|
|
||||||
{
|
|
||||||
var resultBaseURL = cineraResultsProjects[i].attributes.getNamedItem("data-baseURL").value;
|
|
||||||
var resultSearchLocation = cineraResultsProjects[i].attributes.getNamedItem("data-searchLocation").value;
|
|
||||||
var resultPlayerLocation = cineraResultsProjects[i].attributes.getNamedItem("data-playerLocation").value;
|
|
||||||
if(baseURL === resultBaseURL && searchLocation === resultSearchLocation && playerLocation === resultPlayerLocation)
|
|
||||||
{
|
|
||||||
cineraResultsProjects[i].style.display = "none";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function showProjectSearchResults(baseURL, searchLocation, playerLocation)
|
|
||||||
{
|
|
||||||
var cineraResults = document.getElementById("cineraResults");
|
|
||||||
if(cineraResults)
|
|
||||||
{
|
|
||||||
var cineraResultsProjects = cineraResults.querySelectorAll(".projectContainer");
|
|
||||||
for(var i = 0; i < cineraResultsProjects.length; ++i)
|
|
||||||
{
|
|
||||||
var resultBaseURL = cineraResultsProjects[i].attributes.getNamedItem("data-baseURL").value;
|
|
||||||
var resultSearchLocation = cineraResultsProjects[i].attributes.getNamedItem("data-searchLocation").value;
|
|
||||||
var resultPlayerLocation = cineraResultsProjects[i].attributes.getNamedItem("data-playerLocation").value;
|
|
||||||
if(baseURL === resultBaseURL && searchLocation === resultSearchLocation && playerLocation === resultPlayerLocation)
|
|
||||||
{
|
|
||||||
cineraResultsProjects[i].style.display = "flex";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggleEntriesOfProjectAndChildren(ProjectFilterElement)
|
|
||||||
{
|
|
||||||
var baseURL = ProjectFilterElement.attributes.getNamedItem("data-baseURL").value;
|
|
||||||
var searchLocation = ProjectFilterElement.attributes.getNamedItem("data-searchLocation").value;
|
|
||||||
var playerLocation = ProjectFilterElement.attributes.getNamedItem("data-playerLocation").value;
|
|
||||||
var shouldShow = ProjectFilterElement.classList.contains("off");
|
|
||||||
if(shouldShow)
|
|
||||||
{
|
|
||||||
ProjectFilterElement.classList.remove("off");
|
|
||||||
enableSprite(ProjectFilterElement);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ProjectFilterElement.classList.add("off");
|
|
||||||
disableSprite(ProjectFilterElement);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(var i = 0; i < projects.length; ++i)
|
|
||||||
{
|
|
||||||
var ThisProject = projects[i];
|
|
||||||
|
|
||||||
if(baseURL === ThisProject.baseURL && searchLocation === ThisProject.searchLocation && playerLocation === ThisProject.playerLocation)
|
|
||||||
{
|
|
||||||
if(shouldShow)
|
|
||||||
{
|
|
||||||
ThisProject.filteredOut = false;
|
|
||||||
enableSprite(ThisProject.projectTitleElement.parentElement);
|
|
||||||
if(ThisProject.entriesContainer != null)
|
|
||||||
{
|
|
||||||
ThisProject.entriesContainer.style.display = "flex";
|
|
||||||
}
|
|
||||||
showProjectSearchResults(ThisProject.baseURL, ThisProject.searchLocation, ThisProject.playerLocation);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ThisProject.filteredOut = true;
|
|
||||||
disableSprite(ThisProject.projectTitleElement.parentElement);
|
|
||||||
if(ThisProject.entriesContainer != null)
|
|
||||||
{
|
|
||||||
ThisProject.entriesContainer.style.display = "none";
|
|
||||||
}
|
|
||||||
hideProjectSearchResults(ThisProject.baseURL, ThisProject.searchLocation, ThisProject.playerLocation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var indexChildFilterProjects = ProjectFilterElement.querySelectorAll(".cineraFilterProject");
|
|
||||||
|
|
||||||
for(var j = 0; j < indexChildFilterProjects.length; ++j)
|
|
||||||
{
|
|
||||||
var ThisElement = indexChildFilterProjects[j];
|
|
||||||
var baseURL = ThisElement.attributes.getNamedItem("data-baseURL").value;
|
|
||||||
var searchLocation = ThisElement.attributes.getNamedItem("data-searchLocation").value;
|
|
||||||
var playerLocation = ThisElement.attributes.getNamedItem("data-playerLocation").value;
|
|
||||||
if(shouldShow)
|
|
||||||
{
|
|
||||||
showEntriesOfProject(ThisElement);
|
|
||||||
showProjectSearchResults(baseURL, searchLocation, playerLocation);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hideEntriesOfProject(ThisElement);
|
|
||||||
hideProjectSearchResults(baseURL, searchLocation, playerLocation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var indexFilter = indexControl.querySelector(".cineraIndexFilter");
|
|
||||||
if(indexFilter)
|
|
||||||
{
|
|
||||||
var indexFilterProjects = indexFilter.querySelectorAll(".cineraFilterProject");
|
|
||||||
for(var i = 0; i < indexFilterProjects.length; ++i)
|
|
||||||
{
|
|
||||||
indexFilterProjects[i].addEventListener("mouseover", function(ev) {
|
|
||||||
ev.stopPropagation();
|
|
||||||
this.classList.add("focused");
|
|
||||||
focusSprite(this);
|
|
||||||
});
|
|
||||||
indexFilterProjects[i].addEventListener("mouseout", function(ev) {
|
|
||||||
ev.stopPropagation();
|
|
||||||
this.classList.remove("focused");
|
|
||||||
unfocusSprite(this);
|
|
||||||
});
|
|
||||||
indexFilterProjects[i].addEventListener("click", function(ev) {
|
|
||||||
ev.stopPropagation();
|
|
||||||
toggleEntriesOfProjectAndChildren(this);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var resultsSummary = document.getElementById("cineraResultsSummary");
|
|
||||||
var resultsContainer = document.getElementById("cineraResults");
|
|
||||||
|
|
||||||
var indexContainer = document.getElementById("cineraIndex");
|
|
||||||
|
|
||||||
var projectsContainer = indexContainer.querySelectorAll(".cineraIndexProject");
|
|
||||||
|
|
||||||
var projectContainerPrototype = document.createElement("DIV");
|
|
||||||
projectContainerPrototype.classList.add("projectContainer");
|
|
||||||
|
|
||||||
var dayContainerPrototype = document.createElement("DIV");
|
|
||||||
dayContainerPrototype.classList.add("dayContainer");
|
|
||||||
|
|
||||||
var dayNamePrototype = document.createElement("SPAN");
|
|
||||||
dayNamePrototype.classList.add("dayName");
|
|
||||||
dayContainerPrototype.appendChild(dayNamePrototype);
|
|
||||||
|
|
||||||
var markerListPrototype = document.createElement("DIV");
|
|
||||||
markerListPrototype.classList.add("markerList");
|
|
||||||
dayContainerPrototype.appendChild(markerListPrototype);
|
|
||||||
|
|
||||||
var markerPrototype = document.createElement("A");
|
|
||||||
markerPrototype.classList.add("marker");
|
|
||||||
if(resultsContainer.getAttribute("data-single") == 0)
|
|
||||||
{
|
|
||||||
markerPrototype.setAttribute("target", "_blank");
|
|
||||||
}
|
|
||||||
|
|
||||||
function prepareToParseIndexFile(project)
|
|
||||||
{
|
|
||||||
project.xhr.addEventListener("load", function() {
|
|
||||||
var contents = project.xhr.response;
|
|
||||||
var lines = contents.split("\n");
|
|
||||||
var mode = "none";
|
|
||||||
var episode = null;
|
|
||||||
for (var i = 0; i < lines.length; ++i) {
|
|
||||||
var line = lines[i];
|
|
||||||
if (line.trim().length == 0) { continue; }
|
|
||||||
if (line == "---") {
|
|
||||||
if (episode != null && episode.name != null && episode.title != null) {
|
|
||||||
episode.filename = episode.name;
|
|
||||||
episode.day = getEpisodeName(episode.filename + ".html.md");
|
|
||||||
episode.dayContainerPrototype = project.dayContainerPrototype;
|
|
||||||
episode.markerPrototype = markerPrototype;
|
|
||||||
episode.playerURLPrefix = project.playerURLPrefix;
|
|
||||||
project.episodes.push(episode);
|
|
||||||
}
|
|
||||||
episode = {};
|
|
||||||
mode = "none";
|
|
||||||
} else if (line.startsWith("name:")) {
|
|
||||||
episode.name = line.slice(6);
|
|
||||||
} else if (line.startsWith("title:")) {
|
|
||||||
episode.title = line.slice(7).trim().slice(1, -1);
|
|
||||||
} else if (line.startsWith("markers")) {
|
|
||||||
mode = "markers";
|
|
||||||
episode.markers = [];
|
|
||||||
} else if (mode == "markers") {
|
|
||||||
var match = line.match(/"(\d+)": "(.+)"/);
|
|
||||||
if (match == null) {
|
|
||||||
console.log(name, line);
|
|
||||||
} else {
|
|
||||||
var totalTime = parseInt(line.slice(1));
|
|
||||||
var marker = {
|
|
||||||
totalTime: totalTime,
|
|
||||||
prettyTime: markerTime(totalTime),
|
|
||||||
text: match[2].replace(/\\"/g, "\"")
|
|
||||||
}
|
|
||||||
episode.markers.push(marker);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
document.querySelector(".spinner").classList.remove("show");
|
|
||||||
project.parsed = true;
|
|
||||||
runSearch(true);
|
|
||||||
});
|
|
||||||
project.xhr.addEventListener("error", function() {
|
|
||||||
console.error("Failed to load content");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var projects = [];
|
|
||||||
function prepareProjects()
|
|
||||||
{
|
|
||||||
for(var i = 0; i < projectsContainer.length; ++i)
|
|
||||||
{
|
|
||||||
var ID = projectsContainer[i].attributes.getNamedItem("data-project").value;
|
|
||||||
var baseURL = projectsContainer[i].attributes.getNamedItem("data-baseURL").value;
|
|
||||||
var searchLocation = projectsContainer[i].attributes.getNamedItem("data-searchLocation").value;
|
|
||||||
var playerLocation = projectsContainer[i].attributes.getNamedItem("data-playerLocation").value;
|
|
||||||
var theme = projectsContainer[i].classList.item(1);
|
|
||||||
|
|
||||||
projects[i] =
|
|
||||||
{
|
|
||||||
baseURL: baseURL,
|
|
||||||
searchLocation: searchLocation,
|
|
||||||
playerLocation: playerLocation,
|
|
||||||
playerURLPrefix: (baseURL ? baseURL + "/" : "") + (playerLocation ? playerLocation + "/" : ""),
|
|
||||||
indexLocation: (baseURL ? baseURL + "/" : "") + (searchLocation ? searchLocation + "/" : "") + ID + ".index",
|
|
||||||
projectTitleElement: projectsContainer[i].querySelector(":scope > .cineraProjectTitle"),
|
|
||||||
entriesContainer: projectsContainer[i].querySelector(":scope > .cineraIndexEntries"),
|
|
||||||
dayContainerPrototype: dayContainerPrototype.cloneNode(true),
|
|
||||||
filteredOut: false,
|
|
||||||
parsed: false,
|
|
||||||
searched: false,
|
|
||||||
resultsToRender: [],
|
|
||||||
resultsIndex: 0,
|
|
||||||
theme: theme,
|
|
||||||
episodes: [],
|
|
||||||
xhr: new XMLHttpRequest(),
|
|
||||||
}
|
|
||||||
|
|
||||||
projects[i].dayContainerPrototype.classList.add(theme);
|
|
||||||
projects[i].dayContainerPrototype.children[1].classList.add(theme);
|
|
||||||
|
|
||||||
document.querySelector(".spinner").classList.add("show");
|
|
||||||
projects[i].xhr.open("GET", projects[i].indexLocation);
|
|
||||||
projects[i].xhr.setRequestHeader("Content-Type", "text/plain");
|
|
||||||
projects[i].xhr.send();
|
|
||||||
prepareToParseIndexFile(projects[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
prepareProjects();
|
|
||||||
|
|
||||||
indexSort.addEventListener("click", function(ev) {
|
|
||||||
if(indexSortChronological)
|
|
||||||
{
|
|
||||||
this.firstChild.nodeValue = "Sort: New to Old ⏷"
|
|
||||||
for(var i = 0; i < projects.length; ++i)
|
|
||||||
{
|
|
||||||
if(projects[i].entriesContainer)
|
|
||||||
{
|
|
||||||
projects[i].entriesContainer.style.flexFlow = "column-reverse";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.firstChild.nodeValue = "Sort: Old to New ⏶"
|
|
||||||
for(var i = 0; i < projects.length; ++i)
|
|
||||||
{
|
|
||||||
if(projects[i].entriesContainer)
|
|
||||||
{
|
|
||||||
projects[i].entriesContainer.style.flexFlow = "column";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
indexSortChronological = !indexSortChronological;
|
|
||||||
runSearch(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
var lastQuery = null;
|
|
||||||
var markerList = null;
|
|
||||||
var projectContainer = null;
|
|
||||||
var resultsMarkerIndex = -1;
|
|
||||||
var rendering = false;
|
|
||||||
|
|
||||||
var highlightPrototype = document.createElement("B");
|
|
||||||
|
|
||||||
function getEpisodeName(filename) {
|
|
||||||
var day = filename;
|
|
||||||
var dayParts = day.match(/([a-zA-Z_-]+)([0-9]+)?([a-zA-Z]+)?/);
|
|
||||||
day = dayParts[1].slice(0, 1).toUpperCase() + dayParts[1].slice(1) + (dayParts[2] ? " " + dayParts[2] : "") + (dayParts[3] ? " " + dayParts[3].toUpperCase() : "");
|
|
||||||
return day;
|
|
||||||
}
|
|
||||||
|
|
||||||
function markerTime(totalTime) {
|
|
||||||
var markTime = "(";
|
|
||||||
var hours = Math.floor(totalTime / 60 / 60);
|
|
||||||
var minutes = Math.floor(totalTime / 60) % 60;
|
|
||||||
var seconds = totalTime % 60;
|
|
||||||
if (hours > 0) {
|
|
||||||
markTime += padTimeComponent(hours) + ":";
|
|
||||||
}
|
|
||||||
|
|
||||||
markTime += padTimeComponent(minutes) + ":" + padTimeComponent(seconds) + ")";
|
|
||||||
|
|
||||||
return markTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
function padTimeComponent(component) {
|
|
||||||
return (component < 10 ? "0" + component : component);
|
|
||||||
}
|
|
||||||
|
|
||||||
function resetProjectsForSearch()
|
|
||||||
{
|
|
||||||
for(var i = 0; i < projects.length; ++i)
|
|
||||||
{
|
|
||||||
var project = projects[i];
|
|
||||||
project.searched = false;
|
|
||||||
project.resultsToRender = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var renderHandle;
|
|
||||||
|
|
||||||
function runSearch(refresh) {
|
|
||||||
var queryStr = document.getElementById("query").value;
|
|
||||||
if (refresh || lastQuery != queryStr) {
|
|
||||||
var oldResultsContainer = resultsContainer;
|
|
||||||
resultsContainer = oldResultsContainer.cloneNode(false);
|
|
||||||
oldResultsContainer.parentNode.insertBefore(resultsContainer, oldResultsContainer);
|
|
||||||
oldResultsContainer.remove();
|
|
||||||
for(var i = 0; i < projects.length; ++i)
|
|
||||||
{
|
|
||||||
projects[i].resultsIndex = 0;
|
|
||||||
}
|
|
||||||
resultsMarkerIndex = -1;
|
|
||||||
}
|
|
||||||
lastQuery = queryStr;
|
|
||||||
|
|
||||||
resetProjectsForSearch();
|
|
||||||
|
|
||||||
var numEpisodes = 0;
|
|
||||||
var numMarkers = 0;
|
|
||||||
var totalSeconds = 0;
|
|
||||||
|
|
||||||
// NOTE(matt): Function defined within runSearch() so that we can modify numEpisodes, numMarkers and totalSeconds
|
|
||||||
function runSearchInterior(resultsToRender, query, episode)
|
|
||||||
{
|
|
||||||
var matches = [];
|
|
||||||
for (var k = 0; k < episode.markers.length; ++k) {
|
|
||||||
query.lastIndex = 0;
|
|
||||||
var result = query.exec(episode.markers[k].text);
|
|
||||||
if (result && result[0].length > 0) {
|
|
||||||
numMarkers++;
|
|
||||||
matches.push(episode.markers[k]);
|
|
||||||
if (k < episode.markers.length-1) {
|
|
||||||
totalSeconds += episode.markers[k+1].totalTime - episode.markers[k].totalTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (matches.length > 0) {
|
|
||||||
numEpisodes++;
|
|
||||||
resultsToRender.push({
|
|
||||||
query: query,
|
|
||||||
episode: episode,
|
|
||||||
matches: matches
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (queryStr && queryStr.length > 0) {
|
|
||||||
indexContainer.style.display = "none";
|
|
||||||
resultsSummary.style.display = "block";
|
|
||||||
var shouldRender = false;
|
|
||||||
var query = new RegExp(queryStr.replace("(", "\\(").replace(")", "\\)").replace(/\|+/, "\|").replace(/\|$/, "").replace(/(^|[^\\])\\$/, "$1"), "gi");
|
|
||||||
|
|
||||||
// Visible
|
|
||||||
for(var i = 0; i < projects.length; ++i)
|
|
||||||
{
|
|
||||||
var project = projects[i];
|
|
||||||
if(project.parsed && !project.filteredOut && project.episodes.length > 0) {
|
|
||||||
if(indexSortChronological)
|
|
||||||
{
|
|
||||||
for(var j = 0; j < project.episodes.length; ++j) {
|
|
||||||
var episode = project.episodes[j];
|
|
||||||
runSearchInterior(project.resultsToRender, query, episode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for(var j = project.episodes.length; j > 0; --j) {
|
|
||||||
var episode = project.episodes[j - 1];
|
|
||||||
runSearchInterior(project.resultsToRender, query, episode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
shouldRender = true;
|
|
||||||
project.searched = true;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invisible
|
|
||||||
for(var i = 0; i < projects.length; ++i)
|
|
||||||
{
|
|
||||||
var project = projects[i];
|
|
||||||
if(project.parsed && project.filteredOut && !project.searched && project.episodes.length > 0) {
|
|
||||||
if(indexSortChronological)
|
|
||||||
{
|
|
||||||
for(var j = 0; j < project.episodes.length; ++j) {
|
|
||||||
var episode = project.episodes[j];
|
|
||||||
runSearchInterior(project.resultsToRender, query, episode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for(var j = project.episodes.length; j > 0; --j) {
|
|
||||||
var episode = project.episodes[j - 1];
|
|
||||||
runSearchInterior(project.resultsToRender, query, episode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
shouldRender = true;
|
|
||||||
project.searched = true;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(shouldRender)
|
|
||||||
{
|
|
||||||
if (rendering) {
|
|
||||||
clearTimeout(renderHandle);
|
|
||||||
}
|
|
||||||
renderResults();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
indexContainer.style.display = "block";
|
|
||||||
resultsSummary.style.display = "none";
|
|
||||||
}
|
|
||||||
|
|
||||||
var totalTime = Math.floor(totalSeconds/60/60) + "h " + Math.floor(totalSeconds/60)%60 + "m " + totalSeconds%60 + "s ";
|
|
||||||
|
|
||||||
resultsSummary.textContent = "Found: " + numEpisodes + " episodes, " + numMarkers + " markers, " + totalTime + "total.";
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderResults() {
|
|
||||||
var maxItems = 42;
|
|
||||||
var numItems = 0;
|
|
||||||
for(var i = 0; i < projects.length; ++i)
|
|
||||||
{
|
|
||||||
var project = projects[i];
|
|
||||||
if (project.resultsIndex < project.resultsToRender.length) {
|
|
||||||
rendering = true;
|
|
||||||
while (numItems < maxItems && project.resultsIndex < project.resultsToRender.length) {
|
|
||||||
var query = project.resultsToRender[project.resultsIndex].query;
|
|
||||||
var episode = project.resultsToRender[project.resultsIndex].episode;
|
|
||||||
var matches = project.resultsToRender[project.resultsIndex].matches;
|
|
||||||
if (resultsMarkerIndex == -1) {
|
|
||||||
if(project.resultsIndex == 0 || project.resultsToRender[project.resultsIndex - 1].episode.playerURLPrefix != episode.playerURLPrefix)
|
|
||||||
{
|
|
||||||
projectContainer = projectContainerPrototype.cloneNode(true);
|
|
||||||
for(var i = 0; i < projects.length; ++i)
|
|
||||||
{
|
|
||||||
if(projects[i].playerURLPrefix === episode.playerURLPrefix)
|
|
||||||
{
|
|
||||||
projectContainer.setAttribute("data-baseURL", projects[i].baseURL);
|
|
||||||
projectContainer.setAttribute("data-searchLocation", projects[i].searchLocation);
|
|
||||||
projectContainer.setAttribute("data-playerLocation", projects[i].playerLocation);
|
|
||||||
if(projects[i].filteredOut)
|
|
||||||
{
|
|
||||||
projectContainer.style.display = "none";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resultsContainer.appendChild(projectContainer);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
projectContainer = resultsContainer.lastElementChild;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var dayContainer = episode.dayContainerPrototype.cloneNode(true);
|
|
||||||
var dayName = dayContainer.children[0];
|
|
||||||
markerList = dayContainer.children[1];
|
|
||||||
dayName.textContent = episode.day + ": " + episode.title;
|
|
||||||
projectContainer.appendChild(dayContainer);
|
|
||||||
resultsMarkerIndex = 0;
|
|
||||||
numItems++;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (numItems < maxItems && resultsMarkerIndex < matches.length) {
|
|
||||||
var match = matches[resultsMarkerIndex];
|
|
||||||
var marker = episode.markerPrototype.cloneNode(true);
|
|
||||||
marker.setAttribute("href", episode.playerURLPrefix + episode.filename.replace(/"/g, "") + "/#" + match.totalTime);
|
|
||||||
query.lastIndex = 0;
|
|
||||||
var cursor = 0;
|
|
||||||
var text = match.text;
|
|
||||||
var result = null;
|
|
||||||
marker.appendChild(document.createTextNode(match.prettyTime + " "));
|
|
||||||
while (result = query.exec(text)) {
|
|
||||||
if (result.index > cursor) {
|
|
||||||
marker.appendChild(document.createTextNode(text.slice(cursor, result.index)));
|
|
||||||
}
|
|
||||||
var highlightEl = highlightPrototype.cloneNode();
|
|
||||||
highlightEl.textContent = result[0];
|
|
||||||
marker.appendChild(highlightEl);
|
|
||||||
cursor = result.index + result[0].length;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cursor < text.length) {
|
|
||||||
marker.appendChild(document.createTextNode(text.slice(cursor, text.length)));
|
|
||||||
}
|
|
||||||
markerList.appendChild(marker);
|
|
||||||
numItems++;
|
|
||||||
resultsMarkerIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resultsMarkerIndex == matches.length) {
|
|
||||||
resultsMarkerIndex = -1;
|
|
||||||
project.resultsIndex++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
renderHandle = setTimeout(renderResults, 0);
|
|
||||||
} else {
|
|
||||||
rendering = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function IsVisible(el) {
|
|
||||||
var xPos = 0;
|
|
||||||
var yPos = 0;
|
|
||||||
var Height = parseInt(getComputedStyle(el).height);
|
|
||||||
|
|
||||||
while (el) {
|
|
||||||
if (el.tagName == "BODY") {
|
|
||||||
var xScroll = el.scrollLeft || document.documentElement.scrollLeft;
|
|
||||||
var yScroll = el.scrollTop || document.documentElement.scrollTop;
|
|
||||||
|
|
||||||
xPos += (el.offsetLeft - xScroll + el.clientLeft)
|
|
||||||
yPos += (el.offsetTop - yScroll + el.clientTop)
|
|
||||||
} else {
|
|
||||||
xPos += (el.offsetLeft - el.scrollLeft + el.clientLeft);
|
|
||||||
yPos += (el.offsetTop - el.scrollTop + el.clientTop);
|
|
||||||
}
|
|
||||||
|
|
||||||
el = el.offsetParent;
|
|
||||||
}
|
|
||||||
return ((xPos > 0 && xPos < window.innerWidth) && (yPos > 0 && yPos + Height < window.innerHeight));
|
|
||||||
}
|
|
||||||
|
|
||||||
var queryEl = document.getElementById("query");
|
|
||||||
if(document.hasFocus() && IsVisible(queryEl)) { queryEl.focus(); }
|
|
||||||
queryEl.addEventListener("input", function(ev) {
|
|
||||||
history.replaceState(null, null, "#" + encodeURIComponent(queryEl.value));
|
|
||||||
runSearch();
|
|
||||||
});
|
|
||||||
|
|
||||||
runSearch();
|
|
||||||
|
|
||||||
// Testing
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
document.body.style.overflowY = "scroll";
|
||||||
|
|
||||||
|
// Element Selection
|
||||||
|
//
|
||||||
|
Nav.Nexus = document.getElementById("cineraIndex");
|
||||||
|
Nav.Controls.Header = document.getElementById("cineraIndexControl");
|
||||||
|
Nav.Controls.Sort = Nav.Controls.Header.querySelector(".cineraMenuItem.sort");
|
||||||
|
Nav.Controls.View = Nav.Controls.Header.querySelector(".cineraMenuItem.view");
|
||||||
|
Nav.Controls.Anim = Nav.Controls.Header.querySelector(".cineraMenuItem.anim");
|
||||||
|
Nav.Controls.Save = Nav.Controls.Header.querySelector(".cineraMenuItem.save");
|
||||||
|
Nav.Controls.Help = Nav.Nexus.querySelector(".cineraHelp");
|
||||||
|
Nav.Controls.HelpDocumentation = Nav.Controls.Help.querySelector(".help_container");
|
||||||
|
Nav.GridContainer = Nav.Nexus.querySelector(".cineraIndexGridContainer");
|
||||||
|
Nav.Controls.GridTraversal.Header = Nav.GridContainer.querySelector(".cineraTraversal");
|
||||||
|
Nav.Controls.GridTraversal.Ascend = Nav.Controls.GridTraversal.Header.querySelector(".cineraButton.ascension");
|
||||||
|
Nav.Controls.GridTraversal.Prev = Nav.Controls.GridTraversal.Header.querySelector(".cineraButton.prev");
|
||||||
|
Nav.Controls.GridTraversal.Next = Nav.Controls.GridTraversal.Header.querySelector(".cineraButton.next");
|
||||||
|
|
||||||
|
Search.QueryElement = document.getElementById("query");
|
||||||
|
Search.ResultsSummary = document.getElementById("cineraResultsSummary");
|
||||||
|
Search.ResultsContainer = document.getElementById("cineraResults");
|
||||||
|
Search.IndexContainer = document.getElementById("cineraIndexList");
|
||||||
|
Search.ProjectsContainer = Search.IndexContainer.querySelectorAll(".cineraIndexProject");
|
||||||
|
//
|
||||||
|
///
|
||||||
|
|
||||||
|
// NOTE(matt): Initialisation
|
||||||
|
//
|
||||||
|
if(CineraProps.IsMobile)
|
||||||
|
{
|
||||||
|
Nav.Nexus.classList.add("mobile");
|
||||||
|
}
|
||||||
|
InitTraversalStack();
|
||||||
|
InitNexus();
|
||||||
|
InitHelpKeys(Nav.Controls.HelpDocumentation);
|
||||||
|
Nav.GridSize = ComputeOptimalGridSize();
|
||||||
|
SetHelpKeyAvailability(Nav.GridSize);
|
||||||
|
InitButtons(); // NOTE(matt): Also does "keydown" listeners, needed before UpdateButtons()
|
||||||
|
UpdateButtons();
|
||||||
|
|
||||||
|
InitQuery(Search.QueryElement);
|
||||||
|
InitPrototypes(Search.ResultsContainer);
|
||||||
|
prepareProjects();
|
||||||
|
|
||||||
|
SyncNavState();
|
||||||
|
//
|
||||||
|
////
|
||||||
|
|
||||||
|
// NOTE(matt): Listeners
|
||||||
|
//
|
||||||
|
BindControls();
|
||||||
|
InitResizeEventListener();
|
||||||
|
InitOrientationChangeListener();
|
||||||
|
InitScrollEventListener(Nav.Nexus);
|
||||||
|
//
|
||||||
|
////
|
||||||
|
|
||||||
|
// NOTE(matt): On-load Execution
|
||||||
|
//
|
||||||
|
runSearch();
|
||||||
|
//
|
||||||
|
////
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue