Лучшая практика для вставки больших кусков HTML в элементы с Javascript? - PullRequest
18 голосов
/ 15 мая 2010

Я создаю веб-приложение (использующее прототип), которое требует добавления больших кусков HTML в DOM. Большинство из них являются строками, которые содержат элементы со всевозможными атрибутами.

В настоящее время я храню пустую строку HTML в переменной и

var blankRow = '<tr><td>'
    +'<a href="{LINK}" onclick="someFunc(\'{STRING}\');">{WORD}</a>'
    +'</td></tr>';

function insertRow(o) {
    newRow = blankRow
        .sub('{LINK}',o.link)
        .sub('{STRING}',o.string)
        .sub('{WORD}',o.word);
    $('tbodyElem').insert( newRow );
}

Теперь все работает хорошо, но не лучше ли это?

Мне нужно обновить код в blankRow при обновлении кода на странице, чтобы новые вставляемые элементы были одинаковыми. Это становится неприятно, когда у меня есть около 40 строк HTML-кода, чтобы войти в blankRow, а затем мне тоже нужно его избежать.

Есть ли более простой способ? Я думал о urlencoding, а затем расшифровал его перед вставкой, но это все равно будет означать blankRow и много экранирования.

Что бы означало eof-функция в духе PHP и др.

$blankRow = <<<EOF
text
text
EOF;

Это означало бы, что бежать не нужно, но для этого все еще нужен пустой ряд.

Что вы делаете в этой ситуации?

решаемые

Заканчивается использованием DOMBuilder в прототипе. Никаких других библиотек не требовалось:

$w('a div p span img table thead td th tr tbody tfoot input').each(function(e) {
        window['$' + e] = function() {
            return new Element(e, arguments[0]);
        }
});

newPart = $div({id: 'partition-4'})
    .insert( $p()
        .insert('<b>Stuff</b>')
    )
    .insert( $p({
        id: 'a-p'})
        .insert('<b>More stuff</b>')
    );

$('parentDiv').insert(newPart);

См. Мое решение здесь или здесь .

Ответы [ 3 ]

20 голосов
/ 15 мая 2010

это лучшая практика?

Нет. Фактически у вас есть проблемы с HTML-инъекцией, приводящие к ошибкам, и в худшем случае, когда внедренные строки могут содержать пользовательский контент, дыры в безопасности XSS.

Когда вы помещаете текстовое содержимое и значения атрибутов в строку HTML, вы должны кодировать их HTML. В PHP вы должны вызывать htmlspecialchars() для строк, входящих в HTML, чтобы сделать это. В JavaScript у вас нет встроенной функции экранирования HTML, поэтому вы должны сделать свою собственную, например. используя s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/"/g, '&quot;') для строки, входящей в HTML.

OnClick = "SomeFunc (\ '{STRING} \');"

Это совершенно новый уровень избегания беспорядка. В строковом литерале JavaScript внутри атрибута обработчика события вам придется JS-кодировать строку (\ -эскапинг ' и \ плюс несколько символов Юникода для полноты) и , затем HTML -кодировать результаты. В противном случае строка может выйти за пределы строкового литерала и ввести произвольный код JS. Избегайте встроенных атрибутов обработчика событий во всех случаях, но особенно в шаблонах.

Создание содержимого страницы с помощью HTML-строк - отстой. Вы, скорее всего, совершите ошибки, которые могут избежать проблем, и поставить под угрозу безопасность вашего приложения. Вместо этого используйте DOM-подобные методы, и вам не нужно об этом беспокоиться. Кажется, вы используете jQuery, поэтому попробуйте ярлыки создания элемента jQuery 1.4:

$('<tr>').append(
    $('<td>').append(
        $('<a>', {
            href: o.link,
            text: o.word,
            onclick: function() {
                someFunc(o.string);
            }
        })
    )
);

или оставьте пустую строку внутри документа как HTML, но затем скройте ее (display: none) или отсоедините ее от документа во время запуска (removeChild или jQuery detach). Затем, когда вы хотите новую строку, клонируйте пустую строку и внесите необходимые изменения:

var blankRow= $('#blankRow').detach();

    ...

var newRow= blankRow.clone();
var link= newRow.find('td>a');
link.attr('href': o.link);
link.text(o.word);
link.click(function() {
    someFunc(o.string);
});

Если вам необходимо создать контент из строковых шаблонов, убедитесь, что ваша шаблонная функция HTML-по умолчанию экранирует каждую замену, и присоединяйте события, выбирая узлы внутри анализируемого контента для вызова click(function() { ... }). Или используйте делегирование событий (например, jQuery live()) для обработки событий без необходимости привязки к новым узлам при добавлении.

5 голосов
/ 15 мая 2010

Вы делаете это хорошим способом, и это довольно быстро, учитывая другие манеры.

Альтернативное, предположительно чистое решение состоит в том, чтобы встроить в JavaScript элементы DOM, которые вы будете использовать, вызвав несколько

document.createElement (тэгу); * +1006 *

Но ваш код будет быстро расти, как мне кажется, даром.

Еще один мой любимый способ создания DOM - поместить в тело HTML код, который вы хотите скопировать, присвоить ему className и / или идентификатор типа «template», который дополнительно (используя css) его скрывает и затем обработайте его по мере необходимости для события, вернув элемент, клонировав его и установив желаемое свойство перед добавлением, где он принадлежит

1 голос
/ 15 мая 2010

Если я вас хорошо понимаю, ваш вопрос касается инициализации больших строк, как вы это сделаете в PHP (или Perl)? Для длинной (многострочной) строки я использую:

var blankRow = [
     'a line',
     'another line',
     'still more lines',
     'lines lines lines',
     '... etc'
    ].join('')

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

var blankRow = 'a line\
another line\
still more lines\
lines lines lines\
... etc';

РЕДАКТИРОВАТЬ на основе комментария: я тоже ленивый! Поэтому я использую это для побега:

function qs(str){
    str = str || this || '';
    return "'"+str+"'";
}

function qd(str){
    str = str || this || '';
    return '"'+str+'"';

}

String.prototype.qs = qs;
String.prototype.qd = qd;

// applied:
var blankRow = [
         'a line',
         'another '+qd('line'),
         'still more lines',
         'lines '+'lines'.qs()+ ' lines',
         '... etc'
        ].join('');

Проблема с ленивостью: справиться с ленивостью довольно тяжело

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