DocumentHistory.js 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001
  1. MWF.xApplication.process.Xform.widget = MWF.xApplication.process.Xform.widget || {};
  2. MWF.xApplication.process.Xform.widget.DocumentHistory = new Class({
  3. Implements: [Options, Events],
  4. options: {
  5. "speed": 1,
  6. "fxTime": 500,
  7. "inforTime": 2000
  8. },
  9. initialize: function(documentEditor, options){
  10. this.setOptions(options);
  11. this.documentEditor = documentEditor;
  12. this.css = this.documentEditor.css;
  13. },
  14. is_iPad: function(){
  15. var ua = navigator.userAgent.toLowerCase();
  16. return (ua.match(/iPad/i)=="ipad");
  17. },
  18. load: function(callback){
  19. this.getHistroyDocumentList(function(){
  20. if (this.historyDocumentList && this.historyDocumentList.length){
  21. this.getHistoryDataList(function(){
  22. this.createHistoryToolbar();
  23. if (!layout.mobile || this.is_iPad()) this.createHistoryListNode();
  24. this.documentEditor.options.pageShow = "single";
  25. this.documentEditor.resetData();
  26. this.beginDiffHistory();
  27. this.loadHistoryToolbar();
  28. if (!layout.mobile) this.loadHistoryList();
  29. if (callback) callback();
  30. }.bind(this));
  31. }else{
  32. this.documentEditor.form.app.notice(MWF.xApplication.process.Xform.LP.documentHistory.nodiff, "info", this.documentEditor.node);
  33. }
  34. }.bind(this));
  35. },
  36. createHistoryToolbar: function(){
  37. this.documentEditor.documentToolbarNode = this.documentEditor.toolbarNode;
  38. this.toolbarNode = this.documentEditor.toolbarNode.clone(true);
  39. this.toolbarNode.inject(this.documentEditor.toolbarNode, "after");
  40. this.documentEditor.toolbarNode = this.toolbarNode;
  41. this.documentEditor.documentToolbarNode.hide();
  42. this.toolbarNode.empty();
  43. if (this.documentEditor.sidebarNode) this.documentEditor.sidebarNode.hide();
  44. },
  45. loadHistoryToolbar: function(){
  46. var html = "<span MWFnodetype=\"MWFToolBarButton\" MWFButtonImage=\"../x_component_process_Xform/$Form/default/documenteditoricon/play.png\" title=\""+MWF.xApplication.process.Xform.LP.documentHistory.play+"\" MWFButtonAction=\"play\"></span>";
  47. html += "<span MWFnodetype=\"MWFToolBarButton\" MWFButtonImage=\"../x_component_process_Xform/$Form/default/documenteditoricon/pause.png\" title=\""+MWF.xApplication.process.Xform.LP.documentHistory.pause+"\" MWFButtonAction=\"pause\"></span>";
  48. html += "<span MWFnodetype=\"MWFToolBarButton\" MWFButtonImage=\"../x_component_process_Xform/$Form/default/documenteditoricon/stop.png\" title=\""+MWF.xApplication.process.Xform.LP.documentHistory.stop+"\" MWFButtonAction=\"stopPlay\"></span>";
  49. html += "<span MWFnodetype=\"MWFToolBarSeparator\"></span>";
  50. html += "<span MWFnodetype=\"MWFToolBarButton\" MWFButtonImage=\"../x_component_process_Xform/$Form/default/documenteditoricon/prev.png\" title=\""+MWF.xApplication.process.Xform.LP.documentHistory.prev+"\" MWFButtonAction=\"prev\"></span>";
  51. html += "<span MWFnodetype=\"MWFToolBarButton\" MWFButtonImage=\"../x_component_process_Xform/$Form/default/documenteditoricon/next.png\" title=\""+MWF.xApplication.process.Xform.LP.documentHistory.next+"\" MWFButtonAction=\"next\"></span>";
  52. html += "<span MWFnodetype=\"MWFToolBarSeparator\"></span>";
  53. html += "<span MWFnodetype=\"MWFToolBarButton\" MWFButtonImage=\"../x_component_process_Xform/$Form/default/documenteditoricon/exit.png\" title=\""+MWF.xApplication.process.Xform.LP.documentHistory.exit+"\" MWFButtonAction=\"exit\" MWFButtonText=\""+MWF.xApplication.process.Xform.LP.documentHistory.exit+"\"></span>";
  54. html += "<span MWFnodetype=\"MWFToolBarSeparator\"></span>";
  55. var text = MWF.xApplication.process.Xform.LP.documentHistory.diff_patch_count;
  56. text = text.replace(/{history}/, this.historyDataList.length).replace(/{diff}/, this.diffCount);
  57. html += "<span style='float: left; line-height: 24px; color: #666666; margin-left: 10px'>"+text+"</span>";
  58. this.toolbarNode.set("html", html);
  59. MWF.require("MWF.widget.Toolbar", function() {
  60. this.toolbar = new MWF.widget.Toolbar(this.toolbarNode, {"style": "documentEdit"}, this);
  61. this.toolbar.load();
  62. this.checkToolbar();
  63. }.bind(this));
  64. },
  65. checkToolbar: function(){
  66. if (this.toolbar){
  67. if (this.playing){
  68. if (this.stop){
  69. this.toolbar.childrenButton[0].enable();
  70. this.toolbar.childrenButton[1].disable();
  71. if (this.patchIndex==0 && this.diffIndex==0){
  72. this.toolbar.childrenButton[3].disable();
  73. if (this.diffPatch.length) this.toolbar.childrenButton[4].enable();
  74. }else{
  75. if (this.patchIndex<this.diffPatch.length-1){
  76. this.toolbar.childrenButton[3].enable();
  77. this.toolbar.childrenButton[4].enable();
  78. }else if (this.patchIndex<this.diffPatch.length && this.diffIndex < this.diffPatch[this.patchIndex].patch.diffs.length){
  79. this.toolbar.childrenButton[3].enable();
  80. this.toolbar.childrenButton[4].enable();
  81. }else{
  82. if (this.diffPatch.length) this.toolbar.childrenButton[3].enable();
  83. this.toolbar.childrenButton[4].disable();
  84. }
  85. }
  86. }else{
  87. this.toolbar.childrenButton[0].disable();
  88. this.toolbar.childrenButton[1].enable();
  89. this.toolbar.childrenButton[3].disable();
  90. this.toolbar.childrenButton[4].disable();
  91. }
  92. this.toolbar.childrenButton[2].enable();
  93. }else{
  94. this.toolbar.childrenButton[0].enable();
  95. this.toolbar.childrenButton[1].disable();
  96. this.toolbar.childrenButton[2].disable();
  97. if (this.patchIndex==0 && this.diffIndex==0){
  98. this.toolbar.childrenButton[3].disable();
  99. if (this.diffPatch.length) this.toolbar.childrenButton[4].enable();
  100. }else{
  101. if (this.patchIndex<this.diffPatch.length-1){
  102. this.toolbar.childrenButton[3].enable();
  103. this.toolbar.childrenButton[4].enable();
  104. }else if (this.patchIndex<this.diffPatch.length && this.diffIndex < this.diffPatch[this.patchIndex].patch.diffs.length){
  105. this.toolbar.childrenButton[3].enable();
  106. this.toolbar.childrenButton[4].enable();
  107. }else{
  108. if (this.diffPatch.length) this.toolbar.childrenButton[3].enable();
  109. this.toolbar.childrenButton[4].disable();
  110. }
  111. }
  112. }
  113. }
  114. },
  115. createHistoryListNode: function(){
  116. this.historyListAreaNode = new Element("div", {"styles": this.css.historyListAreaNode}).inject(this.documentEditor.contentNode, "before");
  117. this.documentEditor.contentNode.setStyle("width", "auto");
  118. this.documentEditor.zoom(1);
  119. this.documentEditor._checkScale();
  120. var size = this.documentEditor.node.getSize();
  121. var toolbarSize = this.documentEditor.toolbarNode.getSize();
  122. var h = size.y-toolbarSize.y;
  123. this.historyListAreaNode.setStyle("height", ""+h+"px");
  124. this.historyListTitleAreaNode = new Element("div", {"styles": this.css.historyListTitleAreaNode}).inject(this.historyListAreaNode);
  125. this.historyListContentAreaNode = new Element("div", {"styles": this.css.historyListContentAreaNode}).inject(this.historyListAreaNode);
  126. var y = this.historyListContentAreaNode.getEdgeHeight();
  127. var title_y = this.historyListTitleAreaNode.getComputedSize().totalHeight;
  128. h = h-y-title_y;
  129. this.historyListContentAreaNode.setStyle("height", ""+h+"px");
  130. this.historyListTitleNode = new Element("div", {"styles": this.css.historyListTitleNode}).inject(this.historyListTitleAreaNode);
  131. this.historyListTitleInsertNode = new Element("div", {"styles": this.css.historyListTitleInsertNode}).inject(this.historyListTitleAreaNode);
  132. this.historyListTitleDeleteNode = new Element("div", {"styles": this.css.historyListTitleDeleteNode}).inject(this.historyListTitleAreaNode);
  133. },
  134. loadHistoryList: function(){
  135. var text = MWF.xApplication.process.Xform.LP.documentHistory.diff_patch_count;
  136. text = text.replace(/{history}/, this.historyDataList.length).replace(/{diff}/, this.diffCount);
  137. var insertStr = MWF.xApplication.process.Xform.LP.documentHistory.insertTimes;
  138. var deleteStr = MWF.xApplication.process.Xform.LP.documentHistory.deleteTimes;
  139. insertStr = insertStr.replace(/{times}/, this.diffInsertCount);
  140. deleteStr = deleteStr.replace(/{times}/, this.diffDeleteCount);
  141. this.historyListTitleNode.set("text", text);
  142. this.historyListTitleInsertNode.set("text", insertStr);
  143. this.historyListTitleDeleteNode.set("text", deleteStr);
  144. //var original = this.historyDataList[0];
  145. //this.createHistoryListItem(original);
  146. this.historyDataList.each(function(historyData){
  147. this.createHistoryListItem(historyData);
  148. }.bind(this));
  149. // this.diffPatch.each(function(patchObj){
  150. // this.createHistoryListItem(patchObj);
  151. // }.bind(this));
  152. },
  153. createHistoryListItem: function(historyData){
  154. new MWF.xApplication.process.Xform.widget.DocumentHistory.Item(this, historyData);
  155. },
  156. getHistoryDataList: function(callback){
  157. // if (this.historyDataList && this.historyDataList.length){
  158. // this.getHistoryDataListFinish(this.historyDataList);
  159. // if (callback) callback();
  160. // }else{
  161. var historyDataList = [];
  162. var getDataCount = 0;
  163. var idx = 0;
  164. var checkBeginDiffHistory = function(){
  165. if (getDataCount>=this.historyDocumentList.length){
  166. this.getHistoryDataListFinish(historyDataList, callback);
  167. }
  168. }.bind(this);
  169. for (var i=this.historyDocumentList.length-1; i>=0; i--){
  170. historyDataList.push(null);
  171. this.getHistroyDocumentData(this.historyDocumentList[i].id, function(){
  172. getDataCount++;
  173. checkBeginDiffHistory();
  174. }.bind(this), idx, historyDataList);
  175. idx++;
  176. }
  177. //}
  178. },
  179. getHistoryDataListFinish: function(historyDataList, callback){
  180. this.historyDataList = historyDataList;
  181. this.originaHistoryData = historyDataList[0].json.data || null;
  182. if (this.documentEditor.allowEdit){
  183. o2.load("../o2_lib/diff-match-patch/diff_match_patch_uncompressed.js", function(){
  184. var originaData = this.documentEditor.form.businessData.originalData[this.documentEditor.json.id];
  185. var data = this.documentEditor.data.filetext;
  186. var earlyData = originaData.filetext;
  187. if (data!=earlyData){
  188. var dmp = new diff_match_patch();
  189. var diff_d = dmp.diff_main(earlyData, data);
  190. dmp.diff_cleanupSemantic(diff_d);
  191. var patch_list = dmp.patch_make(earlyData, data, diff_d);
  192. if (patch_list.length){
  193. var patch = dmp.patch_toText(patch_list);
  194. var patchData = JSON.stringify({"patchs": patch});
  195. var currentData = {
  196. "data": patchData,
  197. "json": {"patchs": patch},
  198. "person": layout.session.user.distinguishedName,
  199. "activityName": this.documentEditor.form.businessData.activity.name,
  200. "createTime" : (new Date()).format("db")
  201. };
  202. this.historyDataList.push(currentData);
  203. }
  204. }
  205. if (callback) callback();
  206. }.bind(this));
  207. }else{
  208. if (callback) callback();
  209. }
  210. },
  211. getHistroyDocumentData: function(id, callback, i, historyDataList){
  212. o2.Actions.load("x_processplatform_assemble_surface").DocumentVersionAction.get(id, function(json){
  213. var obj = JSON.parse(json.data.data);
  214. json.data.json = obj;
  215. if (historyDataList) historyDataList[i] = json.data;
  216. if (callback) callback(json.data);
  217. }.bind(this));
  218. },
  219. getHistroyDocumentList: function(callback){
  220. //if (!this.historyDocumentList){
  221. var id = this.documentEditor.form.businessData.work.job;
  222. o2.Actions.load("x_processplatform_assemble_surface").DocumentVersionAction.listWithJobCategory(id, this.documentEditor.json.id, function(json){
  223. this.historyDocumentList = json.data;
  224. if (callback) callback();
  225. }.bind(this));
  226. //}else{
  227. // if (callback) callback();
  228. //}
  229. },
  230. beginDiffHistory: function(){
  231. //o2.load("../o2_lib/diff-match-patch/diff_match_patch_uncompressed.js", function(){
  232. this.initAnimation();
  233. //if (callback) callback();
  234. //}.bind(this));
  235. },
  236. initAnimation: function(){
  237. this.diffPatch = this.diffHistroy();
  238. this.diffCount = 0;
  239. this.diffInsertCount = 0;
  240. this.diffDeleteCount = 0;
  241. this.diffPatch.each(function(patch){
  242. patch.patch.diffs.each(function(diff){
  243. if (diff[0]!=0) this.diffCount++;
  244. if (diff[0]==-1) this.diffDeleteCount++;
  245. if (diff[0]==1) this.diffInsertCount++;
  246. }.bind(this));
  247. }.bind(this));
  248. // this.initData();
  249. this.initAnimationStatus();
  250. },
  251. initData: function(){
  252. this.currentHistoryData = this.originaHistoryData;
  253. this.documentEditor.layout_filetext.set("html", this.currentHistoryData);
  254. this.patchIndex = 0;
  255. this.diffIndex = 0;
  256. if (this.originaDiff) this.originaDiff.showCurrent();
  257. },
  258. initAnimationStatus: function(){
  259. this.patchIndex = 0;
  260. this.diffIndex = 0;
  261. this.currentDiffs = null;
  262. this.stop = true;
  263. this.step = false;
  264. this.playing = false;
  265. this.reverse = false;
  266. this.options.fxTime = 500;
  267. this.options.inforTime = 2000;
  268. this.checkToolbar();
  269. },
  270. doAnimationAuto: function(){
  271. this.playing = true;
  272. this.checkToolbar();
  273. this.doPatchAnimation(function(){
  274. this.patchIndex = 0;
  275. this.diffIndex = 0;
  276. this.playing = false;
  277. this.stop = true;
  278. this.documentEditor.resetData();
  279. this.checkToolbar();
  280. }.bind(this));
  281. },
  282. do: function(){
  283. if (this.nextPlayPrefixFunction){
  284. this.nextPlayPrefixFunction();
  285. this.nextPlayPrefixFunction = null;
  286. }else{
  287. this.doAnimationAuto();
  288. }
  289. },
  290. play: function(){
  291. if (!this.playing){
  292. this.initData();
  293. this.initAnimationStatus();
  294. }
  295. this.reverse = false;
  296. this.stop = false;
  297. this.stopWhile = "";
  298. this.options.fxTime = 500;
  299. this.options.inforTime = 2000;
  300. this.toolbar.childrenButton[0].disable();
  301. this.toolbar.childrenButton[3].disable();
  302. this.toolbar.childrenButton[4].disable();
  303. this.do();
  304. },
  305. stopPlay: function(){
  306. if (this.playing){
  307. this.stop = true;
  308. this.playing = false;
  309. if (this.nextPlayPrefixFunction){
  310. this.nextPlayPrefixFunction();
  311. this.nextPlayPrefixFunction = null;
  312. }
  313. this.patchIndex = 0;
  314. this.diffIndex = 0;
  315. this.toolbar.childrenButton[1].disable();
  316. this.toolbar.childrenButton[2].disable();
  317. }
  318. },
  319. pause: function(){
  320. if (this.playing){
  321. this.stop = true;
  322. this.toolbar.childrenButton[1].disable();
  323. this.toolbar.childrenButton[2].disable();
  324. }
  325. },
  326. next: function(){
  327. this.reverse = false;
  328. this.options.fxTime = 0;
  329. this.options.inforTime = 0;
  330. this.stop = true;
  331. this.toolbar.childrenButton[3].disable();
  332. this.toolbar.childrenButton[4].disable();
  333. if (!this.playing) this.initData();
  334. this.do();
  335. },
  336. prev: function(){
  337. this.reverse = true;
  338. this.options.fxTime = 0;
  339. this.options.inforTime = 0;
  340. this.stop = true;
  341. this.toolbar.childrenButton[3].disable();
  342. this.toolbar.childrenButton[4].disable();
  343. if (!this.playing) this.initData();
  344. this.do();
  345. },
  346. to: function(diff){
  347. if (this.nextPlayPrefixFunction){
  348. this.playing = false;
  349. this.nextPlayPrefixFunction(function(){
  350. this.initData();
  351. this.initAnimationStatus();
  352. this.reverse = false;
  353. this.options.fxTime = 0;
  354. this.options.inforTime = 0;
  355. this.stop = false;
  356. this.stopWhile = diff.id;
  357. this.toolbar.childrenButton[3].disable();
  358. this.toolbar.childrenButton[4].disable();
  359. this.doAnimationAuto(diff.id);
  360. }.bind(this));
  361. //this.nextPlayPrefixFunction = null;
  362. }else{
  363. this.initData();
  364. this.initAnimationStatus();
  365. this.reverse = false;
  366. this.options.fxTime = 0;
  367. this.options.inforTime = 0;
  368. this.stop = false;
  369. this.stopWhile = diff.id;
  370. this.toolbar.childrenButton[3].disable();
  371. this.toolbar.childrenButton[4].disable();
  372. this.doAnimationAuto(diff.id);
  373. }
  374. },
  375. origina: function(){
  376. if (this.nextPlayPrefixFunction){
  377. this.playing = false;
  378. this.nextPlayPrefixFunction(function(){
  379. this.initData();
  380. this.initAnimationStatus();
  381. }.bind(this));
  382. this.nextPlayPrefixFunction = null;
  383. }else{
  384. this.initData();
  385. this.initAnimationStatus();
  386. }
  387. },
  388. exit: function(){
  389. this.initAnimationStatus();
  390. this.options.fxTime = 0;
  391. this.options.inforTime = 0;
  392. if (this.nextPlayPrefixFunction){
  393. this.nextPlayPrefixFunction(function(){
  394. this.documentEditor.toolbarNode = this.documentEditor.documentToolbarNode;
  395. this.documentEditor.toolbarNode.show();
  396. if (this.documentEditor.sidebarNode) this.documentEditor.sidebarNode.show();
  397. this.documentEditor.resizeToolbar();
  398. }.bind(this));
  399. this.nextPlayPrefixFunction = null;
  400. }else{
  401. this.documentEditor.toolbarNode = this.documentEditor.documentToolbarNode;
  402. this.documentEditor.toolbarNode.show();
  403. if (this.documentEditor.sidebarNode) this.documentEditor.sidebarNode.show();
  404. this.documentEditor.resizeToolbar();
  405. }
  406. if (this.historyListAreaNode) this.historyListAreaNode.destroy();
  407. this.historyListAreaNode = null;
  408. this.documentEditor.zoom(1);
  409. this.documentEditor._checkScale();
  410. this.documentEditor.resetData();
  411. this.toolbarNode.hide();
  412. },
  413. active: function(callback){
  414. this.getHistroyDocumentList(function(){
  415. if (this.historyDocumentList && this.historyDocumentList.length){
  416. this.getHistoryDataList(function(){
  417. this.documentEditor.options.pageShow = "single";
  418. this.documentEditor.resetData();
  419. this.beginDiffHistory();
  420. this.documentEditor.resetData();
  421. this.toolbarNode.show();
  422. this.documentEditor.documentToolbarNode = this.documentEditor.toolbarNode;
  423. this.documentEditor.documentToolbarNode.hide();
  424. if (this.documentEditor.sidebarNode) this.documentEditor.sidebarNode.hide();
  425. this.documentEditor.toolbarNode = this.toolbarNode;
  426. this.documentEditor.resizeToolbar();
  427. var text = MWF.xApplication.process.Xform.LP.documentHistory.diff_patch_count;
  428. text = text.replace(/{history}/, this.historyDataList.length).replace(/{diff}/, this.diffCount);
  429. this.toolbarNode.getLast().set("html", text);
  430. if (!layout.mobile || this.is_iPad()) {
  431. this.createHistoryListNode();
  432. this.loadHistoryList();
  433. }
  434. this.documentEditor.options.pageShow = "single";
  435. this.documentEditor.resetData();
  436. if (callback) callback();
  437. }.bind(this));
  438. }else{
  439. this.documentEditor.form.app.notice(MWF.xApplication.process.Xform.LP.documentHistory.nodiff, "info", this.documentEditor.node);
  440. }
  441. }.bind(this));
  442. },
  443. diffHistroy: function(){
  444. var diffPatch = [];
  445. //var historyPatchs = [];
  446. for (var i=1; i<this.historyDataList.length; i++){
  447. // var earlyDataText = this.historyDataList[i-1].data;
  448. // var laterData = this.historyDataList[i];
  449. //
  450. // var dmp = new diff_match_patch();
  451. // // dmp.Diff_Timeout = parseFloat(10);
  452. // // dmp.Diff_EditCost = parseFloat(4);
  453. // var diff_d = dmp.diff_main(earlyDataText, laterData.data);
  454. // dmp.diff_cleanupSemantic(diff_d);
  455. // var patch_list = dmp.patch_make(earlyDataText, laterData.data, diff_d);
  456. //historyPatchs.push({"patch_list": patch_list, "obj": laterData});
  457. var history = this.historyDataList[i];
  458. var data = history.json;
  459. history.json = data;
  460. if (data.patchs){
  461. var dmp = new diff_match_patch();
  462. var patch_list = dmp.patch_fromText(data.patchs);
  463. history.json.patchObj = patch_list;
  464. patch_list.each(function(patch){
  465. diffPatch.push({"patch":patch, "obj": history});
  466. }.bind(this));
  467. }
  468. }
  469. return diffPatch;
  470. },
  471. doPatchAnimation: function(callback){
  472. var patchObj = this.diffPatch[this.patchIndex];
  473. var patch = patchObj.patch;
  474. var obj = patchObj.obj;
  475. this.currentDiffs = patch.diffs;
  476. this.diffIndex = (this.reverse) ? patch.diffs.length-1 : 0;
  477. var start = (this.reverse) ? patch.start1+patch.length2 : patch.start1;
  478. this.doDiffsAnimation(obj, start, function(){
  479. if (this.reverse){
  480. this.patchIndex--;
  481. if (this.patchIndex>=0){
  482. this.currentHistoryData = this.documentEditor.layout_filetext.get("html");
  483. this.doPatchAnimation(callback);
  484. }else{
  485. if (callback) callback();
  486. }
  487. }else{
  488. this.patchIndex++;
  489. if (this.patchIndex<this.diffPatch.length){
  490. this.currentHistoryData = this.documentEditor.layout_filetext.get("html");
  491. this.doPatchAnimation(callback);
  492. }else{
  493. if (callback) callback();
  494. }
  495. }
  496. }.bind(this));
  497. },
  498. doPatchAnimationStep: function(i){
  499. if (this.patchIndex>this.diffPatch.length || this.patchIndex<0){
  500. this.initAnimationStatus();
  501. this.documentEditor.resetData();
  502. this.checkToolbar();
  503. }else{
  504. var patchObj = this.diffPatch[this.patchIndex];
  505. var patch = patchObj.patch;
  506. var obj = patchObj.obj;
  507. this.currentDiffs = patch.diffs;
  508. this.diffIndex = 0;
  509. this.doDiffsAnimation(obj, patch.start1);
  510. this.patchIndex = this.patchIndex+i;
  511. }
  512. },
  513. createDiifInforNode: function(obj, node, color, insertInfor){
  514. if (this.historyInforDiv){
  515. this.historyInforDiv.dispose();
  516. this.historyInforDiv = null;
  517. }
  518. var styles = (!layout.mobile) ? this.css.historyInforNode : this.css.historyInforMobileNode
  519. var insertInforDiv = new Element("div", { "styles": styles }).inject(this.documentEditor.node);
  520. insertInforDiv.setStyle("background", color);
  521. insertInfor = insertInfor.replace(/{name}/, o2.name.cn(obj.person))
  522. .replace(/{activity}/, obj.activityName)
  523. .replace(/{time}/, obj.createTime);
  524. insertInforDiv.set("html", insertInfor);
  525. if (!layout.mobile){
  526. insertInforDiv.position({
  527. "relativeTo": node,
  528. "position": 'upperCenter',
  529. "edge": 'bottomCenter',
  530. "offset": {
  531. "x": 0, "y": -10
  532. }
  533. });
  534. }else{
  535. }
  536. // debugger;
  537. // var p = node.getPosition(node.getOffsetParent());
  538. // if (p.x<0) p.x=0;
  539. // var y = (p.y-10-insertInforDiv.getSize().y);
  540. // var x = p.x;
  541. // alert(x)
  542. // var scale = (this.documentEditor.scale<0.7) ? 0.7 : this.documentEditor.scale;
  543. // insertInforDiv.setStyles({
  544. // "left": ""+x+"px",
  545. // "top": ""+y+"px",
  546. // "transform":"scale("+scale+")",
  547. // "transform-origin": "0px 0px",
  548. // });
  549. this.historyInforDiv = insertInforDiv;
  550. return insertInforDiv;
  551. },
  552. doDiffsAnimation: function(obj, start, callback){
  553. var diff = this.currentDiffs[this.diffIndex];
  554. var filetextNode = this.documentEditor.layout_filetext;
  555. switch (diff[0]) {
  556. case DIFF_INSERT:
  557. if (diff["item"]) diff["item"].showCurrent((!this.stopWhile || this.stopWhile == diff["id"]));
  558. if (this.originaDiff) this.originaDiff.hideCurrent();
  559. var text = diff[1];
  560. if (this.reverse){
  561. start -= text.length;
  562. var left = this.currentHistoryData.substring(0, start);
  563. var middle = this.currentHistoryData.substring(start, start+diff[1].length);
  564. var right = this.currentHistoryData.substring(start+diff[1].length);
  565. filetextNode.set("html", left+"<ins style='color:blue;'></ins>"+right);
  566. }else{
  567. var left = this.currentHistoryData.substring(0, start);
  568. var right = this.currentHistoryData.substring(start);
  569. filetextNode.set("html", left+"<ins style='color:blue;'></ins>"+right);
  570. }
  571. var ins = filetextNode.getElement("ins");
  572. if (!this.stopWhile || this.stopWhile == diff["id"]) ins.scrollIn();
  573. this.doInsetAnimation(ins, diff[1], function(invisible){
  574. var insertInforDiv = null;
  575. if (!invisible && (!this.stopWhile || this.stopWhile == diff["id"]) ){
  576. insertInforDiv = this.createDiifInforNode(obj, ins, "#e2edfb", MWF.xApplication.process.Xform.LP.documentHistory.insertContent);
  577. }
  578. window.setTimeout(function(){
  579. var endFunction = function(cb){
  580. if (insertInforDiv) insertInforDiv.fade("out");
  581. var fx = new Fx.Tween(ins, {property: 'opacity', duration:this.options.speed*this.options.fxTime});
  582. fx.start(1.1).chain(function(){
  583. if (insertInforDiv) insertInforDiv.destroy();
  584. if (diff["item"]) diff["item"].hideCurrent();
  585. if (this.reverse){
  586. ins.destroy();
  587. this.currentHistoryData = filetextNode.get("html");
  588. }else{
  589. data = filetextNode.get("html");
  590. this.currentHistoryData = data.replace(/<ins[\s\S]*\/ins>/m, text);
  591. filetextNode.set("html", this.currentHistoryData);
  592. }
  593. if (this.playing){
  594. if (this.reverse){
  595. this.diffIndex--;
  596. if (this.diffIndex>=0){
  597. window.setTimeout(function(){this.doDiffsAnimation(obj, start, function(){
  598. if (callback) callback();
  599. if (cb) cb();
  600. });}.bind(this), this.options.speed*this.options.fxTime);
  601. //this.doDiffsAnimation(obj, start, callback);
  602. }else{
  603. if (callback) callback();
  604. }
  605. }else{
  606. start += text.length;
  607. this.diffIndex++;
  608. if (this.diffIndex<this.currentDiffs.length){
  609. window.setTimeout(function(){this.doDiffsAnimation(obj, start, function(){
  610. if (callback) callback();
  611. if (cb) cb();
  612. });}.bind(this), this.options.speed*this.options.fxTime);
  613. //this.doDiffsAnimation(obj, start, callback);
  614. }else{
  615. if (callback) callback();
  616. }
  617. }
  618. }else{
  619. this.initAnimationStatus();
  620. this.documentEditor.resetData();
  621. if (cb) cb();
  622. }
  623. }.bind(this));
  624. if (this.nextPlayPrefixFunction) this.nextPlayPrefixFunction = null;
  625. }.bind(this)
  626. if (this.stopWhile) if (this.stopWhile == diff["id"]) this.stop = true;
  627. if (!this.stop || !this.playing) {
  628. endFunction();
  629. } else{
  630. if (this.stopWhile){
  631. this.stopWhile = "";
  632. //this.playing = false;
  633. }
  634. this.nextPlayPrefixFunction = endFunction;
  635. }
  636. this.checkToolbar();
  637. }.bind(this), (invisible ? 100: this.options.speed*this.options.inforTime));
  638. }.bind(this));
  639. break;
  640. case DIFF_DELETE:
  641. if (diff["item"]) diff["item"].showCurrent((!this.stopWhile || this.stopWhile == diff["id"]));
  642. if (this.originaDiff) this.originaDiff.hideCurrent();
  643. var text = diff[1];
  644. if (this.reverse){
  645. var left = this.currentHistoryData.substring(0, start);
  646. //var middle = this.currentHistoryData.substring(start, start+diff[1].length);
  647. var right = this.currentHistoryData.substring(start);
  648. filetextNode.set("html", left+"<del style='color: red'>"+text+"</del>"+right);
  649. start -= text.length;
  650. }else{
  651. var left = this.currentHistoryData.substring(0, start);
  652. var middle = this.currentHistoryData.substring(start, start+diff[1].length);
  653. var right = this.currentHistoryData.substring(start+diff[1].length);
  654. //start -= .length;
  655. filetextNode.set("html", left+"<del style='color: red'>"+middle+"</del>"+right);
  656. }
  657. var del = filetextNode.getElement("del");
  658. if (!this.stopWhile || this.stopWhile == diff["id"]) del.scrollIn();
  659. this.doDeleteAnimation(del, diff, obj, function(deleteInforDiv){
  660. // var deleteInforDiv = null;
  661. // if (!invisible){
  662. // deleteInforDiv = this.createDiifInforNode(obj, del, "#fbe0e7", MWF.xApplication.process.Xform.LP.documentHistory.deleteContent);
  663. // }
  664. var invisible = !deleteInforDiv;
  665. window.setTimeout(function(){
  666. var endFunction = function(cb){
  667. if (deleteInforDiv) deleteInforDiv.fade("out");
  668. var fx = new Fx.Tween(del, {property: 'opacity', duration:this.options.speed*this.options.fxTime});
  669. fx.start(0.5,0).chain(function(){
  670. if (deleteInforDiv) deleteInforDiv.destroy();
  671. if (diff["item"]) diff["item"].hideCurrent();
  672. if (this.reverse){
  673. data = filetextNode.get("html");
  674. this.currentHistoryData = data.replace(/<del[\s\S]*\/del>/m, text);
  675. filetextNode.set("html", this.currentHistoryData);
  676. }else{
  677. del.destroy();
  678. this.currentHistoryData = filetextNode.get("html");
  679. }
  680. if (this.playing){
  681. if (this.reverse){
  682. this.diffIndex--;
  683. if (this.diffIndex>=0){
  684. window.setTimeout(function(){this.doDiffsAnimation(obj, start, function(){
  685. if (callback) callback();
  686. if (cb) cb();
  687. });}.bind(this), this.options.speed*this.options.fxTime);
  688. }else{
  689. if (callback) callback();
  690. }
  691. }else{
  692. this.diffIndex++;
  693. if (this.diffIndex<this.currentDiffs.length){
  694. window.setTimeout(function(){this.doDiffsAnimation(obj, start, function(){
  695. if (callback) callback();
  696. if (cb) cb();
  697. });}.bind(this), this.options.speed*this.options.fxTime);
  698. }else{
  699. if (callback) callback();
  700. }
  701. }
  702. }else{
  703. this.initAnimationStatus();
  704. this.documentEditor.resetData();
  705. if (cb) cb();
  706. }
  707. }.bind(this));
  708. if (this.nextPlayPrefixFunction) this.nextPlayPrefixFunction = null;
  709. }.bind(this)
  710. if (this.stopWhile){
  711. if (this.stopWhile == diff["id"]) this.stop = true;
  712. }
  713. if (!this.stop || !this.playing) {
  714. endFunction();
  715. } else{
  716. if (this.stopWhile){
  717. this.stopWhile = "";
  718. //this.playing = false;
  719. }
  720. this.nextPlayPrefixFunction = endFunction;
  721. }
  722. this.checkToolbar();
  723. }.bind(this), (invisible ? 100: this.options.speed*this.options.inforTime));
  724. }.bind(this));
  725. break;
  726. case DIFF_EQUAL:
  727. if (this.reverse){
  728. start -= diff[1].length;
  729. this.diffIndex--;
  730. if (this.diffIndex>=0){
  731. this.doDiffsAnimation(obj, start, callback);
  732. }else{
  733. if (callback) callback();
  734. }
  735. }else{
  736. start += diff[1].length;
  737. this.diffIndex++;
  738. if (this.diffIndex<this.currentDiffs.length){
  739. this.doDiffsAnimation(obj, start, callback);
  740. }else{
  741. if (callback) callback();
  742. }
  743. }
  744. break;
  745. }
  746. },
  747. doInsetAnimation: function(node, str, callback){
  748. var tmp = new Element("div", {"html": str});
  749. if (!tmp.get("text").trim()){
  750. if (callback) callback(true);
  751. }else{
  752. var nodes = tmp.childNodes;
  753. this.doInsetNodeAnimation(node, nodes, 0, callback);
  754. }
  755. },
  756. doInsetNodeAnimation: function(ins, nodes, idx, callback){
  757. var node = nodes[idx];
  758. if (node.nodeType == Node.TEXT_NODE){
  759. this.doCharAnimation(ins, node.nodeValue, 0, function(){
  760. idx++;
  761. if (idx<nodes.length){
  762. this.doInsetNodeAnimation(ins, nodes, idx, callback);
  763. }else{
  764. if (callback) callback();
  765. }
  766. }.bind(this));
  767. }else{
  768. var duration = this.options.speed*this.options.fxTime/nodes.length;
  769. if (!duration){
  770. ins.appendChild(node);
  771. idx++;
  772. if (idx<nodes.length){
  773. this.doInsetNodeAnimation(ins, nodes, idx, callback);
  774. }else{
  775. if (callback) callback();
  776. }
  777. }else{
  778. var span = new Element("span", {"styles": {"opacity": 0}}).inject(ins);
  779. span.appendChild(node);
  780. var fx = new Fx.Tween(span, {property: 'opacity', duration:duration});
  781. fx.start(0,1).chain(function(){
  782. idx++;
  783. if (idx<nodes.length){
  784. this.doInsetNodeAnimation(ins, nodes, idx, callback);
  785. }else{
  786. if (callback) callback();
  787. }
  788. }.bind(this));
  789. }
  790. }
  791. },
  792. doCharAnimation: function(node, str, idx, callback){
  793. var duration = this.options.speed*this.options.fxTime/str.length;
  794. if (!duration){
  795. node.set("html", str);
  796. idx = str.length;
  797. if (callback) callback();
  798. }else{
  799. var char = str.charAt(idx);
  800. var span = new Element("span", {"styles": {"opacity": 0}, "html": char}).inject(node);
  801. var fx = new Fx.Tween(span, {property: 'opacity', duration:duration});
  802. fx.start(0,1).chain(function(){
  803. idx++;
  804. if (idx<str.length){
  805. this.doCharAnimation(node, str, idx, callback);
  806. }else{
  807. if (callback) callback();
  808. }
  809. }.bind(this));
  810. }
  811. },
  812. doDeleteAnimation: function(node, diff, obj, callback){
  813. var str = diff[1];
  814. var tmp = new Element("div", {"html": str});
  815. if (!tmp.get("text").trim()){
  816. if (callback) callback(null);
  817. }else{
  818. var deleteInforDiv = (!this.stopWhile || this.stopWhile == diff["id"]) ? this.createDiifInforNode(obj, node, "#fbe0e7", MWF.xApplication.process.Xform.LP.documentHistory.deleteContent) : null;
  819. var fx = new Fx.Tween(node, {property: 'opacity', duration:this.options.speed*this.options.fxTime});
  820. fx.start(1,0.5).chain(function(){
  821. if (callback) callback(deleteInforDiv);
  822. }.bind(this));
  823. }
  824. }
  825. });
  826. MWF.xApplication.process.Xform.widget.DocumentHistory.Item = new Class({
  827. initialize: function(history, historyData){
  828. this.history = history;
  829. this.documentEditor = this.history.documentEditor;
  830. this.css = this.history.css;
  831. this.historyData = historyData;
  832. this.load();
  833. },
  834. load: function(){
  835. var patchs = this.historyData.json.patchObj || null;
  836. var obj = this.historyData;
  837. this.node = new Element("div", {"styles": this.css.historyListItemNode}).inject(this.history.historyListContentAreaNode);
  838. var patchHtml = "<div style='font-weight: bold; height: 30px; line-height: 30px'>"+o2.name.cn(obj.person)+" ["+obj.activityName+"]</div><div style='height: 20px; line-height: 20px; color:#666666'>"+obj.createTime+"</div>"
  839. this.patchNode = new Element("div", {"styles": this.css.historyListItemPatchNode, "html": patchHtml}).inject(this.node);
  840. this.diffsNode = new Element("div", {"styles": this.css.historyListItemDiffsNode}).inject(this.node);
  841. var _self = this;
  842. if (patchs){
  843. patchs.each(function(patch){
  844. patch.diffs.each(function(diff){
  845. if (diff[0]!=0){
  846. diff["id"] = (new o2.widget.UUID()).toString();
  847. var tmp = new Element("div", {"html": diff[1]});
  848. infor = tmp.get("text");
  849. var infor = ((infor.length>50) ? infor.substring(0, 50)+"..." : infor);
  850. tmp.destroy();
  851. if (diff[0]==-1){
  852. infor = MWF.xApplication.process.Xform.LP.documentHistory.delete +": "+"<span style='color:red'><del>"+infor+"</del></span>"
  853. }else{
  854. infor = MWF.xApplication.process.Xform.LP.documentHistory.insert +": "+"<span style='color:blue'><ins>"+infor+"</ins></span>"
  855. }
  856. diffNode = new Element("div", {"styles": this.css.historyListItemDiffNode, "html": infor}).inject(this.diffsNode);
  857. diffNode.store("diff", diff);
  858. diff["item"] = {
  859. "node": diffNode,
  860. "showCurrent": function(show){
  861. var thisDiff = this.node.retrieve("diff");
  862. var color = (thisDiff[0]==-1) ? "#fbe0e7": "#e2edfb";
  863. this.node.setStyles({"background-color": color});
  864. var ss = _self.history.historyListContentAreaNode.getScrollSize();
  865. var s = _self.history.historyListContentAreaNode.getSize();
  866. if (ss.y>s.y) if (show) this.node.scrollIn();
  867. },
  868. "hideCurrent": function(){
  869. this.node.setStyles(_self.css.historyListItemDiffNode);
  870. }
  871. };
  872. diffNode.addEvents({
  873. // "mouseover": function(){
  874. // if (_self.history.stop){
  875. // var diff = this.retrieve("diff");
  876. // var color = (diff[0]==-1) ? "red": "blue";
  877. // this.setStyles({"border-color": color});
  878. // }
  879. // },
  880. // "mouseout": function(){ if (_self.history.stop) this.setStyles(_self.css.historyListItemDiffNode_out) },
  881. "click": function(){
  882. if (_self.history.stop){
  883. var diff = this.retrieve("diff");
  884. _self.history.to(diff);
  885. }
  886. }
  887. });
  888. }
  889. }.bind(this));
  890. }.bind(this));
  891. }else{
  892. infor = MWF.xApplication.process.Xform.LP.documentHistory.original;
  893. diffNode = new Element("div", {"styles": this.css.historyListItemDiffNode, "html": infor}).inject(this.diffsNode);
  894. this.history.originaDiff = {
  895. "node": diffNode,
  896. "showCurrent": function(){
  897. this.node.setStyles({"background-color": "#e2edfb"});
  898. //if (show) this.node.scrollIn();
  899. },
  900. "hideCurrent": function(){
  901. this.node.setStyles(_self.css.historyListItemDiffNode);
  902. }
  903. };
  904. diffNode.addEvents({
  905. "click": function(){
  906. if (_self.history.stop){
  907. _self.history.origina();
  908. }
  909. }
  910. });
  911. }
  912. }
  913. })