Возврат HTML в JS-части блока response_to приводит к ошибкам в IE - PullRequest
7 голосов
/ 26 февраля 2010

Вот типичный пример действий моего контроллера:

respond_to do |format|
  format.html {}
  format.js {
    render :layout => false
  }
end

Т.е., если запрос не AJAX, я отправлю содержимое HTML в макете на новую страницу. Если запрос - AJAX, я отправлю тот же контент, но без макета (чтобы его можно было вставить на существующую страницу или поместить в лайтбокс или что-то еще).

Так что я всегда возвращаю HTML в части format.js, но Rails устанавливает заголовок ответа Content-Type равным text/javascript. Это приводит к тому, что IE выдает это забавное маленькое сообщение об ошибке:

альтернативный текст http://dl.dropbox.com/u/2792776/screenshots/Screen%20shot%202010-02-25%20at%205.13.49%20PM.png

Конечно, я мог бы задавать тип содержимого ответа каждый раз, когда я делал это (или использовать after_filter или что-то еще), но мне кажется, что я пытаюсь сделать что-то относительно стандартное и не хочу добавить дополнительный шаблонный код.

Как мне исправить эту проблему? В качестве альтернативы, если единственный способ решить проблему - это изменить тип содержимого ответа, каков наилучший способ достижения желаемого поведения (т. Е. Отправка содержимого с макетом для не-AJAX и того же контента без макета для AJAX), не имея дело с этими ошибками?

Редактировать: Эта запись блога содержит дополнительную информацию

Ответы [ 6 ]

6 голосов
/ 11 марта 2010

Это работает для вас?

respond_to do |format|
  format.html { :layout => false if request.xhr? }
  format.js {}
end

А затем вызовите ответ как HTML, а не как JS (Я не проверял это все же.)

По сути, request.xhr? ключ к этому решению

1 голос
/ 05 марта 2010

Проблема в том, что ответ отправляет заголовок Content-Type как text/javascript, который IE затем пытается интерпретировать как javascript, отсюда и отсутствующее сообщение об ошибке ')'. Вам необходимо, чтобы сервер отправил ответ с типом text/html, чтобы браузер не пытался анализировать и выполнять содержимое ответа в виде сценария, но позволял бы использовать его как блок HTML.

Вы можете сделать это в Rails, добавив что-то вроде следующего к одному из ваших контроллеров:

@headers["Content-Type"] = "text/html"

Например, вы можете добавить это в свой Application Controller следующим образом:

class ApplicationController < ActionController::Base
  before_filter :fix_ct
  def fix_ct
    @headers["Content-Type"] = "text/html" 
  end    
end
0 голосов
/ 10 марта 2010

в прошлом я сталкивался с подобными проблемами с IE. вот как я это решил

if request.xhr?
  render 'report', :layout => false
else
  render 'report'
end
0 голосов
/ 04 марта 2010

В основе вашей проблемы лежит прототип Автоматическая оценка ответов JavaScript: http://api.prototypejs.org/ajax/ajax/request.html
Ваши link_to_remote звонки генерируют кусок js, похожий на:

<a href="#" onclick="
    new Ajax.Updater('posts', '/blog/destroy/3', {
      asynchronous:true, 
      evalScripts:true
    }); return false;
">Delete this post</a>

Если вам не нужно оценивать ответ нигде в вашем приложении, вы можете глобально переопределить помощник link_to_remote для генерации JS без evalScripts:true
Если вам все еще нужно оценить ответ в некоторых частях, создайте пользовательский помощник link_to_remote_no_eval, который не генерирует JS с evalScripts:true, то есть:

<a href="#" onclick="
    new Ajax.Updater('posts', '/blog/destroy/3', {
      asynchronous:true
    }); return false;
">Delete this post</a>

Редактировать

В таком случае, почему бы не использовать пользовательский тип контента?

Mime::Type.register "text/html-piece", :html_piece
# add to view in jquery call instead of "text/javascript"
# then in your controller action
def show
  respond_to do |format|
    format.html { }
    format.html_piece { } # no longer js mime so no IE error
  end
end
0 голосов
/ 04 марта 2010

Если вы пытаетесь отправить обратно HTML, вам нужно сделать:

render(:update) do |page|
  page['someDomId'].replace/replace_html(render(:partial => '/partial/path'))
end

Позвольте PrototypeJS делать то, что он делает на внешнем интерфейсе, и вашему идентификатору DOM будет автоматически заменено его содержимое. Обратите внимание, что replace будет заменять идентификатор DOM этим содержимым, replace_html будет заменять только innerHTML.

0 голосов
/ 26 февраля 2010

IE не понимает ответ как HTML. Так что вы либо меняете заголовок ответа, либо тестируете, меняете метод запроса на GET.

...