Где загружаются скрипты после вызова ajax? - PullRequest
6 голосов
/ 23 ноября 2011

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

- main.html -

<!DOCTYPE html>
<html xmlns="https://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript"
   src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-1.6.2.js">
</script>
<script type="text/javascript">
$(function() {
    $.ajax({
         type: 'get', cache: false, url: '/svc.html',
         success: function(h) {
             $('#main').html(h);
         }
    });
});
</script>
</head>

<body>
    <div id='main'>
    loading...
    </div>
</body>
</html>

и загружаемая страница использует небольшой Javascript в отдельном файле:

- svc.html -

<script type="text/javascript"
   src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-1.6.2.js">
</script>
<script type="text/javascript" src="/plugin.js" css="/plugin.css"></script>
<div id='inner'>
dynamically loaded content
</div>

обратите внимание на атрибут css на теге скрипта - он указывает таблицу стилей, которая принадлежит скрипту и которую скрипт будет загружать для нас. Вот сценарий:

- plugin.js -

var css = $('<link />', {
    rel: "stylesheet", type: "text/css", href: $('script:last').attr('css')
});
$('head').append(css);

и, наконец, таблица стилей, которая просто окрашивает загруженный div inner, в качестве доказательства того, что все это работает:

- plugin.css -

#inner
{
    border: solid 1px blue;
}

Теперь вы заметите, как загружается таблица стилей: мы смотрим на $('script') и выбираем последний, затем берем атрибут css и прикрепляем элемент link к голове документ.

Я могу посетить /svc.html, и javascript запускается, загружает мою таблицу стилей, все круто - однако, если я посещаю /main.html, javascript запускается, но не может найти загрузку plugin.js в массиве $('script') (и поэтому не может загрузить таблицу стилей). Обратите внимание, что скрипт плагина действительно работает, он просто не видит себя.

Это ошибка? ограничение метода JQuery AJAX? не должны ли $('script') отражать все скрипты, которые были загружены?

* редактировать *

после долгих воплей и скрежета зубов я решил пойти на решение Кевина Б. Однако я не могу заставить его работать, в основном потому, что код plugin.js запускается в тот момент, когда вставляется scriptNode, но в коде плагина узел еще не вставлен и поэтому недоступен в массиве $('script') - так что я все еще SOL. Я поместил весь код для просмотра здесь:

http://www.arix.com/tmp/loadWithJs/

Ответы [ 5 ]

5 голосов
/ 23 ноября 2011

Код jQuery, который добавляет HTML в DOM, всегда удаляет теги <script>. Он запускает их, а затем выбрасывает.

Исключением из этого поведения является случай, когда вы используете "$ .load ()" с хаком, который позволяет вам загрузить фрагмент страницы:

$.load("http://something.com/whatever #stuff_I_want", function() { ... });

В этом случае сценарии удаляются и не оценивается / запускается.

1 голос
/ 24 ноября 2011

Мое решение было бы довольно простым

Почему бы не загрузить файлы, необходимые в main, при первой загрузке все вместе?Тогда просто имейте событие слушателя.(Проверьте, загружен ли контент просто?)

Единственное решение для загрузки по требованию ...

Вам просто нужно AJAX вызвать сам файл сценария ...

<script type="text/javascript">
$(function () {
    $.ajax({
        type: 'get',
        cache: false, 
        url: 'svc.html',
            success: function(response) {
                if (response) { // If any response aka, loaded the svc.html file...
                    $('#main').html(response);
                    $.ajax({
                        url: 'plugin.js',
                        dataType: 'script',
                        success: function(reponse) {
                            // You can now do something with the response here even...
                        }
                    });
                }
            }
    });
});
</script>

Мой путь

Вместо того, чтобы что-то загружать, загрузите какой-нибудь тип загрузчика на фактической странице перед тем, как что-либо отобразить.(Множество обучающих программ с помощью jQuery в Интернете для этого.)

1 голос
/ 23 ноября 2011

вы можете использовать $ .ajax, чтобы получить html, самостоятельно удалить теги скрипта, добавить содержимое, а затем добавить тег скрипта в то место, где вы хотите, чтобы он выполнялся так, как вы этого хотите.к.

$.ajax({...}).done(function(html){
  var htmlToAppend = html;

  // replace all script tags with divs
  htmlToAppend.replace(/<script/ig,"<div class='script'");
  htmlToAppend.replace(/<\/script>/ig,"</div>");

  // detach script divs from html
  htmlToAppend = $(htmlToAppend);
  var scripts = htmlToAppend.find(".script").detach();

  // append html to target div
  htmlToAppend.appendTo("#target");

  // loop through scripts and append them to the dom
  scripts.each(function(){
    var $script = $(this), 
        scriptText = $script.html(), 
        scriptNode = document.createElement('script');

    $(scriptNode).attr('css', $script.attr('css');
    scriptNode.appendChild(document.createTextNode(scriptText));
    $("#target")[0].appendChild(scriptNode);
  });

});

Я не тестировал этот код, но он основан на коде из history.js

Редактировать: вот более простое решение, более приспособленное для ваших нужд:

$("#target").load(url,function(obj){
    // get css attribute from script tag using the raw returned html
    var cssPath = obj.responseText.match(/css="(.*)"/i)[1];
    $('<link />', {
        rel: "stylesheet", type: "text/css", href: cssPath
    }).appendTo('head');

});

, так как .load () удаляет теги сценария и затем выполняет их, он прочитает необработанный текст ответа и получит из него путь css, затем добавит элемент ссылки.

I'mне совсем уверен, почему он обрабатывается таким образом.

Редактировать: см. комментарий.

$.ajax({...}).done(function(html){
  $("#target")[0].innerHTML = html;
});
0 голосов
/ 24 ноября 2011

хорошо, после многих трудностей, я внедрил решение Кевина Б. в плагин, полезный для других.Улучшения приветствуются!(Должен ли я положить его в github?)

- loadWithJs.js -

// inspired by Kevin B's suggestions
// at: /5574664/gde-zagruzhaytsya-skripty-posle-vyzova-ajax

(function ($) {
    $.fn.loadWithJs = function (o) {
        var target = this;
        var success = o.success;

        o.success = function (html) {
            // convert script tags
            html = $('<div />').append(
                html.replace(/<(\/)?script/ig, "<$1codex")
            );
            // detach script divs from html
            var scripts = html.find("codex").detach();
            // populate target
            target.html(html.children());

            // loop through scripts and append them to the dom
            scripts.each(function () {
                var script = $(this)[0];
                var scriptNode = document.createElement('script');

                for (var i = 0; i < script.attributes.length; i++) {
                    var attr = script.attributes[i];
                    $(scriptNode).attr(attr.name, attr.value);
                }
                scriptNode.appendChild(
                    document.createTextNode($(script).html())
                );
                target[0].appendChild(scriptNode);
            });

            if (success) success();
        };

        $.ajax(o);
    };
})(jQuery);

, тогда вызывающая сторона может сделать:

$(function() {
    $('#main').loadWithJs({
         type: 'get', cache: false, 
         url: '/svc.html',
         success: function() { console.log('loaded'); }
    });
});
0 голосов
/ 23 ноября 2011

Одна из проблем в том, что вы НЕ МОЖЕТЕ перезагружать jQuery на каждой странице.Просто главная страница должна иметь вызов jQuery:

<script type='text/javascript' src='jQuery-url'></script>

Или только одна страница может вызвать его, и только дети (да, страницы загружены оттуда) смогут использовать jQuery.

Я сталкивался с этим несколько раз, прежде чем усвоил урок.Это может быть не полный ответ на ваши проблемы, но может стать началом их решения.

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