Installation

To get the most out of this add-on, you will also want to follow the directions below to customize the look of Google Docs:

1) In a Google Doc, go to Tools -> Document outline (this shows the “NavPane”)

2) Go to View -> Print Layout (this will get rid of lots of white space between pages)

3) In the Google Doc Settings, turn on Offline Editing (scripts won’t work without internet, but you will still be able to access and edit your files)

4) Install the Debate Template Google Add-On (if you haven't done so yet)

***NOTE*** - the steps below are optional. It inserts extra code into Google Docs for formatting purposes. The css code is for formatting the nav-pane on the left and for shrinking the width of the sidebar. The javascript code is for enabling the nav-pane to have collapsable elements and for adding hot keys for many of the formatting operations. Both refer to files stored on my google drive. If you'd like to see the contents of these files, type the urls into your browser's url bar. If you are code savvy and have ideas of how to improve my code, just let me know.

5) Make your function keys work without requiring pressing the Fn key: Mac / Windows / Chromebook

NEW DIRECTIONS

6) Install Tampermonkey for Chrome

7) In Tampermoney, create a new script with the following code:

// ==UserScript==

// @name Debate Template Script

// @namespace http://tampermonkey.net/

// @version 0.1

// @description try to take over the world!

// @author You

// @match https://docs.google.com/document/d/*

// @icon https://www.google.com/s2/favicons?domain=google.com

// @grant none

// ==/UserScript==


(function () {

'use strict';

const appscriptSecret = "M-QjBWlrHgLXJ_3ClAKQETfQq_tZ4bSk_" // apps script project key

const keyMaps = {

'F3': "Condense",

'F4': "Pocket",

'F5': "Hat",

'F6': "Block",

'F7': "Tag",

'F8': "Cite",

'F9': "Underline",

'F10': "Emphasis",

'F11': "Highlight",

'F12': "Clear" // works with e.preventDefault on macos, need to test on other platforms

}

var observer = new MutationObserver(function (mutationRecords) {

var node = document.createElement('div');

var hotkeyNode = document.createTextNode(`Hotkeys loading; Please wait...`);

node.setAttribute('id', 'DocsVerbatimHotkeysStatus')

node.appendChild(hotkeyNode)

document.querySelector("#docs-titlebar-container > div.docs-titlebar-buttons").prepend(node)

observer.disconnect()

});

observer.observe(document.querySelector("#docs-titlebar-container > div.docs-titlebar-buttons"), { childList: true })

window.addEventListener('load', function () {


var simulateMouseEvent = function (element, eventName, coordX, coordY) {

element.dispatchEvent(new MouseEvent(eventName, {

view: window,

bubbles: true,

cancelable: true,

clientX: coordX,

clientY: coordY,

button: 0

}));

};


var execClick = (element) => {

var box = element.getBoundingClientRect(),

coordX = box.left + (box.right - box.left) / 2,

coordY = box.top + (box.bottom - box.top) / 2;

simulateMouseEvent(element, "mousedown", coordX, coordY);

simulateMouseEvent(element, "mouseup", coordX, coordY);

simulateMouseEvent(element, "click", coordX, coordY);

return {

box: box,

coordX: coordX,

coordY: coordY

}

}



execClick(document.querySelector("#docs-extensions-menu")) // click open menu to propagate the divs of the extension

execClick(document.querySelector(`#${appscriptSecret}`))

execClick(document.querySelector("#docs-extensions-menu")) // close the menu that was just opened


// find the div that has all the verbatim options:

var possibleDivs = Array.from(document.querySelector('body').children).filter(x => x.nodeName.toLowerCase() === "div") // all possible divs in body that may contain the extension function custom menu

let funcContainerDiv;

for (var element of possibleDivs) {

try {

if (element.children[0].id.includes(appscriptSecret)) {

funcContainerDiv = element // set the div that contains the function custom menu funcContainerDiv for later use

}

} catch (e) { }

}



var funcMap = {}

for (var ele of funcContainerDiv.children) {

try {

funcMap[`${ele.children[0].textContent}`] = ele

} catch (e) { }

}


document.querySelector('#DocsVerbatimHotkeysStatus').innerHTML = "✓ Hotkeys Loaded!"



// key press handling

var targets = document.getElementsByClassName("docs-texteventtarget-iframe");

targets[0].contentDocument.childNodes[0].addEventListener('keydown', function (event) {


if (event.code.includes('F') && keyMaps[event.code] != undefined) { // detect function keys to improve efficiency

event.preventDefault()

execClick(document.querySelector("#docs-extensions-menu"))

execClick(document.querySelector(`#${appscriptSecret}`))

execClick(funcMap[keyMaps[event.code]])

}

})


}, false);

})();


OLD DIRECTIONS

6) Install This CSS & Javscript Chrome Injector

7) Enter the following code in the CSS and Javascript tabs of the Chrome Injector WHILE ON A GOOGLE DOC.

CSS tab - ***UPDATED July 15th, 2016***

@import url("https://docs.google.com/uc?export=open&id=0BxxolsFkwnDqNUtUeExSWC14V1E");

.navigation-item {

height:20px;

line-height:20px;

}

.collapsed-menu:before {

content:"▶";

}

.expanded-menu:before {

content:"▼";

}

.empty-menu:before {

content:"▶";

visibility:hidden;

}

.navigation-widget-row-controls-control {

display: none;

visibility: hidden;

}

.script-application-sidebar {

width : 200px;

}

Javascript Tab - ***UPDATED July 12th, 2016***

var script = window.localStorage.debateTemplateScript; //read in the script remotely if there is no local data or if the local data is over a day old if(script === undefined || new Date().getTime() - parseInt(window.localStorage.debateTemplateDate) > 60*60*24) { read("https://docs.google.com/uc?export=open&id=0BxxolsFkwnDqZVpqTHZJR1J6dGM", function(result) { window.localStorage.debateTemplateScript = result; window.localStorage.debateTemplateDate = new Date().getTime() + ""; console.log("Using server script"); eval(result); load(); }); } else { console.log("Using local script"); eval(script); load(); } function read(url, callback){ var rawFile = new XMLHttpRequest(); rawFile.onreadystatechange = function () { if(rawFile.readyState === 4) { if(rawFile.status === 200 || rawFile.status === 0) { callback(rawFile.responseText); }

//use the old version if a reaed fails else if(script !== undefined) { eval(script);

load(); } } } rawFile.open("GET", url, true); rawFile.send(); }

Alternate Javascript Tab - This doesn't have navigation controls, but it does have the short cuts

