cinera.c: Search [#7]
Also put the stuff in a new directory called cinera, that contains only the files needed to get going, with example template files.
This commit is contained in:
parent
c7d764c0a6
commit
4572817837
108
README.md
108
README.md
|
@ -1,81 +1,125 @@
|
|||
Fair warning: This is all under development and not yet packaged up for easy
|
||||
deployment
|
||||
|
||||
## hmml_to_html
|
||||
## cinera
|
||||
|
||||
### Download, and prepare the parser
|
||||
|
||||
1. `git clone git@gitssh.handmade.network:Annotation-Pushers/Annotation-System.git`
|
||||
2. `cd Annotation-System/hmmlib`
|
||||
3. `make`
|
||||
4. `cp hmml.a hmmlib.h ../hmml_to_html/`
|
||||
5. `cd ../hmml_to_html/`
|
||||
4. `cp hmml.a hmmlib.h ../cinera/`
|
||||
5. `cd ../cinera/`
|
||||
|
||||
Note: For each parser update, remember to make and copy it into place
|
||||
|
||||
### Build
|
||||
|
||||
1. `zsh hmml_to_html.c` (replacing zsh with your shell as appropriate)
|
||||
1. `zsh cinera.c` (replacing zsh with your shell as appropriate)
|
||||
|
||||
### Run
|
||||
|
||||
#### Ordinary operation
|
||||
#### Single Edition operation
|
||||
|
||||
./hmml_to_html test.hmml
|
||||
cinera test.hmml
|
||||
|
||||
This simply generates an HTML file (and updates `cinera_topics.css` if needed)
|
||||
from `test.hmml` and outputs to `out.html`
|
||||
|
||||
Note that if the `.hmml` file contains quotes (as `test.hmml` does), it would be
|
||||
easiest for now just to remove the quote from `test.hmml`. If you want quotes
|
||||
to work, run:
|
||||
#### Project Edition operation
|
||||
|
||||
mkdir /home/matt/git/GitHub/insofaras/25fc16d58a297a486334
|
||||
git clone https://gist.github.com/insofaras/25fc16d58a297a486334 /home/matt/git/GitHub/insofaras/25fc16d58a297a486334
|
||||
cinera -p ProjectID
|
||||
|
||||
(Seriously, the path is hardcoded for now)
|
||||
Setting the ProjectID with the `-p` flag triggers Project Edition. In this
|
||||
edition `cinera` monitors the Project Input Directory for new, edited and
|
||||
deleted .hmml files, and generates one table of contents / search page and a
|
||||
player page each for valid sets of annotations (or removes them, if needed).
|
||||
|
||||
Note also that `cinera.css` contains a `body {}` block at the bottom which you
|
||||
may want to remove / comment out
|
||||
By default all directories - input and output - are set to the current working
|
||||
directory. Typical operation will involve setting these flags:
|
||||
|
||||
-d Project Input Directory, the directory where the .hmml files reside
|
||||
-r Root Directory, path shallower than or equal to the CSS, Images and JS
|
||||
directories
|
||||
-u Root URL, corresponding to the Root Directory (optional if the Output
|
||||
Base Directory resides in the Root Directory)
|
||||
-b Output Base Directory, location of the table of contents / search page
|
||||
-t Player Template Location
|
||||
-x Index Template Location
|
||||
|
||||
#### Integration
|
||||
|
||||
CINERA_MODE=INTEGRATE ./hmml_to_html test.hmml
|
||||
CINERA_MODE=INTEGRATE cinera test.hmml
|
||||
|
||||
This will integrate into `template.html` (currently hardcoded) the player and
|
||||
related elements generated from `test.hmml` and output to `out.html`
|
||||
This will integrate into `template_player.html` (configurable with -t) the
|
||||
player and related elements generated from `test.hmml` and output to
|
||||
`out_integrated.html`
|
||||
|
||||
Feel free to play with `template.html` to your heart's content. If you do
|
||||
anything invalid, `hmml_to_html` will tell you what's wrong
|
||||
Feel free to play with `template_player.html` to your heart's content. If you do
|
||||
anything invalid, `cinera` will tell you what's wrong
|
||||
|
||||
#### Templates
|
||||
|
||||
Valid tags:
|
||||
|
||||
- `<!-- __CINERA_TITLE__ -->` _the day / episode name, intended to be used
|
||||
inside your own `<title>` element, but may be used wherever and as many times
|
||||
as you want on your page_
|
||||
|
||||
*Index Template*
|
||||
- `<!-- __CINERA_INCLUDES__ -->` _the necessary `.css` and `.js` files_
|
||||
- `<!-- __CINERA_INDEX__ -->` _the table of contents, and search functionality_
|
||||
|
||||
*Player Template*
|
||||
- `<!-- __CINERA_INCLUDES__ -->` _the necessary `.css` and `.js` files, and charset setting_
|
||||
- `<!-- __CINERA_MENUS__ -->` _ _the menu bar that typically appears above the
|
||||
player in my samples_
|
||||
- `<!-- __CINERA_MENUS__ -->` _ _the menu bar that typically appears above the player in my samples_
|
||||
- `<!-- __CINERA_PLAYER__ -->` _the player_
|
||||
- `<!-- __CINERA_SCRIPT__ -->` _the listeners that enable interaction with the player_
|
||||
- `<!-- __CINERA_SCRIPT__ -->` _the filter state objects and `.js` file, which must come after both the MENUS and PLAYER tags_
|
||||
|
||||
#### Arguments
|
||||
|
||||
Usage: ./hmml_to_html [option(s)] filename(s)
|
||||
Usage: ./cinera [option(s)] filename(s)
|
||||
|
||||
Options:
|
||||
Paths:
|
||||
-r <root directory>
|
||||
Override default root directory (".")
|
||||
-u <root URL>
|
||||
Override default root URL ("")
|
||||
-b <base output directory>
|
||||
Override project's default base output directory (".")
|
||||
-c <CSS directory path>
|
||||
Override default CSS directory (".")
|
||||
Override default CSS directory (""), relative to root
|
||||
-i <images directory path>
|
||||
Override default images directory (".")
|
||||
Override default images directory (""), relative to root
|
||||
-j <JS directory path>
|
||||
Override default JS directory (".")
|
||||
-o <output location>
|
||||
Override default output location ("out.html")
|
||||
-q <quotes directory path>
|
||||
Override default quotes directory ("/home/matt/git/GitHub/insofaras/25fc16d58a297a486334")
|
||||
-t <template location>
|
||||
Override default template location ("template.html")
|
||||
Override default JS directory (""), relative to root
|
||||
-t <player template location>
|
||||
Override default player template location ("template_player.html"), relative to root
|
||||
and automatically enable integration
|
||||
-x <index template location>
|
||||
Override default index template location ("template_index.html"), relative to root
|
||||
and automatically enable integration
|
||||
|
||||
-o <output location>
|
||||
Override default output player location for SINGLE_EDITION ("out.html")
|
||||
-d <project directory>
|
||||
Override default project directory (".")
|
||||
|
||||
-f
|
||||
Force integration with an incomplete template
|
||||
-p <project ID>
|
||||
Set the project ID, corresponding to the "project" field in the HMML files
|
||||
-l <n>
|
||||
Override default log level (0), where n is from 0 (terse) to 7 (verbose)
|
||||
-m <default medium>
|
||||
Override default default medium ("programming")
|
||||
-U <seconds>
|
||||
Override default update interval ("4")
|
||||
-h
|
||||
display this help
|
||||
|
||||
#### Environment Variables
|
||||
|
||||
CINERA_MODE=INTEGRATE
|
||||
Enable integration
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,3 +1,87 @@
|
|||
/* Index */
|
||||
|
||||
.queryContainer {
|
||||
width: 1024px;
|
||||
margin: 15px auto;
|
||||
display: flex;
|
||||
flex-direction: horizontal;
|
||||
}
|
||||
|
||||
.queryContainer label {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.queryContainer .inputContainer {
|
||||
flex-grow: 1;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#query {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: 5px;
|
||||
color: black;
|
||||
height: 100%;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.spinner.show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#results,
|
||||
#cineraIndex {
|
||||
width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.dayName {
|
||||
width: 200px;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
box-sizing: border-box;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
#cineraIndex dt a {
|
||||
display: block;
|
||||
padding: 5px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.markerList {
|
||||
display: inline-block;
|
||||
width: 600px;
|
||||
box-sizing: border-box;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.markerList > .marker {
|
||||
padding: 10px 5px;
|
||||
cursor: pointer;
|
||||
border-top: 1px solid;
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.markerList > .marker:first-child {
|
||||
border: none;
|
||||
}
|
||||
|
||||
#resultsSummary {
|
||||
text-align: center;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
/* Player */
|
||||
|
||||
/* Structure */
|
||||
|
||||
.title,
|
||||
|
@ -181,10 +265,14 @@
|
|||
}
|
||||
|
||||
.title > .menu > .credits_container .credit .support {
|
||||
text-align: right;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.title > .menu > .credits_container .credit .support .support_icon {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
.title > .menu > .refs .ref:last-child,
|
||||
.title > .menu > .credits_container .credit:last-child {
|
||||
border: none;
|
|
@ -1,3 +1,37 @@
|
|||
/* Search */
|
||||
|
||||
.dayContainer.hero,
|
||||
#cineraIndex.hero dt {
|
||||
background-color: #161616;
|
||||
}
|
||||
|
||||
.dayContainer:nth-child(2n).hero,
|
||||
#cineraIndex.hero dt:nth-child(2n) {
|
||||
background-color: #303030;
|
||||
}
|
||||
|
||||
.dayContainer.hero > .dayName,
|
||||
#cineraIndex.hero dt a {
|
||||
color: #8A877D;
|
||||
}
|
||||
|
||||
.markerList.hero > .marker
|
||||
{
|
||||
border-color: rgba(255, 255, 255, 0.1);
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
.markerList.hero > .marker b {
|
||||
color: black;
|
||||
background-color: rgb(255, 155, 0);
|
||||
}
|
||||
|
||||
.markerList.hero > .marker:hover {
|
||||
background-color: #444;
|
||||
}
|
||||
|
||||
/* Player */
|
||||
|
||||
.title.hero,
|
||||
.title.hero .menu .refs,
|
||||
.title.hero .menu > .refs .ref,
|
|
@ -1,3 +1,6 @@
|
|||
.dayContainer.riscy,
|
||||
#cineraIndex.riscy dt,
|
||||
|
||||
.title.riscy,
|
||||
.title.riscy > .menu .refs,
|
||||
.title.riscy > .menu .filter_container,
|
||||
|
@ -8,9 +11,31 @@
|
|||
.markers_container.riscy,
|
||||
.markers_container.riscy > .marker {
|
||||
background-color: #EEE;
|
||||
}
|
||||
|
||||
.dayContainer:nth-child(2n).riscy,
|
||||
#cineraIndex.riscy dt:nth-child(2n) {
|
||||
background-color: #FFF;
|
||||
}
|
||||
|
||||
.markerList.riscy > .marker,
|
||||
|
||||
.title.riscy,
|
||||
.title.riscy > .menu .refs,
|
||||
.title.riscy > .menu .filter_container,
|
||||
.title.riscy > .menu > .refs .ref,
|
||||
.title.riscy > .menu > .filter_container .filter_mode,
|
||||
.title.riscy > .menu > .credits_container,
|
||||
.title.riscy > .menu > .credits_container .credit,
|
||||
.markers_container.riscy,
|
||||
.markers_container.riscy > .marker {
|
||||
border-color: rgba(246, 178, 26, 0.8);
|
||||
}
|
||||
|
||||
.dayContainer.riscy > .dayName,
|
||||
.markerList.riscy > .marker,
|
||||
#cineraIndex.riscy dt a,
|
||||
|
||||
.title.riscy,
|
||||
.title.riscy > .menu > .refs .ref,
|
||||
/*.title.riscy > .menu > .refs .ref .timecode:hover:before,*/
|
||||
|
@ -36,23 +61,22 @@
|
|||
}
|
||||
|
||||
.title.riscy > .menu > .refs .ref.current .ref_indices .timecode.focused {
|
||||
color: rgb(246, 178, 26);
|
||||
color: rgb(246, 178, 26);
|
||||
}
|
||||
|
||||
.markerList.riscy > .marker:hover,
|
||||
#cineraIndex.riscy dt:hover,
|
||||
|
||||
/*.title.riscy > .menu:hover,*/
|
||||
.title.riscy > .menu.visible,
|
||||
|
||||
/*.title.riscy > .menu > .refs .ref:hover,*/
|
||||
.title.riscy > .menu > .quotes_container .ref.focused,
|
||||
.title.riscy > .menu > .references_container .ref.focused,
|
||||
|
||||
.title.riscy > .menu > .filter_container .filter_mode:hover,
|
||||
/*.title.riscy > .menu > .filter_container .filter_content:hover,*/
|
||||
.title.riscy > .menu > .filter_container .filter_content.focused,
|
||||
|
||||
/*.title.riscy > .menu > .credits_container .credit *:hover,*/
|
||||
.title.riscy > .menu > .credits_container .credit *.focused,
|
||||
|
||||
.markers_container.riscy > .marker:hover > .content {
|
||||
background-color: #FFF8E7;
|
||||
}
|
||||
|
@ -63,15 +87,13 @@ color: rgb(246, 178, 26);
|
|||
color: #FFF8E7;
|
||||
}
|
||||
|
||||
.markerList.riscy > .marker b,
|
||||
|
||||
.title.riscy > .menu > .refs .ref.current,
|
||||
/*.title.riscy > .menu > .refs .ref.current .timecode:hover:before,*/
|
||||
.markers_container.riscy > .marker > .progress .content {
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
.title.riscy > .menu > .refs .ref.current,
|
||||
.markers_container.riscy > .marker > .progress .content {
|
||||
background-color: rgb(42, 49, 114);
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
/*.title.riscy > .menu > .refs .ref.current:hover,*/
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
@ -0,0 +1,186 @@
|
|||
var menuState = [];
|
||||
var titleBar = document.querySelector(".title");
|
||||
var quotesMenu = titleBar.querySelector(".quotes_container");
|
||||
if(quotesMenu)
|
||||
{
|
||||
menuState.push(quotesMenu);
|
||||
var quoteTimecodes = quotesMenu.querySelectorAll(".refs .ref .ref_indices .timecode");
|
||||
for (var i = 0; i < quoteTimecodes.length; ++i) {
|
||||
quoteTimecodes[i].addEventListener("click", function(ev) {
|
||||
if (player) {
|
||||
var time = ev.currentTarget.getAttribute("data-timestamp");
|
||||
mouseSkipToTimecode(player, time, ev);
|
||||
}
|
||||
});
|
||||
}
|
||||
var lastFocusedQuote = null;
|
||||
}
|
||||
|
||||
var referencesMenu = titleBar.querySelector(".references_container");
|
||||
if(referencesMenu)
|
||||
{
|
||||
menuState.push(referencesMenu);
|
||||
var referenceItems = referencesMenu.querySelectorAll(".ref");
|
||||
if(referenceItems)
|
||||
{
|
||||
for(var i = 0; i < referenceItems.length; ++i)
|
||||
{
|
||||
referenceItems[i].addEventListener("mouseenter", function(ev) {
|
||||
mouseOverReferences(this);
|
||||
})
|
||||
};
|
||||
var lastFocusedReference = null;
|
||||
var lastFocusedIdentifier = null;
|
||||
}
|
||||
|
||||
var refTimecodes = referencesMenu.querySelectorAll(".refs .ref .ref_indices .timecode");
|
||||
for (var i = 0; i < refTimecodes.length; ++i) {
|
||||
refTimecodes[i].addEventListener("click", function(ev) {
|
||||
if (player) {
|
||||
var time = ev.currentTarget.getAttribute("data-timestamp");
|
||||
mouseSkipToTimecode(player, time, ev);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if(referencesMenu || quotesMenu)
|
||||
{
|
||||
var refSources = titleBar.querySelectorAll(".refs .ref"); // This is for both quotes and refs
|
||||
for (var i = 0; i < refSources.length; ++i) {
|
||||
refSources[i].addEventListener("click", function(ev) {
|
||||
if (player) {
|
||||
player.pause();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var filterMenu = titleBar.querySelector(".filter_container");
|
||||
if(filterMenu)
|
||||
{
|
||||
menuState.push(filterMenu);
|
||||
var lastFocusedCategory = null;
|
||||
var lastFocusedTopic = null;
|
||||
var lastFocusedMedium = null;
|
||||
|
||||
var filter = filterMenu.parentNode;
|
||||
|
||||
var filterModeElement = filter.querySelector(".filter_mode");
|
||||
filterModeElement.addEventListener("click", function(ev) {
|
||||
toggleFilterMode();
|
||||
});
|
||||
|
||||
var filterMode = filterModeElement.classList[1];
|
||||
var filterItems = filter.querySelectorAll(".filter_content");
|
||||
for(var i = 0; i < filterItems.length; ++i)
|
||||
{
|
||||
filterItems[i].addEventListener("mouseenter", function(ev) {
|
||||
navigateFilter(this);
|
||||
})
|
||||
|
||||
filterItems[i].addEventListener("click", function(ev) {
|
||||
filterItemToggle(this);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var creditsMenu = titleBar.querySelector(".credits_container");
|
||||
if(creditsMenu)
|
||||
{
|
||||
menuState.push(creditsMenu);
|
||||
var lastFocusedCreditItem = null;
|
||||
|
||||
var creditItems = creditsMenu.querySelectorAll(".person, .support");
|
||||
for(var i = 0; i < creditItems.length; ++i)
|
||||
{
|
||||
creditItems[i].addEventListener("mouseenter", function(ev) {
|
||||
if(this != lastFocusedCreditItem)
|
||||
{
|
||||
lastFocusedCreditItem.classList.remove("focused");
|
||||
if(lastFocusedCreditItem.classList.contains("support"))
|
||||
{
|
||||
setIconLightness(lastFocusedCreditItem.firstChild);
|
||||
}
|
||||
lastFocusedCreditItem = this;
|
||||
focusedElement = lastFocusedCreditItem;
|
||||
focusedElement.classList.add("focused");
|
||||
if(focusedElement.classList.contains("support"))
|
||||
{
|
||||
setIconLightness(focusedElement.firstChild);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var supportIcons = creditsMenu.querySelectorAll(".support_icon");
|
||||
{
|
||||
for(var i = 0; i < supportIcons.length; ++i)
|
||||
{
|
||||
setIconLightness(supportIcons[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
var sourceMenus = titleBar.querySelectorAll(".menu");
|
||||
|
||||
var helpButton = titleBar.querySelector(".help");
|
||||
var helpDocumentation = helpButton.querySelector(".help_container");
|
||||
helpButton.addEventListener("click", function(ev) {
|
||||
handleMouseOverMenu(this, ev.type);
|
||||
})
|
||||
|
||||
var focusedElement = null;
|
||||
var focusedIdentifier = null;
|
||||
|
||||
var playerContainer = document.querySelector(".player_container")
|
||||
var player = new Player(playerContainer, onRefChanged);
|
||||
window.addEventListener("resize", function() { player.updateSize(); });
|
||||
document.addEventListener("keydown", function(ev) {
|
||||
var key = ev.key;
|
||||
if(ev.getModifierState("Shift") && key == " ")
|
||||
{
|
||||
key = "capitalSpace";
|
||||
}
|
||||
|
||||
if(handleKey(key) == true && focusedElement)
|
||||
{
|
||||
ev.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
for(var i = 0; i < sourceMenus.length; ++i)
|
||||
{
|
||||
sourceMenus[i].addEventListener("mouseenter", function(ev) {
|
||||
handleMouseOverMenu(this, ev.type);
|
||||
})
|
||||
sourceMenus[i].addEventListener("mouseleave", function(ev) {
|
||||
handleMouseOverMenu(this, ev.type);
|
||||
})
|
||||
};
|
||||
|
||||
var testMarkers = playerContainer.querySelectorAll(".marker");
|
||||
|
||||
window.addEventListener("blur", function(){
|
||||
document.getElementById("focus-warn").style.display = "block";
|
||||
});
|
||||
|
||||
window.addEventListener("focus", function(){
|
||||
document.getElementById("focus-warn").style.display = "none";
|
||||
});
|
||||
|
||||
var colouredItems = playerContainer.querySelectorAll(".author, .member, .project");
|
||||
for(i = 0; i < colouredItems.length; ++i)
|
||||
{
|
||||
setTextLightness(colouredItems[i]);
|
||||
}
|
||||
|
||||
var topicDots = document.querySelectorAll(".category");
|
||||
for(var i = 0; i < topicDots.length; ++i)
|
||||
{
|
||||
setDotLightness(topicDots[i]);
|
||||
}
|
||||
|
||||
if(location.hash) {
|
||||
player.setTime(location.hash.startsWith('#') ? location.hash.substr(1) : location.hash);
|
||||
}
|
|
@ -392,16 +392,24 @@ function toggleMenuVisibility(element) {
|
|||
if(element.querySelectorAll(".credit .support")[0])
|
||||
{
|
||||
lastFocusedCreditItem = element.querySelectorAll(".credit .support")[0];
|
||||
focusedElement = lastFocusedCreditItem;
|
||||
focusedElement.classList.add("focused");
|
||||
setIconLightness(focusedElement.firstChild);
|
||||
}
|
||||
else
|
||||
{
|
||||
lastFocusedCreditItem = element.querySelectorAll(".credit .person")[0];
|
||||
}
|
||||
}
|
||||
focusedElement = lastFocusedCreditItem;
|
||||
focusedElement.classList.add("focused");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
focusedElement = lastFocusedCreditItem;
|
||||
focusedElement.classList.add("focused");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleKey(key) {
|
||||
|
@ -532,18 +540,21 @@ function handleKey(key) {
|
|||
if(focusedElement.parentNode.previousElementSibling.querySelector(".support") &&
|
||||
focusedElement.classList.contains("support"))
|
||||
{
|
||||
setIconLightness(focusedElement.firstChild);
|
||||
lastFocusedCreditItem = focusedElement.parentNode.previousElementSibling.querySelector(".support");
|
||||
focusedElement = lastFocusedCreditItem;
|
||||
focusedElement.classList.add("focused");
|
||||
setIconLightness(focusedElement.firstChild);
|
||||
}
|
||||
else
|
||||
{
|
||||
lastFocusedCreditItem = focusedElement.parentNode.previousElementSibling.querySelector(".person");
|
||||
focusedElement = lastFocusedCreditItem;
|
||||
}
|
||||
focusedElement.classList.add("focused");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case "s": case "j": case "ArrowDown": {
|
||||
|
@ -596,18 +607,21 @@ function handleKey(key) {
|
|||
if(focusedElement.parentNode.nextElementSibling.querySelector(".support") &&
|
||||
focusedElement.classList.contains("support"))
|
||||
{
|
||||
setIconLightness(focusedElement.firstChild);
|
||||
lastFocusedCreditItem = focusedElement.parentNode.nextElementSibling.querySelector(".support");
|
||||
focusedElement = lastFocusedCreditItem;
|
||||
focusedElement.classList.add("focused");
|
||||
setIconLightness(focusedElement.firstChild);
|
||||
}
|
||||
else
|
||||
{
|
||||
lastFocusedCreditItem = focusedElement.parentNode.nextElementSibling.querySelector(".person");
|
||||
focusedElement = lastFocusedCreditItem;
|
||||
}
|
||||
focusedElement.classList.add("focused");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case "a": case "h": case "ArrowLeft": {
|
||||
|
@ -618,11 +632,17 @@ function handleKey(key) {
|
|||
if(focusedIdentifier.previousElementSibling)
|
||||
{
|
||||
focusedIdentifier.classList.remove("focused");
|
||||
|
||||
lastFocusedIdentifier = focusedIdentifier.previousElementSibling;
|
||||
focusedIdentifier = lastFocusedIdentifier;
|
||||
focusedIdentifier.classList.add("focused");
|
||||
}
|
||||
else if(focusedIdentifier.parentNode.previousElementSibling.classList.contains("ref_indices"))
|
||||
{
|
||||
focusedIdentifier.classList.remove("focused");
|
||||
lastFocusedIdentifier = focusedIdentifier.parentNode.previousElementSibling.lastElementChild;
|
||||
focusedIdentifier = lastFocusedIdentifier;
|
||||
focusedIdentifier.classList.add("focused");
|
||||
}
|
||||
}
|
||||
else if(focusedElement.classList.contains("filter_content"))
|
||||
{
|
||||
|
@ -648,6 +668,7 @@ function handleKey(key) {
|
|||
focusedElement.classList.remove("focused");
|
||||
|
||||
lastFocusedCreditItem = focusedElement.previousElementSibling;
|
||||
setIconLightness(focusedElement.firstChild);
|
||||
focusedElement = lastFocusedCreditItem;
|
||||
focusedElement.classList.add("focused");
|
||||
}
|
||||
|
@ -668,6 +689,13 @@ function handleKey(key) {
|
|||
focusedIdentifier = lastFocusedIdentifier;
|
||||
focusedIdentifier.classList.add("focused");
|
||||
}
|
||||
else if(focusedIdentifier.parentNode.nextElementSibling)
|
||||
{
|
||||
focusedIdentifier.classList.remove("focused");
|
||||
lastFocusedIdentifier = focusedIdentifier.parentNode.nextElementSibling.firstElementChild;
|
||||
focusedIdentifier = lastFocusedIdentifier;
|
||||
focusedIdentifier.classList.add("focused");
|
||||
}
|
||||
}
|
||||
else if(focusedElement.classList.contains("filter_content"))
|
||||
{
|
||||
|
@ -696,6 +724,7 @@ function handleKey(key) {
|
|||
lastFocusedCreditItem = focusedElement.nextElementSibling;
|
||||
focusedElement = lastFocusedCreditItem;
|
||||
focusedElement.classList.add("focused");
|
||||
setIconLightness(focusedElement.firstChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -951,11 +980,16 @@ function filterItemToggle(filterItem) {
|
|||
function resetFilter() {
|
||||
for(i in filterItems)
|
||||
{
|
||||
if(filterItems[i].classList && filterItems[i].classList.contains("off"))
|
||||
if(filterItems[i].classList)
|
||||
{
|
||||
var selectedCategory = filterItems[i].classList[1];
|
||||
if(filterInitState[selectedCategory].off ^ filterState[selectedCategory].off)
|
||||
{
|
||||
filterItemToggle(filterItems[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(filterMode == "exclusive")
|
||||
{
|
||||
toggleFilterMode();
|
||||
|
@ -1082,7 +1116,7 @@ function mouseOverReferences(reference) {
|
|||
focusedElement = lastFocusedReference;
|
||||
focusedElement.classList.add("focused");
|
||||
|
||||
var ourIdentifiers = reference.querySelector(".ref_indices").children;
|
||||
var ourIdentifiers = reference.querySelectorAll(".timecode");
|
||||
weWereLastFocused = false;
|
||||
for(var k = 0; k < ourIdentifiers.length; ++k)
|
||||
{
|
||||
|
@ -1094,7 +1128,7 @@ function mouseOverReferences(reference) {
|
|||
if(!weWereLastFocused)
|
||||
{
|
||||
lastFocusedIdentifier.classList.remove("focused");
|
||||
lastFocusedIdentifier = reference.querySelector(".ref_indices").firstElementChild;
|
||||
lastFocusedIdentifier = ourIdentifiers[0];
|
||||
}
|
||||
focusedIdentifer = lastFocusedIdentifier;
|
||||
focusedIdentifer.classList.add("focused");
|
||||
|
@ -1219,7 +1253,19 @@ function setDotLightness(topicDot)
|
|||
}
|
||||
else
|
||||
{
|
||||
topicDot.style.backgroundColor = ("hsl(" + Hue + ", " + Saturation + "%, 24%)");
|
||||
topicDot.style.borderColor = ("hsl(" + Hue + ", " + Saturation + "%, 24%)");
|
||||
topicDot.style.backgroundColor = ("hsl(" + Hue + ", " + Saturation + "%, 47%)");
|
||||
topicDot.style.borderColor = ("hsl(" + Hue + ", " + Saturation + "%, 47%)");
|
||||
}
|
||||
}
|
||||
|
||||
function setIconLightness(iconElement)
|
||||
{
|
||||
if(getBackgroundBrightness(iconElement) < 127)
|
||||
{
|
||||
iconElement.style.backgroundPosition = ("0px 0px");
|
||||
}
|
||||
else
|
||||
{
|
||||
iconElement.style.backgroundPosition = ("16px 0px");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,240 @@
|
|||
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 indexContainer = document.getElementById("cineraIndex");
|
||||
var lastQuery = null;
|
||||
var resultsToRender = [];
|
||||
var resultsIndex = 0;
|
||||
var resultsMarkerIndex = 0;
|
||||
var resultsContainer = document.getElementById("results");
|
||||
var rendering = false;
|
||||
|
||||
var dayContainerPrototype = document.createElement("DIV");
|
||||
dayContainerPrototype.classList.add("dayContainer");
|
||||
dayContainerPrototype.classList.add(projectID);
|
||||
|
||||
var dayNamePrototype = document.createElement("SPAN");
|
||||
dayNamePrototype.classList.add("dayName");
|
||||
dayContainerPrototype.appendChild(dayNamePrototype);
|
||||
|
||||
var markerListPrototype = document.createElement("DIV");
|
||||
markerListPrototype.classList.add("markerList");
|
||||
markerListPrototype.classList.add(projectID);
|
||||
dayContainerPrototype.appendChild(markerListPrototype);
|
||||
|
||||
var markerPrototype = document.createElement("A");
|
||||
markerPrototype.classList.add("marker");
|
||||
markerPrototype.setAttribute("target", "_blank");
|
||||
|
||||
var highlightPrototype = document.createElement("B");
|
||||
|
||||
var episodes = [];
|
||||
|
||||
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 runSearch() {
|
||||
var queryStr = document.getElementById("query").value;
|
||||
if (lastQuery != queryStr) {
|
||||
var oldResultsContainer = resultsContainer;
|
||||
resultsContainer = oldResultsContainer.cloneNode(false);
|
||||
oldResultsContainer.parentNode.insertBefore(resultsContainer, oldResultsContainer);
|
||||
oldResultsContainer.remove();
|
||||
resultsIndex = 0;
|
||||
resultsMarkerIndex = 0;
|
||||
}
|
||||
lastQuery = queryStr;
|
||||
resultsToRender = [];
|
||||
var numEpisodes = 0;
|
||||
var numMarkers = 0;
|
||||
var totalSeconds = 0;
|
||||
if (queryStr && queryStr.length > 0) {
|
||||
indexContainer.style.display = "none";
|
||||
if (episodes.length > 0) {
|
||||
var query = new RegExp(queryStr.replace("(", "\\(").replace(")", "\\)").replace(/(^|[^\\])\\$/, "$1"), "gi");
|
||||
for (var i = 0; i < episodes.length; ++i) {
|
||||
var episode = episodes[i];
|
||||
var matches = [];
|
||||
for (var j = 0; j < episode.markers.length; ++j) {
|
||||
query.lastIndex = 0;
|
||||
var result = query.exec(episode.markers[j].text);
|
||||
if (result && result[0].length > 0) {
|
||||
numMarkers++;
|
||||
matches.push(episode.markers[j]);
|
||||
if (j < episode.markers.length-1) {
|
||||
totalSeconds += episode.markers[j+1].totalTime - episode.markers[j].totalTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (matches.length > 0) {
|
||||
numEpisodes++;
|
||||
resultsToRender.push({
|
||||
query: query,
|
||||
episode: episode,
|
||||
matches: matches
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!rendering) {
|
||||
renderResults();
|
||||
}
|
||||
} else {
|
||||
document.querySelector(".spinner").classList.add("show");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
indexContainer.style.display = "block";
|
||||
}
|
||||
|
||||
var totalTime = Math.floor(totalSeconds/60/60) + "h " + Math.floor(totalSeconds/60)%60 + "m " + totalSeconds%60 + "s ";
|
||||
|
||||
document.getElementById("resultsSummary").textContent = "Found: " + numEpisodes + " episodes, " + numMarkers + " markers, " + totalTime + "total.";
|
||||
}
|
||||
|
||||
function renderMatches(renderStart) {
|
||||
var query = resultsToRender[resultsIndex].query;
|
||||
var episode = resultsToRender[resultsIndex].episode;
|
||||
var matches = resultsToRender[resultsIndex].matches;
|
||||
var markerList = null;
|
||||
if (resultsMarkerIndex == 0) {
|
||||
var dayContainer = dayContainerPrototype.cloneNode(true);
|
||||
var dayName = dayContainer.children[0];
|
||||
markerList = dayContainer.children[1];
|
||||
dayName.textContent = episode.day + ": " + episode.title;
|
||||
resultsContainer.appendChild(dayContainer);
|
||||
} else {
|
||||
markerList = document.querySelector("#results > .dayContainer:nth-child(" + (resultsIndex+1) + ") .markerList");
|
||||
}
|
||||
|
||||
do {
|
||||
var match = matches[resultsMarkerIndex];
|
||||
var marker = markerPrototype.cloneNode();
|
||||
marker.setAttribute("href", 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);
|
||||
resultsMarkerIndex++;
|
||||
} while (resultsMarkerIndex < matches.length && performance.now() - renderStart < 1);
|
||||
|
||||
return resultsMarkerIndex == matches.length;
|
||||
}
|
||||
|
||||
function renderResults() {
|
||||
if (resultsIndex < resultsToRender.length) {
|
||||
rendering = true;
|
||||
var renderStart = performance.now();
|
||||
while (resultsIndex < resultsToRender.length && performance.now() - renderStart < 1) {
|
||||
var done = renderMatches(renderStart);
|
||||
if (done) {
|
||||
resultsMarkerIndex = 0;
|
||||
resultsIndex++;
|
||||
}
|
||||
}
|
||||
requestAnimationFrame(renderResults);
|
||||
} else {
|
||||
rendering = false;
|
||||
}
|
||||
}
|
||||
|
||||
var queryEl = document.getElementById("query")
|
||||
queryEl.addEventListener("input", function(ev) {
|
||||
history.replaceState(null, null, "#" + encodeURIComponent(queryEl.value));
|
||||
runSearch();
|
||||
});
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.addEventListener("load", function() {
|
||||
var contents = 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.filename = episode.name;
|
||||
episode.day = getEpisodeName(episode.filename + ".html.md");
|
||||
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).replace(/"/g, "");
|
||||
} 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");
|
||||
runSearch();
|
||||
});
|
||||
xhr.addEventListener("error", function() {
|
||||
console.error("Failed to load content");
|
||||
});
|
||||
xhr.open("GET", indexLocation);
|
||||
xhr.setRequestHeader("Content-Type", "text/plain");
|
||||
xhr.send();
|
||||
|
||||
runSearch();
|
Binary file not shown.
After Width: | Height: | Size: 881 B |
|
@ -0,0 +1,12 @@
|
|||
<!-- Index template -->
|
||||
<html>
|
||||
<head>
|
||||
<title>RISCY BUSINESS Episode Guide</title>
|
||||
<!-- __CINERA_INCLUDES__ -->
|
||||
</head>
|
||||
<body>
|
||||
<h1 style="background-color: #3399FF; text-align:center; width: 100%; margin: 0 auto">RISCY BUSINESS Episode Guide</h1>
|
||||
<div>This should just be the table of contents, heroes and heroines</div>
|
||||
<!-- __CINERA_INDEX__ -->
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,17 @@
|
|||
<!-- Player template -->
|
||||
<html>
|
||||
<head>
|
||||
<title><!-- __CINERA_TITLE__ --> - RISCY BUSINESS</title>
|
||||
<!-- __CINERA_INCLUDES__ -->
|
||||
</head>
|
||||
<!-- 1. This is a random comment. How does this affect it, if at all? -->
|
||||
<body>
|
||||
<a href="../">Awesome Contents</a>
|
||||
<h1 style="background-color: #3399FF; text-align:center; width: 100%; margin: 0 auto"><!-- __CINERA_TITLE__ --></h1>
|
||||
<!-- __CINERA_MENUS__ -->
|
||||
<!-- __CINERA_PLAYER__ -->
|
||||
<!-- 2. This is a random comment. How does this affect it, if at all? -->
|
||||
<!-- __CINERA_SCRIPT__ -->
|
||||
<!-- 3. This is a random comment. How does this affect it, if at all? -->
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue