Выполнение javascript, смешанного с HTML, из ответа jQuery ajax - PullRequest
0 голосов
/ 30 декабря 2010

Или не точно "выполнение", но обновление функции, существующей до ответа, с помощью функции, возвращенной в ответе.

Шаг 1

  1. У меня есть страница HTML5, которая описывает местоположение.
  2. На стороне сервера эта страница содержит файл ColdFusion «MapFunction.cfm».(Используется для согласованного отображения по всему сайту в целом.)
  3. MapFunction.cfm выводит функцию javascript «loadMap», смешанную с HTML.
  4. loadMap () содержит весь javascript, необходимый для размещения карты Bing местоположения на странице.
  5. Некоторые javascript в отдельном js-файле фактически вызывают loadMap ().

Это работает при первой загрузке страницы.

Шаг 2

  1. С поиском и результатами тоже все в порядке.Здесь ничего не нужно делать с картой.

Шаг 3

  1. При нажатии на результат поиска детали результата загружаются асинхронно с помощьюзапрос jQuery $ .get ().
  2. Возвращает смешанный HTML и javascript, который я использую для обхода jQuery.
  3. С объектами jQuery я обновляю определенные области страницы, чтобы показать разные детали.

Одной из областей, которую мне нужно обновить, является карта.Эта часть не работает.

Я работаю со смешанным HTML и Javascript, которые одинаковы в Шаг 1 и Шаг 3 :

<section id="mod-map" class="module mod-map">
    <header class="mod-head">
        <a href="#map" class="mod-head-link"> Map <span class="arrow"></span> </a>
    </header>
    <div id="map" class="mod-body">
        <div id="cmMap" style="position:relative;width:369px;height:303px;"></div>
        <script type="text/javascript" id="cfLoadMap">
            // ...some global variables are defined to use...
            function loadMap()
            {                   
                // ...Bing/Virtual Earth Map Stuff...
                // This part here is unique to each location's detail
                var propertypoint = new VELatLong(parseFloat(36.707756),parseFloat(-78.74204));
                // ...More Bing/Virtual Earth Map Stuff...
                // This part here is unique to each location's detail
                var label = "<div class=\"wrapper\"><img onerror=\"replaceImage(this);\" src=\"noimage.jpg\" width=\"100\" class=\"thumb\" alt=\"\" /><div class=\"caption\"><br />City<br /> State, 12345</div></div>";    
                // ...More Bing/Virtual Earth Map Stuff...              
            }
        </script>
    </div>
</section>

Теперь, в Шаг 3 loadMap () снова вызывается , но он просто обновляет карту в том же месте.Функция loadMap (), поскольку браузер знает, что она не обновляется с помощью функции, полученной через ajax.

Этот обновленный блок смешанного HTML и JavaScript, приведенный выше, успешно добавляется на страницу после каждого вызова ajax.Он расположен там, где он изначально, но с другими координатами и подписями, где указано в комментариях выше.Обратный вызов ajax выглядит (немного упрощенно):

$.get(urlToLoad, {}, function(data, status, request){   
    var newData = $(innerShiv(data, false)),
        newModules = newData.find(".module");
    // (innerShiv is used to make HTML5 tags work in IE. It's possible I'm going a little overboard with using it, but I had a lot of issues with IE. :-))
    newModules.each(function(i){
        var thisId = "#" + $(this).attr("id"),
            thisBody = $(this).find(".mod-body").html(),
            toReplaceAll = $("body").find(thisId),
            toReplaceBody = toReplaceAll.find(".mod-body");
        // These variables are used to choose add content in different ways based on thisID. Below is the one the map area is subject to.
        toReplaceBody.html(innerShiv(thisBody));                
    }); // each
    // Various things including loadMap() get called/re-initiated/etc. here
}, "html"); // get

Это работает в Firefox 3.6, но нигде больше я не тестировал (Opera 11, IE 7, Chrome 8).

Я ранее уже делал в аналогичной ситуации с динамически генерируемым PHP javascript, записанным в отдельный файл js - $. GetScript прекрасно работает там.Но это смешано с HTML ответа ajax.

Я искал, нашел и попробовал следующее (среди прочего):

Попытки Решения

