2012-02-04 53 views
8

我有一個shadowbox腳本。當我加載頁面時,一切正常,但是當我調用這個jquery加載函數,然後嘗試通過單擊圖像觸發shadowbox時,大圖像會在新窗口中打開。 這裏是代碼:shadowboxbox在jquery函數調用後停止工作

<link href="CSS/main.css" rel="stylesheet" type="text/css" /> 
<script type="text/javascript" src="shadowbox-3.0.3/shadowbox.js"></script> 
<script type="text/javascript"> 
Shadowbox.init(); 
</script> 

<p id="compas"><a href="images/coverage.jpg" rel="shadowbox" title="Coverage map"></a></p> 

任何想法爲什麼會發生這種情況?

+0

什麼錯誤控制檯(螢火蟲,Chrome瀏覽器控制檯)的報告?您可能也想使用Persist。 – 2012-02-04 21:13:22

+0

沒有顯示。圖像以新的普通窗口打開。 – Igor 2012-02-04 21:14:03

+0

我所看到的,我本身並沒有發現任何錯誤。你有鏈接嗎? – 2012-02-04 21:17:06

回答

10

編輯

所以,我們終於得到的這個底部。在首次評論此問題15小時後,至少50次迭代後,我們最終確定了問題所在,以及如何解決問題。

當我在我的服務器上創建本地aaa.htmlbbb.html時,它實際上突然讓我感到震驚。當$.load()運行回調函數時,正好被替換內容的元素節點完全從DOM中被刪除。因此,一旦#menu-home內容元素被替換,它們將從DOM中移除,並且不再有Shadowbox應用到它們。

一旦我這個,那只是單一的網頁搜索的問題,我發現:

Nabble-Shadowbox - Reinit Shadowbox

具體地,從mjijackson響應。

Shadowbox.clearCache(); 
Shadowbox.setup(); 

所以一旦#menu-home含量重新加載,需要採取什麼是太極拳緩存需要清除(基本上,它關閉的:他描述如何「重啓」(重新初始化)太極拳使用是頁面),那麼運行Shadowbox.setup(),這將再次檢測元素。您不要再次運行Shadowbox.init()方法。

我注意到你曾試圖在$.load()之後複製/粘貼Shadowbox.setup(),至少在代碼中是按順序的。然而,由於需要首先發生緩存清除,並且主要因爲$.load()完成(完成並運行任何回調)之後.clearCache().setup()函數需要運行,所以這不起作用。這兩個函數需要在$.load()回調處理程序中運行;否則,您立即運行它,但$.load()是異步的,並且稍後會完成。

我打算繼續進行一些其他更改,只是爲了讓您明白什麼,爲什麼以及爲何。

注意,我不知道,如果你熟悉<base>,但下面是在HEAD元素的頂部:

<base href="http://62.162.170.125/"/> 

這只是讓我用你的計算機上的資源文件。您不希望在您的實際網站上使用此功能。如果您複製/粘貼,請確保並刪除此行。

<div id="menu"> 
    <ul> 
    <li><a id="menu-home" href="index.html" rel="http://jfcoder.com/test/homecontent.html">Home</a></li> 
    <li><a id="menu-services" href="services.html" rel="http://jfcoder.com/test/servicescontent.html">Services</a></li> 
    <li><a id="menu-tour" href="tour.html" rel="http://jfcoder.com/test/tourcontent.html">Tour</a></li> 
    <li><a id="menulogin" href="login.html">Login</a></li> 
    </ul> 
</div> 

在這裏,你會發現我在HREF屬性的相對URL,併到我的服務器上某些頁面的鏈接。鏈接到我的服務器的原因是,由於跨站點腳本的限制,我無法通過AJAX訪問您的aaa.htmlbbb.html文件。我的網站鏈接也應該刪除。

現在,我在這裏使用rel屬性的原因是,我希望允許鏈接通過href屬性繼續工作,以防JS失效或者出現其他錯誤。如果你有單獨的文件,一個用於完整的HTML文件,另一個用於片段,這就是你想要做的。如果您可以從鏈接文件中提供完整文檔和僅內容文檔,那麼您可能不需要rel屬性,但需要管理該請求,以便服務器知道如何響應(完整文檔或只是內容部分)。

var boxInitialize = function(){ 
    try { 
     if (!Shadowbox.initialized) { 
      Shadowbox.init(); 
      Shadowbox.initialized = true; 
     } else { 
      Shadowbox.clearCache(); 
      Shadowbox.setup(); 
     } 
    } catch(e) { 
     try { 
      Shadowbox.init(); 
     } catch(e) {}; 
    } 
}; 

我在這裏所做的是爲初始化/設置請求創建一箇中央位置。非常坦率的。請注意,我添加了Shadowbox.initialized屬性,因此我可以跟蹤Shadowbox.init()是否已運行,只能運行一次。但是,如果可能的話,將它全部保存在一個地方是一個好主意。

我還創建了一個變量函數可以被稱爲無論是作爲一個普通函數:

