【问题标题】:Returning HTML in the JS portion of a respond_to block throws errors in IE在 response_to 块的 JS 部分中返回 HTML 会在 IE 中引发错误
【发布时间】:2011-01-21 05:43:51
【问题描述】:

这是我的控制器操作中的一个常见模式:

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

即,如果请求不是 AJAX,我将在全新页面上的布局中发送 HTML 内容。如果请求 AJAX,我将发送相同的内容,但没有布局(以便可以将其插入现有页面或放入灯箱等)。

所以我总是在format.js 部分返回HTML,但Rails 将Content-Type 响应标头设置为text/javascript。这会导致 IE 抛出这个有趣的小错误消息:

alt text http://dl.dropbox.com/u/2792776/screenshots/Screen%20shot%202010-02-25%20at%205.13.49%20PM.png

当然,我可以在每次执行此操作时设置响应的内容类型(或使用after_filter 或其他),但似乎我正在尝试做一些相对标准的事情,我不想添加额外的样板代码。

我该如何解决这个问题?或者,如果解决问题的唯一方法是更改​​响应的内容类型,那么实现我想要的行为的最佳方法是什么(即,发送具有非 AJAX 布局的内容和没有布局的相同内容对于 AJAX)而不必处理这些错误?

编辑: This blog post has some more info

【问题讨论】:

  • 呵呵,看来行号准确度不是 IE 的强项……
  • @Nick Craver 你是说 IE 有强项吗?
  • 所以 Internet Explorer 将作为 text/javascript 返回的内容视为 text/javascript 是一个问题?
  • 是的,尽管潜在的问题似乎是 Rails 假设您总是希望发送 text/javascript 以响应从 javascript 发起的 HTTP 请求(我可能只是完全糊涂了)

标签: ruby-on-rails ajax internet-explorer content-type


【解决方案1】:

IE 无法将响应理解为 HTML。因此,要么更改响应的标头,要么测试将请求方法更改为 GET。

【讨论】:

    【解决方案2】:

    如果你想发回 HTML,你必须这样做:

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

    让 PrototypeJS 做它在前端所做的事情,你的 DOM id 会自动替换它的内容。请注意,replace 会将 DOM id 替换为该内容,replace_html 只会替换 innerHTML。

    【讨论】:

    • 不,我正在尝试将 HTML 发送回客户端(没有布局——因此 :layout => false
    • 好的,你的例子并不清楚你的意图。无论我是否更新了答案,您都需要按照指示使用 render(:update) 呈现 RJS 响应。
    【解决方案3】:

    问题的根源在于原型自动 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 帮助器以在没有 evalScripts:true 的情况下生成 JS
    如果您仍然需要评估某些部分的响应,请制作一个自定义的link_to_remote_no_eval 助手,它不会生成带有evalScripts:true 的JS,即:

    <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
    

    【讨论】:

    • 我没有使用原型(或任何 javascript 助手)。我正在使用 jQuery 并将我的 AJAX 请求的内容类型设置为 text/javascript 以触发 respond_to 块的 JS 部分
    • 最初的推理可能仍然适用于 jQuery,请确保您没有评估响应文本(将 dataType 参数设置为“html”可能会有所帮助)。
    • 我没有评估响应文本(我认为这样做会在所有浏览器(不仅仅是 IE)中产生错误)
    【解决方案4】:

    问题在于响应将Content-Type 标头作为text/javascript 发送,然后IE 尝试将其解释为javascript,因此缺少')' 错误消息。您需要服务器以 text/html 类型发送响应,以便浏览器不会尝试将响应内容作为脚本解析和执行,而是允许您将其用作 HTML 块。

    您可以在 Rails 中通过将以下内容添加到您的控制器之一来做到这一点:

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

    例如,您可以将其添加到您的应用程序控制器中,如下所示:

    class ApplicationController < ActionController::Base
      before_filter :fix_ct
      def fix_ct
        @headers["Content-Type"] = "text/html" 
      end    
    end
    

    【讨论】:

      【解决方案5】:

      过去我在 IE 上遇到过类似的问题。这是我的解决方法

      if request.xhr?
        render 'report', :layout => false
      else
        render 'report'
      end
      

      【讨论】:

        【解决方案6】:

        这对你有用吗?

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

        然后将响应调用为 HTML,而不是 JS (不过我还没有测试过。)

        基本上,request.xhr?是这个解决方案的关键

        【讨论】:

        • 同意——这里有一个更简洁的写法:render :layout =&gt; !request.xhr?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-05
        • 1970-01-01
        • 2013-03-21
        相关资源
        最近更新 更多