JavaScript, цель: отображать точный исходный код

Цель состоит в том, чтобы иметь возможность щелкнуть ссылку, чтобы открыть новое окно, которое отображает отформатированный исходный код из родительского окна.

Благодаря исследованиям я смог выполнить большую часть задачи, но мне нужно новое окно, чтобы отобразить исходный код в точности так, как он есть в родителе, отступе и прочем. В настоящее время объекты HTML отображаются в качестве их отображаемого аналога (поэтому он выводит фактическую торговую марку вместо источника ™).

Я думал о том, чтобы перебрать кучу сущностей и заменить строку, как вы увидите в моем примере, но я думаю, что логика отключена, и я не знаю, что происходит.

В частности, объекты: • (бык), & (amp), ® (reg), ™ (trade), <(lt),> (gt)

Вот код, который запускает гиперссылка, которую я имею до сих пор, бонус всем, кто может выяснить, что закрывающий тег тела выводится во второй строке (я в тупике):

Заранее большое спасибо за любое направление, ведущее к решению.

function viewSource( e )
{
    e.preventDefault( );

    var source = '<!DOCTYPE html>' + "\n"
               + '<html xmlns="http://www.w3.org/1999/xhtml">' + "\n\n"
               + "\t" + document.getElementsByTagName( 'html' )[0].innerHTML + "\n\n"
               + '</html>';

    entities = [
        new Entity( '<', '&lt;' ),
        new Entity( '>', '&gt;' )
    ];

    for ( var i = 0; i < entities.length; i++ )
    {
        var regex = new RegExp( entities[i].entity, 'g' );
        source = source.replace( regex, entities[i].html );
    }

    source = '<pre>' + source + '</pre>';

    var sourceWindow = window.open( '', '_blank' );
    sourceWindow.document.write( source );
    sourceWindow.document.close( );

    if ( window.focus )
    {
        sourceWindow.focus( );
    }
}

Обновление (все еще неразгаданные загадки):

Я попытался предложить использовать AJAX-запрос, но он все еще дает те же результаты (строка 11 показывает new Entity( '<', '<'),). Вот как выглядит AJAX-попытка:

function viewSource( e )
{
    e.preventDefault( );

    var xmlhttp;

    if ( window.XMLHttpRequest )
    {
        // IE7+, Fx, Chrome, Opera, Safari
        xmlhttp = new XMLHttpRequest( );
    }
    else
    {
        // IE6, IE5
        xmlhttp = new ActiveXObject( 'Microsoft.XMLHTTP' );
    }

    xmlhttp.onreadystatechange = 
        function ( )
        {
            if ( xmlhttp.readyState == 4 && xmlhttp.status == 200 )
            {
                var source = xmlhttp.responseText.replace( /</g, '&lt;' ).replace( />/g, '&gt;' );
                source = '<pre>' + source + '</pre>';

                var sourceWindow = window.open( '', '_blank' );
                sourceWindow.document.write( source );
                sourceWindow.document.close( );

                if ( window.focus )
                {
                    sourceWindow.focus( );
                }
            }
        };

    xmlhttp.open( 'GET', '/', true );
    xmlhttp.send( );
}

2 ответа

Решение

Итак, спасибо @SLaks за все направления. Мне удалось достичь почти того, чего я хотел, но есть еще несколько маленьких причуд, с которыми мне, возможно, придется смириться. Я специально стараюсь избегать использования каких-либо библиотек, таких как jQuery.

Проблемы, которые все еще возникают, следующие: - В выходном источнике отображаются самозакрывающиеся теги без окончательной косой черты. Так, например, <br /> отображается как <br>, - По какой-то причине закрывающий тег тела переносится на строку ниже. Он должен быть представлен как:

    </body>

</html>

Но вместо этого он выглядит как:

[tab]
</body>

</html>

Несмотря на это, я все еще доволен результатами, и этого должно быть достаточно. Однако, если у кого-то есть более качественные решения, не требующие сторонних библиотек, это будет с благодарностью. Вот последняя попытка:

function htmlEntity( character )
{
    switch ( character.charCodeAt( 0 ) )
    {
        case 174:  return '&reg;';    break;
        case 233:  return '&eacute;'; break;
        case 8211: return '&ndash;';  break;
        case 8220: return '&ldquo;';  break;
        case 8221: return '&rdquo;';  break;
        case 8226: return '&bull;';   break;
        case 8482: return '&trade;';  break;
        default:   return character;
    }

    if ( character.charCodeAt( 0 ) > 127 )
    {
        return '&#' + character.charCodeAt( 0 ) + ';';
    }

    return character;
}

function viewSource( e )
{
    e.preventDefault( );

    var source = '<!DOCTYPE html>' + "\n"
               + '<html xmlns="http://www.w3.org/1999/xhtml">' + "\n\n"
               + "\t" + document.getElementsByTagName( 'html' )[0].innerHTML + "\n\n"
               + '</html>';

    var entities = [ '®' ];
    for ( i = 0; i < entities.length; i++ )
    {
        source.replace( entities[i], htmlEntity( entities[i] ) );
    }

    var temp = '';
    for ( i = 0; i < source.length; i++ )
    {
        temp += htmlEntity( source.charAt( i ) );
    }

    var pre = document.createElement( 'pre' );
    pre.textContent = temp;

    source = '<pre>' + pre.innerHTML + '</pre>';

    var sourceWindow = window.open( '', '_blank' );
    sourceWindow.document.write( source );
    sourceWindow.document.close( );

    if ( window.focus )
    {
        sourceWindow.focus( );
    }
}

Вы не можете избежать вашего источника.
Вы должны создать элемент DOM с текстовым представлением вашего источника.

Используя jQuery:

$('<pre />').text(source).appendTo(document.body);
Другие вопросы по тегам