我打算繼續進行一些其他更改,只是爲了讓您明白什麼,爲什麼以及爲何。
注意,我不知道,如果你熟悉<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.html
和bbb.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沒什麼意義,只要將它們鏈接到相同的內容即可。
有兩個備選方案,將允許您以防止往返重新加載頁面:
設置你的AJAX調用,如果你在URL中?contentonly=true
標誌只要求標記的.content
部分,而不是整個HTML文件。這就是傳統上的做法,如果你有一個腳本環境,通常做起來相對簡單。
$(".content").load('index.html?contentonly=true');
然後,您的服務器僅響應請求的內容視圖。
即成所有相同的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
屬性的用途,以引用單個元素。 class
ES旨在通過它們共享的某些特徵對元素進行分組,因此,當我在內聯內容視圖(參見#2)中查找所有類似的元素(它們都包含內容視圖標記)時,我會查找所有class="content-view"
元素。但$content
變量應參考$('#content');
。這是描述元素是什麼。
什麼錯誤控制檯(螢火蟲,Chrome瀏覽器控制檯)的報告?您可能也想使用Persist。 – 2012-02-04 21:13:22
沒有顯示。圖像以新的普通窗口打開。 – Igor 2012-02-04 21:14:03
我所看到的,我本身並沒有發現任何錯誤。你有鏈接嗎? – 2012-02-04 21:17:06