CopyPasteMenu.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. /**
  2. * grid复制粘贴功能菜单
  3. *
  4. * @author yingp
  5. */
  6. Ext.define('erp.view.core.plugin.CopyPasteMenu', {
  7. ptype : 'copypastemenu',
  8. constructor : function(cfg) {
  9. if (cfg) {
  10. Ext.apply(this, cfg);
  11. }
  12. },
  13. clipPath : basePath + 'resource/ux/zero/ZeroClipboard.js',
  14. moviePath : basePath + 'resource/ux/zero/ZeroClipboard.swf',
  15. copyCls : 'grid-copy',
  16. init : function(grid) {
  17. this.grid = grid;
  18. this.execable = this.isExecable();
  19. if (grid.view) {
  20. var me = this;
  21. grid.on({
  22. cellclick : function(view, td, colIdx, record, tr, rowIdx, e) {
  23. if (e.ctrlKey) {
  24. me.loadSource();
  25. me.createMultiCopy(view, td, colIdx, record, tr, rowIdx, e);
  26. return false;
  27. }
  28. return true;
  29. },
  30. cellpaste : function(view, record, column, e) {
  31. e.preventDefault();
  32. Ext.defer(function(){
  33. me.onEditorPaste(view, record, column, e);
  34. }, 300);
  35. },
  36. specialkey : function(e) {
  37. console.log(e);
  38. }
  39. });
  40. var gridView = grid.view.normalView || grid.view;
  41. gridView.on({
  42. cellcontextmenu : function(view, td, colIdx, record, tr, rowIdx, e) {
  43. me.loadSource();
  44. if (e.ctrlKey) {// 多行多列模式
  45. me.createMultiCopy(view, td, colIdx, record, tr, rowIdx, e);
  46. } else {
  47. me.createDefaultCopy(view, td, colIdx, record, tr, rowIdx, e);
  48. }
  49. }
  50. });
  51. Ext.defer(function(){
  52. me.loadSource();
  53. }, 2000);
  54. }
  55. },
  56. isExecable: function() {
  57. return Ext.isChrome && Number(Ext.userAgent.match(/chrome\/[\d.]+/gi)[0].replace(/[^0-9.]/ig,"").substring(0, 2)) > 42;
  58. },
  59. loadSource: function() {
  60. if (!this.execable && typeof ZeroClipboard === 'undefined') {
  61. var me = this;
  62. Ext.Loader.injectScriptElement(me.clipPath, function(){
  63. ZeroClipboard.moviePath = me.moviePath;
  64. var temp_ = Ext.DomHelper.createDom({
  65. style: 'display:none;'
  66. });
  67. var clip = new ZeroClipboard.Client();
  68. clip.glue(temp_);
  69. });
  70. }
  71. },
  72. createDefaultCopy : function(view, td, colIdx, record, tr, rowIdx, e) {
  73. var me = this,
  74. column = view.getHeaderByCell(td) ||
  75. view.ownerCt.headerCt.getHeaderAtIndex(colIdx);
  76. if (!column) {
  77. return;
  78. }
  79. var dataIndex = column.dataIndex;
  80. e.preventDefault();
  81. var menu = view.copymenu;
  82. if (!menu) {
  83. menu = view.copymenu = me.createMenu();
  84. }
  85. menu.showAt(e.getXY());
  86. me.clearCopyCls();
  87. menu.grid = view.ownerCt;
  88. menu.record = record;
  89. menu.column = column;
  90. menu.dataIndex = dataIndex;
  91. menu.cell = view.getCell(menu.record, menu.column);
  92. menu.cell.addCls(me.copyCls);
  93. },
  94. createMultiCopy : function(view, td, colIdx, record, tr, rowIdx, e) {
  95. var me = this,
  96. column = view.getHeaderByCell(td) ||
  97. view.ownerCt.headerCt.getHeaderAtIndex(colIdx);
  98. if (!column) {
  99. return;
  100. }
  101. e.preventDefault();
  102. var picker = view.copypicker;
  103. if (!picker) {
  104. picker = view.copypicker = me.createPicker();
  105. }
  106. picker.grid = view.ownerCt;
  107. picker.graphics = picker.graphics || new Array();
  108. var cell = view.getCell(record, column),
  109. xy = {x : colIdx, y : rowIdx};
  110. if(Ext.Array.contains(picker.graphics, xy)) {
  111. picker.graphics.remove(xy);
  112. } else {
  113. picker.graphics.push(xy);
  114. }
  115. this.setCopyCls(picker.graphics);
  116. if(picker.graphics.length > 1) {
  117. picker.showAt([(cell.getX() + cell.getWidth()), (cell.getY() + cell.getHeight())]);
  118. }
  119. },
  120. setCopyCls : function(graphics) {
  121. var me = this;
  122. me.clearCopyCls();
  123. if (graphics.length == 1) {
  124. var cell = me.getCell(graphics[0].x, graphics[0].y);
  125. if (cell) {
  126. cell.addCls(me.copyCls);
  127. }
  128. } else if (graphics.length == 2) {
  129. var x = Math.min(graphics[0].x, graphics[1].x),
  130. m = Math.max(graphics[0].x, graphics[1].x),
  131. y = Math.min(graphics[0].y, graphics[1].y),
  132. n = Math.max(graphics[0].y, graphics[1].y);
  133. for (var i = x;i <= m;i++ ) {
  134. var cell = me.getCell(i, y);
  135. if (cell) {
  136. cell.addCls(me.copyCls + '-top');
  137. }
  138. cell = me.getCell(i, n);
  139. if (cell) {
  140. cell.addCls(me.copyCls + '-bottom');
  141. }
  142. }
  143. for (var i = y;i <= n;i++ ) {
  144. var cell = me.getCell(x, i);
  145. if (cell) {
  146. cell.addCls(me.copyCls + '-left');
  147. }
  148. cell = me.getCell(m, i);
  149. if (cell) {
  150. cell.addCls(me.copyCls + '-right');
  151. }
  152. }
  153. }
  154. },
  155. getCell : function(x, y) {
  156. var view = this.grid.view,
  157. column = view.ownerCt.headerCt.getHeaderAtIndex(x),
  158. record = this.grid.store.getAt(y);
  159. if (column)
  160. return view.getCell(record, column);
  161. return null;
  162. },
  163. clearCopyCls : function() {
  164. var view = this.grid.view, me = this;
  165. var doms = view.getEl().query('.' + me.copyCls);
  166. if (doms) {
  167. Ext.each(doms, function() {
  168. me.removeClass(this, me.copyCls);
  169. });
  170. }
  171. if(view.copypicker) {
  172. var dir = ['top', 'bottom', 'left', 'right'];
  173. for(var i in dir) {
  174. var cls = me.copyCls + '-' + dir[i];
  175. doms = view.getEl().query('.' + cls);
  176. if (doms) {
  177. Ext.each(doms, function() {
  178. me.removeClass(this, cls);
  179. });
  180. }
  181. }
  182. }
  183. },
  184. removeClass : function(dom, className) {
  185. var temp = dom.className;
  186. dom.className = null;
  187. dom.className = temp.split(new RegExp(" " + className + "|" + className + " " + "|" + "^" + className + "$","ig")).join("");
  188. },
  189. createPicker : function() {
  190. var me = this;
  191. return Ext.create('Ext.menu.Menu', {
  192. items : [{
  193. copyType : 'multi',
  194. iconCls : 'x-button-icon-copy',
  195. text : '复制',
  196. handler : function(item) {
  197. if(me.execable) {
  198. var m = item.ownerCt;
  199. me.onCopy(me.getMultiText(m.graphics));
  200. }
  201. }
  202. },{
  203. text : '取消'
  204. }],
  205. listeners: {
  206. delay : 100,
  207. mouseover : function(m, item, e) {
  208. if (item && !me.execable) {
  209. me.resetClip(m, item);
  210. }
  211. },
  212. hide : function (m) {
  213. m.graphics = null;
  214. me.clearCopyCls();
  215. }
  216. }
  217. });
  218. },
  219. onCopy: function(text) {
  220. var target = Ext.DomHelper.createDom({
  221. tag: 'textarea',
  222. style: 'opacity: 0;position: absolute;top: -10000px;right: 0;',
  223. html: text
  224. }, document.body);
  225. target.focus();
  226. target.select();
  227. document.execCommand('Copy');
  228. target.blur();
  229. document.body.removeChild(target);
  230. },
  231. createMenu : function() {
  232. var me = this;
  233. return Ext.create('Ext.menu.Menu', {
  234. items: [{
  235. copyType : 'cell',
  236. iconCls : 'x-button-icon-copy',
  237. text : '复制单元格',
  238. handler: function(item) {
  239. if(me.execable) {
  240. var m = item.ownerCt;
  241. me.onCopy(me.getCellText(m.grid, m.record, m.column, m.dataIndex));
  242. }
  243. }
  244. },{
  245. copyType : 'row',
  246. text : '复制行',
  247. handler: function(item) {
  248. if(me.execable) {
  249. var m = item.ownerCt;
  250. me.onCopy(me.getRecordText(m.grid, m.record));
  251. }
  252. }
  253. },{
  254. copyType : 'table',
  255. text : '复制表格',
  256. handler: function(item) {
  257. if(me.execable) {
  258. var m = item.ownerCt;
  259. me.onCopy(me.getTableText(m.grid));
  260. }
  261. }
  262. },{
  263. xtype: 'menuseparator'
  264. },{
  265. text : '复制到整列',
  266. handler : function(t, e) {
  267. var m = t.up('menu'),
  268. val = me.getCellText(m.grid, m.record, m.column, m.dataIndex);
  269. m && me.onColumnPaste(val, m.grid, m.column, m.record, m.dataIndex, m.cell, e);
  270. }
  271. },{
  272. xtype: 'menuseparator'
  273. },{
  274. text : '粘贴',
  275. iconCls : 'x-button-icon-paste',
  276. handler : function() {
  277. me.onCellPaste();
  278. }
  279. }],
  280. listeners: {
  281. delay : 100,
  282. mouseover : function(m, item, e) {
  283. if (item && !me.execable) {
  284. me.resetClip(m, item);
  285. }
  286. },
  287. hide : function (m) {
  288. me.clearCopyCls();
  289. }
  290. }
  291. });
  292. },
  293. resetClip : function(m, item) {
  294. if(!item.copyType) {
  295. return;
  296. }
  297. var me = this, clip = item.clip;
  298. if(!clip) {
  299. clip = item.clip = new ZeroClipboard.Client();
  300. clip.setHandCursor(true);
  301. clip.glue(item.id + '-itemEl', item.id);
  302. clip.addEventListener('complete', function (client, text) {
  303. m.hide();
  304. });
  305. }
  306. if(item.copyType == 'cell') {
  307. clip.setText(me.getCellText(m.grid, m.record, m.column, m.dataIndex));
  308. } else if(item.copyType == 'row') {
  309. clip.setText(me.getRecordText(m.grid, m.record));
  310. } else if(item.copyType == 'table') {
  311. clip.setText(me.getTableText(m.grid));
  312. } else if(item.copyType == 'multi') {
  313. clip.setText(me.getMultiText(m.graphics));
  314. }
  315. },
  316. getCellText : function(grid, record, column, dataIndex) {
  317. var v = record.get(dataIndex);
  318. if (v) {
  319. if(Ext.isDate(v)) {
  320. return Ext.Date.format(v, column.format || Ext.Date.defaultFormat);
  321. }
  322. return v;
  323. }
  324. return '';
  325. },
  326. getRecordText : function(grid, record) {
  327. var s = [], columns = grid.headerCt.getGridColumns(), v = null;
  328. Ext.each(columns, function(c){
  329. if(!c.hidden && c.dataIndex && c.getWidth() > 0) {
  330. v = record.get(c.dataIndex);
  331. if(c == null) {
  332. s.push(' ');
  333. } else {
  334. if(Ext.isDate(v)) {
  335. s.push(Ext.Date.format(v, c.format || Ext.Date.defaultFormat));
  336. } else {
  337. s.push(v);
  338. }
  339. }
  340. }
  341. });
  342. return s.join('\t');
  343. },
  344. getTableText : function(grid) {
  345. var me = this, s = [];
  346. grid.store.each(function(){
  347. s.push(me.getRecordText(grid, this));
  348. });
  349. return s.join('\n');
  350. },
  351. getMultiText : function(graphics) {
  352. if (graphics.length > 0) {
  353. var x = Math.min(graphics[0].x, graphics[1].x),
  354. m = Math.max(graphics[0].x, graphics[1].x),
  355. y = Math.min(graphics[0].y, graphics[1].y),
  356. n = Math.max(graphics[0].y, graphics[1].y);
  357. var me = this, view = me.grid.view, s = [];
  358. for (var i = y;i <= n;i++ ) {
  359. var record = me.grid.store.getAt(i);
  360. var t = [];
  361. for (var j = x;j <= m;j++ ) {
  362. var column = view.ownerCt.headerCt.getHeaderAtIndex(j);
  363. t.push(me.getCellText(me.grid, record, column, column.dataIndex));
  364. }
  365. s.push(t.join('\t'));
  366. }
  367. return s.join('\n');
  368. }
  369. return null;
  370. },
  371. onEditorPaste : function(view, record, column, e) {
  372. var me = this, v = e.target.value;
  373. if(v && (v.indexOf('\n') > -1 || v.indexOf('\t') > -1)) {
  374. var list = v.split('\n'), map, store = view.store,
  375. ct = view.ownerCt.headerCt,
  376. x = ct.getHeaderIndex(column),
  377. y = store.indexOf(record),
  378. nextRecord = record,
  379. nextColumn = column;
  380. Ext.Array.each(list, function(l, i){
  381. if(i > 0)
  382. nextRecord = store.getAt(y + i);
  383. if(nextRecord) {
  384. map = l.split('\t');
  385. Ext.Array.each(map, function(p, j){
  386. nextColumn = j > 1 ? me.getNextHeader(ct, nextColumn) :
  387. (j == 1 ? me.getNextHeader(ct, column) : column);
  388. if(nextColumn) {
  389. nextRecord.set(nextColumn.dataIndex, p);
  390. }
  391. if(i == 0 && j == 0)
  392. e.target.value = p;
  393. });
  394. }
  395. });
  396. }
  397. },
  398. getNextHeader : function(headerCt, startColumn) {
  399. var me = this, index = headerCt.getHeaderIndex(startColumn),
  400. next = headerCt.getHeaderAtIndex(index + 1);
  401. if(next) {
  402. if(!next.hidden && next.getWidth() > 0)
  403. return next;
  404. return me.getNextHeader(headerCt, next);
  405. }
  406. return null;
  407. },
  408. onCellPaste : function() {
  409. var v = this.getClipboard();
  410. if (!v) {
  411. return;
  412. }
  413. var menu = this.grid.view.copymenu,
  414. record = menu.record, dataIndex = menu.dataIndex,
  415. column = menu.column;
  416. var editor = column.getEditor(record);
  417. if (!editor) {
  418. return;
  419. }
  420. if(column.xtype == 'datecolumn') {
  421. try {
  422. v = Ext.Date.parse(v, column.format || Ext.Date.defaultFormat);
  423. } catch (e) {
  424. alert('日期格式错误');return;
  425. }
  426. }
  427. record.set(dataIndex, v);
  428. if (editor.field) {
  429. editor.field.focus();
  430. }
  431. },
  432. onColumnPaste : function(val, grid, column, record, dataIndex, cell, e) {
  433. if(!grid.readOnly) {// 只允许可编辑的列粘贴
  434. var editor = column.getEditor(record);
  435. if(editor) {
  436. grid.store.each(function(record){
  437. record.set(dataIndex, val);
  438. });
  439. }
  440. }
  441. },
  442. getClipboard : function() {
  443. if (window.clipboardData) {
  444. return window.clipboardData.getData('Text');
  445. }
  446. return null;
  447. }
  448. });