Skip to content

Instantly share code, notes, and snippets.

@cdecker
Created October 26, 2009 21:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cdecker/219049 to your computer and use it in GitHub Desktop.
Save cdecker/219049 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name A Bit Better RTM
// @namespace http://www.rememberthemilk.com
// @description Small improvements for Remember The Milk: display list tabs to the left; display tasks count; GoTo & MoveTo list quickly;
// @include http://www.rememberthemilk.com/*
// @include https://www.rememberthemilk.com/*
// ==/UserScript==
//region String
/**
* Encode string into Base64, as defined by RFC 4648 [http://tools.ietf.org/html/rfc4648]
* (instance method extending String object). As per RFC 4648, no newlines are added.
*
* @param utf8encode optional parameter, if set to true Unicode string is encoded to UTF8 before
* conversion to base64; otherwise string is assumed to be 8-bit characters
* @return base64-encoded string
*/
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
String.prototype.encodeBase64 = function(utf8encode) { // http://tools.ietf.org/html/rfc4648
utf8encode = (typeof utf8encode == 'undefined') ? false : utf8encode;
var o1, o2, o3, bits, h1, h2, h3, h4, e=[], pad = '', c, plain, coded;
plain = utf8encode ? this.encodeUTF8() : this;
c = plain.length % 3; // pad string to length of multiple of 3
if (c > 0) { while (c++ < 3) { pad += '='; plain += '\0'; } }
// note: doing padding here saves us doing special-case packing for trailing 1 or 2 chars
for (c=0; c<plain.length; c+=3) { // pack three octets into four hexets
o1 = plain.charCodeAt(c);
o2 = plain.charCodeAt(c+1);
o3 = plain.charCodeAt(c+2);
bits = o1<<16 | o2<<8 | o3;
h1 = bits>>18 & 0x3f;
h2 = bits>>12 & 0x3f;
h3 = bits>>6 & 0x3f;
h4 = bits & 0x3f;
// use hextets to index into b64 string
e[c/3] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
}
coded = e.join(''); // join() is far faster than repeated string concatenation
// replace 'A's from padded nulls with '='s
coded = coded.slice(0, coded.length-pad.length) + pad;
return coded;
}
/**
* Decode string from Base64, as defined by RFC 4648 [http://tools.ietf.org/html/rfc4648]
* (instance method extending String object). As per RFC 4648, newlines are not catered for.
*
* @param utf8decode optional parameter, if set to true UTF8 string is decoded back to Unicode
* after conversion from base64
* @return decoded string
*/
String.prototype.decodeBase64 = function(utf8decode) {
utf8decode = (typeof utf8decode == 'undefined') ? false : utf8decode;
var o1, o2, o3, h1, h2, h3, h4, bits, d=[], plain, coded;
coded = utf8decode ? this.decodeUTF8() : this;
for (var c=0; c<coded.length; c+=4) { // unpack four hexets into three octets
h1 = b64.indexOf(coded.charAt(c));
h2 = b64.indexOf(coded.charAt(c+1));
h3 = b64.indexOf(coded.charAt(c+2));
h4 = b64.indexOf(coded.charAt(c+3));
bits = h1<<18 | h2<<12 | h3<<6 | h4;
o1 = bits>>>16 & 0xff;
o2 = bits>>>8 & 0xff;
o3 = bits & 0xff;
d[c/4] = String.fromCharCode(o1, o2, o3);
// check for padding
if (h4 == 0x40) d[c/4] = String.fromCharCode(o1, o2);
if (h3 == 0x40) d[c/4] = String.fromCharCode(o1);
}
plain = d.join(''); // join() is far faster than repeated string concatenation
return utf8decode ? plain.decodeUTF8() : plain;
}
/**
* Encode multi-byte Unicode string into utf-8 multiple single-byte characters
* (BMP / basic multilingual plane only) (instance method extending String object).
*
* Chars in range U+0080 - U+07FF are encoded in 2 chars, U+0800 - U+FFFF in 3 chars
*
* @return encoded string
*/
String.prototype.encodeUTF8 = function() {
// use regular expressions & String.replace callback function for better efficiency
// than procedural approaches
var str = this.replace(
/[\u0080-\u07ff]/g, // U+0080 - U+07FF => 2 bytes 110yyyyy, 10zzzzzz
function(c) {
var cc = c.charCodeAt(0);
return String.fromCharCode(0xc0 | cc>>6, 0x80 | cc&0x3f); }
);
str = str.replace(
/[\u0800-\uffff]/g, // U+0800 - U+FFFF => 3 bytes 1110xxxx, 10yyyyyy, 10zzzzzz
function(c) {
var cc = c.charCodeAt(0);
return String.fromCharCode(0xe0 | cc>>12, 0x80 | cc>>6&0x3F, 0x80 | cc&0x3f); }
);
return str;
}
/**
* Decode utf-8 encoded string back into multi-byte Unicode characters
* (instance method extending String object).
*
* @return decoded string
*/
String.prototype.decodeUTF8 = function() {
var str = this.replace(
/[\u00c0-\u00df][\u0080-\u00bf]/g, // 2-byte chars
function(c) { // (note parentheses for precence)
var cc = (c.charCodeAt(0)&0x1f)<<6 | c.charCodeAt(1)&0x3f;
return String.fromCharCode(cc); }
);
str = str.replace(
/[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g, // 3-byte chars
function(c) { // (note parentheses for precence)
var cc = ((c.charCodeAt(0)&0x0f)<<12) | ((c.charCodeAt(1)&0x3f)<<6) | ( c.charCodeAt(2)&0x3f);
return String.fromCharCode(cc); }
);
return str;
}
//endregion
//region Utility
function Utility(configuration)
{
this.location = new Utility.Location(configuration);
}
Utility.addGlobalCssStyle = function(css)
{
var head = document.getElementsByTagName('head')[0];
if (!head)
{
return;
}
var style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = css;
head.appendChild(style);
};
Utility.appendToMethod = function(owner, methodName, appendOwner, appendMethodName)
{
if (owner)
{
var oldMethod = owner[methodName];
owner["original" + methodName] = oldMethod;
owner[methodName] = function(param1, param2, param3, param4, param5)
{
oldMethod.call(owner, param1, param2, param3, param4, param5);
appendMethodName.call(appendOwner);
}
}
}
Utility.Location = function(configuration)
{
this.mbn = this.getUniqueMessageBusName();
this.configuration = configuration;
if (this.configuration.getUniqueURLForListAndTask())
{
if (history.length > 1 && location.hash.indexOf("section.tasks") >= 0)
{
history.back();
if (location.hash.indexOf("section.tasks") < 0)
{
history.forward();
}
}
this.locationHash = location.hash;
var that = this;
var checkIfLocationHashChanged = function()
{
if (that.locationHash != location.hash)
{
window.messageBus.broadcast(that, that.mbn + "locationHashChanged");
that.locationHash = location.hash;
}
}
setInterval(checkIfLocationHashChanged, 500);
}
}
Utility.Location.prototype.getUniqueMessageBusName = function()
{
return "abitbetterrtm.utility.location.";
}
Utility.Location.prototype.getListID = function()
{
var hashParams = this.getHashParams();
if (hashParams)
{
if (hashParams.indexOf("list=") > -1)
{
var start = hashParams.indexOf("list=") + 5;
var end = hashParams.indexOf("/", start);
return hashParams.substring(start, end);
}
}
return null;
}
Utility.Location.prototype.getTaskID = function(url)
{
var hashParams = this.getHashParams();
if (hashParams)
{
if (hashParams.indexOf("task=") > -1)
{
var start = hashParams.indexOf("task=") + 5;
var end = hashParams.indexOf("/", start);
return hashParams.substring(start, end);
}
}
return null;
}
Utility.Location.prototype.setTaskID = function(taskID)
{
var hashParams = this.getHashParams();
if (taskID)
{
if (hashParams.indexOf("task=") >= 0 || hashParams.indexOf("list=") >= 0)
{
hashParams = hashParams.replace(/\/(task|list)=\d+\//, "/task=" + taskID + "/");
}
else
{
hashParams = "/task=" + taskID + "/";
}
}
else
{
hashParams = hashParams.replace(/\/task=\d+\//, "");
}
this.setHashParams(hashParams);
}
Utility.Location.prototype.setListID = function(listID)
{
var hashParams = this.getHashParams();
if (listID)
{
if (hashParams.indexOf("list=") >= 0 || hashParams.indexOf("task=") >= 0)
{
hashParams = hashParams.replace(/\/(list|task)=\d+\//, "/list=" + listID + "/");
}
else
{
hashParams += "/list=" + listID + "/";
}
}
else
{
hashParams = hashParams.replace(/\/list=\d+\//, "");
}
this.setHashParams(hashParams);
}
Utility.Location.prototype.getHashParams = function()
{
var hashParts = location.hash.split('/');
if (hashParts[1])
{
return hashParts[1].decodeBase64();
}
return "";
}
Utility.Location.prototype.setHashParams = function(hashParams)
{
var locationHash = location.hash.split('/')[0];
if (hashParams)
{
locationHash += "/" + hashParams.encodeBase64();
}
location.hash = this.locationHash = locationHash;
}
//endregion
//region Initialize
window = window.wrappedJSObject;
function aBitBetterRTMLoad()
{
window.aBitBetterRTM = new ABitBetterRTM();
}
window.addEventListener('load', aBitBetterRTMLoad, false);
//endregion
//region JSON parse an stringify
if(!this.JSON){this.JSON={};}
(function(){function f(n){return n<10?'0'+n:n;}
if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return this.getUTCFullYear()+'-'+
f(this.getUTCMonth()+1)+'-'+
f(this.getUTCDate())+'T'+
f(this.getUTCHours())+':'+
f(this.getUTCMinutes())+':'+
f(this.getUTCSeconds())+'Z';};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf();};}
var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+String.replace(escapable,function(a){var c=meta[a];if(typeof c==='string'){return c;}
return'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4);})+'"':'"'+string+'"';}
function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key);}
if(typeof rep==='function'){value=rep.call(holder,key,value);}
switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null';}
gap+=indent;partial=[];if(typeof value.length==='number'&&!value.propertyIsEnumerable('length')){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||'null';}
v=partial.length===0?'[]':gap?'[\n'+gap+
partial.join(',\n'+gap)+'\n'+
mind+']':'['+partial.join(',')+']';gap=mind;return v;}
if(rep&&typeof rep==='object'){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==='string'){v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}else{for(k in value){if(Object.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}
v=partial.length===0?'{}':gap?'{\n'+gap+partial.join(',\n'+gap)+'\n'+
mind+'}':'{'+partial.join(',')+'}';gap=mind;return v;}}
if(typeof JSON.stringify!=='function'){JSON.stringify=function(value,replacer,space){var i;gap='';indent='';if(typeof space==='number'){for(i=0;i<space;i+=1){indent+=' ';}}else if(typeof space==='string'){indent=space;}
rep=replacer;if(replacer&&typeof replacer!=='function'&&(typeof replacer!=='object'||typeof replacer.length!=='number')){throw new Error('JSON.stringify');}
return str('',{'':value});};}
if(typeof JSON.parse!=='function'){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==='object'){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v;}else{delete value[k];}}}}
return reviver.call(holder,key,value);}
cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return'\\u'+
('0000'+a.charCodeAt(0).toString(16)).slice(-4);});}
if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){j=eval('('+text+')');return typeof reviver==='function'?walk({'':j},''):j;}
throw new SyntaxError('JSON.parse');};}})();
//endregion
//region Configuration
function Configuration()
{
this.displayTabsToTheLeft = (GM_getValue("displayTabsToTheLeft", "") !== "false");
this.hiddenLists = GM_getValue("hiddenLists", "");
this.showTasksCount = (GM_getValue("showTasksCount", "") !== "false");
this.quickAddList = (GM_getValue("quickAddList", "") !== "false");
this.uniqueURLForListAndTask = (GM_getValue("uniqueURLForListAndTask", "") !== "false");
}
Configuration.prototype.makeListHidden = function(listEntry)
{
this.hiddenLists = (this.hiddenLists || "") + listEntry[0] + ",";
GM_setValue("hiddenLists", this.hiddenLists);
};
Configuration.prototype.makeListVisible = function(listEntry)
{
this.hiddenLists = this.hiddenLists.replace(listEntry[0], "");
this.hiddenLists = this.hiddenLists.replace(",,", ",");
GM_setValue("hiddenLists", this.hiddenLists);
};
Configuration.prototype.isListHidden = function(listID)
{
if (this.hiddenLists)
{
return this.hiddenLists.indexOf(listID) >= 0;
}
return false;
}
Configuration.prototype.getDisplayTabsToTheLeft = function()
{
return this.displayTabsToTheLeft;
};
Configuration.prototype.setDisplayTabsToTheLeft = function(value)
{
if (value === true)
{
GM_setValue("displayTabsToTheLeft", "true");
}
else
{
GM_setValue("displayTabsToTheLeft", "false");
}
this.displayTabsToTheLeft = value;
};
Configuration.prototype.getShowTasksCount = function()
{
return this.showTasksCount;
};
Configuration.prototype.setShowTasksCount = function(value)
{
if (value === true)
{
GM_setValue("showTasksCount", "true");
}
else
{
GM_setValue("showTasksCount", "false");
}
this.showTasksCount = value;
};
Configuration.prototype.getQuickAddList = function()
{
return this.quickAddList;
};
Configuration.prototype.setQuickAddList = function(value)
{
if (value === true)
{
GM_setValue("quickAddList", "true");
}
else
{
GM_setValue("quickAddList", "false");
}
this.quickAddList = value;
};
Configuration.prototype.getUniqueURLForListAndTask = function()
{
return this.uniqueURLForListAndTask;
};
Configuration.prototype.setUniqueURLForListAndTask = function(value)
{
if (value === true)
{
GM_setValue("uniqueURLForListAndTask", "true");
}
else
{
GM_setValue("uniqueURLForListAndTask", "false");
}
this.quickAddList = value;
};
//endregion
//region ListAutocompleteStore
function ListAutocompleteStore(listTabs)
{
this.listTabs = listTabs;
}
ListAutocompleteStore.prototype.getCompletions = function(text)
{
if (this.listTabs)
{
var completions = [];
var entries = this.listTabs.getEntries();
var data = this.listTabs.getData();
if (entries && data)
{
for (var i = 0; i < entries.length; ++i)
{
if (entries[i].toLowerCase().indexOf(text.toLowerCase()) === 0 && !this.listTabs.parent.configuration.isListHidden(data[i][1]))
{
completions.push(entries[i]);
}
}
}
return completions;
}
return null;
};
//endregion
//region AutocompleteList
function AutocompleteList(inputField, autocompleteStore, parent)
{
this.inputField = inputField;
this.autocompleteStore = autocompleteStore;
this.parent = parent;
this.output = null;
this.completions = null;
this.position = -1;
this.isVisible = false;
}
AutocompleteList.prototype.createOutput = function()
{
if (!this.inputField)
{
return;
}
this.output = document.createElement('div');
this.output.setAttribute('id','autoCompleteList_' + this.inputField.id);
this.output.style.border = "solid 1px black";
this.output.style.background = "white";
this.output.style.position = "absolute";
this.output.style.width = "150px";
this.output.style.visibility = "hidden";
this.inputField.parentNode.insertBefore(this.output, this.inputField.nextSibling);
};
AutocompleteList.prototype.showOutput = function()
{
if (this.output)
{
this.output.style.visibility = "visible";
}
this.isVisible = true;
};
AutocompleteList.prototype.hideOutput = function()
{
if (this.output)
{
this.output.style.visibility = "hidden";
}
this.isVisible = false;
};
AutocompleteList.prototype.clearOutput = function()
{
while(this.output && this.output.childNodes.length)
{
this.output.removeChild(this.output.firstChild);
}
this.position = -1;
this.hideOutput();
};
AutocompleteList.prototype.addCompletion = function(completion)
{
var autocompleteList = this;
var _mouseOverHandler = function(event)
{
autocompleteList.position = this.position;
autocompleteList.highlightCompletion();
};
var _mouseClickHandler = function(event)
{
autocompleteList.parent.doCallback();
};
var completionBox = document.createElement("div");
completionBox.style.textAlign = "left";
completionBox.style.paddingLeft = "2px";
completionBox.appendChild(document.createTextNode(completion));
completionBox.wrappedJSObject.position = this.output.childNodes.length;
completionBox.addEventListener("mouseover", _mouseOverHandler, false);
completionBox.addEventListener("click", _mouseClickHandler, false);
this.output.appendChild(completionBox);
};
AutocompleteList.prototype.highlightCompletion = function()
{
if (this.output && this.output.childNodes)
{
for (var i = 0; i < this.output.childNodes.length; ++i)
{
if (i == this.position)
{
this.output.childNodes[i].style.color = "white";
this.output.childNodes[i].style.background = "#316ac5";
}
else
{
this.output.childNodes[i].style.color = "black";
this.output.childNodes[i].style.background = "white";
}
}
}
};
AutocompleteList.prototype.highlightNextCompletion = function()
{
if (this.completions && this.completions.length > 0 && this.position < this.completions.length - 1)
{
++this.position;
this.highlightCompletion();
}
};
AutocompleteList.prototype.highlightPreviousCompletion = function()
{
if (this.completions && this.completions.length > 1 && this.position > 0)
{
--this.position;
this.highlightCompletion();
}
};
AutocompleteList.prototype.getCurrentCompletion = function()
{
if (this.completions && this.completions.length > 0)
{
return this.completions[this.position];
}
return null;
};
AutocompleteList.prototype.update = function()
{
if (this.inputField.value.length > 0)
{
this.completions = this.autocompleteStore.getCompletions(this.inputField.value);
if (this.completions && this.completions.length > 0)
{
this.clearOutput();
for (var i = 0; i < this.completions.length; ++i)
{
this.addCompletion(this.completions[i]);
}
this.showOutput();
this.highlightNextCompletion();
}
else
{
this.hideOutput();
this.position = -1;
}
}
else
{
this.hideOutput();
this.position = -1;
}
};
//endregion
//region Autocomplete
function Autocomplete(name, autocompleteStore, owner, callback)
{
var autocompleteBox = document.createElement('div');
autocompleteBox.setAttribute("id", "autocompleteBox_" + name);
autocompleteBox.style.width = "240px";
autocompleteBox.style.position = "absolute";
autocompleteBox.innerHTML = '<div class="white_rbroundbox"> <div class="white_rbtop"> <div> <div></div> </div> </div> <div class="white_rbcontentwrap"> <div class="white_rbcontent"> <div class="taskcloudcontent" style="padding: 0px 5px 0px 5px; height: 17px;" id="listtabscontainer"><div style="width: 70px; font-weight: bold; float: left; height: 17px; padding-top: 1px;">' + name + '</div><div style="text-align: right; float: right; width: 155px; padding-right: 2px;"><input type="text" id="autocompleteInputField_' + name + '" name="text" style="width: 151px; ";/></div> </div> </div> </div> <div class="white_rbbot"> <div><div></div> </div> </div> </div> ';
document.body.appendChild(autocompleteBox);
this.inputField = document.getElementById("autocompleteInputField_" + name);
this.box = document.getElementById("autocompleteBox_" + name);
this.autocompleteList = new AutocompleteList(this.inputField, autocompleteStore, this);
this.owner = owner;
this.callback = callback;
this.hide();
this.bind();
function _centerAutoCompleteBox()
{
var left = window.innerWidth / 2 - 120 + window.scrollX;
var top = window.innerHeight / 2 - 10 + window.scrollY;
autocompleteBox.style.left = left + "px";
autocompleteBox.style.top = top + "px";
}
_centerAutoCompleteBox();
window.addEventListener("scroll", _centerAutoCompleteBox, false);
window.addEventListener("resize", _centerAutoCompleteBox, false);
return this;
}
Autocomplete.prototype.show = function()
{
this.box.wrappedJSObject.style.display = "block";
if (this.inputField)
{
this.inputField.focus();
}
};
Autocomplete.prototype.hide = function()
{
this.box.wrappedJSObject.style.display = "none";
if (this.inputField)
{
this.inputField.value = "";
}
this.autocompleteList.clearOutput();
};
Autocomplete.prototype.doCallback = function()
{
var completion = this.autocompleteList.getCurrentCompletion();
this.hide();
if (this.owner)
{
this.callback.call(this.owner, completion);
}
else
{
this.callback(completion);
}
};
Autocomplete.prototype.bind = function()
{
var autocompleteList = this.autocompleteList;
var inputField = this.inputField;
var currentText = "";
var _handleKeyPressEvent = function(event)
{
currentText = inputField.value;
if (event.keyCode == 9) // Tab
{
if (window.utility)
{
window.utility.stopEvent(event);
}
return false;
}
else if (autocompleteList.isVisible)
{
if (event.keyCode == 13)// Enter
{
autocompleteList.parent.doCallback();
}
if (event.keyCode == 40)// Key down
{
autocompleteList.highlightNextCompletion();
}
else if (event.keyCode == 38) // Key up
{
autocompleteList.highlightPreviousCompletion();
}
else if (event.keyCode == 27) // Esc
{
autocompleteList.clearOutput();
}
}
else if (event.keyCode == 27)
{
autocompleteList.parent.hide();
}
return true;
};
var _handleKeyUpEvent = function(event)
{
if (currentText === null || currentText != inputField.value)
{
autocompleteList.update();
}
};
var _handleClickEvent = function(event)
{
if (autocompleteList.isVisible)
{
autocompleteList.hideOutput();
}
if (window.utility)
{
window.utility.stopEvent(event);
}
};
this.inputField.setAttribute("autocomplete", "off");
this.inputField.addEventListener("keypress", _handleKeyPressEvent, false);
this.inputField.addEventListener("keyup", _handleKeyUpEvent, false);
this.box.addEventListener("click", _handleClickEvent, false);
this.autocompleteList.createOutput();
};
//endregion
//region LeftColumn
function LeftColumn(configuration)
{
this.RTM_listTabs = window.listTabs;
this.RTM_taskCloud = window.taskCloud;
this.configuration = configuration;
this.id = "leftColumn";
this.div = document.createElement("div");
this.appView = document.getElementById("appview");
this.listBox = document.getElementById("listbox");
this.content = document.getElementById("content");
this.children = [];
this.div.setAttribute("id", this.id);
this.div.style.cssFloat = "left";
this.div.style.paddingLeft = "5px";
this.div.style.paddingRight = "8px";
if (this.appView && this.listBox)
{
this.appView.insertBefore(this.div, this.listBox);
}
var that = this;
var handleViewChanged = function(d, e)
{
if (e[0][1] == "Tasks")
{
that.hide();
}
else if (e[1][1] == "Tasks")
{
that.show();
}
};
if (window.messageBus)
{
window.messageBus.subscribe(handleViewChanged, window.view.getUniqueMessageBusName() + "viewChanged");
}
Utility.appendToMethod(this.RTM_listTabs, "blitDiv", this, this.blitDiv);
Utility.appendToMethod(this.RTM_taskCloud, "update", this.RTM_listTabs, this.RTM_listTabs.blitDiv);
}
LeftColumn.prototype.hide = function()
{
this.div.style.display = "none";
this.content.style.width = "980px";
};
LeftColumn.prototype.show = function()
{
this.div.style.display = "block";
};
LeftColumn.prototype.blitDiv = function()
{
if (window.view.selected === 1) //Tasks
{
this.show();
if (this.children)
{
for (var i = 0; i < this.children.length; ++i)
{
this.children[i].blitDiv();
}
}
if (this.children[0] && this.children[0].getWidth)
{
this.div.style.width = this.children[0].getWidth() + "px";
this.content.style.width = (973 + this.div.clientWidth) + "px";
}
}
}
LeftColumn.prototype.appendChild = function(child)
{
if (this.div && child)
{
this.div.appendChild(child.div);
child.container = this;
this.children.push(child);
}
}
//endregion
//region Frame
function Frame(id)
{
this.id = id;
this.container;
this.div = document.createElement('div');
this.div.innerHTML = '<div class="white_rbroundbox"> <div class="white_rbtop"> <div> <div></div> </div> </div> <div class="white_rbcontentwrap"> <div class="white_rbcontent"> <table><tr><td><div class="taskcloudcontent" style="padding: 0px 5px 0px 5px;" id="frame_' + id + '"> </div></td></tr></table> </div> </div> <div class="white_rbbot"> <div><div></div> </div> </div> </div> ';
this.childPlaceHolder;
this.children = [];
}
Frame.prototype.appendChild = function(child)
{
this.childPlaceHolder = document.getElementById("frame_" + this.id);
if (this.childPlaceHolder && child)
{
this.childPlaceHolder.appendChild(child.div);
child.container = this;
this.children.push(child);
}
};
Frame.prototype.blitDiv = function()
{
if (this.children)
{
for (var i = 0; i < this.children.length; ++i)
{
this.children[i].blitDiv();
}
if (this.children[0] && this.children[0].getWidth)
{
this.div.style.width = Math.round(this.children[0].getWidth() + 15) + "px";
}
}
};
Frame.prototype.getWidth = function()
{
return this.div.clientWidth;
}
//endregion
//region ListAdder
function ListAdder(parent)
{
this.parent = parent;
this.RTM_utility = window.utility;
this.RTM_T = window._T;
this.RTM_statusBox = window.statusBox;
this.RTM_transMgr = window.transMgr;
this.div = document.createElement('div');
this.div.cssClass = "addEntryTask";
this.div.style.padding = "0px 0px 10px 3px";
this.div.id = "listAdder";
this.div.innerHTML = '<div style="padding-bottom: 2px;"><img class="taskaddicon" src="http://static.rememberthemilk.com/img/ico/ico_add.gif" alt="Add task"><a title="Add list" href="#" class="taskadd" style="text-decoration: underline;">Add List</a></div>';
this.progressBar = document.createElement('img');
this.progressBar.src = '/img/busy.gif';
this.progressBar.width = '10';
this.progressBar.height = '10';
this.progressBar.style.display = 'none';
this.div.firstChild.appendChild(this.progressBar);
this.listEntryBox = document.createElement('input');
this.listEntryBox.type = "text";
this.div.appendChild(this.listEntryBox);
this.listEntryBox.style.width = (this.parent.getWidth() - 5) + "px";
this.listEntryBox.style.display = "none";
var that = this;
var handleLostFocus = function(ev)
{
that.hideListEntryBox();
};
var handleAddListClick = function(ev)
{
that.showListEntryBox();
that.RTM_utility.stopEvent(ev);
};
var handleKeyPressEvent = function(event)
{
if (event.keyCode === 13)// Enter
{
that.showProgressBar();
that.addList(that.listEntryBox.value);
}
else if (event.keyCode === 27) // Esc
{
that.clearListEntryBox();
that.hideListEntryBox();
}
return true;
};
var handleAddingListSuccess = function()
{
that.clearListEntryBox();
that.hideListEntryBox();
that.hideProgressBar();
}
this.listEntryBox.addEventListener('keypress', handleKeyPressEvent, false);
this.listEntryBox.addEventListener('blur', handleLostFocus, false);
this.div.addEventListener('click', handleAddListClick, false);
Utility.appendToMethod(window.control, "addingListAddSuccess", null, handleAddingListSuccess);
}
ListAdder.prototype.showProgressBar = function()
{
this.progressBar.style.display = 'inline';
};
ListAdder.prototype.hideProgressBar = function()
{
this.progressBar.style.display = 'none';
};
ListAdder.prototype.showListEntryBox = function()
{
this.listEntryBox.style.display = "block";
this.listEntryBox.focus();
};
ListAdder.prototype.hideListEntryBox = function()
{
this.listEntryBox.style.display = "none";
};
ListAdder.prototype.clearListEntryBox = function()
{
this.listEntryBox.value = "";
}
ListAdder.prototype.addList = function(listName)
{
if (listName.toLowerCase() == "inbox" || listName.toLowerCase() == "sent" || listName.toLowerCase() == this.RTM_T("INTERFACE_TASKS_INBOX").toLowerCase() || listName.toLowerCase() == this.RTM_T("INTERFACE_TASKS_SENT").toLowerCase())
{
this.RTM_statusBox.setText(this.RTM_T("INTERFACE_STATUS_CANT_CALL_LIST", {"LIST_NAME" : listName}), false, true);
return false
}
this.RTM_transMgr.request("lists.add", this.RTM_utility.encodeJavaScript( { "name" : listName, "id" : ""}))
}
//endregion
//region ListTabs
function ListTabs(parent, configuration)
{
this.configuration = configuration;
this.parent = parent;
this.container;
this.blitted = false;
this.RTM_control = window.control;
this.RTM_listTabs = window.listTabs;
this.RTM_listList = window.listList;
this.RTM_taskCloud = window.taskCloud;
this.RTM_overviewList = window.overviewList;
this.RTM_stateMgr = window.stateMgr;
this.RTM_format = window.format;
this.tasksCountCache = {};
if (this.RTM_listTabs)
{
if (this.configuration.getDisplayTabsToTheLeft())
{
if (this.configuration.getQuickAddList())
{
this.listAdder = new ListAdder(this);
}
this.div = document.createElement('div');
this.RTM_listTabs.div.className = "";
this.RTM_listTabs.div.style.width = "100%";
this.div.appendChild(this.RTM_listTabs.div);
}
this.overrideSelectLeft();
this.overrideSelectRight();
}
var that = this;
var handleViewChanged = function(d, e)
{
if (e[1][1] == "Tasks")
{
that.RTM_listTabs.blitDiv();
}
};
var handleTabChanged = function(d, e)
{
if (that.configuration.getUniqueURLForListAndTask() === true)
{
that.parent.utility.location.setListID(e[2][1]);
}
if (that.configuration.getShowTasksCount() === true)
{
setTimeout(that.backgroundTasksCountUpdate, 1000, d.selected, that);
}
}
var handleLocationHashChanged = function(d, e)
{
if (window.view.entries[window.view.selected][0] === "Tasks")
{
var taskID = that.parent.utility.location.getTaskID();
if (taskID)
{
that.parent.taskList.selectTaskByID(taskID);
}
else
{
var selectedTaskID = that.parent.taskList.getSelectedTaskID();
if (selectedTaskID)
{
that.parent.utility.location.setTaskID(selectedTaskID);
}
else
{
var listID = that.parent.utility.location.getListID();
if (listID)
{
that.selectListByID(that.parent.utility.location.getListID());
}
else
{
that.parent.utility.location.setListID(that.getSelectedListID());
}
}
}
}
}
if (this.configuration.getUniqueURLForListAndTask())
{
handleLocationHashChanged();
}
var handleSelectFinished = function()
{
if (window.view.entries[window.view.selected][0] === "Tasks")
{
if (!that.parent.taskList.getSelectedTaskID())
{
that.parent.utility.location.setListID(that.getSelectedListID());
}
}
};
if (window.messageBus)
{
window.messageBus.subscribe(handleViewChanged, window.view.getUniqueMessageBusName() + "viewChanged");
window.messageBus.subscribe(this.RTM_listTabs.blitDiv, this.RTM_listList.mbn + "setFilterSuccess");
window.messageBus.subscribe(handleTabChanged, this.RTM_listTabs.mbn + "tabChanged");
if (this.configuration.getUniqueURLForListAndTask())
{
window.messageBus.subscribe(handleSelectFinished, window.taskList.list.getUniqueMessageBusName() + "selectFinished");
window.messageBus.subscribe(handleLocationHashChanged, this.parent.utility.location.mbn + "locationHashChanged");
}
}
this.appendCodeToExistingMethods();
var tools_spacer = document.getElementById("tools_spacer");
if (tools_spacer)
{
tools_spacer.style.paddingTop = "1px";
tools_spacer.style.borderTop = "1px solid #CACACA";
}
var sorting = document.getElementById("sorting");
if (sorting)
{
sorting.style.marginTop = "0px";
}
var tools = document.getElementById("tools");
if (tools)
{
tools.style.paddingTop = "5px";
}
}
ListTabs.prototype.appendCodeToExistingMethods = function()
{
if (this.configuration.getShowTasksCount() === true)
{
Utility.appendToMethod(this.RTM_taskCloud, "update", this, this.backgroundTasksCountUpdate);
}
if (this.configuration.getDisplayTabsToTheLeft() !== true)
{
Utility.appendToMethod(this.RTM_listTabs, "blitDiv", this, this.blitDiv);
Utility.appendToMethod(this.RTM_taskCloud, "update", this.RTM_listTabs, this.RTM_listTabs.blitDiv);
}
};
ListTabs.prototype.getWidth = function()
{
var maxListEntryName = "";
for (var i = 0; i < this.RTM_listTabs.entries.length; ++i)
{
if (this.RTM_listTabs.entries[i].length > maxListEntryName.length)
{
maxListEntryName = this.RTM_listTabs.entries[i];
}
}
return maxListEntryName.length * 9 + 4;
}
ListTabs.prototype.getEntries = function()
{
if (this.RTM_listTabs)
{
return this.RTM_listTabs.entries;
}
return null;
}
ListTabs.prototype.getData = function()
{
if (this.RTM_listTabs)
{
return this.RTM_listTabs.data;
}
return null;
}
ListTabs.prototype.showTasksCount = function()
{
if (this.RTM_listTabs)
{
var listItems = this.RTM_listTabs.div.getElementsByTagName("li");
for (var i = 0; this.RTM_listTabs.data && this.RTM_listTabs.data[i]; ++i)
{
if (this.RTM_listTabs.data[i][2])
{
this.smartListTasksCountUpdate(this.RTM_listTabs.data[i][1], this.RTM_listTabs.data[i][2], listItems[i], this.tasksCountCache, false, this.getListNameWithTasksCount);
}
else
{
this.regularListTasksCountUpdate(this.RTM_listTabs.data[i][1], listItems[i], this.tasksCountCache, false, this.getListNameWithTasksCount);
}
}
}
};
ListTabs.prototype.hideTasksCount = function()
{
if (this.RTM_listTabs)
{
var listItems = this.RTM_listTabs.div.getElementsByTagName("li");
for (var i = 0; this.RTM_listTabs.data && this.RTM_listTabs.data[i]; ++i)
{
listItems[i].firstChild.innerHTML = this.getListNameWithoutTasksCount(listItems[i].firstChild.innerHTML);
}
}
}
ListTabs.prototype.backgroundTasksCountUpdate = function(selectedListNumber, that)
{
if (that === undefined)
{
that = this;
}
if (that.RTM_listTabs)
{
if (selectedListNumber !== undefined && selectedListNumber != that.RTM_listTabs.selected)
{
return;
}
var listItems = that.RTM_listTabs.div.getElementsByTagName("li");
var timeout = 300;
for (var i = 0; that.RTM_listTabs.data && that.RTM_listTabs.data[i]; ++i)
{
if (selectedListNumber !== undefined && i != selectedListNumber)
{
continue;
}
if (that.RTM_listTabs.data[i][2])
{
setTimeout(that.smartListTasksCountUpdate, timeout, that.RTM_listTabs.data[i][1], that.RTM_listTabs.data[i][2], listItems[i], that.tasksCountCache, true, that.getListNameWithTasksCount);
}
else
{
setTimeout(that.regularListTasksCountUpdate, timeout, that.RTM_listTabs.data[i][1], listItems[i], that.tasksCountCache, true, that.getListNameWithTasksCount);
}
timeout += 300;
}
}
};
ListTabs.prototype.regularListTasksCountUpdate = function(listID, listItem, cache, reloadCache, getListNameCallback)
{
var tasksCount = cache[listID];
if (tasksCount === undefined || reloadCache === true)
{
if (window.format)
{
tasksCount = window.format.getListStatistics(listID)[5];
}
}
if (listItem && getListNameCallback)
{
listItem.firstChild.innerHTML = getListNameCallback(listItem.firstChild.innerHTML, tasksCount);
}
cache[listID] = tasksCount;
};
ListTabs.prototype.getListNameWithoutTasksCount = function(listName)
{
if (listName)
{
var regExp = /\(\d+\)$/;
if (regExp.test(listName))
{
listName = listName.replace(regExp, "");
}
}
return listName;
}
ListTabs.prototype.getListNameWithTasksCount = function(listName, tasksCount)
{
if (listName)
{
var regExp = /\(\d+\)$/;
if (regExp.test(listName))
{
listName = listName.replace(regExp, "(" + tasksCount + ")");
}
else
{
listName = listName + " (" + tasksCount + ")";
}
if (!tasksCount || tasksCount == 0)
{
listName = listName.replace(regExp, "");
}
}
return listName;
};
ListTabs.prototype.smartListTasksCountUpdate = function(listID, filter, listItem, cache, reloadCache, getListNameCallback)
{
var tasksCount = cache[listID];
if (tasksCount === undefined || reloadCache === true)
{
if (filter && filter.indexOf("status:") < 0)
{
filter = "(" + filter + ") and (status:incomplete)";
}
if (window.overviewList && filter)
{
tasksCount = window.overviewList.getFilteredList(filter).length;
}
}
if (listItem && getListNameCallback)
{
listItem.firstChild.innerHTML = getListNameCallback(listItem.firstChild.innerHTML, tasksCount);
}
cache[listID] = tasksCount;
};
ListTabs.prototype.hideDisabledLists = function(listItems)
{
var listItems = this.RTM_listTabs.div.getElementsByTagName("li");
for (var i = 0; i < this.RTM_listTabs.data.length; ++i)
{
if (listItems[i] && this.RTM_listTabs.data[i] && this.parent.configuration.isListHidden(this.RTM_listTabs.data[i][1]))
{
listItems[i].style.display = "none";
}
}
}
ListTabs.prototype.blitDiv = function()
{
if (window.view.entries[window.view.selected][0] === "Tasks")
{
if (this.configuration.getDisplayTabsToTheLeft())
{
this.RTM_listTabs.div.firstChild.style.listStyle = "none";
this.RTM_listTabs.div.firstChild.style.padding = "0px 5px 0px 5px";
this.RTM_listTabs.div.firstChild.style.whiteSpace = "nowrap";
var listItems = this.RTM_listTabs.div.getElementsByTagName("li");
for (var i = 0; i < this.RTM_listTabs.data.length; ++i)
{
if (!this.RTM_listTabs.data[i][2])
{
listItems[i].firstChild.style.color = "black";
}
}
}
this.hideDisabledLists();
if (this.configuration.getShowTasksCount() === true)
{
this.showTasksCount();
}
if (!this.blitted && this.listAdder)
{
this.div.insertBefore(this.listAdder.div, this.div.firstChild);
}
}
};
ListTabs.prototype.selectNextList = function()
{
if (this.RTM_listTabs)
{
this.RTM_listTabs.selectRight();
}
};
ListTabs.prototype.selectPreviousList = function()
{
if (this.RTM_listTabs)
{
this.RTM_listTabs.selectLeft();
}
};
ListTabs.prototype.selectListByName = function(text)
{
if (!this.RTM_listTabs || !this.RTM_listTabs.entries)
{
return;
}
for (var i = 0; i < this.RTM_listTabs.entries.length; ++i)
{
if (this.RTM_listTabs.entries[i].toLowerCase() == text.toLowerCase())
{
this.RTM_listTabs.selectTabByPosition(i);
}
}
};
ListTabs.prototype.selectListByID = function(listID)
{
if (this.RTM_listTabs && listID)
{
this.RTM_listTabs.selectTabByData(listID);
}
};
ListTabs.prototype.moveSelectedTasksToListByName = function(text)
{
if (!this.RTM_listTabs || !this.RTM_listTabs.entries || !this.RTM_control)
{
return;
}
for (var i = 0; i < window.listTabs.entries.length; ++i)
{
if (this.RTM_listTabs.entries[i].toLowerCase() == text.toLowerCase())
{
this.RTM_control.tasksSelectionChanged("", ["", "tasks.moveTo." + window.listTabs.data[i][1]]);
}
}
};
ListTabs.prototype.overrideSelectLeft = function()
{
var that = this;
if (this.RTM_listTabs)
{
this.RTM_listTabs.selectLeft = function()
{
var position = this.selected - 1;
while (true)
{
if (position >= 0)
{
if (!that.parent.configuration.isListHidden(this.data[position][1]))
{
break;
}
--position;
}
else
{
position = this.entries.length - 1;
}
}
this.selectTabByPosition(position);
};
}
};
ListTabs.prototype.overrideSelectRight = function()
{
var that = this;
if (this.RTM_listTabs)
{
this.RTM_listTabs.selectRight = function()
{
var position = this.selected + 1;
while (true)
{
if (position < this.entries.length)
{
if (!that.parent.configuration.isListHidden(this.data[position][1]))
{
break;
}
++position;
}
else
{
position = 0;
}
}
this.selectTabByPosition(position);
};
}
};
ListTabs.prototype.getSelectedListID = function()
{
return this.RTM_listTabs.data[this.RTM_listTabs.selected][1];
}
//endregion
//region Shortcut
function Shortcut(key, owner, method, ctrlKey, shiftKey, altKey)
{
this.key = key;
this.owner = owner;
this.method = method;
this.ctrlKey = ctrlKey;
this.shiftKey = shiftKey;
this.altKey = altKey;
}
Shortcut.prototype.run = function()
{
if (this.method)
{
if (this.owner)
{
this.method.call(this.owner);
}
else
{
this.method();
}
}
};
//endregion
//region TaskList
function TaskList(parent)
{
this.parent = parent;
this.RTM_taskList = window.taskList;
this.RTM_control = window.control;
var that = this;
var handleSelectFinished = function()
{
that.parent.utility.location.setTaskID(that.getSelectedTaskID());
};
window.messageBus.subscribe(handleSelectFinished, window.taskList.list.getUniqueMessageBusName() + "selectFinished");
}
TaskList.prototype.getSelectedTaskID = function()
{
if (this.RTM_taskList)
{
var selectedTasks = this.RTM_taskList.getViewList().getSelected();
if (selectedTasks && selectedTasks.length > 0)
{
return selectedTasks[selectedTasks.length - 1];
}
}
return null;
};
TaskList.prototype.selectTaskByID = function(taskID)
{
if (this.RTM_control)
{
this.RTM_control.showTaskById(taskID);
}
};
//endregion
//region ListList
function ListList(configuration)
{
this.configuration = configuration;
this.RTM_listList = window.listList;
this.RTM_utility = window.utility;
this.RTM_stateMgr = window.stateMgr;
this._overrideListListUpdateEntry();
}
ListList.prototype._overrideListListUpdateEntry = function()
{
if (this.RTM_listList)
{
var oldListListUpdateEntry = this.RTM_listList.list.updateEntry;
var that = this;
this.RTM_listList.list.updateEntry = function(entry, D)
{
oldListListUpdateEntry.call(that.RTM_listList.list, entry, D);
var index = that.RTM_listList.list.map[entry[0]];
var row = that.RTM_listList.list.table.rows[index];
row.entry = entry;
row.rowText.innerHTML = "<div id='listName_" + entry[0] + "' style='float: left;'>" + entry[1] + "</div><div style='align: right; float: right;'><a href=\"# \" id='displayListLink_" + entry[0] + "'></a></div>";
var displayListLink = document.getElementById('displayListLink_' + entry[0]);
var listName = document.getElementById('listName_' + entry[0]);
var listClickHandler = function(event)
{
if (that.configuration.isListHidden(entry[0]))
{
that.makeListVisible(entry);
}
else
{
that.makeListHidden(entry);
}
if (that.RTM_utility)
{
that.RTM_utility.stopEvent(event);
}
};
displayListLink.addEventListener('click', listClickHandler, false);
if (!that.isListArchived(entry[0]))
{
if (that.configuration.isListHidden(entry[0]))
{
displayListLink.innerHTML = "show";
listName.style.color = "#cacaca";
}
else
{
displayListLink.innerHTML = "hide";
listName.style.color = "";
}
}
};
this.RTM_listList.doStyles();
}
};
ListList.prototype.isListArchived = function(listID)
{
if (this.RTM_stateMgr.lists[listID] && this.RTM_stateMgr.lists[listID].archived)
{
return true;
}
return false;
};
ListList.prototype.makeListHidden = function(listEntry)
{
this.configuration.makeListHidden(listEntry);
this.RTM_listList.list.updateEntry(listEntry);
};
ListList.prototype.makeListVisible = function(listEntry)
{
this.configuration.makeListVisible(listEntry);
this.RTM_listList.list.updateEntry(listEntry);
};
//endregion
//region Settings
function Settings(configuration)
{
this.mbn = this.getUniqueMessageBusName();
this.configuration = configuration;
this.div = document.createElement("div");
var generalSettings = document.getElementById("general");
if (generalSettings)
{
generalSettings.parentNode.appendChild(this.div);
}
this.div.style.display = "none";
this.div.innerHTML = '<div style="padding: 12px 25px 21px;" class="contentboxwrap"><form id="abitbetterrtmform" autocomplete="off"><table style="width: 100%;"><tr><td class="label"><label>Tasks count</label></td><td class="field" colspan="2"><span><input id="abbrtm_taskscount_on" name="showtaskscount" type="radio" /><label for="abbrtm_taskscount_on" style="font-weight: normal;">On</label></span><span style="padding-left: 9px;"><input id="abbrtm_taskscount_off" name="showtaskscount" type="radio" /><label for="abbrtm_taskscount_off" style="font-weight: normal;">Off</label></span></td></tr><tr><td class="label"><label>Tabs on the left</label></td><td class="field" colspan="2"><span><input id="abbrtm_tabsontheleft_on" name="abbrtm_tabsontheleft" type="radio" /><label for="abbrtm_tabsontheleft_on" style="font-weight: normal;">On</label></span><span style="padding-left: 9px;"><input id="abbrtm_tabsontheleft_off" name="abbrtm_tabsontheleft" type="radio" /><label for="abbrtm_tabstotheleft_off" style="font-weight: normal;">Off</label></span></td></tr><tr><td class="label"><label>Quick add list</label></td><td class="field" colspan="2"><span><input id="abbrtm_quickaddlist_on" name="abbrtm_quickaddlist" style="font-weight: normal;" type="radio">On</label></span><span style="padding-left: 9px;"><input id="abbrtm_quickaddlist_off" name="abbrtm_quickaddlist" type="radio" /><label for="abbrtm_quickaddlist_off" style="font-weight: normal;">Off</label></span></td></tr><tr><td class="label"><label>Unique URL for list/task</label></td><td class="field" colspan="2"><span><input id="abbrtm_uniqueurl_on" name="abbrtm_uniqueurl" style="font-weight: normal;" type="radio">On</label></span><span style="padding-left: 9px;"><input id="abbrtm_uniqueurl_off" name="abbrtm_uniqueurl" type="radio" /><label for="abbrtm_uniqueurl_off" style="font-weight: normal;">Off</label></span></td></tr><tr><td class="hiddenlabel"><label for="settingssubmit">Save Changes</label></td><td class="field" colspan="2"><input id="abbrtm_settingssubmit" name="settingssave" type="button" value="Save Changes" /><label for="settingscancel" style="display: none;">Cancel</label><input id="abbrtm_settingscancel" name="settingscancel" type="button" value="Cancel" /></td></tr></table></form></div>';
this.tasksCount_on = document.getElementById("abbrtm_taskscount_on");
this.tasksCount_off = document.getElementById("abbrtm_taskscount_off");
this.tabsOnTheLeft_on = document.getElementById("abbrtm_tabsontheleft_on");
this.tabsOnTheLeft_off = document.getElementById("abbrtm_tabsontheleft_off");
this.quickAddList_on = document.getElementById("abbrtm_quickaddlist_on");
this.quickAddList_off = document.getElementById("abbrtm_quickaddlist_off");
this.uniqueURL_on = document.getElementById("abbrtm_uniqueurl_on");
this.uniqueURL_off = document.getElementById("abbrtm_uniqueurl_off");
this.settingsSave = document.getElementById("abbrtm_settingssubmit");
this.settingsCancel = document.getElementById("abbrtm_settingscancel");
this.settingsSave.disabled = true;
this.settingsCancel.disabled = true;
this.loadSettings();
var that = this;
var optionClickHandler = function()
{
that.settingsSave.disabled = false;
that.settingsCancel.disabled = false;
}
var cancelClickHandler = function(event)
{
that.loadSettings();
that.settingsSave.disabled = true;
that.settingsCancel.disabled = true;
return false;
}
var saveClickHandler = function()
{
that.saveSettings();
that.settingsSave.disabled = true;
that.settingsCancel.disabled = true;
location.reload(true);
}
this.tasksCount_on.addEventListener("click", optionClickHandler, false);
this.tasksCount_off.addEventListener("click", optionClickHandler, false);
this.tabsOnTheLeft_on.addEventListener("click", optionClickHandler, false);
this.tabsOnTheLeft_off.addEventListener("click", optionClickHandler, false);
this.quickAddList_on.addEventListener("click", optionClickHandler, false);
this.quickAddList_off.addEventListener("click", optionClickHandler, false);
this.uniqueURL_on.addEventListener("click", optionClickHandler, false);
this.uniqueURL_off.addEventListener("click", optionClickHandler, false);
this.settingsCancel.addEventListener("click", cancelClickHandler, false);;
this.settingsSave.addEventListener("click", saveClickHandler, false);;
}
Settings.prototype.getUniqueMessageBusName = function()
{
return "abitbetterrtm.settings.";
}
Settings.prototype.loadSettings = function()
{
if (this.configuration.getShowTasksCount() === true)
{
this.tasksCount_on.checked = 'true';
}
else
{
this.tasksCount_off.checked = 'true';
}
if (this.configuration.getDisplayTabsToTheLeft() === true)
{
this.tabsOnTheLeft_on.checked = 'true';
}
else
{
this.tabsOnTheLeft_off.checked = 'true';
}
if (this.configuration.getQuickAddList() === true)
{
this.quickAddList_on.checked = 'true';
}
else
{
this.quickAddList_off.checked = 'true';
}
if (this.configuration.getUniqueURLForListAndTask() === true)
{
this.uniqueURL_on.checked = 'true';
}
else
{
this.uniqueURL_off.checked = 'true';
}
}
Settings.prototype.saveSettings = function()
{
this.configuration.setShowTasksCount(this.tasksCount_on.checked);
this.configuration.setDisplayTabsToTheLeft(this.tabsOnTheLeft_on.checked);
this.configuration.setQuickAddList(this.quickAddList_on.checked && this.tabsOnTheLeft_on.checked);
this.configuration.setUniqueURLForListAndTask(this.uniqueURL_on.checked);
}
Settings.prototype.hide = function()
{
this.div.style.display = "none";
}
Settings.prototype.show = function()
{
this.div.style.display = "";
}
//endregion
//region ABitBetterRTM
function ABitBetterRTM()
{
this.configuration = new Configuration();
this.utility = new Utility(this.configuration);
this.settings = new Settings(this.configuration);
this.taskList = new TaskList(this);
this.listList = new ListList(this.configuration);
this.listTabs = new ListTabs(this, this.configuration);
if (this.configuration.getDisplayTabsToTheLeft())
{
this.leftColumn = new LeftColumn(this.configuration);
this.leftColumn.hide();
this.leftColumn.appendChild(new Frame('listTabsFrame'));
this.leftColumn.children[0].appendChild(this.listTabs);
}
if (window.view.entries[window.view.selected][0] === "Tasks")
{
if (this.configuration.getDisplayTabsToTheLeft())
{
this.leftColumn.blitDiv();
}
else
{
this.listTabs.blitDiv();
}
}
this.autocompletes = {};
this.shortcuts = [];
this._initAutocompletes();
this._initShortcuts();
this._overrideBodyKeyPressHandler();
Utility.addGlobalCssStyle('html { overflow: scroll; overflow-x: auto; }');
window.settingsTabs.addEntry("A Bit Better RTM");
window.settingsView.addState("A Bit Better RTM", [this.settings], window.settingsTabs);
window.settingsTabs.blitDiv();
}
ABitBetterRTM.prototype._initShortcuts = function()
{
this.shortcuts.push(new Shortcut(74, this.listTabs, this.listTabs.selectNextList, false, true, false));
this.shortcuts.push(new Shortcut(75, this.listTabs, this.listTabs.selectPreviousList, false, true, false));
this.shortcuts.push(new Shortcut(103, this.autocompletes.goTo, this.autocompletes.goTo.show, true, false, false));
this.shortcuts.push(new Shortcut(109, this.autocompletes.moveTo, this.autocompletes.moveTo.show, true, false, false));
if (this.configuration.getDisplayTabsToTheLeft() && this.configuration.getQuickAddList())
{
this.shortcuts.push(new Shortcut(113, this.listTabs.listAdder, this.listTabs.listAdder.showListEntryBox, false, false, false));
}
};
ABitBetterRTM.prototype._initAutocompletes = function()
{
this.autocompletes.goTo = new Autocomplete("GO TO: ", new ListAutocompleteStore(this.listTabs), this.listTabs, this.listTabs.selectListByName);
this.autocompletes.moveTo = new Autocomplete("MOVE TO: ", new ListAutocompleteStore(this.listTabs), this.listTabs, this.listTabs.moveSelectedTasksToListByName);
}
ABitBetterRTM.prototype._overrideBodyKeyPressHandler = function()
{
var that = this;
var handleKeyPressEvent = function(ev, ignoreCombo)
{
if (!ev)
{
ev = window.event;
}
if (ev === null)
{
return;
}
var target = null;
if (window.utility)
{
target = window.utility.getEventTarget(ev);
}
if (target === null)
{
return true;
}
var pressed = (ev.charCode) ? ev.charCode: ((ev.which) ? ev.which: ev.keyCode);
if (target !== null && target.type !== null && target.type !== undefined && (target.type == "textarea" || target.type == "input" || target.type.indexOf("select") === 0 || target.type == "button" || target.type === "submit" || target.type == "text" || target.type == "password" || (target.id !== null && target.id == "map")))
{
return true;
}
var tabs = null;
if (window.view)
{
tabs = window.view.getViewTabs();
}
if (tabs)
{
for (var i = 0; i < that.shortcuts.length; ++i)
{
if ((that.shortcuts[i].key === pressed) && (that.shortcuts[i].ctrlKey === ev.ctrlKey) && (that.shortcuts[i].shiftKey === ev.shiftKey) && (that.shortcuts[i].altKey === ev.altKey) && (ev.metaKey === false))
{
that.shortcuts[i].run();
if (window.utility)
{
window.utility.stopEvent(ev);
}
return false;
}
}
}
return true;
}
if (window.eventMgr)
{
var oldBodyKeyPressHandler = window.eventMgr.bodyKeyPressHandler;
window.eventMgr.bodyKeyPressHandler = function(ev, ignoreCombo)
{
if (handleKeyPressEvent(ev, ignoreCombo))
{
return oldBodyKeyPressHandler.call(window.eventMgr, ev, ignoreCombo);
}
return true;
};
}
}
//endregion
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment