2012-02-04 4 views
8

У меня есть сценарий shadowbox. Когда я загружаю страницу, все работает нормально, но когда я вызываю эту функцию загрузки jquery, а затем пытаюсь вызвать теневой блок, щелкнув по изображению, вместо этого откроется большое изображение. Вот код:shadowbox перестает работать после вызова функции 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

Что делает консоль ошибок (Firebug, Chrome консоль) отчет?Вероятно, вы захотите использовать Persist. –

+0

Ничего не показывает. Изображения открываются в новом обычном окне. – Igor

+0

Что я вижу, я не вижу в себе ничего плохого. У вас есть ссылка? –

ответ

10

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, как это, когда вы можете просто связать их с одним и тем же контентом без проблем.

Есть две альтернативы, которые позволили бы вам предотвратить спускоподъемные перезагрузки страницы:

  1. Настройте AJAX вызовов только просить .content части разметки, если у вас есть ?contentonly=true флага в URL, а не весь 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, для ссылки на один элемент. class es предназначены для группировки элементов по какой-либо характеристике, которую они разделяют, поэтому выше, когда я вставляю содержимое в виде встроенного содержимого (см. # 2), я ищу все элементы class="content-view", которые все схожи (они содержат разметку представления контента). Но переменная $content должна относиться к $('#content');. Это описание элементов.

+0

Я бы скорее связал фактические страницы, но это не соответствует требованиям. Клиент хочет, чтобы содержимое менялось без перезагрузки страницы. Я запрашиваю всю HTML-страницу и выбираю контент из нее, потому что я думал о том, чтобы поместить фактическую ссылку в пункты меню «href», поэтому, если какой-то браузер пользователя не поддерживает javascript, он все равно будет работать. – Igor

+0

AJAX не собирается проваливаться к поведению, подобному ссылке, он ничего не сделает (в том числе не запускает полную загрузку страницы). Вам нужно откликнуться на полный HTML-документ (регулярный запрос GET roundtrip, например, по ссылке) или просто фрагмент для отображения (часть контента) во время запроса AJAX. Вы можете выполнить это с помощью флага GET на AJAX; просто опустите флаг из URL-адреса атрибута 'href', чтобы он попал на полную страницу. Затем на скрипте сервера определите, нужно ли вам отвечать либо полным HTML-документом, либо просто содержимым. –

+0

Просмотрите [это демо] (http://www.asp.net/ajaxLibrary/jQueryCodeSamplesWebForms/jQueryLoad/MainContentForm.aspx) с открытой консолью Firebug или Chrome, и когда запрос сделан для фрагмента страницы, просмотрите, что ответ текст был. Вы увидите, что это всего лишь фрагмент HTML, а не полный документ. –

1

Это работал на нас, мы сделали сайт, который использовал вертикальные вкладки и призвал на страницах с нашими Shadowbox изображениями с помощью jQuery.load

Просто дайте все ваши якоря тегам класса = «Sbox» и вставить это скрипт в заголовке.

<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 на всех наших отн = «Shadowbox» якорей, а также на якорь для вкладки, которая называется .load

Благодаря этому с помощью растяжек >http://www.webmuse.co.uk/blog/shadowbox-ajax-and-other-generated-content-with-jquery-and-javascript/

0

Ну, на основании ответа Шема, это мое решение. Каждый клик по определенному классу, настройки и открытого Shadowbox с элементами из того же класса:

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

Спасибо всем