function load(){findAddOnMenu()}function findAddOnMenu(){for(var e=document.getElementsByClassName("goog-control"),n=!1,t=0;t<e.length;t++)0==e[t].innerText.indexOf("Add-ons")&&(n=!0,addOnMenu=e[t]);if(n)findDebateMenu();else{if(0===attemptCounter)return void console.log("Couldn't find add-on menu!");setTimeout(findAddOnMenu,1e3),console.log("Finding Add-On Menu..."),attemptCounter--}}function findDebateMenu(){for(var e=document.getElementsByClassName("goog-menuitem-content"),n=!1,t=0;t<e.length;t++)0==e[t].innerText.indexOf("Debate Template")&&(n=!0,menu=e[t].parentElement);if(n){setupKeyEvents();var o=document.createEvent("Events");o.initEvent("mousedown",!0,!1),addOnMenu.dispatchEvent(o),(o=document.createEvent("Events")).initEvent("mousedown",!0,!1),menu.dispatchEvent(o),(o=document.createEvent("Events")).initEvent("mouseup",!0,!1),menu.dispatchEvent(o);var c=document.getElementsByClassName("goog-menuitem-content");for(t=0;t<c.length&&("Show Sidebar (Auto)"===c[t].innerText&&((o=document.createEvent("Events")).initEvent("mousedown",!0,!1),addOnMenu.dispatchEvent(o),(o=document.createEvent("Events")).initEvent("mousedown",!0,!1),menu.dispatchEvent(o),(o=document.createEvent("Events")).initEvent("mousedown",!0,!1),c[t].dispatchEvent(o),(o=document.createEvent("Events")).initEvent("mouseup",!0,!1),c[t].dispatchEvent(o)),"Help"!==c[t].innerText);t++)if(c[t].innerText in menuMap){var u=menuMap[c[t].innerText];menuItemElements[c[t].innerText]=c[t].parentElement;var a=document.createElement("span");a.setAttribute("class","goog-menuitem-accel"),a.setAttribute("aria-label","shortcut "+u.accel),a.setAttribute("style","-webkit-user-select: none;"),a.innerHTML=u.accel,c[t].appendChild(a),u.found=!0}(o=document.createEvent("Events")).initEvent("mousedown",!0,!1),addOnMenu.dispatchEvent(o)}else{if(0===attemptCounter)return void console.log("Couldn't find debate menu!");setTimeout(findDebateMenu,1e3),console.log("Finding Debate Menu..."),attemptCounter--}}function setupKeyEvents(){var e=document.getElementsByClassName("docs-texteventtarget-iframe");if(0!==e.length){var n=e[0];n.contentDocument.childNodes[0].addEventListener("keydown",function(e){if(isFullScreen()){var n=0;if(38==e.keyCode)n=30-window.innerHeight;else if(40==e.keyCode)n=window.innerHeight-30;else if(192!=e.keyCode&&27!=e.keyCode)return e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),!1;if(0!==n){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation();var t=document.getElementsByClassName("kix-appview-editor")[0],o=t.scrollTop;return o=null===o?0:parseInt(o),t.scrollTop=o+n,console.log("scroll"),!1}}}),n.contentDocument.addEventListener("keydown",function(e){var n=isFullScreen(),t=null;for(key in menuMap)if(value=menuMap[key],value.found&&e.keyCode==value.keycode&&value.cntrlKey==e.ctrlKey&&(void 0===value.fullScreen||n===value.fullScreen)){t=key;break}if(console.log(t),null!==t){e.preventDefault();var o=document.createEvent("Events");o.initEvent("mousedown",!0,!1),menu.dispatchEvent(o),(o=document.createEvent("Events")).initEvent("mousedown",!0,!1),menuItemElements.Preferences.dispatchEvent(o),(o=document.createEvent("Events")).initEvent("mousedown",!0,!1),menuItemElements[t].dispatchEvent(o),(o=document.createEvent("Events")).initEvent("mouseup",!0,!1),menuItemElements[t].dispatchEvent(o)}},!1)}else console.log("Couldn't find text area...")}function isFullScreen(){return"none"==document.getElementById("docs-menubars").style.display}load();var menuItemElements={},addOnMenu=null,menu=null,menuMap={};menuMap.Condense={accel:"F3",keycode:114,cntrlKey:!1,found:!1},menuMap.Pocket={accel:"F4",keycode:115,cntrlKey:!1,found:!1},menuMap.Hat={accel:"F5",keycode:116,cntrlKey:!1,found:!1},menuMap.Block={accel:"F6",keycode:117,cntrlKey:!1,found:!1},menuMap.Tag={accel:"F7",keycode:118,cntrlKey:!1,found:!1},menuMap.Cite={accel:"F8",keycode:119,cntrlKey:!1,found:!1},menuMap.Underline={accel:"F9",keycode:120,cntrlKey:!1,found:!1},menuMap.Emphasis={accel:"F10",keycode:121,cntrlKey:!1,found:!1},menuMap.Highlight={accel:"F11",keycode:122,cntrlKey:!1,found:!1},menuMap.Clear={accel:"F12",keycode:123,cntrlKey:!1,found:!1},menuMap.Shrink={accel:"Cntrl+8",keycode:56,cntrlKey:!0,found:!1},menuMap["Send to Speech"]={accel:"~",keycode:192,cntrlKey:!1,found:!1,fullScreen:!1},menuMap["Send to Speech / Set Insertion Point"]={accel:"~",keycode:192,cntrlKey:!1,found:!1,fullScreen:!1},menuMap.Mark={accel:"~",keycode:192,cntrlKey:!1,found:!1,fullScreen:!0},menuMap["Mark Speech"]={accel:"~",keycode:192,cntrlKey:!1,found:!1,fullScreen:!0},menuMap.Preferences={accel:"",keycode:-1,cntrlKey:!1,found:!1,fullScreen:!1};var attemptCounter=30;