Главная > JavaScript, Программирование > Консоль для всех браузеров

Консоль для всех браузеров

25 Декабрь 2008

Это попытка заставить работать синтаксис консоли FireBug'a со всеми браузерами. ИМХО кроссбраузерный дебаг звучит не ок, но это именно он! А все получилось как-то само собой когда я сегодня что-то дебажил на тестовой платформе и для того чтобы тестеры не видели ошибок прикрывал вызовы консоли заглушками.


if(window.console)
	console.log("myLog");

В общем это как-то гнило, нашел что по данному поводу пишут разработчики Prototype и jQuery, и даже сами разработчики FireBug'a склоняются к заглушкам

Уж очень мне эти затычки не нравятся. И решил я выяснить что можно с этим сделать. Уточнив с какой версии у браузеров появилась консоль (и текущую версию): IE8b2 (IE7), Opera 9.50 (9.63), Safari 1.3 (3.21), FireFox 2.0.0 (3.0.5), я принялся за работу.

Первое что приходило на ум это что-то вроде


if (!window.console) {
	window.console = {};
	window.console.log = alert;
		
}

Но не все так просто, FireBug славится тем что показывает содержимое любого объекта и может делать форматированный вывод. То есть во-первых можно сделать


console.info({a:null});

и увидеть содержимое объекта в закладке DOM, а во-вторых можно сделать форматированный вывод


console.info("string: %d %s %d", 10, "text", 10);

и увидеть строку "string: 10 text 10". В остальных же браузерах можно наблюдать только строку [object Object] и "string: %d %s %d" соответственно, кроме IE8b2, он поддерживает форматный вывод, выпендрился, блин!

Я решил начать с написания форматного вывода, но функция sprintf оказалась настолько громоздкой и избыточной что я решил обойтись небольшим регулярным выражением, для своих нужд, тем более что FireBug тоже не различает %d и %s ;) в отличие от IE8b2 который корректно выводит 0 вместо %d которому соответствует строка. Из этого вывод что достаточно использовать только %s.

Потом я решили что было бы неплохо научиться отображать содержимое объектов и массивов, для этого как нельзя хорошо подходила одна известная функция, написанная очень нелюбимым мной человеком, имя которого можете прочитать в комментарии в коде. Единственные минус этой функции в том что она не может корректно отобразить объекты типа window, на нем она уходит куда-то в глубь рекурсии и безнадежно вешает браузер. Но этот недостаток я постараюсь решить в следующей версии, если такая появиться.

Уже неплохо. Последним штрихом к портрету было прикручивание уровня дебага "log", "debug", "info", "warn", "error". Тут для меня было несколько откровений. Первое это то что массив arguments не такой уже и массив потому что содержит в себе еще и метод callee. Второе - что объект arguments прекрасно превращается в массив с помощью волшебной строки


var args = Array.prototype.slice.call(arguments);

Третье - что этот метод не работает (правильно!) в IE7 и IE8b2, а поэтому не годиться. И наконец четвертое и последние что чертов arguments не возможно обойти циклом через in нужно обязательно это делать через длину


for(var i in arguments) // fail
	alert(arguments[i]);
for(var i=0,j=arguments.length;i<j;i++) // ok
	alert(arguments[i]);

Но это все не помешало мне дописать сегодня этот скрипт и выложит его на ваше растерзание


myConsole = function(){
	var args = (function(a,x){for(var i=0,j=a.length;i<j;i++){x.push(a[i])};return x;})(arguments,[]);
	
	if (args.length>2){
		(window.opera?opera.postError:window.alert)(args.shift() +'':\\n''+ args.shift().replace(/(%[ds])/g, function(){
			return args.shift();
			})
		)
	}else{
		// автор функции dump - Дмитрий Котеров
		// http://dklab.ru/chicken/nablas/38.html
		(window.opera?opera.postError:window.alert)(args.shift() +'':\\n''+ (function dump(d,l) {
			if (l == null) l = 1;
			var s = '''';
			if (typeof(d) == "object") {
				s += typeof(d) + " {\\n";				for (var k in d) {
					for (var i=0; i<l; i++){
						s += "  ";
					}
					s += k+": " + dump(d[k],l+1);
				}
				for (var i=0; i<l-1; i++){
					s += "  ";
				}
				s += "}\\n"
			} else {
				s += "" + d + "\\n";
			}
			return s;
		})(args.shift()));
	}
}

if (window.loadFirebugConsole) { // since FireBug 1.2
	window.loadFirebugConsole();
} else if (!window.console) {
	window.console = {};
	var names = ["log", "debug", "info", "warn", "error"];
	for (var i in names){
		window.console[names[i]] = (function(name){return function(){
			myConsole.apply(null,(function(a,x){for(var i=0,j=a.length;i<j;i++){x.push(a[i])};return x;})(arguments,[name]))
		}})(names[i]);
	}
}

Кому пригодиться пишите в каменты...

Комментирование отключено.