привет!
может кто небудь посоветует как делаеть debug javascript.
понимаю что можно делать что то типа алерт и вызывать в функции. но что делать если
функция возврашает object. неужели нет никакой возможности делать дебаг на клиентскои
стороне(имею доступ практически к любым средствам разработки vs7,6. может dot.net ето делает???)...
если кто знает какои то open sourse project на ету тему поделитесь ссилочкои
спасибо
Здравствуйте, RobinHood, Вы писали:
RH>привет! RH>может кто небудь посоветует как делаеть debug javascript. RH>понимаю что можно делать что то типа алерт и вызывать в функции. но что делать если RH>функция возврашает object. неужели нет никакой возможности делать дебаг на клиентскои RH>стороне(имею доступ практически к любым средствам разработки vs7,6. может dot.net ето делает???)... RH> если кто знает какои то open sourse project на ету тему поделитесь ссилочкои RH>спасибо
В VS7 вообще есть дебагер скриптов. Есть еще и Microsoft Script Editor.
Здравствуйте, RobinHood, Вы писали:
RH>привет! RH>может кто небудь посоветует как делаеть debug javascript. RH>понимаю что можно делать что то типа алерт и вызывать в функции. но что делать если RH>функция возврашает object. неужели нет никакой возможности делать дебаг на клиентскои RH>стороне(имею доступ практически к любым средствам разработки vs7,6. может dot.net ето делает???)... RH> если кто знает какои то open sourse project на ету тему поделитесь ссилочкои RH>спасибо
1. Microsoft Visual Studio .NET точно умеет — сам видел
2. Mozilla. Имеет JavaScript Console + DOM Inspector
3. А можно и самому сделать дебаггер (для любителей всё сделать своими руками) :
например, вот такой:
/**
* Класс jsDump для отладки
*
* @author Mikhail Stadnik aka }|{yK <root@autoweb.ws>
* @copyright (c) 2004
*/function jsDump() {
this.strDump = '';
this.wnd = window.open( 'about:blank');
}
/**
* Делает "мгновенный снимок" HTML.
* Это может быть полезно когда мы динамически изменяем
* HTML страницы и хотим посмотреть, на чо он похож в какой то определенный момент.
*/
jsDump.prototype.dumpHTML = function() {
if (navigator.appName == 'Netscape') {
this.strDump = '<HTML>' + document.getElementsByTagName( 'HTML').item(0).innerHTML + '</HTML>';
} else {
this.strDump = document.getElementsByTagName( 'HTML').item(0).outerHTML;
}
this.wnd.document.write( '<pre style="font-family: Courier;">' + this.strDump.html2view() + '</pre><HR size="1px">');
this.strDump = '';
}
/**
* Распечатывает переменную.
* Нужно отнестись с пониманием к работе данной функции и учитывать,
* что она абсолютно бесполезна в тех случаяк, когда с ёё помощью производится
* попытка "отдампить" объект, содержащий рекурсивные ссылки объектов на самих себя
* (эт такие объекты, как window, document, document.body и т.п.), так как это приведет
* к stack overflow at line xxx, потому что мы никак не сможем выйти из рекурсии
* Зато можеть быть полезной при попытке "отдампить" какие-то свои объекты, или,
* например, такой объект, как document.body.style
*
* З.Ы. Виду позднего времени (безумно хочется спать) нет желания сию минуту решить
* проблемму с рекурсией объектов. Возможно оно не появится и завтра :) Поэтому
* буду благодарен, если кто-то своим наметанным глазом увидит и подскажет всем остальным,
* как обойти данную проблемму...
*/
jsDump.prototype.dumpVar = jsDump_dumpVar;
function jsDump_dumpVar( _var, rem) {
this.strDump += '<i style="color: #0000FF;">' + typeof( _var) + '</i> <b>=</b> ';
switch ( typeof(_var)) {
case 'object': {
this.strDump += ' {<blockquote>';
for (var i in _var) {
this.strDump += '[<b>' + i + '</b>] ';
this.dumpVar( _var[i], true);
}
this.strDump += '</blockquote>}<br>';
break;
}
default: {
var addStr = typeof( _var) == 'string' ? '"' : '';
this.strDump += addStr + _var.toString().html2view() + addStr + '<br>';
break;
}
}
if (!rem) {
this.wnd.document.write( '<pre style="font-family: Courier;">' + this.strDump + '</pre><hr size="1px">');
this.strDump = '';
}
}
/**
* А это просто безумно хитрая приблуда :D
* Угадайте - что она делает?
*/
String.prototype.html2view = function() {
return this.replace( /&/g, '&').replace( /</g, '<').replace( />/g, '>');
}
// Пример использованияvar var1 = 'Blablabla';
var var2 = new Array(1, 2, 3, 4, 5, 6, 7, 'Blablabla');
var var3 = new Object();
var3.gg = var2;
var3.rr = 'Hahaha';
var3.cc = 4.236;
var3.ii = 456875;
var dd = new jsDump();
dd.dumpVar( var1);
dd.dumpVar( var2);
dd.dumpVar( var3);
dd.dumpVar( document.body.style);
dd.dumpHTML();
Думаю, что alert() + jsDump в большинстве случаев будет достаточно (если под рукой не оказалось путёвого дебаггера)
Вот наваял новую версию, в которой устранен глюк с рекурсией объектов
В принципе, мне самому даже понравилось Очень удобно тем, что этот дебагер не привязан к какому-то браузеру. Правда тестил только в ИЕ 6 и Мозилла 1.6. Так вот дампим одно и то же но в разных браузерах — сразу же можно искать отличия, посмотреть какие свойства, методы и т.п. присущи одному и тому же объекто в одном браузере, какие в другом...
Вообщем предлагаю глянуть всем, кому это интересно. Клацайте мышкой на объекты с фигурными скобками, чтобы их раскрывать. Пример работы дебаггера здесь.
Исходник дебагерра:
/**
* Класс jsDump для отладки
*
* @author Mikhail Stadnik aka }|{yK <root@autoweb.ws>
* @copyright (c) 2004
*/function jsDump() {
this.wnd = window.open( '');
this.doc = this.wnd.document;
this.entries = new Array();
this.pre = this.doc.createElement( 'PRE');
this.doc.body.appendChild( this.pre);
this.variable = null;
this.dumpString = new String();
}
/**
* Распечатывает переменную.
* Дампит все возможные переменные. Если в переменной есть вложенность
* объектов - дампит по частям, требует от пользователя инициализации
* распечатки следующего блока
*/
jsDump.prototype.dumpVar = jsDump_dumpVar;
function jsDump_dumpVar( variable, oEntryPoint, name) {
var oEntryPoint = oEntryPoint || this.pre;
var oCaption = this.doc.createElement( 'SPAN');
oEntryPoint.appendChild( oCaption);
switch (typeof( variable)) {
case 'object': {
var idPrfx = this.entries.length;
var eI = this.doc.createElement( 'I');
eI.style.color = "navy";
eI.appendChild( this.doc.createTextNode( typeof( variable) + " "));
oCaption.appendChild( eI);
var eB = this.doc.createElement( 'B');
eB.appendChild( this.doc.createTextNode( (name ? name : variable) + " = "))
oCaption.appendChild( eB);
if (variable != null) {
oCaption.appendChild( this.doc.createTextNode( "{"));
var oBlock = this.doc.createElement( "BLOCKQUOTE");
oBlock.setAttribute( 'id', 'oBlock' + idPrfx);
this.entries[idPrfx] = oBlock.getAttribute( 'id');
oCaption.setAttribute( 'id', 'oCaption' + idPrfx);
oCaption.style.cursor = navigator.appName == 'Netscape' ? 'pointer' : 'hand';
oEntryPoint.appendChild( oBlock);
oEntryPoint.appendChild( this.doc.createTextNode( "}"));
oEntryPoint.appendChild( this.doc.createElement( "BR"));
var __js__dd = this;
oCaption.onclick = function() {
for (var i in variable) {
__js__dd.dumpVar( variable[i], oBlock, i);
}
this.style.cursor = '';
this.style.backgroundColor = '#EEEEEE';
this.onclick = '';
}
} else {
var oBlock = this.doc.createTextNode( variable);
oEntryPoint.appendChild( oBlock);
oEntryPoint.appendChild( this.doc.createElement( "BR"));
}
break;
}
default: {
var eI = this.doc.createElement( 'I');
eI.style.color = "navy";
eI.appendChild( this.doc.createTextNode( typeof( variable) + " "));
oEntryPoint.appendChild( eI);
var eB = this.doc.createElement( 'B');
eB.appendChild( this.doc.createTextNode( name + " = "))
oEntryPoint.appendChild( eB);
oEntryPoint.appendChild( this.doc.createTextNode( variable));
oEntryPoint.appendChild( this.doc.createElement( "BR"));
break;
}
}
}
/**
* Делает "мгновенный снимок" HTML.
* Это может быть полезно когда мы динамически изменяем
* HTML страницы и хотим посмотреть, на чо он похож в какой то определенный момент.
*/
jsDump.prototype.dumpHTML = function() {
if (navigator.appName == 'Netscape') {
this.dumpString = '<HTML>' + document.getElementsByTagName( 'HTML').item(0).innerHTML + '</HTML>';
} else {
this.dumpString = document.getElementsByTagName( 'HTML').item(0).outerHTML;
}
this.pre.appendChild( this.doc.createElement( 'HR'));
this.pre.appendChild( this.doc.createTextNode( this.dumpString));
this.dumpString = '';
}
// Пример использованияvar dd = new jsDump();
dd.dumpVar( document);
dd.dumpHTML();
Так как со временем всплывают всякие глюки, исходники меняются.
На свежую версию исходников вы можете посмортеть здесь
Для того, чтобы скачать исходники жмите сюда
Здравствуйте, ЖуК, Вы писали:
ЖуК>Так как со временем всплывают всякие глюки, исходники меняются. ЖуК>На свежую версию исходников вы можете посмортеть здесь ЖуК>Для того, чтобы скачать исходники жмите сюда
Слегка поколдовал над твоим творением.
1. Сделал наглядное (цветовое) выделение раскрываемых нодов
2. Сделал сворачивание, разворачивание нодов.
Здравствуйте, uzzy, Вы писали:
U>Слегка поколдовал над твоим творением. U>1. Сделал наглядное (цветовое) выделение раскрываемых нодов U>2. Сделал сворачивание, разворачивание нодов.
U>Забрать можно отсюда
Я немного переделал так, чтобы работало в Mozilla. Все ссылки в предыдущем посте
Здравствуйте, ЖуК, Вы писали:
ЖуК>Спасибо, uzzy! Если честно, я как раз и надеялся на то, что кто-то подхватит идею — она не так уж и бесполезна!
я то и ее подхватил, когда под рукой было только notepad, и отлаживать alert-ами задолбался . В общем если у меня еще появятся идеи, то реализация за мной не застоит.
тогда минимальный документ будет создан автоматически, соответственно там будет и пустой <body>... возможно это прокатит и в других браузерах — не проверял...
Здравствуйте, ЖуК, Вы писали:
ЖуК>З.Ы. Я обновил исходники у себя, так что все теперь могут посмотреть на них, ссылки были приведены в предыдущих постах. Для очень ленивых напомню.
ЖуК>Пример здесь ЖуК>Исходник здесь ЖуК>Качать отсюда или отсюда
есть такая идея (проверил — работает):
в bookmark'ах создается закладка со следующим содержанием:
при нажатии на эту закладку появится окошко с приглашением ввести имя переменной/объекта, и далее, после ввода, отобразится дамп этой переменной/объекта... по моему весьма удобно...
я думаю скрипт в закладке можно даже переработать так, что саму в саму страницу ничего не нужно будет дописывать... а скрипт будет присоединяться динамически...
[skiped]
A>тогда минимальный документ будет создан автоматически, соответственно там будет и пустой <body>... возможно это прокатит и в других браузерах — не проверял...
Спасибо, anonymous! Правда в Опере упорно не желает работать ни так, ни так...
В дополнение добавлю, что кроме изменения, предложенного товарищем anonymous я сделал возможность не показывать переменные, которые равны null || undefined, и так теперь по-умолчанию
Появилось свойство jsDump::showEmpty и метод jsDump::showEmptyVars( needShow), который как раз и предназначен для того, чтобы задавать это свойство
Мало того, метод jsDump::dumpVar() вторым параметром теперь тоже принимает флаг showEmpty приоритет которого будет выше, чем у jsDump::showEmpty
Таким образом мы можем теперь управлять выводом нулл переменных (зачастую они не нужны и скорость отработки без их вывода увеличивается)
A>но есть проблема, если скрипт не успел подгрузиться, то будет ошибка... ищем решение...
Решения:
1. В конце скрипта выставляем глобальную переменную. В закладке в цикле проверяем ее на существование
2. Все, что должно вызыватся после загрузки скрипта ложим в функцию. В скрипте в конце ее вызываем.
3. В цикле после начала загрузки скрипта проверяем его состояние.
A>P.S. Жук, ничего что скрипт пользователи с твоего сайта подгружать будут?...
A>но есть проблема, если скрипт не успел подгрузиться, то будет ошибка... ищем решение...
Решаем проблемму
javascript:var w=window; if (w.jsDump==undefined){var d=w.document;var s=d.createElement('script');s.src='http://scripts.kiev.ua/scripts/jsdump.js';d.body.appendChild(s)}; while(!JS_DUMP_LOADED) { try { var dd=new jsDump(); } catch(err) { continue; }} var v=w.prompt('Enter object name:'); dd.dumpVar(eval(v));
Только протестить сейчас не могу... Вообщем такова идея, возможно при реализации нужно будет добавить задержку по времени в цикл...
Намекни, если заработает
A>P.S. Жук, ничего что скрипт пользователи с твоего сайта подгружать будут?...
Здравствуйте, King Oleg, Вы писали:
KO>Решения: KO>1. В конце скрипта выставляем глобальную переменную. В закладке в цикле проверяем ее на существование KO>2. Все, что должно вызыватся после загрузки скрипта ложим в функцию. В скрипте в конце ее вызываем. KO>3. В цикле после начала загрузки скрипта проверяем его состояние.
Клево, пока ты писал идею я писал ее реализацию и чуть позже тебя запостил — бывает же так
A>>но есть проблема, если скрипт не успел подгрузиться, то будет ошибка... ищем решение...
ЖуК>Уже нету проблемы. Вот код, который все решает:
Хотя с практической точки зрения эта фича нифиг не нужна
Потому что нам нужно дампить нечто в какой-то момент, а в данном случае мы дампим конечный результат. Хотя ингода и это нужно...