ujs + remotipaart - 当 运行 jQuery `.html(...)` 调用时,附加的 html 变为纯文本
ujs + remotipaart - when running jQuery `.html(...)` calls, the appended html becomes just text
我正在使用 rails 5,带有远程部分。远程版本为:
gem 'remotipart', github: 'mshibuya/remotipart'
(在这个问题的时刻,当前提交是 88d9a7d55bde66acb6cf3a3c6036a5a1fc991d5e)。
当我想提交具有 multipart: true and
remote: true` 但不发送任何附加文件 的表单时,效果很好。但是当我发送文件时,它失败了。
为了说明这个案例,请考虑这样的响应:
(function() {
modelErrors('<div class=\'alert alert-danger alert-dismissible\' role=\'alert\'>\n <div aria-label=\'Close\' class=\'close fade in\' data-dismiss=\'alert\'>\n <span aria-hidden>\n ×\n <\/span>\n <\/div>\n Code can\'t be blank\n<\/div>\n');
}).call(this);
当这个响应被执行时,到达后立即(因为它是 js),表单看起来像它预期的那样(在这种情况下,这个验证错误是正确的发生,并且呈现的危险警报是正确的出现这样的文字):
但是,当我填写文件字段并重复完全相同的情况(完全相同的验证错误)时,表单看起来完全不同:
如果您能猜到,内容是作为文本传递的。从服务器收到的实际响应有点不同:
<script type="text/javascript">try{window.parent.document;}catch(err){document.domain=document.domain;}</script>(function() {
modelErrors('<div class=\'alert alert-danger alert-dismissible\' role=\'alert\'>\n <div aria-label=\'Close\' class=\'close fade in\' data-dismiss=\'alert\'>\n <span aria-hidden>\n ×\n <\/span>\n <\/div>\n Code can\'t be blank\n<\/div>\n');
}).call(this);
这是我回复的实际正文(它不是一个糟糕的复制粘贴,而是 remotipart 包装的实际回复)。
modalErrors
函数相当愚蠢:
function modalErrors(html) {
$('#main-modal > .modal-dialog > .modal-content > .modal-body > .errors').html(html);
}
比较 jQuery 附加的 html 块(我在浏览器的 DOM 检查器中查找它们),它们看起来像这样:
好:
<div class="alert alert-danger" role="alert">
<ul style="list-style-type: none">
<li>Code can't be blank</li>
</ul>
</div>
差:
Code can't be blank
我在这里错过了什么?我想要的是允许我的响应在需要时附加 html 内容。
remotipart
库,它使用名为 iframe-transport
的东西,稍后解包内容并执行响应,就好像它是用 ajax.
获取的一样
但是,标签已从响应中剥离,因此响应将转换为如下内容:
try{window.parent.document;}catch(err){document.domain=document.domain;}(function() {
modelErrors('\n \n \n ×\n \n \n Code can\'t be blank\n\n');
}).call(this);
我发现以理智的方式与这个库交互的解决方案是定义另一个 helper helper,类似于 j
/ escape_javascript
:
module ApplicationHelper
JS_ESCAPE_MAP = {
'\' => '\\',
'<' => '\u003c',
'&' => '\u0026',
'>' => '\u003e',
"\r\n" => '\n',
"\n" => '\n',
"\r" => '\n',
'"' => '\u0022',
"'" => "\u0027"
}
JS_ESCAPE_MAP["200".force_encoding(Encoding::UTF_8).encode!] = '
'
JS_ESCAPE_MAP["201".force_encoding(Encoding::UTF_8).encode!] = '
'
def escape_javascript_with_inside_html(javascript)
if javascript
result = javascript.gsub(/(\|\r\n|200|201|[\n\r<>&"'])/u) {|match| JS_ESCAPE_MAP[match] }
javascript.html_safe? ? result.html_safe : result
else
''
end
end
alias_method :jh, :escape_javascript_with_inside_html
end
在容易被常规 ajax 和 remotipart 发送的视图中 - 在不同的情况下,我的意思是 - 只需将 j
调用替换为 jh
调用。示例:
modalErrors('<%= j render 'shared/model_errors_alert', instance: @team %>')
被替换为
modalErrors('<%= jh render 'shared/model_errors_alert', instance: @team %>')
我正在使用 rails 5,带有远程部分。远程版本为:
gem 'remotipart', github: 'mshibuya/remotipart'
(在这个问题的时刻,当前提交是 88d9a7d55bde66acb6cf3a3c6036a5a1fc991d5e)。
当我想提交具有 multipart: true and
remote: true` 但不发送任何附加文件 的表单时,效果很好。但是当我发送文件时,它失败了。
为了说明这个案例,请考虑这样的响应:
(function() {
modelErrors('<div class=\'alert alert-danger alert-dismissible\' role=\'alert\'>\n <div aria-label=\'Close\' class=\'close fade in\' data-dismiss=\'alert\'>\n <span aria-hidden>\n ×\n <\/span>\n <\/div>\n Code can\'t be blank\n<\/div>\n');
}).call(this);
当这个响应被执行时,到达后立即(因为它是 js),表单看起来像它预期的那样(在这种情况下,这个验证错误是正确的发生,并且呈现的危险警报是正确的出现这样的文字):
但是,当我填写文件字段并重复完全相同的情况(完全相同的验证错误)时,表单看起来完全不同:
如果您能猜到,内容是作为文本传递的。从服务器收到的实际响应有点不同:
<script type="text/javascript">try{window.parent.document;}catch(err){document.domain=document.domain;}</script>(function() {
modelErrors('<div class=\'alert alert-danger alert-dismissible\' role=\'alert\'>\n <div aria-label=\'Close\' class=\'close fade in\' data-dismiss=\'alert\'>\n <span aria-hidden>\n ×\n <\/span>\n <\/div>\n Code can\'t be blank\n<\/div>\n');
}).call(this);
这是我回复的实际正文(它不是一个糟糕的复制粘贴,而是 remotipart 包装的实际回复)。
modalErrors
函数相当愚蠢:
function modalErrors(html) {
$('#main-modal > .modal-dialog > .modal-content > .modal-body > .errors').html(html);
}
比较 jQuery 附加的 html 块(我在浏览器的 DOM 检查器中查找它们),它们看起来像这样:
好:
<div class="alert alert-danger" role="alert">
<ul style="list-style-type: none">
<li>Code can't be blank</li>
</ul>
</div>
差:
Code can't be blank
我在这里错过了什么?我想要的是允许我的响应在需要时附加 html 内容。
remotipart
库,它使用名为 iframe-transport
的东西,稍后解包内容并执行响应,就好像它是用 ajax.
但是,标签已从响应中剥离,因此响应将转换为如下内容:
try{window.parent.document;}catch(err){document.domain=document.domain;}(function() {
modelErrors('\n \n \n ×\n \n \n Code can\'t be blank\n\n');
}).call(this);
我发现以理智的方式与这个库交互的解决方案是定义另一个 helper helper,类似于 j
/ escape_javascript
:
module ApplicationHelper
JS_ESCAPE_MAP = {
'\' => '\\',
'<' => '\u003c',
'&' => '\u0026',
'>' => '\u003e',
"\r\n" => '\n',
"\n" => '\n',
"\r" => '\n',
'"' => '\u0022',
"'" => "\u0027"
}
JS_ESCAPE_MAP["200".force_encoding(Encoding::UTF_8).encode!] = '
'
JS_ESCAPE_MAP["201".force_encoding(Encoding::UTF_8).encode!] = '
'
def escape_javascript_with_inside_html(javascript)
if javascript
result = javascript.gsub(/(\|\r\n|200|201|[\n\r<>&"'])/u) {|match| JS_ESCAPE_MAP[match] }
javascript.html_safe? ? result.html_safe : result
else
''
end
end
alias_method :jh, :escape_javascript_with_inside_html
end
在容易被常规 ajax 和 remotipart 发送的视图中 - 在不同的情况下,我的意思是 - 只需将 j
调用替换为 jh
调用。示例:
modalErrors('<%= j render 'shared/model_errors_alert', instance: @team %>')
被替换为
modalErrors('<%= jh render 'shared/model_errors_alert', instance: @team %>')