Rumah hujung hadapan web tutorial js 利用 jQuery Clone进行复制操作

利用 jQuery Clone进行复制操作

May 14, 2018 pm 02:47 PM
clone jquery guna salinan kelakuan

最近客串了一把前端,有行复制的功能用 jQuery 来实现了。感觉比以前原生js用 CreateElement 要简单多了,但还是遇到了一些陷阱比如IE7的bug,这里记录下来。先看看 table 的样子:这里3行是一组,按下"Copy"连值复制,按下"Add"只增加行不复制值。calendar 使用的是 jQuery UI 里的 datepicker 
下图只是一个简单的demo,没有复杂的样式表:

为了灵活对应不同的表格,提取了一个共通的 js 来处理,作为使用前提:
1. table 必须有 id;
2. 有 id 的 tr 才会被复制;(tr的id从1开始编号)
3. table 内所有id都必须以 xxx_n 编号

function RowCopyUtility(opts) {
  // 表格Id
  this.tableId = opts.tableId;
  // 分组内有多少行
  this.rowGroupNumber = opts.rowGroupNumber;
  // 一组内Button对应的方法Map(key=Button value, value=对应方法名)
  // 所有方法都应以 function (idx) 方式调用
  this.buttonHandlers = opts.buttonHandlers;
  
  this._countForRowsGroup = -1;
  this._keyForRow = -1;

  this.getTargetRowGroup = function(groupIdx) {

    var rows = [];
    if (groupIdx > 0) {
      for(var i=1; i<this.rowGroupNumber+1; i++) {
        rows[i-1] = $("#row" + i + "_" + groupIdx);
      }
    } else {
      for(var i=0; i<this.rowGroupNumber; i++) {
        rows[i] = $("#" + this.tableId + " tr[id]").eq(i);
      }
    }
    return rows;
  };

  this.addRow = function (groupIdx, needCopyValue) {

    if (this._countForRowsGroup == -1) {
      this._countForRowsGroup = ($("#" + this.tableId + " tr[id]").length - 1)/this.rowGroupNumber;
      this._keyForRow =  parseInt($("#" + this.tableId + " tr[id]:not(#row_add):last").attr("id").split("_")[1]) + 1;
    }

    if (groupIdx == 0) {
      var firstRow = $("#" + this.tableId + " tr[id]:first");
      var currentIdx = firstRow.attr("id").split("_")[1];
      groupIdx = currentIdx;
    }

    var regForId = new RegExp("^(\\w+_)" + groupIdx + "$");
    var regForName = new RegExp("^(\\w+_)" + groupIdx + "$");
    var regForRadioId = new RegExp("^(\\w+_)" + groupIdx + "(.*)$");

    var targetRows = this.getTargetRowGroup(groupIdx);

    // 重要:注意闭包参数的作用域
    var idx = this._keyForRow;

    for(var i=0; i<targetRows.length; i++) {
      // clone target rows
      var cloneRow = targetRows[i].clone(false);
      var newRowId = cloneRow.attr("id").split("_")[0] + "_" + idx;
      cloneRow.attr("id", newRowId);

      var radios = [];
      cloneRow.find("[id]").each(function() {
          var id = $(this).attr("id");
          var oldId = id;
          var name = $(this).attr("name");
         
          id = id.replace(regForId, "$1" + idx);
          $(this).attr("id", id);
         
          var newname = name.replace(regForName, "$1" + idx);
          $(this).attr("name", newname);
          
          if ($(this).hasClass("hasDatepicker")) {
          	  $(this).removeClass("hasDatepicker");
          }
         
          if ($(this).attr("type") == "checkbox") {
              if($(this).next().attr("for") != "") {
                  $(this).next().attr("for", id);
              }
              if (!needCopyValue) {
            	  $(this).attr("checked", "");
              }
          }
          else if ($(this).attr("type") == "radio") {           
              id = id.replace(regForRadioId, "$1" + idx);
              $(this).attr("id", id);
         
              var radio = new Object();
              radio.id = id;
              radio.oldId = oldId;
              radio.name = name;
              radio.newname = newname;
              // IE7&#39;s Bug
              radio.checked = document.getElementById(oldId).checked;
              radios[radios.length] = radio;
         
              if($(this).next().attr("for") != "") {
                  $(this).next().attr("for", id);
              }
            
              if (!needCopyValue) {
            	  $(this).attr("checked", "");
              }
          }
          else if ($(this).attr("tagName") == "SELECT") {
	          if (needCopyValue) {
	          	  $(this).val(document.getElementById(oldId).value);
	          }
          }
          else if ($(this).attr("tagName") == "TEXTAREA" || 
                   $(this).attr("type") == "text" || 
                   $(this).attr("type") == "hidden") {
	          if (!needCopyValue) {
	              $(this).val("");
	          }
          }
      });

      // insert into document
      cloneRow.insertBefore("#" + this.tableId + " tr:last");

      // replace name for radio
      for(var n=0; n<radios.length; n++) {
         document.getElementById(radios[n].id).outerHTML =
           document.getElementById(radios[n].id).outerHTML.replace(radios[n].name, radios[n].newname);
         // IE7&#39;s Bug
         document.getElementById(radios[n].oldId).checked = radios[n].checked;
      }

      // Event Handler
      var maps = this.buttonHandlers;
      cloneRow.find("input:button").each(function() {
         var value = $(this).attr("value");
        
         var funcName = maps[value];
         if (funcName != undefined) {         
	         var func = null;
	         func = function() { eval(funcName + "(" + idx + ")"); };
	         	
	         if (func != null) {
	           $(this).attr("onclick", "");
	           $(this).unbind("click");
	           $(this).attr("onclick", "").click(func);
	         }
         }
      });
    }

    this._countForRowsGroup++;
    this._keyForRow++;
   
  };


  this.copyRow = function(groupIdx) {
    this.addRow(groupIdx, true);
  };

  this.deleteRow = function(groupIdx) {

    if (this._countForRowsGroup == -1) {
      this._countForRowsGroup = ($("#" + this.tableId + " tr[id]").length - 1)/this.rowGroupNumber;
      this._keyForRow =  parseInt($("#" + this.tableId + " tr[id]:not(#row_add):last").attr("id").split("_")[1]) + 1;
    }

    var allRows = $("#" + this.tableId + " tr[id]");
    var miniRowsCount = this.rowGroupNumber + 1;
    var tbl = $("#" + this.tableId);

    if (allRows.length == miniRowsCount) {
      tbl.find("input:text").each(function() { $(this).val(""); });
      tbl.find("textarea").each(function() { $(this).val(""); });
      tbl.find("input:hidden").each(function() { $(this).val(""); });
      tbl.find("input:radio").each(function() { $(this).attr("checked", ""); });
      tbl.find("input:checkbox").each(function() { $(this).attr("checked", ""); });
      tbl.find("select").each(function() { document.getElementById($(this).attr("id")).selectedIndex = 0; });
      tbl.find(".fg-common-field-errored").each(function() {
        $(this).removeClass("fg-common-field-errored");
      });
      return;
    }

    for(var i=1; i<this.rowGroupNumber+1; i++) {
      tbl.find("#row" + i + "_" + groupIdx).remove();
    }

    this._countForRowsGroup--;
  };

}
Salin selepas log masuk