boxInitialize(); 

或者作爲一個函數引用:

window.onload = boxInitialize; // Note, no() at the end, which execute the function 

你可能會注意到我刪除了$()和改爲用jQuery()代替它們。如果最終結果是多個框架和庫競爭$(),那麼這可能會變成真正的噩夢,所以最好避免它。這一天實際上讓我覺得很不錯。

由於我們在.ready()回調中有一個閉包範圍,我們可以利用它在腳本執行的不同時間保存幾個ow使用的「私有」變量。

var $ = jQuery, 
    $content = jQuery("#content"), // This is "caching" the jQuery selected result 
    view = '', 
    detectcachedview = '', 
    $fragment, 
    s = Object.prototype.toString, 
    init; 

注意,在所有的結束,但最後一行。看看我如何通過使其等於jQuery變量來「導入」$,這意味着您可以在#中實際使用它。

var loadCallback = function(response, status, xhr){ 
    if (init != '' && s.call(init) == '[object Function]') { 
     boxInitialize(); 
    } 

    if (xhr.success() 
      && view != '' 
      && typeof view == 'string' 
       && view.length > 1) { 
     $fragment = $content.clone(true, true); 
     cacheContent(view, $fragment); 
    } 
}; 

這在$.load()完成AJAX請求的過程時運行。請注意,請求中返回的內容在運行時已經放置在DOM上。請注意,我們正在將實際緩存的內容存儲在$content.data()中,該內容不應從網頁中刪除;只有它下面的內容。

var cacheContent = function(key, $data){ 
    if (typeof key == 'string' 
      && key.length > 1 
      && $data instanceof jQuery) { 
     $content.data(key, $data.html()); 
     $content.data(detectcachedview, true); 
    } 
}; 

cacheContent()是一種你可能不想要的方法;基本上,如果它已經加載了先前的請求,那麼它將被緩存,然後直接檢索,而不是啓動另一個$.load()從服務器獲取內容。你可能不想這樣做;如果是這樣,只需註釋掉menuLoadContent()函數中的第二個if塊。

var setContent = function(html){ 
    $content.empty().html(html); 

    if (init != '' && s.call(init) == '[object Function]') { 
     boxInitialize(); 
    } 
}; 

這樣做是第一個空它的$content元素的內容/元素,然後補充說,我們通過獲取$content.html()先前保存的指定基於字符串的標記。這是我們在可能的情況下重新添加的內容;你可以看到一旦不同的鏈接被點擊和加載,重新點擊以獲得重新顯示是非常快速的。而且,如果它與當前加載的請求是相同的,那麼它也將完全跳過運行代碼。我們使用$content,因爲它是一個包含jQuery元素的變量的引用,我這樣做是因爲它在閉包範圍內,這意味着它不會顯示在全局範圍內,但會是。可對於像事件處理

查找代碼內嵌批註

var menuLoadContent = function(){ 
    // This is where I cancel the request; we're going to show the same thing 
    // again, so why not just cancel? 
    if (view == this.id || !this.rel) { 
     return false; 
    } 

    // I use this in setContent() and loadCallback() functions to detect if 
    // the Shadowbox needs to be cleared and re-setup. This and code below 
    // resolve the issue you were having with the compass functionality. 
    init = this.id == 'menu-home' ? boxInitialize : ''; 
    view = this.id; 
    detectcachedview = "__" + view; 

    // This is what blocks the superfluous $.load() calls for content that's 
    // already been cached. 
    if ($content.data(detectcachedview) === true) { 
     setContent($content.data(view)); 
     return false; 
    } 

    // Now I have this in two different spots; there's also one up in 
    // loadCallback(). Why? Because I want to cache the content that 
    // loaded on the initial page view, so if you try to go back to 
    // it, you'll just pickup what was sent with the full document. 
    // Also note I'm cloning $content, and then get it's .html() 
    // in cacheContent(). 
    $fragment = $content.clone(true, true); 
    cacheContent(view, $fragment); 

    // See how I use the loadCallback as a function reference, and omit 
    // the() so it's not called immediately? 
    $content.load(this.rel, loadCallback); 

    // These return false's in this function block the link from navigating 
    // to it's href URL. 
    return false; 
}; 

現在,我選擇相關的菜單項不同你並不需要一個單獨的$.click()聲明每個元素。相反,我選擇了#menu a[rel],這將得到每個具有rel="not empty rel attribute"的菜單中的元素。再次請注意,我如何在這裏使用menuLoadContent作爲函數參考。

jQuery("#menu a[rel]").click(menuLoadContent); 

然後,在最底部,我運行boxInitialize();來設置Shadowbox。

讓我知道如果您有任何問題。


我想我可能已經到底了。我認爲這個安全漏洞是你點擊一個菜單項時處理新內容的$.load()的方式,再加上我看到有與iframe做了一個未捕獲的異常:

未捕獲的異常:未知播放器IFRAME

這個Nabble-Shadowbox forum thread處理這個錯誤。我實際上不再那樣了,但是我認爲它出現了,我點擊了tour菜單項。

