bjui-tabledit.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. /*!
  2. * B-JUI v1.2 (http://b-jui.com)
  3. * Git@OSC (http://git.oschina.net/xknaan/B-JUI)
  4. * Copyright 2014 K'naan (xknaan@163.com).
  5. * Licensed under Apache (http://www.apache.org/licenses/LICENSE-2.0)
  6. */
  7. /* ========================================================================
  8. * B-JUI: bjui-tabledit.js v1.2
  9. * @author K'naan (xknaan@163.com)
  10. * -- Modified from dwz.database.js (author:ZhangHuihua@msn.com)
  11. * http://git.oschina.net/xknaan/B-JUI/blob/master/BJUI/js/bjui-tabledit.js
  12. * ========================================================================
  13. * Copyright 2014 K'naan.
  14. * Licensed under Apache (http://www.apache.org/licenses/LICENSE-2.0)
  15. * ======================================================================== */
  16. +function ($) {
  17. 'use strict';
  18. // TABLEDIT CLASS DEFINITION
  19. // ======================
  20. var Tabledit = function(element, options) {
  21. this.$element = $(element)
  22. this.options = options
  23. this.tools = this.TOOLS()
  24. this.$tbody = this.$element.find('> tbody')
  25. if (!this.$tbody.length) {
  26. this.$tbody = $('<tbody></tbody>')
  27. this.$element.append(this.$tbody)
  28. }
  29. this.$numAdd =
  30. this.$btnAdd = null
  31. }
  32. Tabledit.DEFAULTS = {
  33. singleNoindex : true
  34. }
  35. Tabledit.EVENTS = {
  36. afterDelete: 'afterdelete.bjui.tabledit'
  37. }
  38. Tabledit.prototype.TOOLS = function() {
  39. var that = this
  40. var tools = {
  41. initSuffix: function($tbody) {
  42. var $trs = $tbody.find('> tr')
  43. $trs.each(function(i) {
  44. var $tr = $(this)
  45. $tr.find(':input, :file, a, label, div').each(function() {
  46. var $child = $(this),
  47. name = $child.attr('name'),
  48. val = $child.val(),
  49. fors = $child.attr('for'),
  50. id = $child.attr('id'),
  51. href = $child.attr('href'),
  52. group = $child.attr('data-group'),
  53. suffix = $child.attr('data-suffix')
  54. if (name) $child.attr('name', name.replaceSuffix(i))
  55. if (fors) $child.attr('for', fors.replaceSuffix(i))
  56. if (id) $child.attr('id', id.replaceSuffix(i).replaceSuffix2(i))
  57. if (href) $child.attr('href', href.replaceSuffix(i))
  58. if (group) $child.attr('data-group', group.replaceSuffix(i))
  59. if (suffix) $child.attr('data-suffix', suffix.replaceSuffix(i))
  60. if (val && val.indexOf('#index#') >= 0) $child.val(val.replace('#index#', i + 1))
  61. if ($child.hasClass('no')) {
  62. var prefix = $child.data('prefix') ? $child.data('prefix') : ''
  63. $child.val(prefix + (i + 1))
  64. }
  65. })
  66. })
  67. },
  68. // Enter for Tab
  69. initEnter: function($tbody) {
  70. var $texts = $tbody.find(':text')
  71. $texts.each(function(i) {
  72. $(this).bind('keydown', function (e) {
  73. if (e.which == BJUI.keyCode.ENTER) {
  74. var nexInd = i + 1
  75. if ($texts.eq(nexInd)) {
  76. $texts.eq(nexInd).focus()
  77. }
  78. e.preventDefault()
  79. }
  80. })
  81. })
  82. this.initInput($tbody)
  83. },
  84. initInput: function($tbody) {
  85. $tbody.find('> tr > td').each(function() {
  86. var $span = $(this).find('.input-hold')
  87. if (!$span.length) {
  88. $span = $('<span class="input-hold" style="display:block; padding:0 4px; height:0px; font-size:12px; visibility:hidden;"></span>')
  89. $(this).append($span)
  90. }
  91. if (!$.support.leadingWhitespace) { // for ie8
  92. $(this).on('propertychange', ':text', function(e) {
  93. $span.text($(this).val())
  94. })
  95. } else {
  96. $(this).on('input', ':text', function(e) {
  97. $span.text($(this).val())
  98. })
  99. }
  100. })
  101. },
  102. initTbody: function() {
  103. var $table = that.$element,
  104. $tbody = that.$tbody
  105. $tbody.find('> tr').each(function() {
  106. var $tr = $(this), $tds = $tr.find('> td'), $ths = $table.data('bjui.tabledit.tr').clone().find('> th')
  107. $tr.data('bjui.tabledit.oldTds', $tr.html())
  108. $ths.each(function(i) {
  109. var $td = $tds.eq(i), val = $td.data('val'),
  110. $th = $(this), $child = $th.children(), $pic = $th.find('.pic-box')
  111. if (typeof val == 'undefined') val = $td.html()
  112. if (!$td.data('noedit')) {
  113. if ($child.length) {
  114. if ($child.is('input:checkbox') || $child.is('input:radio')) {
  115. $child.filter('[value="'+ val +'"]').attr('checked', 'checked')
  116. } else if ($child.isTag('select')) {
  117. $child.find('option[value="'+ $td.data('val') +'"]').attr('selected', 'selected')
  118. } else if ($pic.length) {
  119. if ($td.data('val')) $th.find('.pic-name').val($td.data('val'))
  120. $pic.html($td.html())
  121. } else if ($child.hasClass('wrap_bjui_btn_box')) {
  122. $child.find('input[data-toggle]').attr('value', val +'')
  123. } else if ($child.is('textarea')) {
  124. $child.html(val)
  125. if ($child.attr('data-toggle') == 'kindeditor') {
  126. $child.attr('data-toggle-old', 'kindeditor').removeAttr('data-toggle')
  127. }
  128. } else {
  129. $child.attr('value', val +'')
  130. }
  131. $td.html($th.html())
  132. }
  133. }
  134. })
  135. $tr.on('dblclick', $.proxy(function(e) { _doEdit($tr) }, that)).initui()
  136. that.tools.initSuffix($tbody)
  137. _doRead($tr)
  138. })
  139. $tbody
  140. .on('click.bjui.tabledit.readonly', '[data-toggle="doedit"]', function(e) {
  141. _doEdit($(this).closest('tr'))
  142. })
  143. .on('click.bjui.tabledit.readonly', '[data-toggle="dosave"]', function(e) {
  144. var $tr = $(this).closest('tr'), index = $tr.index(), callback = that.options.callback
  145. if (that.options.action) {
  146. $tr.wrap('<form action="" method="POST"></form>')
  147. if ($tr.attr('data-id')) {
  148. var name = $table.find('> thead > tr:eq(0)').data('idname') || 'id'
  149. $tr.before('<input type="hidden" name="'+ name.replaceSuffix(index) +'" value="'+ $tr.attr('data-id') +'">')
  150. }
  151. var data = $tr.parent().serializeArray()
  152. if (that.options.singleNoindex) {
  153. $.each(data, function(ii, nn) {
  154. $.extend(nn, {name:nn.name.replaceSuffix(0)})
  155. })
  156. }
  157. $tr.prev('input').remove()
  158. $tr
  159. .unwrap()
  160. .isValid(function(v) {
  161. if (v) {
  162. if (callback) {
  163. callback = callback.toFunc()
  164. } else {
  165. callback = function(json) {
  166. if (json[BJUI.keys.statusCode] == BJUI.statusCode.ok) {
  167. _doRead($tr)
  168. } else {
  169. $tr.bjuiajax('ajaxDone', json)
  170. }
  171. }
  172. }
  173. $tr.bjuiajax('doAjax', {url:that.options.action, data:data, type:that.options.type || 'POST', callback:callback})
  174. }
  175. })
  176. } else {
  177. _doRead($tr)
  178. }
  179. })
  180. that.tools.initEnter($tbody)
  181. function _doEdit($tr) {
  182. $tr.removeClass('readonly').find('> td *').each(function() {
  183. var $this = $(this), $td = $this.closest('td'), val = $td.data('val'), toggle = $this.attr('data-toggle-old'), readonly = $td.data('readonly')
  184. if (typeof val == 'undefined') val = $td.html()
  185. if ($td.data('notread')) return true
  186. if ($this.isTag('select'))
  187. $this.val($td.attr('data-val')).selectpicker('refresh').nextAll('.bootstrap-select').removeClass('readonly').find('button').removeClass('disabled')
  188. if ($this.is(':checkbox')) {
  189. $this.closest('.icheckbox_minimal-purple').removeClass('disabled')
  190. $this.closest('.icheckbox_minimal-purple').find('ins').removeClass('readonly')
  191. }
  192. if ($this.is(':radio')) {
  193. $this.closest('.iradio_minimal-purple').removeClass('disabled')
  194. $this.closest('.iradio_minimal-purple').find('ins').removeClass('readonly')
  195. }
  196. if (toggle) {
  197. if (toggle == 'dosave') return true
  198. else $this.removeAttr('data-toggle-old').attr('data-toggle', toggle)
  199. if (toggle == 'spinner') {
  200. $this.spinner('destroy').spinner()
  201. }
  202. if (toggle == 'kindeditor') {
  203. //$this.attr('data-toggle', 'kindeditor')
  204. $td.initui()
  205. }
  206. }
  207. if ($this.is(':text') || $this.is('textarea')) {
  208. $this.off('keydown.readonly')
  209. if (readonly) $this.prop('readonly', true)
  210. }
  211. $this.find('.bjui-lookup, .bjui-spinner, .bjui-upload').show()
  212. })
  213. $tr.find('[data-toggle="doedit"]')
  214. .attr('data-toggle', 'dosave')
  215. .text('完成')
  216. }
  217. function _doRead($tr) {
  218. $tr.addClass('readonly').find('> td *').each(function() {
  219. var $this = $(this), $td = $this.closest('td'), toggle = $this.attr('data-toggle')
  220. if ($td.data('notread')) return true
  221. if ($this.isTag('select'))
  222. $this.nextAll('.bootstrap-select').addClass('readonly').find('button').addClass('disabled')
  223. if ($this.is(':checkbox')) {
  224. $this.closest('.icheckbox_minimal-purple').addClass('disabled')
  225. $this.closest('.icheckbox_minimal-purple').find('ins').addClass('readonly')
  226. }
  227. if ($this.is(':radio')) {
  228. $this.closest('.iradio_minimal-purple').addClass('disabled')
  229. $this.closest('.iradio_minimal-purple').find('ins').addClass('readonly')
  230. }
  231. if (toggle) {
  232. if (toggle == 'doedit' || toggle == 'dosave') return true
  233. else $this.removeAttr('data-toggle').attr('data-toggle-old', toggle)
  234. if (toggle == 'kindeditor') {
  235. KindEditor.remove($this)
  236. }
  237. }
  238. if ($this.is(':text') || $this.is('textarea'))
  239. $this.on('keydown.readonly', function(e) { e.preventDefault() })
  240. $this.find('.bjui-lookup, .bjui-spinner, .bjui-upload').hide()
  241. })
  242. $tr.find('[data-toggle="dosave"]')
  243. .attr('data-toggle', 'doedit')
  244. .text('编辑')
  245. }
  246. },
  247. doAdd: function() {
  248. var tool = this
  249. var $table = that.$element
  250. if (!that.$numAdd || !that.$btnAdd) return
  251. $table
  252. .on('keydown.bjui.tabledit.add', 'thead .num-add', function(e) {
  253. if (e.which == BJUI.keyCode.ENTER) {
  254. that.$btnAdd.trigger('click.bjui.tabledit.add')
  255. e.preventDefault()
  256. }
  257. })
  258. .on('click.bjui.tabledit.add', 'thead .row-add', function(e) {
  259. var rowNum = 1
  260. if (!isNaN(that.$numAdd.val())) rowNum = parseInt(that.$numAdd.val())
  261. that.add($table, rowNum)
  262. e.preventDefault()
  263. })
  264. },
  265. doDel: function($tbody) {
  266. var tool = this
  267. var delEvent = 'click.bjui.tabledit.del'
  268. $tbody.off(delEvent).on(delEvent, '.row-del', function(e) {
  269. var $btnDel = $(this)
  270. if ($btnDel.data('confirmMsg')) {
  271. $btnDel.alertmsg('confirm', $btnDel.data('confirmMsg'), {okCall: function() { tool.delData($btnDel) }})
  272. } else {
  273. tool.delData($btnDel)
  274. }
  275. e.preventDefault()
  276. })
  277. },
  278. delData: function($btnDel) {
  279. var tool = this
  280. var $tbody = $btnDel.closest('tbody')
  281. var options = $btnDel.data()
  282. var _delRow = function(json) {
  283. $btnDel.closest('tr').remove()
  284. tool.initSuffix($tbody)
  285. tool.afterDelete($tbody)
  286. if (options.callback) (options.callback.toFunc()).apply(that, [json])
  287. }
  288. if ($btnDel.is('[href^=javascript:]') || $btnDel.is('[href^="#"]')) {
  289. _delRow()
  290. } else {
  291. $btnDel.bjuiajax('doAjax', {
  292. url : $btnDel.attr('href'),
  293. data : options.data,
  294. callback : _delRow
  295. })
  296. }
  297. },
  298. afterDelete: function($tbody) {
  299. var deletedEvent = $.Event(Tabledit.EVENTS.afterDelete, {relatedTarget: $tbody[0]})
  300. that.$element.trigger(deletedEvent)
  301. if (deletedEvent.isDefaultPrevented()) return
  302. }
  303. }
  304. return tools
  305. }
  306. Tabledit.prototype.init = function() {
  307. var that = this
  308. var tools = this.tools
  309. var $table = this.$element.addClass('bjui-tabledit'), $tr = $table.find('> thead > tr:first'), $tbody = this.$tbody
  310. var trHtml = $table.find('> thead > tr:first').html()
  311. $tr.find('> th').each(function() {
  312. var $th = $(this)
  313. var title = $th.attr('title')
  314. var add = $th.data('addtool')
  315. if (title) $th.html(title)
  316. if (add) {
  317. var $addBox = $('<span style="position:relative;"></span>')
  318. $th.empty()
  319. that.$numAdd = $('<input type="text" value="1" class="form-control num-add" size="2" title="待添加的行数">')
  320. that.$btnAdd = $('<a href="javascript:;" class="row-add" title="添加行"><i class="fa fa-plus-square"></i></a>')
  321. $addBox.append(that.$numAdd).append(that.$btnAdd).appendTo($th)
  322. }
  323. })
  324. $table.data('bjui.tabledit.tr', $('<tr>'+ trHtml +'</tr>'))
  325. tools.initTbody()
  326. tools.doAdd()
  327. tools.doDel($tbody)
  328. }
  329. Tabledit.prototype.add = function($table, num) {
  330. var tools = this.tools
  331. var $tbody = $table.find('> tbody')
  332. var $firstTr, $tr = $table.data('bjui.tabledit.tr')
  333. for (var i = 0; i < num; i++) {
  334. $tr.find('> th').each(function() { $(this).replaceWith('<td>'+ $(this).html() +'</td>') })
  335. var $addTr = $tr.clone()
  336. if (i == 0) $firstTr = $addTr
  337. $addTr.hide().appendTo($tbody)
  338. tools.initSuffix($tbody)
  339. tools.initEnter($tbody)
  340. $addTr.show().css('display', '').initui()
  341. }
  342. /*置入焦点*/
  343. if ($firstTr && $firstTr.length) {
  344. var $input = $firstTr.find(':text')
  345. $input.each(function() {
  346. var $txt = $(this)
  347. if (!$txt.prop('readonly')) {
  348. $txt.focus()
  349. return false
  350. }
  351. })
  352. }
  353. }
  354. // TABLEDIT PLUGIN DEFINITION
  355. // =======================
  356. function Plugin(option) {
  357. var args = arguments
  358. var property = option
  359. return this.each(function () {
  360. var $this = $(this)
  361. var options = $.extend({}, Tabledit.DEFAULTS, $this.data(), typeof option == 'object' && option)
  362. var data = $this.data('bjui.tabledit')
  363. if (!data) $this.data('bjui.tabledit', (data = new Tabledit(this, options)))
  364. if (typeof property == 'string' && $.isFunction(data[property])) {
  365. [].shift.apply(args)
  366. if (!args) data[property]()
  367. else data[property].apply(data, args)
  368. } else {
  369. data.init()
  370. }
  371. })
  372. }
  373. var old = $.fn.tabledit
  374. $.fn.tabledit = Plugin
  375. $.fn.tabledit.Constructor = Tabledit
  376. // TABLEDIT NO CONFLICT
  377. // =================
  378. $.fn.tabledit.noConflict = function () {
  379. $.fn.tabledit = old
  380. return this
  381. }
  382. // TABLEDIT DATA-API
  383. // ==============
  384. $(document).on(BJUI.eventType.initUI, function(e) {
  385. var $this = $(e.target).find('table[data-toggle="tabledit"]')
  386. if (!$this.length) return
  387. Plugin.call($this)
  388. })
  389. // init add tr
  390. $(document).on(BJUI.eventType.afterInitUI, function(e) {
  391. var $this = $(e.target).find('table[data-toggle="tabledit"]')
  392. $this.each(function() {
  393. if ($(this).is('[data-initnum]')) {
  394. var initNum = $(this).data('initnum')
  395. if (initNum > 0) {
  396. Plugin.call($(this), 'add', $(this), initNum)
  397. }
  398. }
  399. })
  400. })
  401. $(document).on('click.bjui.tabledit.data-api', '[data-toggle="tableditadd"]', function(e) {
  402. var $this = $(this)
  403. var num = $this.data('num') || 1
  404. var table = $this.data('target')
  405. if (!table || !$(table).length) return
  406. if (!$(table).isTag('table')) return
  407. Plugin.call($this, 'add', $(table), num)
  408. e.preventDefault()
  409. })
  410. }(jQuery);