【问题标题】:How to create jquery editable tables using Bootstrap's typeahead functionality如何使用 Bootstrap 的 typeahead 功能创建 jquery 可编辑表
【发布时间】:2014-08-26 04:56:17
【问题描述】:

我有两个单独工作的函数。第一个使用 Bootstrap 的 typeahead 功能。第二个允许在不进行提交或页面刷新的情况下编辑 HTML 表格单元格。我想要做的是结合两者而不为它编写一个全新的函数。例如:当用户双击表格单元格时,我希望启用预先输入的文本框,以便在他开始输入条目时,有效的条目开始显示在下面的菜单中。一旦用户做出选择,当焦点丢失时,底层数据库表将照常更新。

我想我可以像这样向“可编辑”添加一个事件:

cell.on('keydown', function() {$(".autofill").typeahead();});

但是没有运气:-(。有什么建议吗?下面是这两个函数的代码.... 顺便说一句,我使用的是 Bootstrap 版本 2.1.1 和 Jquery 1.8.3

$(document).ready(function(){

/************************************************************
              USING BOOTSTRAP'S TYPEAHEAD 
************************************************************/
$('.autofill').typeahead({
  source: function (query, process) {
    query = $(".autofill").val();
    link = 'ajax/gdata.aspx';
    sp = $(".autofill").attr("proc");
    src = $(".autofill").attr("src");
    if(!src) src = "No Source";

        $.get(link, {desc:query}, function(data) {
          var x = $.parseJSON(data);
          codes = [];
          map = {}; 
          $.each(x, function(i, cd) {
            map[cd.code_desc] = cd;
            codes.push(cd.code_desc);
            process(codes);
          });
        });
  },

  matcher: function(item) {
    if (item.toLowerCase().indexOf(this.query.trim().toLowerCase()) != -1) { 
      return true;
    }
  },

  sorter: function(items) {
    return items.sort();
  },

  highlighter: function(item) {
    var regex = new RegExp( '(' + this.query + ')', 'gi' );
    return item.replace( regex, "<b>$1</b>" );
  },

  updater: function(item) {
    d = $(".autofill").attr("show");
    selectedItem = map[item].code;
    if (d == 0) {
      return selectedItem;  //return code
    } else {
      return item;      //return description
    }
  }
});


/************************************************************
  Edit underlying table's column directly from HTML table.
        An editable field is highlighted in yellow
************************************************************/
$(".editable").dblclick(function() {
  var a = $.url().param("type");
  var b = $.url().param("id");
  var c = $.url().param("grpid");
  var d = $("input[name='step']").val();
  var e = $(this).attr("data-cap");
  var f = $(this).attr("data-ihtml");
  var m = "table";
  var warn = "#warn" + d;
  var id = $(this).attr("data-id");
  var type = $(this).attr("data-rec");
  var db = "MyDB";
  var tab = a + b + '_' + type;
  var column = $(this).attr("data-col");
  var idcol = $(this).attr("data-idcol");
  var idcolval = $(this).attr("data-idcolval");
  var cell = $(this);
  var cellWidth = cell.attr("width");
  var prevContent = cell.text();
  var URL = "ajax/p.aspx";
  var et = $(this).attr("entry-type");
  var s = $(this).attr("show");
  var src = $(this).attr("src");

  if(!src) {
    src = '""';
  }

  if(!s) {
    s = "1";
  }

  if(!e) {
    e = "Y";
  }

  if(!et) {
    et = "";
  }

  if(!f) {
    if(et == "") var f = '<input type="text" name="newValue" size="4" value="' + prevContent + '" id="txt' + id + '" />';
    if(et == "autofill") var f = '<input type="text" data-provide="typeahead" class="autofill" autocomplete="off" proc="1" show="' + s + '" name="newValue" size="4" value="' + prevContent + '" id="txt' + id + '" />';
  }

  var form = '<form action = "javascript: this.preventDefault">' + f + '</form>';
  var msg = "Changes will take effect immediately after moving off this cell!";

  $(warn).html('');
  $(warn).append('<div class="alert alert-warning">' + msg  + '</div>');
  cell.html(form).find('input[type=text]').focus().select().attr('width', cellWidth);
  cell.on('click', function() {return false;});
  cell.focusout(function() {
    var newContent = $("#txt" + id).val();
    var newVal = newContent;
    var g = f.slice(f.search("select"), 7);
    if (g == "select") {
      var h = "#txt" + id + " option:selected";
      newContent = $(h).text();
    }
    if (newContent == "") {
      cell.text(prevContent);
      return false;
    }
    if (newContent == prevContent) {
      cell.text(prevContent);
      return false;
    }

    if (e == "Y") {
      newVal = newVal.toUpperCase();
      newContent = newContent.toUpperCase();
    }

    var formData = 'type=' + a + '&id=' + b + '&grpid=' + c + '&modal=' + m + '&db=' + db + '&tab=' + tab + '&col=' + column + '&val=' + newVal + '&idcol=' + idcol + '&idcolval=' + idcolval + '&orig=' + prevContent + '&cap=' + e;

    $.ajax({
      url   : URL,
      type  : "POST",
      data  : formData,
      dataType  : "html"
    })
      .done(function(msg) {
    //console.log(msg);

    if(!msg) {
      $(warn).html('');
      $(warn).append('<div class="alert alert-success">' + "Record successfully updated!" + '</div>');
          //location.reload(true);
      cell.text(newContent);
    } else {
      $(warn).html('');
      $(warn).append('<div class="alert alert-error">' + msg + '</div>');
      cell.text(prevContent);
    }
    }); 
  });   
});

});

【问题讨论】:

  • 您是指 Bootstrap v2 的 typeahead 小部件,还是 Twitter 的 Typeahead.js 小部件?
  • Bootstrap v2 的小部件,而不是与 Bootstrap v3 一起使用的 Twitter 的 Typeahead.js ....

标签: jquery twitter-bootstrap autofill typeahead


【解决方案1】:

回答我自己的问题并不好玩,但我想我可以帮助某人在一个很少涉及的主题上节省数小时的挫败感。所以我想出了一个解决方法,它就像一个已经生产了两周的冠军,没有任何问题!首先颠倒执行顺序:首先启用预先输入,然后在更改时自动更新字段。其次,在 DOM 中添加一个隐藏字段来存储启用预输入的文本框的键值。最后,将这两个过程更改为函数:getData(e) 和 updateNow(e),它们可以在运行时调用。自动更新功能 UpdateNow(e) 将在使用其值更新数据库之前查找对隐藏字段(不是启用预输入的文本框)的更改。添加了其他数据属性以增强功能和通用可重用性,例如要求状态值列表取决于所选国家/地区代码的要求。这是修改后的代码:

/************************************************************
              USING BOOTSTRAP'S TYPEAHEAD 
************************************************************/
getData("#auto_idst");
getData("#auto_idctry");


function getData(elem) {
$(elem).typeahead({
  source: function (query, process) {
    var query = $(elem).val();
    var link = 'ajax/gdata.aspx';
    data_fld = $(elem).attr("data-fld");
    var src = $(elem).attr("src");
    var dependence = $(elem).attr("data-slave");
    if(!dependence) {dependence = "";}
    var ctry = $("#" + dependence).val();
    if(!ctry) {ctry = "";}
    if(!src) var src = 0;
    if(src == '3') {link = 'ajax/gdata.aspx?c=' + ctry;}

    $.get(link, {desc:query, src:src}, function(data) {
      var x = $.parseJSON(data);
      codes = [];
      map = {}; 
      $.each(x, function(i, cd) {
        map[cd.code_desc] = cd;
        codes.push(cd.code_desc);
        process(codes);
      });
    });
  },

  matcher: function(item) {
    if (item.toLowerCase().indexOf(this.query.trim().toLowerCase()) != -1) { 
      return true;
    }
  },

  sorter: function(items) {
    return items.sort();
  },

  highlighter: function(item) {
    var regex = new RegExp( '(' + this.query + ')', 'gi' );
    return item.replace( regex, "<b>$1</b>" );
  },

  updater: function(item) {
    d = $(elem).attr("show");
    selectedItem = map[item].code;

    if (d == 0) {
      $("#" + data_fld).val(selectedItem);
      $("#" + data_fld).trigger("change");
      return selectedItem;  //return code
    } else {
      $("#" + data_fld).val(item);
      $("#" + data_fld).trigger("change");
      return item;      //return description
    }
  }
});
};


/************************************************************
  Edit underlying table's column directly from HTML table.
************************************************************/

$(".now").on("change", function() {
 if ($(this).is(":checkbox")) {
    var id = $(this).attr("id");
    id = "#" + id;
  } else {
    var id = $(this).attr("data-id");
    id = "#" + id;
  }

  updateNow($(id));
});



$(this).on("focusout", function() {
  var val = $(this).val();
  val = $.trim(val);

  if (val == "") {
    var c = $(".now").val();
    $(this).val(c);
  }
});


function updateNow(e) {
  var t = e.attr("data-rec");
  var p = e.attr("data-fld");
  var warn = "#stat_" + p;
  var type = $.url().param("type");
  var id = $.url().param("id");
  var grpid = $.url().param("grpid");
  var db = e.attr("data-db");
  var tab = type + id + '_' + t;
  var col = e.attr("data-col");
  var idcol = e.attr("data-idcol");
  var idcolval = e.attr("data-idcolval");
  var oldval = e.attr("data-oldval");
  var URL = "ajax/p.aspx";
  var m = "table";

/*======================================================
  First find out if element is a checkbox.  If so, find
  out if it's checked.  If so, set newval to it's value;
  otherwise, set it to blank.
========================================================*/
   if (e.is(":checkbox")) {
    var chk = e.is(":checked");
    if (chk == "1") {
      var newval = e.val();
    } else {
      var newval = "";
      var control = "#" + e.attr("data-master");
      if (!control) {
        control = "";
      } else {
        $(control).attr("data-oldval", newval);
      }
    }
  } else if (e.is("select")) {
    var newval = "";
    var mm = $("#" + p + "_mm").val();
    var dd = $("#" + p + "_dd").val();
    var yy = $("#" + p + "_yy").val();
    var omm = $("#" + p + "_mm").attr("data-oldval");
    var odd = $("#" + p + "_dd").attr("data-oldval");
    var oyy = $("#" + p + "_yy").attr("data-oldval");

    if ((!mm) || (!dd) || (!yy)) {
      var newval = $("#" + p).val();
    }
    else {
      var sel_dt = 1;
      newval = mm + dd + yy;
      oldval = omm + odd + oyy;
    }
  } else {
      var newval = $("#" + p).val();
  }


  newval = newval.toUpperCase();
  var formData = 'type=' + type + '&id=' + id + '&grpid=' + grpid + '&modal=' + m + '&db=' + db + '&tab=' + tab + '&col=' + col + '&idcol=' + idcol + '&idcolval=' + idcolval + '&val=' + newval + '&orig=' + oldval;
  if((!db) || (!idcol) || (!idcolval)) return false;     

  $.ajax({
    url     : URL,
    type    : "POST",
    data    : formData,
    dataType    : "html"
  })
    .done(function(msg) {
    //console.log(msg);
    if(!msg) {
      $(warn).html('');
      var i = '<img src="assets/images/icon-good.png" />';
      $(warn).html(i);
      e.attr("data-oldval", newval);
      if (sel_dt == 1) {
        $("#" + p + "_mm").val(mm);
        $("#" + p + "_dd").val(dd);
        $("#" + p + "_yy").val(yy);
      } else { 
        e.val(newval); 
      }
    }
    else {
      $(warn).html('');
      var i = '<a href="#" title="' + msg + '"><img src="assets/images/icon-bad.png" /></a>';
      if (sel_dt == 1) {
        $("#" + p + "_mm").val(omm);
        $("#" + p + "_dd").val(odd);
        $("#" + p + "_yy").val(oyy);
      } else { 
        e.val(oldval);
      }
      $(warn).html(i);
    }
    }); 
};

你的 DOM 表应该有类似下面的内容:

<td><span id="stat_idctry"></span> ID Issuing Country:</td><td><input name="f4A_idctry" type="text" id="auto_idctry" class="autofill input-large" data-provide="typeahead" autocomplete="off" maxlength="50" data-db="1" data-col="id_iss_ctry" data-idcol="seq" data-idcolval="1" data-rec="4A" data-fld="idctry" data-oldval="" show="0" src="1" value="" /><input type="hidden" name="h_idctry" id="idctry" data-id="auto_idctry" class="now" value="" /></td>
<td><span id="stat_idst"></span> ID Issuing State:</td><td><input name="f4A_idst" type="text" id="auto_idst" class="autofill input-mini" data-provide="typeahead" autocomplete="off" maxlength="15" data-db="1" data-col="id_iss_st" data-oldval="" data-idcol="seq" data-idcolval="1" data-rec="4A" data-fld="idst" show="0" src="3" data-slave="idctry" value="" /><input type="hidden" name="h_idst" id="idst" data-id="auto_idst" class="now" value="" /></td>

关于此处使用的数据属性的一些说明。要使 typeahead 使用上面的 getData(e) 函数工作,您必须使用 class="autofill"、data-provide="typeahead",并且 src 必须有一个值。在我的实现中, src 属性用作后端存储过程的参数,将所需数据拉入文本框。这样做,允许我对多种类型的预输入文本框使用一个存储过程,并使用相同的 ajax URL 链接。设置 autocomplete="off" 可防止现代浏览器在用户键入值时使用以前为用户使用的值自动完成文本框。设置 show="0" 强制文本框显示键值而不是显示的描述。 show 的“0”以外的值将在文本框中显示选定的描述,在我需要代码而不是描述的情况下为我提供一定程度的灵活性。 data-slave 属性被 typeahead 用来设置一个附加参数,以根据 data-slave 属性指示的文本框中的值来获取依赖文本框中的正确数据。

对于自动更新,您必须将隐藏字段的类设置为“现在”,并将数据 ID 设置为更新其值的预输入文本框的相同 ID。这允许自动更新功能查看预先输入文本框中的其他关键数据属性,例如:data-db、data-col、data-idcol、data-idcolval 和 data-rec。是的,我确实可以将额外的数据属性添加到隐藏字段中,但这需要我必须从原始文本框中剪切并粘贴必要的数据属性到隐藏字段中。无论哪种方式都可以,但如果这样做,请确保将这段代码更改为:

$(".now").on("change", function() {
 if ($(this).is(":checkbox")) {
    var id = $(this).attr("id");
    id = "#" + id;
  } else {
    var id = $(this).attr("id");
    id = "#" + id;
  }

  updateNow($(id));
});

【讨论】:

    猜你喜欢
    • 2011-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-30
    • 1970-01-01
    • 2013-09-13
    • 1970-01-01
    相关资源
    最近更新 更多