現在,你正在做什麼來加載菜單項的內容真的沒有任何意義。您正在請求整個HTML文檔,然後選擇一個帶有class="content"的元素。我看到這樣做的唯一好處是頁面不會重新加載,但是您需要採取另一種方法來獲取和顯示不涉及通過AJAX下載整個頁面的數據,然後嘗試讓jQuery解析只是你想要的部分。

我相信處理這種加載內容是你的問題的根本原因,因此菜單視圖的切換會以意想不到的方式打破你的頁面。

問題:爲什麼不直接鏈接到實際頁面並跳過所有的$.load()幻想?速度方面,它不會產生太大的影響,如果有的話。這樣使用AJAX沒什麼意義,只要將它們鏈接到相同的內容即可。

有兩個備選方案,將允許您以防止往返重新加載頁面:

  1. 設置你的AJAX調用,如果你在URL中?contentonly=true標誌只要求標記的.content部分,而不是整個HTML文件。這就是傳統上的做法,如果你有一個腳本環境,通常做起來相對簡單。

    $(".content").load('index.html?contentonly=true'); 
    

    然後,您的服務器僅響應請求的內容視圖。

  2. 即成所有相同的HTML文檔中的內容的意見,然後顯示在適當:

    var $content = $('.content'); 
    $content.find('.content-view').hide(); 
    $content.find('#services-content').show(); 
    

    它看起來並不像你有內容的整體很多提供,因此初始頁面加載可能不會對這種特定方法產生太大的影響。您可能需要研究如何預加載圖像,但這是一項非常知名的技術,其中包含許多高質量的腳本和教程。

無論這些技術可以使用#!(hashbang)技術來加載內容,但我相信有一些的問題與此搜索引擎之一。然而,這裏是一個簡單的技術我前一段時間把一個鏈接:

http://jfcoder.com/test/hash.html

而且,這僅僅是一個提示,但不涉及您的「內容」的元素與class,即,.content。標記中只應該有一個內容顯示元素,對吧?有不止一個?使用id="content";這就是ID屬性的用途,以引用單個元素。 classES旨在通過它們共享的某些特徵對元素進行分組,因此,當我在內聯內容視圖(參見#2)中查找所有類似的元素(它們都包含內容視圖標記)時,我會查找所有class="content-view"元素。但$content變量應參考$('#content');。這是描述元素是什麼。

+0

我寧願鏈接實際的頁面,但這不符合要求。客戶希望在沒有頁面重新加載的情況下更改內容。我正在請求整個HTML頁面並從中選擇內容,因爲我正在考慮將實際鏈接放在菜單項「href」中,所以如果某個用戶的瀏覽器不支持JavaScript,它仍然可以工作。 – Igor 2012-02-05 00:05:09

+0

AJAX不會陷入類似鏈接的行爲,它不會執行任何操作(包括不觸發整頁加載)。您需要在完整的HTML文檔(常規的GET往返請求,例如點擊鏈接)或者AJAX請求期間顯示的片段(內容部分)中迴應。你可以用AJAX上的GET標誌來完成這個任務;只需省略'href'屬性URL中的標誌,這樣就可以進入整個頁面。然後,在服務器腳本上,檢測您是否需要使用完整的HTML文檔或僅內容進行響應。 – 2012-02-05 00:07:52

+0

查看[此演示](http://www.asp.net/ajaxLibrary/jQueryCodeSamplesWebForms/jQueryLoad/MainContentForm.aspx)與Firebug或Chrome的網絡控制檯打開,並且當請求是針對頁面片段時,查看響應文字是。你會看到它只是一個HTML片段,而不是一個完整的文檔。 – 2012-02-05 00:15:12

1

這個工作對我們來說,我們提出,使用垂直選項卡,並呼籲與使用jQuery.load

只要給所有定位我們的太極拳圖像的網頁標記中的class =「S盒」,並粘貼此網站標題中的腳本。

<script> 
    Shadowbox.init({ 
    skipSetup:true, 
}); 
$(document).ready(function() { 
    Shadowbox.setup($('.sbox'));//set up links with class of sbox 
    $('a.sbox').live('click',function(e){ 
     Shadowbox.open(this); 
     //Stops loading link 
     e.preventDefault(); 
    }); 
}); 
</script> 

注:我們不得不把.sbox類對我們所有的rel =「太極拳」錨以及信中的錨那個叫.load

由於這種guy-標籤>http://www.webmuse.co.uk/blog/shadowbox-ajax-and-other-generated-content-with-jquery-and-javascript/

0

那麼,根據Shem的回答,這是我的解決方案。 在特定的類,設置和開放式太極拳與來自同一類元素的每個點擊:

jQuery('.sb-gallery a').live('click',function(e){ 
    Shadowbox.setup(jQuery('.sb-gallery a')); 
    Shadowbox.open(this); 
    //Stops loading link 
    e.preventDefault(); 
}); 

感謝所有

相關問題