2012-07-09 52 views
3

我通過$.ajax()加載網頁並插入部分結果到頁面的相應部分從HTML文本腳本元素:查詢使用jQuery

$.ajax({ 
    url: '/whole_page.html', 
    success: function (data, status, xhr) { 
    $result = $(xhr.responseText); 
    $('#menu').html($('#menu', $result).html()); 
    $('#content').html($('#content', $result).html()); 
    } 
}); 

工程就像一個魅力,但我已經遇到了問題。

現在我的頁面包含一些特定於頁面的JS,當結果被獲取並插入時,它們必須執行。據我所知,jQuery不會返回script元素,如果你從HTML文本構建一個jQuery對象並查詢它(我已經made a fiddle來演示)。所以,我沒有辦法選擇性地只通過jQuery插入我想要的腳本。

因此,我似乎必須從自己的回覆文本中提取script元素。基本上,我正在尋找正確的方法來做到這一點。這是我到目前爲止:

function pullScripts(text) { 
    var frag = document.createDocumentFragment() 
    , div = document.createElement('div') 
    , scriptElements 
    ; 

    // This is roughly how jQuery finds the scripts when cleaning text 
    frag.appendChild(div); 
    div.innerHTML = text; 

    scriptElements = div.getElementsByClassName('class-for-scripts-that-we-want'); 

    $('head').append(scriptElements); 
} 

這工作得很好,雖然我還沒有在任何蹩腳的瀏覽器上測試過它。無論如何,複製jQuery的這些基本功能只是爲了避免其功能之一(特殊的script處理)而感到不舒服。從小提琴中可以看出,jQuery對象實際上包含script s,但它不會像.html().get()那樣返回它們。 我是否錯過了一些明顯的做法?

注:一旦jQuery的內部parseHTML功能暴露這整個主題將是毫無意義

注2:我也看到了Trying to select script tags from a jQuery ajax get response但接受的答案是「你不是可以」,其次是「使用正則表達式「。兩者都不能令人滿意

+0

只需要注意,傳入成功回調的第一個參數是來自請求的數據,而不是事件 – Austin 2012-07-09 17:34:28

+0

$ .load()是否解決此問題? – Christophe 2012-07-09 17:35:22

+0

@奧斯汀,謝謝。我徒手打字,知道我會搞砸了。 Christophe:從某種意義上說,如果你在URL中添加一個選擇器(就像我需要使用它的那樣),你會遇到上述同樣的問題。 – bkconrad 2012-07-09 17:41:04

回答

1

在jQuery 1.8.0b1中,您現在可以使用$.parseHTML()方法來使這更容易。

$.parseHTML(xhr.responseText,true)會給你一個包含腳本元素的jQuery對象。然後,您可以提取腳本標記並在追加HTML後附加或執行它們。

$.ajax({ 
    url: '/whole_page.html', 
    success: function (data, status, xhr) { 
    var $result = $.parseHTML(xhr.responseText,true), 
     $scripts = $result.find("script").add($result.filter("script")).detach(); 

    $('#menu').html($('#menu', $result).html()); 
    $('#content').html($('#content', $result).html()); 
    $('head').append($scripts); 
    } 
}); 

儘管您可能需要過濾腳本,以避免在個案的基礎上加入jQuery。這將取決於您正在加載的內容。

如果升級jQuery是不是一種選擇,你可以只取$.parseHTML實施,它作爲一個插件到您當前的jQuery

(function($) { 
    if (!$.parseHTML) { 
     var rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/; 
     // data: string of html 
     // context (optional): If specified, the fragment will be created in this context, defaults to document 
     // scripts (optional): If true, will include scripts passed in the html string 
     $.parseHTML = function(data, context, scripts) { 
      var parsed; 
      if (!data || typeof data !== "string") { 
       return null; 
      } 
      if (typeof context === "boolean") { 
       scripts = context; 
       context = 0; 
      } 
      context = context || document; 

      // Single tag 
      if ((parsed = rsingleTag.exec(data))) { 
       return [ context.createElement(parsed[1]) ]; 
      } 

      parsed = jQuery.buildFragment([ data ], context, scripts ? null : []); 
      return jQuery.merge([], 
       (parsed.cacheable ? jQuery.clone(parsed.fragment) : parsed.fragment).childNodes); 
     } 
    } 
})(jQuery); 
2

當我與jQuery(邊緣)昨晚玩jsFiddle,我無法使用.find()和朋友對$.parseHTML()的結果。問題是$.parseHTML返回一個元素數組而不是一個jQuery對象,如果你用$()創建一個元素,你就回到了原來的問題。所以,你仍然不能真正使用選擇器。沒有太大的麻煩,雖然的:

$.ajax({ 
    url: '/some_page.html', 
    success: function (data, text, xhr) { 
    var result = $.parseHTML(data, true) 
     , scripts = [] 
     , i; 

    // filter the scripts somehow 
    for (i = 0; i < result.length; i++) { 
     if (result[i].getAttribute('class') === 'good') { 
      scripts.push(result[i]); 
     } 
    } 

    $('head').append(scripts); 
    } 
});​ 

我做了a working fiddle這一點。