EDIT
Итак, мы наконец получить в нижней части этого. Через 15 часов после первого комментирования этой проблемы и по меньшей мере 50 итераций позже мы, наконец, определили, в чем проблема и как ее исправить.
Это действительно поразило меня внезапно, когда я создавал локальные aaa.html
и bbb.html
на моем сервере. Именно тогда я ударил меня, что узлы элементов для подлежащего замене содержимого полностью удалялись из DOM, когда $.load()
запускает функцию обратного вызова. Итак, после замены элементов контента #menu-home
они были удалены из DOM и больше не применялись к ним Shadowbox.
После того, как я понял это, это просто вопрос одного веб-поиска, и я нашел:
Nabble-Shadowbox - Reinit Shadowbox
В частности, ответ от mjijackson. То, что он описывает, как «перезагрузка» (повторная инициализация) Shadowbox с помощью:
Shadowbox.clearCache();
Shadowbox.setup();
Так как только #menu-home
контента был перезагружен, что должно произойти, это кэш Shadowbox должен быть очищен (по существу, закрывая его вниз на страница), затем запускается Shadowbox.setup()
, который будет обнаруживать элементы снова и снова. Вы снова не запускаете метод Shadowbox.init()
.
Я заметил, что вы попытались скопировать/вставить Shadowbox.setup()
после $.load()
, по крайней мере последовательно в коде. Однако это не сработало, из-за очистки кеша, который должен произойти первым, и в первую очередь потому, что функции .clearCache()
и .setup()
должны быть запущены после$.load()
завершает (завершает и выполняет любые обратные вызовы). Эти две функции должны выполняться в обработчике обратного вызова $.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>
Здесь вы заметите, у меня есть относительный URL в атрибуте HREF
, и ссылки на некоторые страницы на моем сервере. Причиной ссылок на мой сервер является то, что я не мог получить доступ к файлам aaa.html
и bbb.html
через AJAX из-за ограничений межсайтового скриптинга. Ссылки на мой сайт также должны быть удалены.
Теперь причина, по которой я использую атрибут 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()
, мы можем воспользоваться этим, чтобы сохранить несколько «частных» переменных для использования в разное время выполнения скриптов.
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()
для получения содержимого с сервера. Вы не можете этого делать; если да, просто закомментируйте второй блок if
в функции menuLoadContent()
.
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]
, который получит каждый a
в меню, которое имеет rel="not empty rel attribute"
. Опять же, обратите внимание на то, как я использую menuLoadContent
здесь как функцию ссылки.
jQuery("#menu a[rel]").click(menuLoadContent);
Затем, в самом низу, я бегу boxInitialize();
для установки Shadowbox.
Дайте мне знать, если возникнут какие-либо вопросы.
Я думаю, что я мог бы добраться до сути. Я думаю, что недостаток является способом вы обработки $.load()
нового контента при нажатии на пункт меню, в сочетании с неперехваченным исключением я видел, имеющее отношение с iframe
:
Uncaught исключения: Неизвестный игроком IFrame
Этот Nabble-Shadowbox forum thread имеет дело с этой ошибкой. Я на самом деле не получаю этого больше, но я думаю, что это пришло, я нажал на пункт меню tour
.
Теперь, что вы делаете, чтобы загрузить контент для пунктов меню, на самом деле не имеет никакого смысла. Вы запрашиваете весь HTML-документ, а затем выбираете только элемент с class="content"
. Единственное преимущество, которое я вижу для этого, заключается в том, что страница никогда не перезагружается, но вам нужно взять другой подход к тому, как получить и отобразить данные, которые не связаны с загрузкой всей страницы через AJAX, а затем попытка получить jQuery для синтаксического анализа просто часть, которую вы хотите.
Я считаю, что обработка содержимого таким образом является основной причиной вашей проблемы, следовательно, переключение меню в меню неожиданно открывает страницу.
Вопрос: Почему бы вам не перейти на страницу фактического перевода и перейти сюда через $.load()
? Скорее, это не повлияет на это, если вообще будет. Просто не имеет смысла использовать AJAX, как это, когда вы можете просто связать их с одним и тем же контентом без проблем.
Есть две альтернативы, которые позволили бы вам предотвратить спускоподъемные перезагрузки страницы:
Настройте AJAX вызовов только просить .content
части разметки, если у вас есть ?contentonly=true
флага в URL, а не весь 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');
. Это описание элементов.
Что делает консоль ошибок (Firebug, Chrome консоль) отчет?Вероятно, вы захотите использовать Persist. –
Ничего не показывает. Изображения открываются в новом обычном окне. – Igor
Что я вижу, я не вижу в себе ничего плохого. У вас есть ссылка? –