587 lines
15 KiB
JavaScript
587 lines
15 KiB
JavaScript
// bigblow.js --- BigBlow JS file
|
||
//
|
||
// Copyright (C) 2011-2016 All Right Reserved, Fabrice Niessen
|
||
//
|
||
// This file is free software: you can redistribute it and/or
|
||
// modify it under the terms of the GNU General Public License as
|
||
// published by the Free Software Foundation, either version 3 of
|
||
// the License, or (at your option) any later version.
|
||
//
|
||
// This file is distributed in the hope that it will be useful,
|
||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
// GNU General Public License for more details.
|
||
//
|
||
// Author: Fabrice Niessen <(concat "fniessen" at-sign "pirilampo.org")>
|
||
// URL: https://github.com/fniessen/org-html-themes/
|
||
// Version: 20140515.1841
|
||
|
||
$(function () {
|
||
$("p").html(function (index, old) {
|
||
return old.replace("FIXME", '<span class="fixme">FIXME</span>');
|
||
});
|
||
$("p").html(function (index, old) {
|
||
return old.replace("XXX", '<span class="fixme">XXX</span>');
|
||
});
|
||
});
|
||
|
||
// Remove leading section number
|
||
$(function () {
|
||
$(".section-number-2").text("");
|
||
for (var i = 3; i <= 5; i++) {
|
||
$(".section-number-" + i).each(function () {
|
||
$(this).text(
|
||
$(this)
|
||
.text()
|
||
.replace(/^[0-9]+\./g, "")
|
||
);
|
||
});
|
||
}
|
||
});
|
||
|
||
$(function () {
|
||
$('<div id="minitoc" class="dontprint"></div>').prependTo("body");
|
||
});
|
||
|
||
// generate contents of minitoc
|
||
function generateMiniToc(divId) {
|
||
$("#minitoc").empty().append("<h2>In this section</h2>");
|
||
$("#" + divId)
|
||
.find("h3")
|
||
.each(function (i) {
|
||
let pos = $(this).text().search(" ");
|
||
let text = $(this).text().substring(0, pos);
|
||
$("#minitoc").append(
|
||
"<a href='#" + $(this).attr("id") + "'>" + text + "</a>"
|
||
);
|
||
});
|
||
// Ensure that the target is expanded (hideShow)
|
||
$('#minitoc a[href^="#"]').click(function () {
|
||
var href = $(this).attr("href");
|
||
hsExpandAnchor(href);
|
||
});
|
||
}
|
||
|
||
// display tabs
|
||
function tabifySections() {
|
||
// hide TOC (if present)
|
||
$("#table-of-contents").hide();
|
||
|
||
// grab the list of `h2' from the page
|
||
var allSections = [];
|
||
$("h2").each(function () {
|
||
// Remove TODO keywords and tags (contained in spans)
|
||
var tabText = $(this).clone().find("span").remove().end().text().trim();
|
||
var tabId = $(this).parent().attr("id");
|
||
if (tabText) {
|
||
// - remove heading number (all leading digits)
|
||
// - remove progress logging (between square brackets)
|
||
// - remove leading and trailing spaces
|
||
tabText = tabText
|
||
.replace(/^\d+\s+/, "")
|
||
.replace(/\[[\d/%]+\]/, "")
|
||
.trim();
|
||
|
||
allSections.push({
|
||
text: tabText,
|
||
id: tabId,
|
||
});
|
||
}
|
||
});
|
||
|
||
// create the tab links
|
||
var tabs = $('<ul id="tabs"></ul>');
|
||
for (i = 0; i < allSections.length; i++) {
|
||
var item = allSections[i];
|
||
html = $('<li><a href="#' + item.id + '">' + item.text + "</a></li>");
|
||
tabs.append(html);
|
||
}
|
||
|
||
// insert tabs menu after title (`h1'), or at the beginning of the content
|
||
if ($(".title").length !== 0) {
|
||
$(".title").after(tabs);
|
||
} else {
|
||
$("#content").prepend(tabs);
|
||
}
|
||
}
|
||
|
||
function selectTabAndScroll(href) {
|
||
// At this point we assume that href is local (starts with #)
|
||
// alert(href);
|
||
|
||
// Find the tab to activate
|
||
var targetTab = $(href).closest(".ui-tabs-panel");
|
||
var targetTabId = targetTab.attr("id");
|
||
var targetTabAriaLabel = targetTab.attr("aria-labelledby");
|
||
|
||
var targetTabIndex = $("#content ul li").index(
|
||
$('[aria-labelledby="' + targetTabAriaLabel + '"]')
|
||
);
|
||
|
||
// Activate target tab
|
||
$("#content").tabs("option", "active", targetTabIndex);
|
||
|
||
// Rebuild minitoc
|
||
generateMiniToc(targetTabId);
|
||
|
||
// Set the location hash
|
||
// document.location.hash = href;
|
||
|
||
// Scroll to top if href was a tab
|
||
if (href == "#" + targetTabId) {
|
||
// alert(targetTabId);
|
||
$.scrollTo(0);
|
||
}
|
||
// Scroll to href if href was not a tab
|
||
else {
|
||
$.scrollTo(href);
|
||
}
|
||
}
|
||
|
||
$(document).ready(function () {
|
||
$("#preamble").remove();
|
||
$("#table-of-contents").remove();
|
||
|
||
// Prepare for tabs
|
||
tabifySections();
|
||
|
||
// Build the tabs from the #content div
|
||
$("#content").tabs();
|
||
|
||
// Set default animation
|
||
$("#content").tabs("option", "show", true);
|
||
|
||
// Rebuild minitoc when a tab is activated
|
||
$("#content").tabs({
|
||
activate: function (event, ui) {
|
||
var divId = ui.newTab.attr("aria-controls");
|
||
generateMiniToc(divId);
|
||
},
|
||
});
|
||
|
||
// Required to get the link of the tab in URL
|
||
$("#content ul").localScroll({
|
||
target: "#content",
|
||
duration: 0,
|
||
hash: true,
|
||
});
|
||
|
||
// Handle hash in URL
|
||
if ($("#content") && document.location.hash) {
|
||
hsExpandAnchor(document.location.hash);
|
||
selectTabAndScroll(document.location.hash);
|
||
}
|
||
// If no hash, build the minitoc anyway for selected tab
|
||
else {
|
||
var divId = $("#content div[aria-expanded=true]").attr("id");
|
||
generateMiniToc(divId);
|
||
}
|
||
|
||
// Handle click on internal links
|
||
$('.ui-tabs-panel a[href^="#"]').click(function (e) {
|
||
var href = $(this).attr("href");
|
||
hsExpandAnchor(href);
|
||
selectTabAndScroll(href);
|
||
e.preventDefault();
|
||
});
|
||
|
||
// Initialize hideShow
|
||
hsInit();
|
||
|
||
// add sticky headers to tables
|
||
$("table").stickyTableHeaders();
|
||
});
|
||
|
||
function copyToClipboard(text) {
|
||
if (window.clipboardData && window.clipboardData.setData) {
|
||
// Internet Explorer
|
||
window.clipboardData.setData("Text", text);
|
||
} else {
|
||
// Copy text to clipboard
|
||
navigator.clipboard.writeText(text).then(
|
||
() => {},
|
||
() => {}
|
||
);
|
||
}
|
||
}
|
||
|
||
$(document).ready(function () {
|
||
// Assuming that the ZeroClipboard swf file is in the same folder than bigblow,
|
||
// get the path to it (it will be relative to the current page location).
|
||
var bbScriptPath = $('script[src$="bigblow.js"]').attr("src"); // the js file path
|
||
var bbPathToZeroClipboardSwf = bbScriptPath.replace(
|
||
"bigblow.js",
|
||
"ZeroClipboard.swf"
|
||
);
|
||
|
||
// Add copy to clipboard snippets
|
||
$(".org-src-container").prepend(
|
||
'<div class="snippet-copy-to-clipboard"><span class="copy-to-clipboard-button">[copy]</span></div>'
|
||
);
|
||
|
||
// Display/hide snippets on source block mouseenter/mouseleave
|
||
$(document)
|
||
.on("mouseenter", ".org-src-container", function () {
|
||
$(this).find(".snippet-copy-to-clipboard").show();
|
||
})
|
||
.on("mouseleave", ".org-src-container", function () {
|
||
$(this).find(".snippet-copy-to-clipboard").hide();
|
||
});
|
||
|
||
// Handle copy to clipboard (here, for a local file only 'file://...'
|
||
if (window.location.protocol == "file:") {
|
||
// if local file use browser-specific code
|
||
$(".copy-to-clipboard-button").click(function () {
|
||
// Copy of src block
|
||
var codeBlock = $(this).parent().parent().find(".src").clone();
|
||
// Remove line numbers if present
|
||
$(codeBlock).children(".linenr").remove();
|
||
|
||
// Text to be copied
|
||
text = $(codeBlock).text();
|
||
text = text.replace(/\n/g, "\r\n", "");
|
||
copyToClipboard(text);
|
||
});
|
||
}
|
||
});
|
||
|
||
$(function () {
|
||
$('li > code :contains("[X]")').parent().addClass("checked").end().remove();
|
||
$('li > code :contains("[-]")')
|
||
.parent()
|
||
.addClass("halfchecked")
|
||
.end()
|
||
.remove();
|
||
$('li > code :contains("[ ]")').parent().addClass("unchecked").end().remove();
|
||
});
|
||
|
||
$(function () {
|
||
$('i :contains("[#A]")').replaceWith(
|
||
'<i><span style="color: #F67777;">[#A]</span></i>'
|
||
);
|
||
$('i :contains("[#B]")').replaceWith(
|
||
'<i><span style="color: #B6E864;">[#B]</span></i>'
|
||
);
|
||
$('i :contains("[#C]")').replaceWith(
|
||
'<i><span style="color: #C3DCFF;">[#C]</span></i>'
|
||
);
|
||
});
|
||
|
||
$(function () {
|
||
$(
|
||
'<div id="toTop" class="dontprint"><span>^ Back to Top</span></div>'
|
||
).appendTo("body");
|
||
|
||
$(window).scroll(function () {
|
||
if ($(this).scrollTop() != 0) {
|
||
$("#toTop").fadeIn();
|
||
} else {
|
||
$("#toTop").fadeOut();
|
||
}
|
||
});
|
||
|
||
$("#toTop").click(function (e) {
|
||
$("html, body").animate({ scrollTop: 0 }, 800);
|
||
e.preventDefault(); // Disable default browser behavior
|
||
});
|
||
});
|
||
|
||
function togglePanel(e) {
|
||
e.preventDefault();
|
||
|
||
$("#left-panel-contents").toggleClass("active").toggle(200);
|
||
$("#right-panel-contents").toggleClass("active").toggle(200);
|
||
|
||
var slidePos =
|
||
$("#left-panel-button").css("left") == "-23px" ? "182px" : "-23px";
|
||
|
||
$("#left-panel-button").animate(
|
||
{ left: slidePos, opacity: 0.9 },
|
||
{ duration: "200" }
|
||
);
|
||
|
||
// if ($("#left-panel-contents").hasClass('active')) {
|
||
// hsHideTodoKeyword('done');
|
||
// } else {
|
||
// hsShowTodoKeyword('done');
|
||
// }
|
||
|
||
// return false;
|
||
}
|
||
|
||
$(function () {
|
||
$(
|
||
'<div id="left-panel-wrapper" class="dontprint"><div id="left-panel-contents" style="opacity: 0.9"></div><div id="left-panel-button" class="dontprint"><a href="#">Dashboard</a></div></div>'
|
||
).appendTo("body");
|
||
|
||
$(
|
||
'<div id="right-panel-wrapper" class="dontprint"><div id="right-panel-contents" style="opacity: 0.9"></div></div>'
|
||
).appendTo("body");
|
||
|
||
$("#left-panel-button").click(togglePanel);
|
||
});
|
||
|
||
$(function () {
|
||
var ul = $('<ul id="listOfTodo"></ul>').appendTo("#left-panel-contents");
|
||
var countOfTodo = {},
|
||
listOfTodo = [],
|
||
totalOfTodo = 0;
|
||
|
||
// assign the counts (avoid double-counting elements from the ToC)
|
||
$("span.todo")
|
||
.not($("#table-of-contents span.todo"))
|
||
.each(function () {
|
||
var $thisTodo = $(this).text().trim();
|
||
|
||
if ($.inArray($thisTodo, listOfTodo) == -1) {
|
||
countOfTodo[$thisTodo] = 1;
|
||
listOfTodo.push($thisTodo);
|
||
} else countOfTodo[$thisTodo] += 1;
|
||
totalOfTodo += 1;
|
||
});
|
||
|
||
function scoreTodo(t) {
|
||
switch (t) {
|
||
case "NEW":
|
||
return 1;
|
||
case "TODO":
|
||
return 2;
|
||
case "STRT":
|
||
return 3;
|
||
case "WAIT":
|
||
return 4;
|
||
case "DLGT":
|
||
return 5;
|
||
case "SDAY":
|
||
return 6;
|
||
case "DFRD":
|
||
return 7;
|
||
case "DONE":
|
||
return 8;
|
||
case "CANX":
|
||
return 9;
|
||
default:
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
function compareTodo(a, b) {
|
||
if (scoreTodo(a) < scoreTodo(b)) return -1;
|
||
if (scoreTodo(a) > scoreTodo(b)) return 1;
|
||
return 0;
|
||
}
|
||
|
||
listOfTodo.sort(compareTodo);
|
||
|
||
// display
|
||
for (i = 0; i < listOfTodo.length; i++) {
|
||
var $thisTodo = listOfTodo[i];
|
||
$(ul).append(
|
||
'<li><span class="todo ' +
|
||
$thisTodo +
|
||
'">' +
|
||
$thisTodo +
|
||
"</span>" +
|
||
" <small>(" +
|
||
countOfTodo[$thisTodo] +
|
||
")</small></li>"
|
||
);
|
||
}
|
||
|
||
$("#listOfTodo").before(
|
||
"<b>Next Actions</b> <small>(" + totalOfTodo + ")</small>:<br>"
|
||
);
|
||
});
|
||
|
||
$(function () {
|
||
var ul = $('<ul id="listOfDone"></ul>').appendTo("#left-panel-contents");
|
||
var countOfDone = {},
|
||
listOfDone = [],
|
||
totalOfDone = 0;
|
||
|
||
// assign the counts (avoid double-counting elements from the ToC)
|
||
$("span.done")
|
||
.not($("#table-of-contents span.done"))
|
||
.each(function () {
|
||
var $thisDone = $(this).text().trim();
|
||
|
||
if ($.inArray($thisDone, listOfDone) == -1) {
|
||
countOfDone[$thisDone] = 1;
|
||
listOfDone.push($thisDone);
|
||
} else countOfDone[$thisDone] += 1;
|
||
totalOfDone += 1;
|
||
});
|
||
|
||
// display
|
||
for (i = 0; i < listOfDone.length; i++) {
|
||
var $thisDone = listOfDone[i];
|
||
$(ul).append(
|
||
'<li><span class="done ' +
|
||
$thisDone +
|
||
'">' +
|
||
$thisDone +
|
||
"</span>" +
|
||
" <small>(" +
|
||
countOfDone[$thisDone] +
|
||
")</small></li>"
|
||
);
|
||
}
|
||
|
||
$("#listOfDone").before(
|
||
"<b>Done Actions</b> <small>(" + totalOfDone + "):</small><br>"
|
||
);
|
||
});
|
||
|
||
$(function () {
|
||
var ul = $('<ul id="listOfTags"></ul>').appendTo("#right-panel-contents");
|
||
var countOfTags = {},
|
||
listOfTags = [],
|
||
totalOfTags = 0;
|
||
|
||
// assign the counts (avoid double-counting elements from the ToC)
|
||
$("span.tag")
|
||
.not($("#table-of-contents span.tag"))
|
||
.each(function () {
|
||
var $thisTagGroup = $(this).text().trim().split(/\s/);
|
||
// \s matches spaces, tabs, new lines, etc.
|
||
|
||
for (tag in $thisTagGroup) {
|
||
if ($.inArray($thisTagGroup[tag], listOfTags) == -1) {
|
||
countOfTags[$thisTagGroup[tag]] = 1;
|
||
listOfTags.push($thisTagGroup[tag]);
|
||
} else countOfTags[$thisTagGroup[tag]] += 1;
|
||
totalOfTags += 1;
|
||
}
|
||
});
|
||
|
||
listOfTags.sort();
|
||
|
||
// display
|
||
for (i = 0; i < listOfTags.length; i++) {
|
||
var $thisTag = listOfTags[i];
|
||
// $(ul).append('<li><span class="tag ' + $thisTag + '">'+
|
||
// $thisTag + '</span> <small>(' + countOfTags[$thisTag] + ')</small></li>');
|
||
$(ul).append(
|
||
'<li><span class="tag"><span class="' +
|
||
$thisTag +
|
||
'">' +
|
||
$thisTag +
|
||
"</span></span>" +
|
||
" <small>(" +
|
||
countOfTags[$thisTag] +
|
||
")</small></li>"
|
||
);
|
||
}
|
||
|
||
$("#listOfTags").before(
|
||
"<b>Contexts</b> <small>(" + totalOfTags + "):</small><br>"
|
||
);
|
||
});
|
||
|
||
$(function () {
|
||
$(".done").parent(":header").parent().find(":header").addClass("DONEheader");
|
||
$(".done").parent(":header").parent().css({ color: "#999999" });
|
||
});
|
||
|
||
$(function () {
|
||
$("span.todo").click(function (e) {
|
||
var orgKeyword = $(this).text().trim();
|
||
$("." + orgKeyword).toggleClass("selected");
|
||
$("#content ." + orgKeyword)
|
||
.parent()
|
||
.parent()
|
||
.toggleClass("match" + orgKeyword);
|
||
$("#left-panel-wrapper ." + orgKeyword)
|
||
.parent()
|
||
.toggleClass("match" + orgKeyword);
|
||
e.preventDefault();
|
||
});
|
||
});
|
||
|
||
$(function () {
|
||
$(".tag span").click(function (e) {
|
||
var orgTag = $(this).text().trim();
|
||
$("." + orgTag).toggleClass("selected");
|
||
$("#content ." + orgTag)
|
||
.parent()
|
||
.parent()
|
||
.parent()
|
||
.toggleClass("matchtag");
|
||
$("#right-panel-wrapper ." + orgTag)
|
||
.parent()
|
||
.parent()
|
||
.toggleClass("matchtag");
|
||
e.preventDefault();
|
||
});
|
||
});
|
||
|
||
function clickPreviousTab() {
|
||
var active = $("#content").tabs("option", "active");
|
||
// Avoid going back to last tab
|
||
if (active == 0) return;
|
||
|
||
$("#content").tabs("option", "active", active - 1);
|
||
|
||
// Set the location href
|
||
var href = $("#content div[aria-expanded=true]").attr("id");
|
||
document.location.hash = href;
|
||
$.scrollTo(0);
|
||
}
|
||
|
||
function clickNextTab() {
|
||
var active = $("#content").tabs("option", "active");
|
||
$("#content").tabs("option", "active", active + 1);
|
||
|
||
// Set the location href
|
||
var href = $("#content div[aria-expanded=true]").attr("id");
|
||
document.location.hash = href;
|
||
$.scrollTo(0);
|
||
}
|
||
|
||
function orgDefkey(e) {
|
||
if (!e) var e = window.event;
|
||
var keycode = e.keyCode ? e.keyCode : e.which;
|
||
var actualkey = String.fromCharCode(keycode);
|
||
switch (actualkey) {
|
||
case "?": // help (dashboard)
|
||
case "h":
|
||
togglePanel(e);
|
||
break;
|
||
case "n": // next
|
||
clickNextTab();
|
||
break;
|
||
case "p": // previous
|
||
clickPreviousTab();
|
||
break;
|
||
// case "b": // scroll down - should be mapped to Shift-SPC
|
||
// $(window).scrollTop($(window).scrollTop()-$(window).height());
|
||
// break;
|
||
case "<": // scroll to top
|
||
$(window).scrollTop(0);
|
||
break;
|
||
case ">": // scroll to bottom
|
||
$(window).scrollTop($(document).height());
|
||
break;
|
||
case "-": // collapse all
|
||
hsCollapseAll();
|
||
break;
|
||
case "+": // expand all
|
||
hsExpandAll();
|
||
break;
|
||
case "r": // go to next task
|
||
hsReviewTaskNext();
|
||
break;
|
||
case "R": // go to previous task
|
||
hsReviewTaskPrev();
|
||
break;
|
||
case "q": // quit reviewing
|
||
hsReviewTaskQuit();
|
||
break;
|
||
case "g": // refresh the page (from the server, rather than the cache)
|
||
location.reload(true);
|
||
break;
|
||
}
|
||
}
|
||
|
||
document.onkeypress = orgDefkey;
|