1. var myScript = new Function($('script#cfLoadMap', data).text()); myScript();
2. eval(newData.text());
3. eval(newData.find("#cfLoadMap").text());
4. $("head").append(newData.find("#cfLoadMap"));

Пока что ни один из них не приносит никакой пользы.

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

  • Детали будут обновляться с помощью ajax.
  • Javascript будет смешан с HTML.
  • Javascript будетФункция javascript, динамически генерируемая ColdFusion.

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

Любая помощь будет признательна.

Ответ

Он неожиданно начал работать сследующий код:

$.get(urlToLoad, {}, function(data, status, request){   
    var safeData = $(innerShiv(data, false)),
        newModules = safeData.find(".module"),
        newScript = safeData.find("script#cfLoadMap");
    // Update Each module
    newModules.each(function(i){
        var jqoThis = $(this),
            thisId = "#" + jqoThis.attr("id"),
            newModule = jqoThis,
            newModBody = jqoThis.find(".mod-body"),
            curModule = $("body").find(thisId),
            curModBody = curModule.find(".mod-body");
        // Varies by id, this one is used by the map area.
        curModBody.html(innerShiv(newModBody.html()));      
    }); // each
    // Make sure plugins are bound to new content
    $("body").oneTime(100, function(){
        // Various things get initiated here
        // Maps -- this one works: Chrome, Firefox, IE7, Opera
        $("head").append(newScript);
        // Maps -- these did not work
        /* 
            // Firefox only (but Firefox always works)
            runScript = new Function(newScript.text());
            runScript();
        */
        /*
            // Firefox only (but Firefox always works)
            eval(newScript.text());
        */
    }); // oneTime
}, "html"); // get

Одна вещь, которую я сделал наверняка заметил, это то, что без innerShiv во всех моих браузерах $ (data) .find ("script # cfLoadMap"). text() было пусто - что я и сделал не ожидаем.

Ответы [ 2 ]

1 голос
/ 30 декабря 2010

Скорее всего, функции в JavaScript могут быть объявлены в неглобальной области, поэтому, когда вы вставляете тег <script>, jQuery eval использует его, но не заменяет исходную функцию (как вы заметили).

Исправление для этого - изменить способ объявления функции следующим образом:

function loadMap()
{
  ...
}

на следующее:

window.loadMap = function loadMap() {
  ...
}

Таким образом, верхний уровеньloadMap всегда будет последним, пришедшим с сервера.

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

0 голосов
/ 04 января 2011

Он неожиданно начал работать со следующим кодом:

$.get(urlToLoad, {}, function(data, status, request){   
    var safeData = $(innerShiv(data, false)),
        newModules = safeData.find(".module"),
        newScript = safeData.find("script#cfLoadMap");
    // Update Each module
    newModules.each(function(i){
        var jqoThis = $(this),
            thisId = "#" + jqoThis.attr("id"),
            newModule = jqoThis,
            newModBody = jqoThis.find(".mod-body"),
            curModule = $("body").find(thisId),
            curModBody = curModule.find(".mod-body");
        // Varies by id, this one is used by the map area.
        curModBody.html(innerShiv(newModBody.html()));      
    }); // each
    // Make sure plugins are bound to new content
    $("body").oneTime(100, function(){
        // Various things get initiated here
        // Maps -- this one works: Chrome, Firefox, IE7, Opera
        $("head").append(newScript);
        // Maps -- these did not work
        /* 
            // Firefox only (but Firefox always works)
            runScript = new Function(newScript.text());
            runScript();
        */
        /*
            // Firefox only (but Firefox always works)
            eval(newScript.text());
        */
    }); // oneTime
}, "html"); // get

Одна вещь, которую я сделал , точно заметил, что во всех моих браузерах без innerShiv $ (data) .find ("script # cfLoadMap"). Text () был blank - что я и сделал не ожидаю.

Однако я не очень понимаю, как это отличается от того, что я пробовал раньше и что не получилось. Если кто-то заметит существенную разницу, пожалуйста, дайте мне знать, для дальнейшего использования?

(Примечание: кажется, что разница в том, что бит карты помещен в тайм-аут, не имеет значения, он также работает над ним.)

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