实际遇到的问题与解决办法:
1. jQuery 的 Clone() 方法,就算传入 false,元素的事件依然会被复制过来。(IE测试)
2. attr("name", name); 在IE中,不会直接替换掉,而是生成 submitName 保存。在 IE7 里 radio 会因为 name 相同而出现问题。
3. 在大量的匿名方法中,特别要注意闭包封送参数的作用域。
4. IE7里的Bug:在radio被复制时,原来的元素的选择值就没了。因此在复制前保存了复制源的radio属性,加入document之后再次设定:

// replace name for radio
for(var n=0; n<radios.length; n++) {
   document.getElementById(radios[n].id).outerHTML =
     document.getElementById(radios[n].id).outerHTML.replace(radios[n].name, radios[n].newname);
   // IE7&#39;s Bug
   document.getElementById(radios[n].oldId).checked = radios[n].checked;
}
Salin selepas log masuk

5. jQuery里清除事件单独用 attr("onclick", "") 并不好用;后期用 click(function) 绑定的事件用 unbind("click") 可以移除。

if (func != null) {
  $(this).attr("onclick", "");
  $(this).unbind("click");
  $(this).attr("onclick", "").click(func);
}
Salin selepas log masuk

6. jQuery UI 的 DatePicker 当创建了 datepicker 之后,可以通过 hasClass("hasDatepick") 判断是否存在,否则在复制之后有问题。
(多次复制之后 datepicker settings 会莫名其妙丢失)

