530 lines
17 KiB
JavaScript
530 lines
17 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) {
|
||
$("#minitoc").append("<a href='#" + $(this).attr("id") + "'>"
|
||
+ $(this).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 { // Fallback solution
|
||
window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
|
||
}
|
||
}
|
||
|
||
$(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();
|
||
|
||
// Need to call zclip here, once the button is visible.
|
||
// Beacause when the button is not visible, zclip does nothing.
|
||
if ((window.location.protocol != 'file:') && ($(this).find('.zclip').length == 0)) {
|
||
$(this).find('.copy-to-clipboard-button').zclip({
|
||
//path: 'http://www.steamdev.com/zclip/js/ZeroClipboard.swf',
|
||
//path: 'styles/bigblow/js/ZeroClipboard.swf',
|
||
path: bbPathToZeroClipboardSwf,
|
||
copy: function() {
|
||
return $(this).parent().parent().find('.src').text();
|
||
}
|
||
});
|
||
}
|
||
}).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() {
|
||
// Get the text to be copied
|
||
var text = $(this).parent().parent().find('.src').text();
|
||
text = text.replace(/\n/g, "\r\n");
|
||
// alert(text);
|
||
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;
|