diff --git a/feedlist.js b/feedlist.js
index b140c6d075a645e3a72af3e2a03638f357a211ef..8860424b1947a863ceeca12a149a8a56f2abe30c 100644
--- a/feedlist.js
+++ b/feedlist.js
@@ -46,7 +46,7 @@ function render_feedlist(data) {
 
 function feedlist_callback2(transport) {
 	try {
-		debug("feedlist_callback2");
+		console.log("feedlist_callback2");
 		if (!transport_error_check(transport)) return;
 		render_feedlist(transport.responseText);
 	} catch (e) {
@@ -58,7 +58,7 @@ function viewNextFeedPage() {
 	try {
 		//if (!getActiveFeedId()) return;
 
-		debug("viewNextFeedPage: calling viewfeed(), p: " + parseInt(_feed_cur_page+1));
+		console.log("viewNextFeedPage: calling viewfeed(), p: " + parseInt(_feed_cur_page+1));
 
 		viewfeed(getActiveFeedId(), undefined, activeFeedIsCat(), undefined,
 			undefined, parseInt(_feed_cur_page+1));
@@ -112,10 +112,10 @@ function viewfeed(feed, subop, is_cat, subop_param, skip_history, offset) {
 			var date = new Date();
 			var timestamp = Math.round(date.getTime() / 1000);
 
-			debug("<b>" + _infscroll_request_sent + " : " + timestamp + "</b>");
+			console.log("<b>" + _infscroll_request_sent + " : " + timestamp + "</b>");
 
 			if (_infscroll_request_sent && _infscroll_request_sent + 30 > timestamp) {
-				debug("infscroll request in progress, aborting");
+				console.log("infscroll request in progress, aborting");
 				return;
 			}
 
@@ -149,7 +149,7 @@ function viewfeed(feed, subop, is_cat, subop_param, skip_history, offset) {
 			force_nocache = true;
 		}
 
-//		debug("IS_CAT_STORED: " + activeFeedIsCat() + ", IS_CAT: " + is_cat);
+//		console.log("IS_CAT_STORED: " + activeFeedIsCat() + ", IS_CAT: " + is_cat);
 
 		if (subop == "MarkAllRead") {
 
@@ -220,7 +220,7 @@ function viewfeed(feed, subop, is_cat, subop_param, skip_history, offset) {
 			query = query + "&csync=true";
 		}
 
-		debug(query);
+		console.log(query);
 
 		var container = $("headlinesInnerContainer");
 
@@ -246,7 +246,7 @@ function viewfeed(feed, subop, is_cat, subop_param, skip_history, offset) {
 			}
 
 			cache_check = cache_check_param(cache_prefix + feed, unread_ctr);
-			debug("headline cache check: " + cache_check);
+			console.log("headline cache check: " + cache_check);
 		}
 
 		if (cache_check) {
@@ -383,7 +383,7 @@ function feedlist_dragsorted(ctr) {
 			var query = "?op=feeds&subop=catsort&corder=" + 
 				param_escape(ordered_cats.toString());
 
-			debug(query);
+			console.log(query);
 
 			new Ajax.Request("backend.php", { parameters: query });
 		}
@@ -397,7 +397,7 @@ function feedlist_init() {
 	try {
 		loading_set_progress(90);
 
-		debug("in feedlist init");
+		console.log("in feedlist init");
 		
 		hideOrShowFeeds(getInitParam("hide_read_feeds") == 1);
 		document.onkeydown = hotkey_handler;
@@ -414,7 +414,7 @@ function feedlist_init() {
 		}
 
 		if (getActiveFeedId()) {
-			//debug("some feed is open on feedlist refresh, reloading");
+			//console.log("some feed is open on feedlist refresh, reloading");
 			//setTimeout("viewCurrentFeed()", 100);
 		} else {
 			if (getInitParam("cdm_auto_catchup") != 1 && get_feed_unread(-3) > 0) {
@@ -477,7 +477,7 @@ function hide_footer() {
 
 function init_collapsable_feedlist() {
 	try {
-		debug("init_collapsable_feedlist");
+		console.log("init_collapsable_feedlist");
 
 		var theme = getInitParam("theme");
 		var options = getInitParam("theme_options");
@@ -586,7 +586,7 @@ function request_counters_real() {
 
 		if (offline_mode) return;
 
-		debug("requesting counters...");
+		console.log("requesting counters...");
 
 		var query = "?op=rpc&subop=getAllCounters";
 
@@ -625,11 +625,11 @@ function request_counters() {
 //				timestamp - counters_last_request > 10) {
 
 		if (timestamp - counters_last_request > 15) {
-			debug("scheduling request of counters...");
+			console.log("scheduling request of counters...");
 			window.setTimeout("request_counters_real()", 1000);
 			counters_last_request = timestamp;
 		} else {
-			debug("request_counters: rate limit reached: " + (timestamp - counters_last_request));
+			console.log("request_counters: rate limit reached: " + (timestamp - counters_last_request));
 		}
 
 	} catch (e) {
diff --git a/functions.js b/functions.js
index 7901c00f32ccdc256f2359b381e0aee592ea22a1..b3fc8876a24d63bd21f168ef0cc59d4797159189 100644
--- a/functions.js
+++ b/functions.js
@@ -11,14 +11,17 @@ Array.prototype.remove = function(s) {
 	}
 }
 
-function is_opera() {
-	return window.opera;
-}
+/* create console.log if it doesn't exist */
+
+if (!window.console) console = {};
+console.log = console.log || function(msg) { debug(msg); };
+console.warn = console.warn || function(msg) { debug(msg); };
+console.error = console.error || function(msg) { debug(msg); };
 
 function exception_error(location, e, ext_info) {
 	var msg = format_exception_error(location, e);
 
-	if (!ext_info) ext_info = "N/A";
+	if (!ext_info) ext_info = false;
 
 	disableHotkeys();
 
@@ -39,10 +42,16 @@ function exception_error(location, e, ext_info) {
 	
 			ebc.innerHTML = 
 				"<div><b>Error message:</b></div>" +
-				"<pre>" + msg + "</pre>" +
-				"<div><b>Additional information:</b></div>" +
-				"<textarea readonly=\"1\">" + ext_info + "</textarea>";
-	
+				"<pre>" + msg + "</pre>";
+
+			if (ext_info) {
+				ebc.innerHTML += "<div><b>Additional information:</b></div>" +
+					"<textarea readonly=\"1\">" + ext_info + "</textarea>";
+			}
+
+			ebc.innerHTML += "<div><b>Stack trace:</b></div>" +
+				"<textarea readonly=\"1\">" + e.stack + "</textarea>";
+
 		} else {
 			alert(msg);
 		}
@@ -70,7 +79,7 @@ function format_exception_error(location, e) {
 		msg = "Exception: " + e + "\nFunction: " + location + "()";
 	}
 
-	debug("<b>EXCEPTION: " + msg + "</b>");
+	console.error("EXCEPTION: " + msg);
 
 	return msg;
 }
@@ -313,7 +322,7 @@ function setCookie(name, value, lifetime, path, domain, secure) {
 		d.setTime(d.getTime() + (lifetime * 1000));
 	}
 
-	debug("setCookie: " + name + " => " + value + ": " + d);
+	console.log("setCookie: " + name + " => " + value + ": " + d);
 	
 	int_setCookie(name, value, d, path, domain, secure);
 
@@ -511,13 +520,13 @@ function parse_counters(reply, scheduled_call) {
 
 		var feeds_stored = number_of_feeds;
 
-		debug("Feed counters, C: " + feeds_found + ", S:" + feeds_stored);
+		console.log("Feed counters, C: " + feeds_found + ", S:" + feeds_stored);
 
 		if (feeds_stored != feeds_found) {
 			number_of_feeds = feeds_found;
 
 			if (feeds_stored != 0 && feeds_found != 0) {
-				debug("Subscribed feed number changed, refreshing feedlist");
+				console.log("Subscribed feed number changed, refreshing feedlist");
 				setTimeout('updateFeedList(false, false)', 50);
 			}
 		} else {
@@ -572,9 +581,9 @@ function all_counters_callback2(transport, async_call) {
 		
 		if (offline_mode) return;
 
-		debug("<b>all_counters_callback2 IN: " + transport + "</b>");
+		console.log("<b>all_counters_callback2 IN: " + transport + "</b>");
 		parse_counters_reply(transport);
-		debug("<b>all_counters_callback2 OUT: " + transport + "</b>");
+		console.log("<b>all_counters_callback2 OUT: " + transport + "</b>");
 
 	} catch (e) {
 		exception_error("all_counters_callback2", e, transport);
@@ -625,7 +634,7 @@ function resort_category(node, cat_mode) {
 
 	try {
 
-		debug("resort_category: " + node + " CM=" + cat_mode);
+		console.log("resort_category: " + node + " CM=" + cat_mode);
 	
 		var by_unread = feedsSortByUnread();
 	
@@ -660,7 +669,7 @@ function resort_category(node, cat_mode) {
 }
 
 function resort_feedlist() {
-	debug("resort_feedlist");
+	console.log("resort_feedlist");
 
 	if ($("FCATLIST--1")) {
 
@@ -715,7 +724,7 @@ function hideOrShowFeeds(hide) {
 
 	try {
 
-	debug("hideOrShowFeeds: " + hide);
+	console.log("hideOrShowFeeds: " + hide);
 
 	if ($("FCATLIST--1")) {
 
@@ -752,16 +761,16 @@ function hideOrShowFeedsCategory(id, hide) {
 			node = $("feedList"); // no categories
 		}
 
-	//	debug("hideOrShowFeedsCategory: " + node + " (" + hide + ")");
+	//	console.log("hideOrShowFeedsCategory: " + node + " (" + hide + ")");
 	
 		var cat_unread = 0;
 	
 		if (!node) {
-			debug("hideOrShowFeeds: passed node is null, aborting");
+			console.log("hideOrShowFeeds: passed node is null, aborting");
 			return;
 		}
 	
-	//	debug("cat: " + node.id);
+	//	console.log("cat: " + node.id);
 	
 		if (node.hasChildNodes() && node.firstChild.nextSibling != false) {  
 			for (i = 0; i < node.childNodes.length; i++) {
@@ -776,7 +785,7 @@ function hideOrShowFeedsCategory(id, hide) {
 						node.childNodes[i].className != "error" && 
 						node.childNodes[i].className != "tag");
 		
-	//				debug(node.childNodes[i].id + " --> " + has_unread);
+	//				console.log(node.childNodes[i].id + " --> " + has_unread);
 		
 					if (hide && !has_unread) {
 						//node.childNodes[i].style.display = "none";
@@ -800,13 +809,13 @@ function hideOrShowFeedsCategory(id, hide) {
 			}
 		}	
 	
-	//	debug("end cat: " + node.id + " unread " + cat_unread);
+	//	console.log("end cat: " + node.id + " unread " + cat_unread);
 
 		if (cat_node) {
 
 			if (cat_unread == 0) {
 				if (cat_node.style == undefined) {
-					debug("ERROR: supplied cat_node " + cat_node + 
+					console.log("ERROR: supplied cat_node " + cat_node + 
 						" has no styles. WTF?");
 					return;
 				}
@@ -821,12 +830,12 @@ function hideOrShowFeedsCategory(id, hide) {
 				try {
 					cat_node.style.display = "list-item";
 				} catch (e) {
-					debug(e);
+					console.log(e);
 				}
 			}
 		}
 
-//	debug("unread for category: " + cat_unread);
+//	console.log("unread for category: " + cat_unread);
 
 	} catch (e) {
 		exception_error("hideOrShowFeedsCategory", e);
@@ -867,7 +876,7 @@ function selectTableRowsByIdPrefix(content_id, prefix, check_prefix, do_select,
 	var content = $(content_id);
 
 	if (!content) {
-		debug("[selectTableRows] Element " + content_id + " not found.");
+		console.log("[selectTableRows] Element " + content_id + " not found.");
 		return;
 	}
 
@@ -915,7 +924,7 @@ function getSelectedTableRowIds(content_id, prefix) {
 	var content = $(content_id);
 
 	if (!content) {
-		debug("[getSelectedTableRowIds] Element " + content_id + " not found.");
+		console.log("[getSelectedTableRowIds] Element " + content_id + " not found.");
 		return new Array();
 	}
 
@@ -1211,6 +1220,14 @@ function leading_zero(p) {
 	return s;
 }
 
+function make_timestamp() {
+	var d = new Date();
+
+  	return leading_zero(d.getHours()) + ":" + leading_zero(d.getMinutes()) +
+			":" + leading_zero(d.getSeconds());
+}
+
+
 function closeErrorBox() {
 
 	if (Element.visible("errorBoxShadow")) {
@@ -1279,7 +1296,7 @@ function infobox_submit_callback2(transport) {
 function infobox_callback2(transport) {
 	try {
 
-		debug("infobox_callback2");
+		console.log("infobox_callback2");
 
 		var box = $('infoBox');
 		
@@ -1355,7 +1372,7 @@ function subscribeToFeed() {
 
 	var query = Form.serialize("feed_add_form");
 	
-	debug("subscribe q: " + query);
+	console.log("subscribe q: " + query);
 
 	Form.disable("feed_add_form");
 
@@ -1436,9 +1453,7 @@ function debug(msg) {
 			c.removeChild(c.lastChild);
 		}
 	
-		var d = new Date();
-		var ts = leading_zero(d.getHours()) + ":" + leading_zero(d.getMinutes()) +
-			":" + leading_zero(d.getSeconds());
+		var ts = make_timestamp();
 		c.innerHTML = "<li class=\"" + debug_last_class + "\"><span class=\"debugTS\">[" + ts + "]</span> " + 
 			msg + "</li>" + c.innerHTML;
 	}
@@ -1520,7 +1535,7 @@ function filterDlgCheckType(sender) {
 		}
 
 		if (!form) {
-			debug("filterDlgCheckType: can't find form!");
+			console.log("filterDlgCheckType: can't find form!");
 			return;
 		}
 
@@ -1553,14 +1568,14 @@ function filterDlgCheckAction(sender) {
 		}
 
 		if (!form) {
-			debug("filterDlgCheckAction: can't find form!");
+			console.log("filterDlgCheckAction: can't find form!");
 			return;
 		}
 
 		var action_param = $("filter_dlg_param_box");
 
 		if (!action_param) {
-			debug("filterDlgCheckAction: can't find action param box!");
+			console.log("filterDlgCheckAction: can't find action param box!");
 			return;
 		}
 
@@ -1593,7 +1608,7 @@ function filterDlgCheckDate() {
 		}
 
 		if (!form) {
-			debug("filterDlgCheckAction: can't find form!");
+			console.log("filterDlgCheckAction: can't find form!");
 			return;
 		}
 
@@ -1643,7 +1658,7 @@ function getRelativePostIds(id, limit) {
 
 	if (!limit) limit = 3;
 
-	debug("getRelativePostIds: " + id + " limit=" + limit);
+	console.log("getRelativePostIds: " + id + " limit=" + limit);
 
 	var ids = new Array();
 	var container = $("headlinesList");
@@ -1675,12 +1690,12 @@ function getRelativePostIds(id, limit) {
 
 function openArticleInNewWindow(id) {
 	try {
-		debug("openArticleInNewWindow: " + id);
+		console.log("openArticleInNewWindow: " + id);
 
 		var query = "?op=rpc&subop=getArticleLink&id=" + id;
 		var wname = "ttrss_article_" + id;
 
-		debug(query + " " + wname);
+		console.log(query + " " + wname);
 
 		var w = window.open("", wname);
 
@@ -1693,13 +1708,13 @@ function openArticleInNewWindow(id) {
 					var link = transport.responseXML.getElementsByTagName("link")[0];
 					var id = transport.responseXML.getElementsByTagName("id")[0];
 		
-					debug("open_article received link: " + link);
+					console.log("open_article received link: " + link);
 		
 					if (link && id) {
 		
 						var wname = "ttrss_article_" + id.firstChild.nodeValue;
 		
-						debug("link url: " + link.firstChild.nodeValue + ", wname " + wname);
+						console.log("link url: " + link.firstChild.nodeValue + ", wname " + wname);
 		
 						var w = window.open(link.firstChild.nodeValue, wname);
 		
@@ -1800,7 +1815,7 @@ function loading_set_progress(p) {
 	try {
 		if (p < last_progress_point || !Element.visible("overlay")) return;
 
-		debug("<b>loading_set_progress : " + p + " (" + last_progress_point + ")</b>");
+		console.log("<b>loading_set_progress : " + p + " (" + last_progress_point + ")</b>");
 
 		var o = $("l_progress_i");
 
@@ -1821,9 +1836,9 @@ function loading_set_progress(p) {
 
 function remove_splash() {
 	if (Element.visible("overlay")) {
-		debug("about to remove splash, OMG!");
+		console.log("about to remove splash, OMG!");
 		Element.hide("overlay");
-		debug("removed splash!");
+		console.log("removed splash!");
 	}
 }
 
@@ -1924,7 +1939,7 @@ function hotkey_prefix_timeout() {
 		var ts = Math.round(date.getTime() / 1000);
 
 		if (hotkey_prefix_pressed && ts - hotkey_prefix_pressed >= 5) {
-			debug("hotkey_prefix seems to be stuck, aborting");
+			console.log("hotkey_prefix seems to be stuck, aborting");
 			hotkey_prefix_pressed = false;
 			hotkey_prefix = false;
 			Element.hide('cmdline');
@@ -2066,7 +2081,7 @@ function removeFeedIcon(id) {
 		if (confirm(__("Remove stored feed icon?"))) {
 			var query = "backend.php?op=pref-feeds&subop=removeicon&feed_id=" + param_escape(id);
 
-			debug(query);
+			console.log(query);
 
 			notify_progress("Removing feed icon...", true);
 
diff --git a/offline.js b/offline.js
index 372d94392790cc4cb2ad103e3e3ec488f83e626d..9abad919ae2ba7de85f3128e5980f5a027831a49 100644
--- a/offline.js
+++ b/offline.js
@@ -115,7 +115,7 @@ function viewfeed_offline(feed_id, subop, is_cat, subop_param, skip_history, off
 		var f = $("headlines-frame");
 		try {
 			if (reply.offset == 0) { 
-				debug("resetting headlines scrollTop");
+				console.log("resetting headlines scrollTop");
 				f.scrollTop = 0; 
 			}
 		} catch (e) { };
@@ -660,7 +660,7 @@ function offline_download_parse(stage, transport) {
 					var marked = sync_ok[i].getAttribute("marked");
 
 					if (id) {
-						debug("synced offline info for id " + id);
+						console.log("synced offline info for id " + id);
 
 						if (unread != undefined && marked != undefined) {
 							db.execute("UPDATE articles SET "+
@@ -771,7 +771,7 @@ function offline_download_parse(stage, transport) {
 					}
 				}
 
-				debug("downloaded articles: " + articles_found + " limit: " + limit);
+				console.log("downloaded articles: " + articles_found + " limit: " + limit);
 
 				articles_synced += articles_found;
 
@@ -784,11 +784,11 @@ function offline_download_parse(stage, transport) {
 				if (articles_found >= limit || has_sync_data) {
 					sync_timer = window.setTimeout("update_offline_data("+(stage+1)+")", 
 						3*1000);
-					debug("<b>update_offline_data: done " + stage + " HSD: " + 
+					console.log("<b>update_offline_data: done " + stage + " HSD: " + 
 						has_sync_data + "</b>");
 				} else {
 					window.setTimeout("offlineDownloadStart()", 180*1000);
-					debug("update_offline_data: finished");
+					console.log("update_offline_data: finished");
 
 					var pic = $("offlineModePic");
 
@@ -868,7 +868,7 @@ function update_offline_data(stage) {
 
 		rs.close();
 
-		debug("update_offline_data: stage " + stage);
+		console.log("update_offline_data: stage " + stage);
 
 		query = query + "&stage=" + stage;
 
@@ -894,7 +894,7 @@ function update_offline_data(stage) {
 
 		sync_in_progress = true;
 
-		debug(query);
+		console.log(query);
 
 		new Ajax.Request("backend.php", {
 			parameters: query,
@@ -1184,7 +1184,7 @@ function offlineArticlesStored() {
 
 function gotoOffline() {
 
-//	debug("[Local store] currentVersion = " + store.currentVersion);
+//	console.log("[Local store] currentVersion = " + store.currentVersion);
 
 
 	if (offlineArticlesStored() == 0) {
@@ -1202,7 +1202,7 @@ function gotoOffline() {
 		var timerId = window.setInterval(function() {
 			if (store.currentVersion) {
 				window.clearInterval(timerId);
-				debug("[Local store] sync complete: " + store.currentVersion);
+				console.log("[Local store] sync complete: " + store.currentVersion);
 
 				//window.location.href = "tt-rss.php";
 
@@ -1212,7 +1212,7 @@ function gotoOffline() {
 				notify_info("Tiny Tiny RSS is in offline mode.");
 
 			} else if (store.updateStatus == 3) {
-				debug("[Local store] sync error: " + store.lastErrorMessage);
+				console.log("[Local store] sync error: " + store.lastErrorMessage);
 				notify_error(store.lastErrorMessage, true);
 			} }, 500);
 	}
@@ -1387,7 +1387,7 @@ function get_local_article_labels(id) {
 
 function label_local_add_article(id, label_id) {
 	try {
-		//debug("label_local_add_article " + id + " => " + label_id);
+		//console.log("label_local_add_article " + id + " => " + label_id);
 
 		var rs = db.execute("SELECT COUNT(id) FROM article_labels WHERE "+
 			"id = ? AND label_id = ?", [id, label_id]);
@@ -1698,9 +1698,9 @@ function offlineUpdateStore() {
 		var timerId = window.setInterval(function() {
 			if (store.currentVersion) {
 				window.clearInterval(timerId);
-				debug("[Local store] sync complete: " + store.currentVersion);
+				console.log("[Local store] sync complete: " + store.currentVersion);
 			} else if (store.updateStatus == 3) {
-				debug("[Local store] sync error: " + store.lastErrorMessage);
+				console.log("[Local store] sync error: " + store.lastErrorMessage);
 			} }, 500);
 
 	} catch (e) {
diff --git a/prefs.js b/prefs.js
index 43e6b28bd49bf126ef79883e790ff3253f2f3ab6..36e4569e4933a7c2933d08ec6dd50c2905d865c4 100644
--- a/prefs.js
+++ b/prefs.js
@@ -544,7 +544,7 @@ function removeSelectedFeeds() {
 				var query = "?op=pref-feeds&subop=remove&ids="+
 					param_escape(sel_rows.toString());
 
-				debug(query);
+				console.log(query);
 
 				new Ajax.Request("backend.php",	{
 					parameters: query,
@@ -605,7 +605,7 @@ function purgeSelectedFeeds() {
 			var query = "?op=rpc&subop=purge&ids="+
 				param_escape(sel_rows.toString()) + "&days=" + pr;
 
-			debug(query);
+			console.log(query);
 
 			new Ajax.Request("prefs.php",	{
 				parameters: query,
@@ -951,7 +951,7 @@ function editSelectedFeeds() {
 
 function piggie(enable) {
 	if (enable) {
-		debug("I LOVEDED IT!");
+		console.log("I LOVEDED IT!");
 		var piggie = $("piggie");
 
 		Element.show(piggie);
@@ -1050,7 +1050,7 @@ function selectTab(id, noupdate, subop) {
 
 		if (!noupdate) {
 
-			debug("selectTab: " + id + "(NU: " + noupdate + ")");
+			console.log("selectTab: " + id + "(NU: " + noupdate + ")");
 	
 			notify_progress("Loading, please wait...");
 	
@@ -1135,18 +1135,18 @@ function backend_sanity_check_callback2(transport) {
 			return fatalError(error_code, reply.getAttribute("error-msg"));
 		}
 
-		debug("sanity check ok");
+		console.log("sanity check ok");
 
 		var params = reply.nextSibling;
 
 		if (params) {
-			debug('reading init-params...');
+			console.log('reading init-params...');
 			var param = params.firstChild;
 
 			while (param) {
 				var k = param.getAttribute("key");
 				var v = param.getAttribute("value");
-				debug(k + " => " + v);
+				console.log(k + " => " + v);
 				init_params[k] = v;					
 				param = param.nextSibling;
 			}
@@ -1206,7 +1206,7 @@ function init() {
 	
 		if (getURLParam('debug')) {
 			Element.show("debug_output");
-			debug('debug mode activated');
+			console.log('debug mode activated');
 		}
 
 		loading_set_progress(30);
@@ -1232,7 +1232,7 @@ function validatePrefsReset() {
 
 			var query = Form.serialize("pref_prefs_form");
 			query = query + "&subop=reset-config";
-			debug(query);
+			console.log(query);
 
 			new Ajax.Request("backend.php", {
 				parameters: query,
@@ -1370,7 +1370,7 @@ function pref_hotkey_handler(e) {
 		} 
 
 		if (!hotkeys_enabled) {
-			debug("hotkeys disabled");
+			console.log("hotkeys disabled");
 			return;
 		}
 
@@ -1387,7 +1387,7 @@ function pref_hotkey_handler(e) {
 			cmdline.innerHTML = keychar;
 			Element.show(cmdline);
 
-			debug("KP: PREFIX=" + keycode + " CHAR=" + keychar);
+			console.log("KP: PREFIX=" + keycode + " CHAR=" + keychar);
 			return;
 		}
 
@@ -1410,7 +1410,7 @@ function pref_hotkey_handler(e) {
 			if (keycode == 68 && shift_key) { // d
 				if (!Element.visible("debug_output")) {
 					Element.show("debug_output");
-					debug('debug mode activated');
+					console.log('debug mode activated');
 				} else {
 					Element.hide("debug_output");
 				}
@@ -1520,9 +1520,9 @@ function pref_hotkey_handler(e) {
 		}
 
 		if (hotkey_prefix) {
-			debug("KP: PREFIX=" + hotkey_prefix + " CODE=" + keycode + " CHAR=" + keychar);
+			console.log("KP: PREFIX=" + hotkey_prefix + " CODE=" + keycode + " CHAR=" + keychar);
 		} else {
-			debug("KP: CODE=" + keycode + " CHAR=" + keychar);
+			console.log("KP: CODE=" + keycode + " CHAR=" + keychar);
 		}
 
 	} catch (e) {
@@ -1717,7 +1717,7 @@ function validatePrefsSave() {
 
 			var query = Form.serialize("pref_prefs_form");
 			query = query + "&subop=save-config";
-			debug(query);
+			console.log(query);
 
 			new Ajax.Request("backend.php", {
 				parameters: query,
diff --git a/tt-rss.css b/tt-rss.css
index 809c540846efa6b818d193ac45fa73afa5e7e0b3..064315a4823bbee5f25fc55fa49871efee72f77d 100644
--- a/tt-rss.css
+++ b/tt-rss.css
@@ -1955,7 +1955,7 @@ div#errorBox div#xebContent {
 
 div#errorBox textarea {
 	width : 100%;
-	height : 200px;
+	height : 100px;
 }
 
 div#errorBox input {
diff --git a/tt-rss.js b/tt-rss.js
index 36aec2f8f407df7cce866d318c0a5c8d995ea536..e0d822512072193bb6dbc1f92172f4e1e4eab40c 100644
--- a/tt-rss.js
+++ b/tt-rss.js
@@ -28,7 +28,7 @@ function activeFeedIsCat() {
 
 function getActiveFeedId() {
 	try {
-		debug("gAFID: " + _active_feed_id);
+		console.log("gAFID: " + _active_feed_id);
 		return _active_feed_id;
 	} catch (e) {
 		exception_error("getActiveFeedId", e);
@@ -37,7 +37,7 @@ function getActiveFeedId() {
 
 function setActiveFeedId(id, is_cat) {
 	try {
-		debug("sAFID(" + id + ", " + is_cat + ")");
+		console.log("sAFID(" + id + ", " + is_cat + ")");
 		_active_feed_id = id;
 
 		if (is_cat != undefined) {
@@ -62,7 +62,7 @@ function toggleTags(show_all) {
 
 	try {
 
-	debug("toggleTags: " + show_all + "; " + display_tags);
+	console.log("toggleTags: " + show_all + "; " + display_tags);
 
 	var p = $("dispSwitchPrompt");
 
@@ -137,18 +137,18 @@ function backend_sanity_check_callback(transport) {
 			return fatalError(error_code, reply.getAttribute("error-msg"));
 		}
 
-		debug("sanity check ok");
+		console.log("sanity check ok");
 
 		var params = reply.nextSibling;
 
 		if (params) {
-			debug('reading init-params...');
+			console.log('reading init-params...');
 			var param = params.firstChild;
 
 			while (param) {
 				var k = param.getAttribute("key");
 				var v = param.getAttribute("value");
-				debug(k + " => " + v);
+				console.log(k + " => " + v);
 				init_params[k] = v;					
 
 				if (db) {
@@ -172,7 +172,7 @@ function backend_sanity_check_callback(transport) {
 
 function scheduleFeedUpdate(force) {
 
-	debug("in scheduleFeedUpdate");
+	console.log("in scheduleFeedUpdate");
 
 /*	if (!daemon_enabled && !daemon_refresh_only) {
 		notify_progress("Updating feeds...", true);
@@ -202,7 +202,7 @@ function scheduleFeedUpdate(force) {
 	query_str = query_str + "&omode=" + omode;
 	query_str = query_str + "&uctr=" + global_unread;
 
-	debug("REFETCH query: " + query_str);
+	console.log("REFETCH query: " + query_str);
 
 	new Ajax.Request("backend.php", {
 		parameters: query_str,
@@ -217,7 +217,7 @@ function updateFeedList(silent, fetch) {
 //		notify("Loading feed list...");
 //	}
 
-	debug("<b>updateFeedList</b>");
+	console.log("<b>updateFeedList</b>");
 
 	if (offline_mode) return render_offline_feedlist();
 
@@ -236,7 +236,7 @@ function updateFeedList(silent, fetch) {
 //	var feeds_frame = $("feeds-frame");
 //	feeds_frame.src = query_str;
 
-	debug("updateFeedList Q=" + query_str);
+	console.log("updateFeedList Q=" + query_str);
 
 	new Ajax.Request("backend.php", {
 		parameters: query_str,
@@ -256,7 +256,7 @@ function catchupAllFeeds() {
 
 		notify_progress("Marking all feeds as read...");
 
-		debug("catchupAllFeeds Q=" + query_str);
+		console.log("catchupAllFeeds Q=" + query_str);
 
 		new Ajax.Request("backend.php", {
 			parameters: query_str,
@@ -369,7 +369,7 @@ function init() {
 
 		if (getURLParam('debug')) {
 			Element.show("debug_output");
-			debug('debug mode activated');
+			console.log('debug mode activated');
 		}
 
 		var params = "&ua=" + param_escape(navigator.userAgent);
@@ -391,7 +391,7 @@ function resize_headlines(delta_x, delta_y) {
 
 	try {
 
-		debug("resize_headlines: " + delta_x + ":" + delta_y);
+		console.log("resize_headlines: " + delta_x + ":" + delta_y);
 	
 		var h_frame = $("headlines-frame");
 		var c_frame = $("content-frame");
@@ -414,7 +414,7 @@ function resize_headlines(delta_x, delta_y) {
 				}
 			}
 	
-			debug("resize_headlines: HOR-mode: " + hor_offset);
+			console.log("resize_headlines: HOR-mode: " + hor_offset);
 	
 			c_frame.style.width = (400 + hor_offset) + "px";
 			h_frame.style.right = c_frame.offsetWidth - 1 + "px";
@@ -435,7 +435,7 @@ function resize_headlines(delta_x, delta_y) {
 				}
 			}
 	
-			debug("resize_headlines: VER-mode: " + ver_offset);
+			console.log("resize_headlines: VER-mode: " + ver_offset);
 	
 			h_frame.style.height = (300 - ver_offset) + "px";
 	
@@ -493,21 +493,21 @@ function init_second_stage() {
 
 		setTimeout('updateFeedList(false, false)', 50);
 
-		debug("second stage ok");
+		console.log("second stage ok");
 
 		loading_set_progress(60);
 
 		ver_offset = parseInt(getCookie("ttrss_offset_ver"));
 		hor_offset = parseInt(getCookie("ttrss_offset_hor"));
 
-		debug("got offsets from cookies: ver " + ver_offset + " hor " + hor_offset);
+		console.log("got offsets from cookies: ver " + ver_offset + " hor " + hor_offset);
 
 		/* fuck IE */
 
 		if (isNaN(hor_offset)) hor_offset = 0;
 		if (isNaN(ver_offset)) ver_offset = 0;
 
-		debug("offsets from cookies [x:y]: " + hor_offset + ":" + ver_offset);
+		console.log("offsets from cookies [x:y]: " + hor_offset + ":" + ver_offset);
 
 		resize_headlines();
 
@@ -674,19 +674,19 @@ function toggleDispRead() {
 
 function parse_runtime_info(elem) {
 	if (!elem) {
-		debug("parse_runtime_info: elem is null, aborting");
+		console.log("parse_runtime_info: elem is null, aborting");
 		return;
 	}
 
 	var param = elem.firstChild;
 
-	debug("parse_runtime_info: " + param);
+	console.log("parse_runtime_info: " + param);
 
 	while (param) {
 		var k = param.getAttribute("key");
 		var v = param.getAttribute("value");
 
-		debug("RI: " + k + " => " + v);
+		console.log("RI: " + k + " => " + v);
 
 		if (k == "num_feeds") {
 			init_params[k] = v;					
@@ -833,7 +833,7 @@ function feedEditSave() {
 
 function collapse_feedlist() {
 	try {
-		debug("collapse_feedlist");
+		console.log("collapse_feedlist");
 		
 		var theme = getInitParam("theme");
 		if (theme != "" && 
@@ -992,7 +992,7 @@ function hotkey_handler(e) {
 		} 
 
 		if (!hotkeys_enabled) {
-			debug("hotkeys disabled");
+			console.log("hotkeys disabled");
 			return;
 		}
 
@@ -1010,7 +1010,7 @@ function hotkey_handler(e) {
 			cmdline.innerHTML = keychar;
 			Element.show(cmdline);
 
-			debug("KP: PREFIX=" + keycode + " CHAR=" + keychar + " TS=" + ts);
+			console.log("KP: PREFIX=" + keycode + " CHAR=" + keychar + " TS=" + ts);
 			return true;
 		}
 
@@ -1027,7 +1027,7 @@ function hotkey_handler(e) {
 			if (keycode == 68 && shift_key) { // d
 				if (!Element.visible("debug_output")) {
 					Element.show("debug_output");
-					debug('debug mode activated');
+					console.log('debug mode activated');
 				} else {
 					Element.hide("debug_output");
 				}
@@ -1362,9 +1362,9 @@ function hotkey_handler(e) {
 		}
 
 		if (hotkey_prefix) {
-			debug("KP: PREFIX=" + hotkey_prefix + " CODE=" + keycode + " CHAR=" + keychar);
+			console.log("KP: PREFIX=" + hotkey_prefix + " CODE=" + keycode + " CHAR=" + keychar);
 		} else {
-			debug("KP: CODE=" + keycode + " CHAR=" + keychar);
+			console.log("KP: CODE=" + keycode + " CHAR=" + keychar);
 		}
 
 
diff --git a/viewfeed.js b/viewfeed.js
index d51323553b2e28ea9231e738888341728f30bba4..4a7cc9e7ffd097a61fd9685ec1ff24fa4227d60d 100644
--- a/viewfeed.js
+++ b/viewfeed.js
@@ -17,7 +17,7 @@ var last_requested_article = false;
 
 function catchup_callback2(transport, callback) {
 	try {
-		debug("catchup_callback2 " + transport + ", " + callback);
+		console.log("catchup_callback2 " + transport + ", " + callback);
 		notify("");			
 		all_counters_callback2(transport);
 		if (callback) {
@@ -55,7 +55,7 @@ function headlines_callback2(transport, feed_cur_page) {
 
 		loading_set_progress(100);
 
-		debug("headlines_callback2 [page=" + feed_cur_page + "]");
+		console.log("headlines_callback2 [page=" + feed_cur_page + "]");
 
 		if (!transport_error_check(transport)) return;
 
@@ -101,7 +101,7 @@ function headlines_callback2(transport, feed_cur_page) {
 		var f = $("headlines-frame");
 		try {
 			if (feed_cur_page == 0) { 
-				debug("resetting headlines scrollTop");
+				console.log("resetting headlines scrollTop");
 				f.scrollTop = 0; 
 			}
 		} catch (e) { };
@@ -150,14 +150,14 @@ function headlines_callback2(transport, feed_cur_page) {
 					}
 
 				} else {
-					debug("headlines_callback: returned no data");
+					console.log("headlines_callback: returned no data");
 				f.innerHTML = "<div class='whiteBox'>" + __('Could not update headlines (missing XML data)') + "</div>";
 	
 				}
 			} else {
 				if (headlines) {
 					if (headlines_count > 0) {
-						debug("adding some more headlines...");
+						console.log("adding some more headlines...");
 	
 						var c = $("headlinesList");
 		
@@ -169,17 +169,17 @@ function headlines_callback2(transport, feed_cur_page) {
 	
 						c.innerHTML = c.innerHTML + headlines.firstChild.nodeValue;
 
-						debug("restore selected ids: " + ids);
+						console.log("restore selected ids: " + ids);
 
 						for (var i = 0; i < ids.length; i++) {
 							markHeadline(ids[i]);
 						}
 
 					} else {
-						debug("no new headlines received");
+						console.log("no new headlines received");
 					}
 				} else {
-					debug("headlines_callback: returned no data");
+					console.log("headlines_callback: returned no data");
 					notify_error("Error while trying to load more headlines");	
 				}
 
@@ -188,30 +188,30 @@ function headlines_callback2(transport, feed_cur_page) {
 			if (articles) {
 				for (var i = 0; i < articles.length; i++) {
 					var a_id = articles[i].getAttribute("id");
-					debug("found id: " + a_id);
+					console.log("found id: " + a_id);
 					cache_inject(a_id, articles[i].firstChild.nodeValue);
 				}
 			} else {
-				debug("no cached articles received");
+				console.log("no cached articles received");
 			}
 	
 			if (counters) {
-				debug("parsing piggybacked counters: " + counters);
+				console.log("parsing piggybacked counters: " + counters);
 				parse_counters(counters, false);
 			} else {
-				debug("counters container not found in reply, requesting...");
+				console.log("counters container not found in reply, requesting...");
 				request_counters();
 			}
 	
 			if (runtime_info) {
-				debug("parsing runtime info: " + runtime_info[0]);
+				console.log("parsing runtime info: " + runtime_info[0]);
 				parse_runtime_info(runtime_info[0]);
 			} else {
-				debug("counters container not found in reply");
+				console.log("counters container not found in reply");
 			}
 	
 		} else {
-			debug("headlines_callback: returned no XML object");
+			console.log("headlines_callback: returned no XML object");
 			f.innerHTML = "<div class='whiteBox'>" + __('Could not update headlines (missing XML object)') + "</div>";
 		}
 	
@@ -224,11 +224,11 @@ function headlines_callback2(transport, feed_cur_page) {
 		if (!$("headlinesList") && 
 				getActiveFeedId() != -3 &&
 				getInitParam("cdm_auto_catchup") == 1) {
-			debug("starting CDM watchdog");
+			console.log("starting CDM watchdog");
 			_cdm_wd_timeout = window.setTimeout("cdmWatchdog()", 5000);
 			_cdm_wd_vishist = new Array();
 		} else {
-			debug("not in CDM mode or watchdog disabled");
+			console.log("not in CDM mode or watchdog disabled");
 		}
 	
 		_feed_cur_page = feed_cur_page;
@@ -332,7 +332,7 @@ function showArticleInHeadlines(id) {
 
 function article_callback2(transport, id) {
 	try {
-		debug("article_callback2 " + id);
+		console.log("article_callback2 " + id);
 
 		if (!transport.responseText && db) {
 			offlineConfirmModeChange();
@@ -355,23 +355,23 @@ function article_callback2(transport, id) {
 			}
 
 			if (id != last_requested_article) {
-				debug("requested article id is out of sequence, aborting");
+				console.log("requested article id is out of sequence, aborting");
 				return;
 			}
 
 			active_post_id = id; 
 
-			debug("looking for articles to cache...");
+			console.log("looking for articles to cache...");
 
 			var articles = transport.responseXML.getElementsByTagName("article");
 
 			for (var i = 0; i < articles.length; i++) {
 				var a_id = articles[i].getAttribute("id");
 
-				debug("found id: " + a_id);
+				console.log("found id: " + a_id);
 
 				if (a_id == active_post_id) {
-					debug("active article, rendering...");					
+					console.log("active article, rendering...");					
 					render_article(articles[i].firstChild.nodeValue);
 				}
 
@@ -388,7 +388,7 @@ function article_callback2(transport, id) {
 			var reply = transport.responseXML.firstChild.firstChild;
 		
 		} else {
-			debug("article_callback: returned no XML object");
+			console.log("article_callback: returned no XML object");
 			//var f = $("content-frame");
 			//f.innerHTML = "<div class='whiteBox'>" + __('Could not display article (missing XML object)') + "</div>";
 		}
@@ -408,10 +408,10 @@ function article_callback2(transport, id) {
 				var counters = transport.responseXML.getElementsByTagName("counters")[0];
 
 				if (counters) {
-					debug("parsing piggybacked counters: " + counters);
+					console.log("parsing piggybacked counters: " + counters);
 					parse_counters(counters, false);
 				} else {
-					debug("counters container not found in reply, requesting...");
+					console.log("counters container not found in reply, requesting...");
 					request_counters();
 				}
 			}
@@ -425,13 +425,13 @@ function article_callback2(transport, id) {
 
 function view(id) {
 	try {
-		debug("loading article: " + id);
+		console.log("loading article: " + id);
 
 		if (offline_mode) return view_offline(id);
 
 		var cached_article = cache_find(id);
 
-		debug("cache check result: " + (cached_article != false));
+		console.log("cache check result: " + (cached_article != false));
 	
 		enableHotkeys();
 		hideAuxDlg();
@@ -450,7 +450,7 @@ function view(id) {
 			}
 		}
 
-		debug("additional ids: " + cids_to_request.toString());			
+		console.log("additional ids: " + cids_to_request.toString());			
 
 		/* additional info for piggyback counters */
 
@@ -521,7 +521,7 @@ function tMark_afh_off(effect) {
 	try {
 		var elem = effect.effects[0].element;
 
-		debug("tMark_afh_off : " + elem.id);
+		console.log("tMark_afh_off : " + elem.id);
 
 		if (elem) {
 			elem.src = elem.src.replace("mark_set", "mark_unset");
@@ -538,7 +538,7 @@ function tPub_afh_off(effect) {
 	try {
 		var elem = effect.effects[0].element;
 
-		debug("tPub_afh_off : " + elem.id);
+		console.log("tPub_afh_off : " + elem.id);
 
 		if (elem) {
 			elem.src = elem.src.replace("pub_set", "pub_unset");
@@ -601,7 +601,7 @@ function toggleMark(id, client_only, no_effects) {
 		if (!no_effects) update_local_feedlist_counters();
 
 		if (!client_only) {
-			debug(query);
+			console.log(query);
 
 			new Ajax.Request("backend.php", {
 				parameters: query,
@@ -708,8 +708,8 @@ function correctHeadlinesOffset(id) {
 		var rel_offset_top = row.offsetTop - container.scrollTop;
 		var rel_offset_bottom = row.offsetTop + row.offsetHeight - container.scrollTop;
 	
-		debug("Rtop: " + rel_offset_top + " Rbtm: " + rel_offset_bottom);
-		debug("Vport: " + viewport);
+		console.log("Rtop: " + rel_offset_top + " Rbtm: " + rel_offset_bottom);
+		console.log("Vport: " + viewport);
 
 		if (rel_offset_top <= 0 || rel_offset_top > viewport) {
 			container.scrollTop = row.offsetTop;
@@ -1309,7 +1309,7 @@ function deleteSelection() {
 
 		query = "?op=rpc&subop=delete&ids=" + param_escape(rows);
 
-		debug(query);
+		console.log(query);
 
 		new Ajax.Request("backend.php",	{
 			parameters: query,
@@ -1361,7 +1361,7 @@ function archiveSelection() {
 
 		query = "?op=rpc&subop="+op+"&ids=" + param_escape(rows);
 
-		debug(query);
+		console.log(query);
 
 		for (var i = 0; i < rows.length; i++) {
 			cache_invalidate(rows[i]);
@@ -1437,13 +1437,13 @@ function editTagsSave() {
 
 	query = "?op=rpc&subop=setArticleTags&" + query;
 
-	debug(query);
+	console.log(query);
 
 	new Ajax.Request("backend.php",	{
 		parameters: query,
 		onComplete: function(transport) {
 				try {
-					debug("tags saved...");
+					console.log("tags saved...");
 			
 					closeInfoBox();
 					notify("");
@@ -1501,7 +1501,7 @@ function editTagsInsert() {
 }
 
 function cdmScrollViewport(where) {
-	debug("cdmScrollViewport: " + where);
+	console.log("cdmScrollViewport: " + where);
 
 	var ctr = $("headlinesInnerContainer");
 
@@ -1620,7 +1620,7 @@ function cdmWatchdog() {
 				if (ctr.scrollTop <= e.offsetTop && e.offsetTop + e.offsetHeight <=
 						ctr.scrollTop + ctr.offsetHeight) {
 
-//					debug(e.id + " is visible " + e.offsetTop + "." + 
+//					console.log(e.id + " is visible " + e.offsetTop + "." + 
 //						(e.offsetTop + e.offsetHeight) + " vs " + ctr.scrollTop + "." +
 //						(ctr.scrollTop + ctr.offsetHeight));
 
@@ -1648,7 +1648,7 @@ function cdmWatchdog() {
 			e = e.nextSibling;
 		}
 
-		debug("cdmWatchdog, ids= " + ids.toString());
+		console.log("cdmWatchdog, ids= " + ids.toString());
 
 		if (ids.length > 0) {
 
@@ -1682,7 +1682,7 @@ function cdmWatchdog() {
 function cache_inject(id, article, param) {
 	try {
 		if (!cache_check_param(id, param)) {
-			debug("cache_article: miss: " + id + " [p=" + param + "]");
+			console.log("cache_article: miss: " + id + " [p=" + param + "]");
 	
 			if (db) {
 
@@ -1703,7 +1703,7 @@ function cache_inject(id, article, param) {
 			}
 	
 		} else {
-			debug("cache_article: hit: " + id + " [p=" + param + "]");
+			console.log("cache_article: hit: " + id + " [p=" + param + "]");
 		}
 	} catch (e) {	
 		exception_error("cache_inject", e);
@@ -1842,7 +1842,7 @@ function cache_invalidate(id) {
 
 			while (i < article_cache.length) {
 				if (article_cache[i]["id"] == id) {
-					debug("cache_invalidate: removed id " + id);
+					console.log("cache_invalidate: removed id " + id);
 					article_cache.splice(i, 1);
 					return true;
 				}
@@ -1850,7 +1850,7 @@ function cache_invalidate(id) {
 			}
 		}
 
-		debug("cache_invalidate: id not found: " + id);
+		console.log("cache_invalidate: id not found: " + id);
 		return false;
 	} catch (e) {
 		exception_error("cache_invalidate", e);
@@ -1885,7 +1885,7 @@ function preloadArticleUnderPointer(id) {
 
 		if (post_under_pointer == id && !cache_check(id)) {
 
-			debug("trying to preload article " + id);
+			console.log("trying to preload article " + id);
 
 			var neighbor_ids = getRelativePostIds(id, 1);
 
@@ -1898,7 +1898,7 @@ function preloadArticleUnderPointer(id) {
 					cids_to_request.push(neighbor_ids[i]);
 				}
 			}
-			debug("additional ids: " + cids_to_request.toString());
+			console.log("additional ids: " + cids_to_request.toString());
 
 			cids_to_request.push(id);
 
@@ -1914,7 +1914,7 @@ function preloadArticleUnderPointer(id) {
 						var id = articles[i].getAttribute("id");
 						if (!cache_check(id)) {
 							cache_inject(id, articles[i].firstChild.nodeValue);				
-							debug("preloaded article: " + id);
+							console.log("preloaded article: " + id);
 						}
 					}
 			} });
@@ -1953,12 +1953,12 @@ function headlines_scroll_handler() {
 
 		var toolbar_form = document.forms["main_toolbar_form"];
 
-		debug((e.scrollTop + e.offsetHeight) + " vs " + e.scrollHeight + " dis? " +
+		console.log((e.scrollTop + e.offsetHeight) + " vs " + e.scrollHeight + " dis? " +
 			_infscroll_disable);
 
 		if (e.scrollTop + e.offsetHeight > e.scrollHeight - 100) {
 			if (!_infscroll_disable) {
-				debug("more cowbell!");
+				console.log("more cowbell!");
 				viewNextFeedPage();
 			}
 		}