7. 其他,剩下就是要注意 jQuery 选择器不要过度使用了,越复杂的表达式效率越低。
顺便推荐看一下:15个值得开发人员关注的jQuery开发技巧和心得

还要说下IE9 的 debug 工具真心不错,提高不少开发效率哦一定要利用。

就这些,希望能对大家有帮助。最后附上,测试用的 html:

<html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Cache-Control" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<style>
body{font-family:&#39;Open Sans&#39;,arial,sans-serif;}
tr{height:30px}
input.button{width:60px}
table.main {
	border-width: 2px;
	border-spacing: 1px;
	border-style: solid;
	border-color: gray;
	border-collapse: collapse;
	background-color: white;
}
table.main th {
	border-width: 1px;
	padding: 5px;
	border-style: inset;
	border-color: gray;
	background-color: #f0f0f0;
	-moz-border-radius: ;
}
table.main td {
	border-width: 1px;
	padding: 5px;
	border-style: inset;
	border-color: gray;
	background-color: white;
	-moz-border-radius: ;
}
</style>

<script type="text/javascript" language="JavaScript" src="jquery.js"></script>
<script type="text/javascript" language="JavaScript" src="jquery-ui.js"></script>
<script type="text/javascript" language="JavaScript" src="rowCopyUtil.js"></script>
<link rel="stylesheet" href="jquery-ui.css" type="text/css" media="all" />
<link type="text/css" href="jqueryCalendarStyle.css" rel="stylesheet" />

<script type="text/javascript" >
 var rowUtil = new RowCopyUtility(
    {
      tableId: "tab1",
      rowGroupNumber: 3,
      buttonHandlers: {"Copy":"copyRows", "Delete":"deleteRows", "calendar":"showDatepicker", "some button":"someButtonClick"}
    }
 );
   
 function showDatepicker(idx) {
      var textId = "#calendar_" + idx;
      if (!$(textId).hasClass("hasDatepicker")) {
		  var text = $(textId).datepicker({
		    showOn : "calendar",
		    dateFormat : "yy/mm/dd"
		  });
	  }
	  $(textId).datepicker(&#39;show&#39;);
 }
 
 function addRows() {
    rowUtil.addRow(0, false);
 }
 function copyRows(idx) {
    rowUtil.copyRow(idx);
 }
 function deleteRows(idx) {
    rowUtil.deleteRow(idx);
 }
 function someButtonClick(idx) {
    alert(idx);
 }
</script>
</head>
<body>
  <table id="tab1" class="main">
    <tr>
       <th>Header1</th>
       <th>Header2</th>
       <th>Header3</th>
       <th>Header4</th>
    </tr>
    <tr id="row1_0">
       <td rowspan="3" >
           <input class="button" type="button" value="Copy" onclick="copyRows(0);" />
           <input class="button" type="button" value="Delete" onclick="deleteRows(0);" />
       </td>
       <td>text:<input type="text" id="text_0" /></td>
       <td>
           <input type="radio" name="radioAB_0" id="radioA_0" value="1" /><label for="radioA_0">Raido_A </label>
           <input type="radio" name="radioAB_0" id="radioB_0" value="2" /><label for="radioB_0">Radio_B </label>
       </td>
       <td>
           <select id="select_0">
              <option value="0">---select---</option>
              <option value="1">select option1</option>
              <option value="2">select option2</option>
           </select>
       </td>
    </tr>
    <tr id="row2_0">
      <td>
          <input type="checkbox" id="checkA_0" /><label for="checkA_0">Check_A </label>
          <input type="checkbox" id="checkB_0" /><label for="checkB_0">Check_B </label>
      </td>
      <td colspan="2">
        <input type="text" id="calendar_0" style="width:90px"/><input type="button" value="calendar" onclick="showDatepicker(0);" />
        <input type="button" value="some button" onclick="someButtonClick(0);" />
      </td>
    </tr>
    <tr id="row3_0">
      <td colspan="3">
        textarea:<textarea id="textarea_0" style="width:100%"></textarea>
      </td>
    </tr>
    <tr id="row_add">
      <td colspan="4">
      	<input class="button" type="button" value="Add" onclick="addRows();" />
      </td>
    </tr>
  </table>
</body>

</html>
Salin selepas log masuk

Atas ialah kandungan terperinci 利用 jQuery Clone进行复制操作. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Bagaimana untuk menyalin lirik dari QQ Music Bagaimana untuk menyalin lirik Bagaimana untuk menyalin lirik dari QQ Music Bagaimana untuk menyalin lirik Mar 12, 2024 pm 08:22 PM

Kami pengguna seharusnya dapat memahami kepelbagaian beberapa fungsi apabila menggunakan platform ini Kami tahu bahawa lirik beberapa lagu ditulis dengan sangat baik. Kadang-kadang kita mendengarnya beberapa kali dan merasakan maknanya sangat mendalam, jadi jika kita ingin memahami maksudnya, kita ingin menyalinnya secara langsung dan menggunakannya sebagai copywriting masih perlu Anda hanya perlu belajar bagaimana untuk menyalin lirik Saya percaya bahawa semua orang sudah biasa dengan operasi ini, tetapi ia memang agak sukar untuk beroperasi pada telefon bimbit Jadi untuk memberi anda pemahaman yang lebih baik, hari ini editor ada di sini untuk membantu anda. Penjelasan yang baik tentang beberapa pengalaman operasi di atas. ,

Bagaimana untuk menggunakan kaedah permintaan PUT dalam jQuery? Bagaimana untuk menggunakan kaedah permintaan PUT dalam jQuery? Feb 28, 2024 pm 03:12 PM

Bagaimana untuk menggunakan kaedah permintaan PUT dalam jQuery? Dalam jQuery, kaedah menghantar permintaan PUT adalah serupa dengan menghantar jenis permintaan lain, tetapi anda perlu memberi perhatian kepada beberapa butiran dan tetapan parameter. Permintaan PUT biasanya digunakan untuk mengemas kini sumber, seperti mengemas kini data dalam pangkalan data atau mengemas kini fail pada pelayan. Berikut ialah contoh kod khusus menggunakan kaedah permintaan PUT dalam jQuery. Mula-mula, pastikan anda memasukkan fail perpustakaan jQuery, kemudian anda boleh menghantar permintaan PUT melalui: $.ajax({u

Bagaimana untuk mengalih keluar atribut ketinggian elemen dengan jQuery? Bagaimana untuk mengalih keluar atribut ketinggian elemen dengan jQuery? Feb 28, 2024 am 08:39 AM

Bagaimana untuk mengalih keluar atribut ketinggian elemen dengan jQuery? Dalam pembangunan bahagian hadapan, kita sering menghadapi keperluan untuk memanipulasi atribut ketinggian elemen. Kadangkala, kita mungkin perlu menukar ketinggian unsur secara dinamik, dan kadangkala kita perlu mengalih keluar atribut ketinggian unsur. Artikel ini akan memperkenalkan cara menggunakan jQuery untuk mengalih keluar atribut ketinggian elemen dan memberikan contoh kod khusus. Sebelum menggunakan jQuery untuk mengendalikan atribut ketinggian, kita perlu terlebih dahulu memahami atribut ketinggian dalam CSS. Atribut ketinggian digunakan untuk menetapkan ketinggian elemen

Petua jQuery: Cepat ubah suai teks semua teg pada halaman Petua jQuery: Cepat ubah suai teks semua teg pada halaman Feb 28, 2024 pm 09:06 PM

Tajuk: Petua jQuery: Cepat ubah suai teks semua teg pada halaman Dalam pembangunan web, kita selalunya perlu mengubah suai dan mengendalikan elemen pada halaman. Apabila menggunakan jQuery, kadangkala anda perlu mengubah suai kandungan teks semua teg dalam halaman sekaligus, yang boleh menjimatkan masa dan tenaga. Berikut akan memperkenalkan cara menggunakan jQuery untuk mengubah suai teks semua teg pada halaman dengan cepat, dan memberikan contoh kod khusus. Pertama, kita perlu memperkenalkan fail perpustakaan jQuery dan memastikan bahawa kod berikut dimasukkan ke dalam halaman: &lt

Apakah yang perlu saya tambahkan pada kekunci pintasan salin ctrl? Apakah yang perlu saya tambahkan pada kekunci pintasan salin ctrl? Mar 15, 2024 am 09:57 AM

Dalam sistem Windows, kekunci pintasan untuk menyalin ialah Ctrl+C dalam sistem Apple, kekunci pintasan untuk menyalin ialah Command+C dalam sistem Linux, kekunci pintasan untuk menyalin ialah Ctrl+Shift+C; Mengetahui kekunci pintasan ini boleh meningkatkan kecekapan kerja pengguna dan memudahkan operasi penyalinan teks atau fail.

Bagaimana untuk menyalin jadual dalam Excel dan mengekalkan format asal? Bagaimana untuk menyalin jadual dalam Excel dan mengekalkan format asal? Mar 21, 2024 am 10:26 AM

Kami sering menggunakan Excel untuk memproses berbilang data jadual Selepas menyalin dan menampal jadual yang ditetapkan, format asal kembali kepada lalai, dan kami perlu menetapkannya semula. Malah, terdapat cara untuk menyalin jadual dalam Excel dan mengekalkan format asal Editor akan menerangkan kaedah khusus di bawah. 1. Langkah operasi menyeret dan menyalin kekunci Ctrl: Gunakan kekunci pintasan [Ctrl+A] untuk memilih semua kandungan jadual, dan kemudian gerakkan kursor tetikus ke tepi jadual sehingga kursor bergerak muncul. Tekan dan tahan kekunci [Ctrl], dan kemudian seret jadual ke kedudukan yang dikehendaki untuk melengkapkan pergerakan. Perlu diingatkan bahawa kaedah ini hanya berfungsi pada satu lembaran kerja dan tidak boleh dialihkan antara lembaran kerja yang berbeza. 2. Langkah-langkah untuk menampal terpilih: Tekan kekunci pintasan [Ctrl+A] untuk memilih semua jadual, dan tekan

Gunakan jQuery untuk mengubah suai kandungan teks semua teg Gunakan jQuery untuk mengubah suai kandungan teks semua teg Feb 28, 2024 pm 05:42 PM

Tajuk: Gunakan jQuery untuk mengubah suai kandungan teks semua teg jQuery ialah perpustakaan JavaScript yang popular yang digunakan secara meluas untuk mengendalikan operasi DOM. Dalam pembangunan web, kita sering menghadapi keperluan untuk mengubah suai kandungan teks tag pautan (tag) pada halaman. Artikel ini akan menerangkan cara menggunakan jQuery untuk mencapai matlamat ini dan memberikan contoh kod khusus. Pertama, kita perlu memperkenalkan perpustakaan jQuery ke dalam halaman. Tambahkan kod berikut dalam fail HTML:

Bagaimana untuk membuat sandaran fail pangkalan data CMS DreamWeaver? Bagaimana untuk membuat sandaran fail pangkalan data CMS DreamWeaver? Mar 13, 2024 pm 06:09 PM

Bagaimana untuk membuat sandaran fail pangkalan data CMS DreamWeaver? Dalam proses menggunakan CMS untuk membina laman web, adalah sangat penting untuk memastikan keselamatan fail pangkalan data untuk mengelakkan kehilangan atau kerosakan data. Menyandarkan fail pangkalan data ialah operasi penting Perkara berikut akan memperkenalkan cara menyandarkan fail pangkalan data CMS DreamWeaver dan melampirkan contoh kod tertentu. 1. Gunakan phpMyAdmin untuk sandaran phpMyAdmin ialah alat pengurusan pangkalan data yang biasa digunakan di mana anda boleh membuat sandaran pangkalan data dengan mudah. Berikut adalah menggunakan phpMyAdm

See all articles