Monitor.js 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  1. MWF.xApplication.process.Xform.widget = MWF.xApplication.process.Xform.widget || {};
  2. //MWF.xDesktop.requireApp("process.Xform", "widget.RestActions", null, false);
  3. MWF.require("MWF.widget.Common", null, false);
  4. MWF.require("MWF.widget.MWFRaphael", null, false);
  5. MWF.xApplication.process.Xform.widget.Monitor = new Class({
  6. Implements: [Options, Events],
  7. Extends: MWF.widget.Common,
  8. options: {
  9. "style": "default"
  10. },
  11. initialize: function(container, worklog, recordList, processid, options, module){
  12. this.setOptions(options);
  13. this.path = "../x_component_process_Xform/widget/$Monitor/";
  14. this.cssPath = "../x_component_process_Xform/widget/$Monitor/"+this.options.style+"/css.wcss";
  15. this._loadCss();
  16. this.container = $(container);
  17. this.worklog = worklog;
  18. this.recordList = recordList;
  19. this.processid = processid;
  20. this.mobileScale = 2;
  21. this.module = module;
  22. this.load();
  23. },
  24. load: function(){
  25. this.logProcessChartNode = new Element("div", {"styles": this.css.logProcessChartNode}).inject(this.container);
  26. this.logPathChartNode = new Element("div", {"styles": this.css.logPathChartNode}).inject(this.container);
  27. this.checkMonitorOpen();
  28. },
  29. checkMonitorOpen: function(){
  30. var moduleNode = this.container;
  31. var module = moduleNode.retrieve("module");
  32. var isDisplayNode = false;
  33. var isTabContent = false;
  34. while (true){
  35. if (moduleNode.getStyle("display")==="none"){
  36. isDisplayNode = true;
  37. }
  38. if (module && module.json.type==="Tab$Content"){
  39. isTabContent = true;
  40. }
  41. if (isDisplayNode && isTabContent) break;
  42. moduleNode = moduleNode.getParent();
  43. if (!moduleNode) break;
  44. if (!isTabContent) module = moduleNode.retrieve("module");
  45. }
  46. if (isDisplayNode){
  47. if (isTabContent){
  48. for (var i=0; i<module.tab.tab.pages.length; i++){
  49. if (module.tab.tab.pages[i].contentNode === module.node) break;
  50. }
  51. module.tab.tab.pages[i].setOptions({
  52. "onPostShow": function(){
  53. this.openProcess();
  54. }.bind(this)
  55. });
  56. }else{
  57. this.openProcessChartAction = new Element("div", {"styles": this.css.openProcessChartAction, "text": "Show Process"}).inject(this.logProcessChartNode);
  58. this.openProcessChartAction.addEvent("click", function(e){
  59. this.openProcess(e);
  60. }.bind(this));
  61. }
  62. }else{
  63. this.openProcess();
  64. }
  65. },
  66. openProcess: function(){
  67. if (!this.process){
  68. this.logProcessChartNode.empty();
  69. this.loadToolbar();
  70. this.paperNode = new Element("div.paperNode", {"styles": (layout.mobile) ? this.css.paperNodeMobile : this.css.paperNode}).inject(this.logProcessChartNode);
  71. //this.paperNode.addEvent("scroll", function(){
  72. // this.setCountNodePosition();
  73. //}.bind(this));
  74. this.getProcess(function(json){
  75. this.processData = json.data;
  76. this.loadPaper();
  77. this.bindTabEvent();
  78. }.bind(this));
  79. }
  80. },
  81. loadToolbar: function(){
  82. MWF.require("MWF.widget.Toolbar", function(){
  83. this.toolbarNode = new Element("div").inject(this.logProcessChartNode);
  84. this.createToolbarNode("play.png", "logPlay", "");
  85. //this.createToolbarNode("pause.png", "logPause", "true");
  86. //this.createToolbarNode("stop.png", "playStop", "true");
  87. //this.createToolbarNode("prev.png", "logPrev", "true");
  88. //this.createToolbarNode("next.png", "logNext", "");
  89. this.toolbar = new MWF.widget.Toolbar(this.toolbarNode, {"style": this.options.style}, this);
  90. this.toolbar.load();
  91. }.bind(this));
  92. },
  93. createToolbarNode: function(img, action, disabled){
  94. new Element("div", {
  95. "MWFnodetype": "MWFToolBarButton",
  96. "MWFButtonImage": this.path+""+this.options.style+"/tools/"+img,
  97. "title": "",
  98. "MWFButtonAction": action,
  99. "MWFButtonText": "",
  100. "MWFButtonDisable": disabled
  101. }).inject(this.toolbarNode);
  102. },
  103. logPlay: function(){
  104. if (this.process){
  105. this.isPlaying = true;
  106. this.toolbar.childrenButton[0].setDisable(true);
  107. //this.toolbar.childrenButton[1].setDisable(false);
  108. //this.toolbar.childrenButton[2].setDisable(false);
  109. this.processReturnStyle();
  110. this.playBegin();
  111. this.playToNextActivity();
  112. }
  113. },
  114. playBegin: function(){
  115. var src = "../x_component_process_Xform/widget/$Monitor/"+this.options.style+"/fly.png";
  116. this.playIcon = this.paper.image(src, this.process.begin.center.x-16, this.process.begin.center.y-16, 32, 32);
  117. this.playLogNode = null;
  118. this.playsStatus = {
  119. "index": 0
  120. };
  121. this.isPlaying = true;
  122. },
  123. playGetNextActivity: function(){
  124. var log = this.worklog[this.playsStatus.index];
  125. var activityType = log.fromActivityType;
  126. var activity = (activityType.toLowerCase()=="begin") ? this.process.begin : this.process[activityType+"s"][log.fromActivity];
  127. return {"log": log, "activity": activity};
  128. },
  129. playToNextActivity: function(route){
  130. var activity = this.playGetNextActivity();
  131. if (this.playsStatus.index == 0){
  132. this.playToActivityStop(activity.activity, activity.log);
  133. }else{
  134. this.playMoveToActivity(activity.activity, activity.log, route);
  135. }
  136. },
  137. playMoveToActivity: function(activity, log, route){
  138. if (route){
  139. var points = [route.beginPoint];
  140. points = points.concat(route.positionPoints, [route.endPoint], [{"x": activity.center.x, "y": activity.center.y}]);
  141. this.playMoveByRoutePoint(points, function(){
  142. this.playToActivityStop(activity, log, route);
  143. }.bind(this));
  144. }else{
  145. this.playToActivityStop(activity, log, route);
  146. }
  147. },
  148. playMoveByRoutePoint: function(points, callback){
  149. var p = {"x": this.playIcon.attr("x").toFloat(), "y": this.playIcon.attr("y").toFloat()};
  150. var toP = points.shift();
  151. var d = MWFRaphael.getPointDistance(p, toP);
  152. var ms = d/0.2;
  153. this.playIcon.animate({"x": toP.x-16, "y": toP.y-16}, ms, "linear", function() {
  154. if (points.length) {
  155. this.playMoveByRoutePoint(points, callback);
  156. } else {
  157. if (callback) callback();
  158. }
  159. }.bind(this));
  160. },
  161. playToActivityStop: function(activity, log, prevRoute){
  162. this.playIcon.attr({
  163. "x": activity.center.x-16,
  164. "y": activity.center.y-16
  165. });
  166. if (log.connected){
  167. activity.shap.attr(this.css.passedActivityShap);
  168. }else{
  169. activity.shap.attr(this.css.currentActivityShap);
  170. }
  171. var route = this.process.routes[log.route];
  172. if (prevRoute){
  173. prevRoute.line.attr(this.css.passedRouteShap);
  174. prevRoute.point.attr(this.css.passedRouteFillShap);
  175. prevRoute.arrow.attr(this.css.passedRouteFillShap);
  176. }
  177. if( !layout.mobile ){
  178. this.ensureRectIsVisible(activity);
  179. }
  180. this.showPlayLog(activity,log);
  181. this.playsStatus.index++;
  182. window.setTimeout(function(){
  183. if (this.worklog.length<=this.playsStatus.index){
  184. this.playStop();
  185. }else{
  186. this.playLogNode.destroy();
  187. this.playLogNode = null;
  188. this.playToNextActivity(route);
  189. }
  190. }.bind(this), 2000);
  191. },
  192. showPlayLog: function(activity,log){
  193. // var offset = this.paperNode.getPosition(this.paperNode.getOffsetParent());
  194. // var size = this.paperNode.getSize();
  195. this.playLogNode = this.createWorkLogNode([log], activity);
  196. this.playLogNode.setStyle("display", this.playLogNode.get("html") ? "block" : "none");
  197. // var p = this.getlogNodePosition(activity, this.playLogNode, offset, size);
  198. // this.playLogNode.setPosition({"x": p.x, "y": p.y});
  199. this.setWorkLogPosition(activity, this.playLogNode);
  200. },
  201. ensureRectIsVisible: function(activity) {
  202. // 获取矩形的位置和尺寸
  203. var rectTop = activity.point.y;
  204. var rectLeft = activity.point.x;
  205. var rectHeight = activity.height;
  206. var rectWidth = activity.width;
  207. var rectBottom = rectTop + rectHeight;
  208. var rectRight = rectLeft + rectWidth;
  209. var scrollParent = this.paperNode;
  210. // 获取父滚动区域的尺寸和滚动位置
  211. var scrollSize = scrollParent.getSize();
  212. var scrollTop = scrollParent.scrollTop;
  213. var scrollLeft = scrollParent.scrollLeft;
  214. var scrollBottom = scrollSize.y + scrollTop;
  215. var scrollRight = scrollSize.x + scrollLeft;
  216. // console.log(JSON.stringify({
  217. // rectTop: rectTop,
  218. // rectLeft: rectLeft,
  219. // rectRight: rectRight,
  220. // rectBottom: rectBottom,
  221. // rectHeight: rectHeight,
  222. // rectWidth: rectWidth,
  223. // scrollTop: scrollTop,
  224. // scrollLeft:scrollLeft,
  225. // scrollBottom: scrollBottom,
  226. // scrollRight:scrollRight,
  227. // scrollSizeX: scrollSize.x,
  228. // scrollSizeY: scrollSize.y
  229. // }, null, 2));
  230. if( layout.mobile ){
  231. // rectTop = rectTop / this.mobileScale;
  232. // rectLeft = rectLeft / this.mobileScale;
  233. // rectHeight = rectHeight / this.mobileScale;
  234. // rectWidth = rectWidth / this.mobileScale;
  235. // rectBottom = (rectTop + rectHeight) / this.mobileScale;
  236. // rectRight = (rectLeft + rectWidth) / this.mobileScale;
  237. // scrollTop = scrollTop / this.mobileScale;
  238. // scrollLeft = scrollLeft / this.mobileScale;
  239. // scrollBottom = scrollBottom / this.mobileScale;
  240. // scrollRight = scrollRight / this.mobileScale;
  241. // scrollSize.x = scrollSize.x * this.mobileScale;
  242. // scrollSize.y = scrollSize.y * this.mobileScale;
  243. }
  244. // 检查是否需要垂直滚动
  245. if (rectTop < scrollTop) {
  246. // 矩形顶部在视口上方,需要向上滚动
  247. scrollParent.scrollTop = rectTop;
  248. } else if (rectBottom > scrollBottom) {
  249. // 矩形底部在视口下方,需要向下滚动
  250. scrollParent.scrollTop = rectBottom - scrollSize.y;
  251. }
  252. // 检查是否需要水平滚动
  253. if (rectLeft < scrollLeft) {
  254. // 矩形左侧在视口左方,需要向左滚动
  255. scrollParent.scrollLeft = rectLeft;
  256. } else if (rectRight > scrollRight) {
  257. // 矩形右侧在视口右方,需要向右滚动
  258. scrollParent.scrollLeft = rectRight - scrollSize.x;
  259. }
  260. },
  261. playStop: function(){
  262. this.playIcon.remove();
  263. if (this.playLogNode) this.playLogNode.destroy();
  264. this.playLogNode = null;
  265. this.playsStatus = {
  266. "index": 0
  267. };
  268. this.isPlaying = false;
  269. this.toolbar.childrenButton[0].setDisable(false);
  270. //this.toolbar.childrenButton[1].setDisable(true);
  271. //this.toolbar.childrenButton[2].setDisable(true);
  272. this.clearCount();
  273. this.loadWorkLog();
  274. },
  275. processReturnStyle: function(){
  276. this.worklog.each(function(log){
  277. var activityType = log.fromActivityType;
  278. var activity = (activityType.toLowerCase()=="begin") ? this.process.begin : this.process[activityType+"s"][log.fromActivity];
  279. activity.shap.attr(activity.style.shap);
  280. activity.passedCount = 0;
  281. activity.worklogs = [];
  282. var route = this.process.routes[log.route];
  283. if (route){
  284. route.line.attr(this.process.css.route.line.normal);
  285. route.point.attr(this.process.css.route.decision.normal);
  286. route.arrow.attr(this.process.css.route.arrow.normal);
  287. }
  288. if (log.taskCompletedList && log.taskCompletedList.length){
  289. log.taskCompletedList.each(function(tc){
  290. if (tc.processingType === "appendTask"){
  291. if (activity.routes && activity.routes.length){
  292. activity.routes.each(function(r){
  293. if (tc.routeName === r.data.name){
  294. r.line.attr(this.process.css.route.line.normal);
  295. r.point.attr(this.process.css.route.decision.normal);
  296. r.arrow.attr(this.process.css.route.arrow.normal);
  297. }
  298. }.bind(this));
  299. }
  300. }
  301. }.bind(this));
  302. }
  303. if (activity.countSet) activity.countSet.remove();
  304. }.bind(this));
  305. },
  306. loadPaper: function(){
  307. MWFRaphael.load(function(){
  308. this.paperInNode = new Element("div", {"styles": this.css.paperInNode}).inject(this.paperNode);
  309. this.paper = Raphael(this.paperInNode, "98%", "99%");
  310. this.paper.container = this.paperNode;
  311. MWF.xDesktop.requireApp("process.ProcessDesigner", "Process", function(){
  312. this.process = new MWF.APPPD.Process(this.paper, this.processData, this, {"style":"flat", "isView": true,
  313. "onPostLoad": function(){
  314. if (layout.mobile){
  315. var s = this.paper.canvas.getSize();
  316. var x = s.x*this.mobileScale;
  317. var y = s.y*this.mobileScale;
  318. this.paper.canvas.set({
  319. "viewBox": "0 0 "+x+" "+y+"",
  320. "preserveAspectRatio": "xMinYMin meet"
  321. });
  322. }
  323. this.loadWorkLog();
  324. this.fireEvent("postLoad");
  325. }.bind(this)
  326. });
  327. this.process.load();
  328. }.bind(this));
  329. }.bind(this));
  330. },
  331. getProcess: function(callback){
  332. this.action = MWF.Actions.get("x_processplatform_assemble_surface");
  333. //this.action = new MWF.xApplication.process.Xform.widget.RestActions("x_processplatform_assemble_surface");
  334. //this.action = new MWF.xApplication.process.Xform.widget.RestActions("x_processplatform_assemble_designer");
  335. this.action.getProcess(function(json){
  336. if (callback) callback(json);
  337. }, null, this.processid)
  338. },
  339. clearCount: function (){
  340. var activitys = {};
  341. this.worklog.each(function(log){
  342. var activityType = log.fromActivityType;
  343. var activity = (activityType.toLowerCase()=="begin") ? this.process.begin : this.process[activityType+"s"][log.fromActivity];
  344. activity.passedCount = 0;
  345. activity.worklogs = [];
  346. if (!activitys[log.fromActivity]) activitys[log.fromActivity] = activity
  347. }.bind(this));
  348. if (this.recordList){
  349. this.recordList.each(function (r, i){
  350. var activity = activitys[r.fromActivity];
  351. if(activity)activity.recordCount = 0;
  352. }.bind(this));
  353. }
  354. },
  355. loadWorkLog: function(){
  356. this.countNodes = [];
  357. var activitys = {};
  358. this.worklogToken = {};
  359. this.worklog.each(function(log){
  360. this.worklogToken[log.fromActivityToken] = log;
  361. var activityType = log.fromActivityType;
  362. var activity = (activityType.toLowerCase()=="begin") ? this.process.begin : this.process[activityType+"s"][log.fromActivity];
  363. if (log.connected){
  364. activity.shap.attr(this.css.passedActivityShap);
  365. }else{
  366. activity.shap.attr(this.css.currentActivityShap);
  367. }
  368. var route = this.process.routes[log.route];
  369. if (route){
  370. route.line.attr(this.css.passedRouteShap);
  371. route.point.attr(this.css.passedRouteFillShap);
  372. route.arrow.attr(this.css.passedRouteFillShap);
  373. }
  374. if (log.taskCompletedList && log.taskCompletedList.length){
  375. log.taskCompletedList.each(function(tc){
  376. if (tc.processingType === "appendTask"){
  377. if (activity.routes && activity.routes.length){
  378. activity.routes.each(function(r){
  379. if (tc.routeName === r.data.name){
  380. r.line.attr(this.css.passedRouteShap);
  381. r.point.attr(this.css.passedRouteFillShap);
  382. r.arrow.attr(this.css.passedRouteFillShap);
  383. }
  384. }.bind(this));
  385. }
  386. }
  387. }.bind(this));
  388. }
  389. var passedCount = log.taskCompletedList.length;
  390. //var passedCount = log.taskCompletedList.length || 1;
  391. if (passedCount) activity.passedCount = (activity.passedCount) ? activity.passedCount+passedCount : passedCount;
  392. if (!activity.worklogs) activity.worklogs = [];
  393. activity.worklogs.push(log);
  394. if (!activitys[log.fromActivity]) activitys[log.fromActivity] = activity
  395. }.bind(this));
  396. if (this.recordList){
  397. this.recordList.each(function (r, i){
  398. var activity = activitys[r.fromActivity];
  399. if (!activity.recordCount) activity.recordCount = 0
  400. activity.recordCount++;
  401. }.bind(this));
  402. }
  403. var offset = this.paperNode.getPosition(this.paperNode.getOffsetParent());
  404. var size = this.paperNode.getSize();
  405. Object.each(activitys, function(activity){
  406. this.writePassCount(activity);
  407. this.writeWorkLog(activity, offset, size);
  408. }.bind(this));
  409. },
  410. writePassCount: function(activity){
  411. if (activity.passedCount || activity.recordCount){
  412. var x = activity.point.x+activity.width;
  413. var y = activity.point.y;
  414. var shap = this.paper.circle(x, y, 9);
  415. shap.attr(this.css.activityPassedCount);
  416. text = this.paper.text(x, y, activity.recordCount || activity.passedCount);
  417. text.attr(this.css.activityPassedCountText);
  418. activity.countSet = this.paper.set();
  419. activity.countSet.push(shap, text);
  420. }
  421. },
  422. writeWorkLog: function(activity, offset, size){
  423. var _self = this;
  424. activity.set.click(function(e){
  425. if (!_self.isPlaying){
  426. if (this.process.selectedActivitys.length){
  427. if (!this.noselected){
  428. this.selected();
  429. _self.showWorklog(this, offset, size);
  430. }
  431. this.noselected = false;
  432. }
  433. if (this.countSet) this.countSet.toFront();
  434. }
  435. e.stopPropagation();
  436. }.bind(activity));
  437. activity.set.mousedown(function(e){
  438. if (!_self.isPlaying) {
  439. if (!this.process.selectedActivitys.length) {
  440. this.selected();
  441. _self.showWorklog(this, offset, size);
  442. }
  443. if (this.countSet) this.countSet.toFront();
  444. }
  445. e.stopPropagation();
  446. }.bind(activity));
  447. this.paper.canvas.addEvent("click", function(e){
  448. if (!_self.isPlaying) {
  449. if (this.unSelectedEvent) {
  450. if (this.currentSelected || this.selectedActivitys.length) {
  451. this.unSelected(e);
  452. _self.hideCurrentWorklog();
  453. }
  454. } else {
  455. this.unSelectedEvent = true;
  456. }
  457. }
  458. }.bind(this.process));
  459. },
  460. getlogNodePosition : function(activity, node, offset, psize){
  461. var targetCoondinates = {
  462. left: activity.point.x,
  463. top: activity.point.y,
  464. width: activity.width,
  465. height: activity.height,
  466. right: activity.point.x + activity.width,
  467. bottom: activity.point.y + activity.height
  468. };
  469. var containerScroll = this.paperNode.getScroll();
  470. var containerSize = this.paperNode.getSize();
  471. var nodeSize = node.getSize();
  472. var left;
  473. var offsetX = 10;
  474. var priorityOfX = [ "center", "right", "left" ];
  475. for( var i=0; i<priorityOfX.length; i++ ){
  476. if( priorityOfX[i] === "left" ){
  477. if( targetCoondinates.left - containerScroll.x > containerSize.x - targetCoondinates.right){
  478. left = targetCoondinates.left - nodeSize.x - offsetX;
  479. positionX = "left";
  480. break;
  481. }
  482. }
  483. if( priorityOfX[i] === "right" ){
  484. if( containerSize.x + containerScroll.x - targetCoondinates.right > nodeSize.x ){
  485. left = targetCoondinates.right + offsetX;
  486. positionX = "right";
  487. break;
  488. }
  489. }
  490. }
  491. if( !left ){
  492. if( targetCoondinates.left - containerScroll.x > containerSize.x - targetCoondinates.right){
  493. left = targetCoondinates.left - nodeSize.x - offsetX;
  494. positionX = "left";
  495. }else{
  496. left = targetCoondinates.right + offsetX;
  497. positionX = "right";
  498. }
  499. }
  500. var top;
  501. var priorityOfY = [ "middle", "bottom", "top" ];
  502. for( var i=0; i<priorityOfY.length; i++ ){
  503. if( priorityOfY[i] === "middle" ){
  504. if( targetCoondinates.top + (targetCoondinates.height/2) - ( nodeSize.y / 2 ) > containerScroll.y &&
  505. targetCoondinates.bottom - (targetCoondinates.height/2) + ( nodeSize.y / 2 ) - containerScroll.y < containerSize.y ){
  506. top = targetCoondinates.top + (targetCoondinates.height/2) - ( nodeSize.y / 2 ) ;
  507. this.positionY = "middle";
  508. break;
  509. }
  510. }
  511. if( priorityOfY[i] === "top" ){
  512. if( targetCoondinates.top - containerScroll.y > containerSize.y - targetCoondinates.bottom ){
  513. top = targetCoondinates.bottom - nodeSize.y;
  514. this.positionY = "top";
  515. break;
  516. }
  517. }
  518. if( priorityOfY[i] === "bottom" ){
  519. if( containerSize.y + containerScroll.y - targetCoondinates.bottom > nodeSize.y ){
  520. top = targetCoondinates.top;
  521. this.positionY = "bottom";
  522. break;
  523. }
  524. }
  525. }
  526. if( !top ){
  527. if( targetCoondinates.top + (targetCoondinates.height/2) - ( nodeSize.y / 2 ) > containerScroll.y &&
  528. targetCoondinates.bottom - (targetCoondinates.height/2) + ( nodeSize.y / 2 ) - containerScroll.y < containerSize.y ){
  529. top = targetCoondinates.top + (targetCoondinates.height/2) - ( nodeSize.y / 2 ) ;
  530. this.positionY = "middle";
  531. } else if( targetCoondinates.top - containerScroll.y > containerSize.y - targetCoondinates.bottom ){
  532. top = targetCoondinates.bottom - nodeSize.y;
  533. this.positionY = "top";
  534. }else{
  535. top = targetCoondinates.top;
  536. this.positionY = "bottom";
  537. }
  538. }
  539. // var arrowOffsetY = 0;
  540. // if( this.options.isFitToContainer ){
  541. if( top < containerScroll.y ){
  542. // arrowOffsetY = containerScroll.y - top;
  543. top = containerScroll.y;
  544. }else if( top + nodeSize.y > containerSize.y + containerScroll.y ){
  545. // arrowOffsetY = containerSize.y + containerScroll.y - top - nodeSize.y;
  546. top = containerSize.y + containerScroll.y - nodeSize.y;
  547. }
  548. return {
  549. "x" : left,
  550. "y" : top
  551. };
  552. },
  553. getlogNodePosition_bak: function(activity, node, offset, psize){
  554. offset.x = 0;
  555. offset.y = 0;
  556. var size = node.getSize();
  557. var y = 0;
  558. var x = activity.point.x+activity.width+15+offset.x;
  559. tmpX = x + size.x;
  560. if (tmpX>offset.x+psize.x){
  561. x = activity.point.x - size.x - 15 + offset.x;
  562. if (x<offset.x){
  563. y = activity.point.y-size.y-15+offset.y;
  564. x = activity.center.x - (size.x/2) + offset.x;
  565. }else{
  566. y = activity.center.y - (size.y/2) + offset.y;
  567. if (y<offset.y){
  568. y = offset.y
  569. }
  570. }
  571. }else{
  572. y = activity.center.y - (size.y/2) + offset.y;
  573. if (y<offset.y){
  574. y = offset.y
  575. }
  576. }
  577. if( x + size.x > psize.x )x = psize.x - size.x;
  578. if( y + size.y > psize.y )y = psize.y - size.y;
  579. if( x < 0 )x = 0;
  580. if( y < 0 )y = 0;
  581. // var p = this.paperNode.getScroll();
  582. // var scrollY = 0;
  583. // var scrollX = 0;
  584. // var tmpNode = this.paperNode.getParent();
  585. // while (tmpNode){
  586. // var s = tmpNode.getScroll();
  587. // scrollY += s.y;
  588. // scrollX += s.x;
  589. // tmpNode = tmpNode.getParent();
  590. // }
  591. // y = y-p.y-scrollY;
  592. // x = x-p.x-scrollX;
  593. return {"x": x, "y": y};
  594. },
  595. showWorklog: function(activity, offset, psize){
  596. this.hideCurrentWorklog();
  597. if (!activity.worklogNode) activity.worklogNode = this.createWorkLogNode(activity.worklogs, activity);
  598. this.currentWorklogNode = activity.worklogNode;
  599. this.currentWorklogNode.setStyle("display", !!this.currentWorklogNode.get("html") ? "block" : "none");
  600. this.setWorkLogPosition(activity, activity.worklogNode, offset, psize);
  601. },
  602. setWorkLogPosition(activity, logNode, offset, psize){
  603. if( !logNode )logNode = activity.worklogNode;
  604. if( layout.mobile ){
  605. var pSize = this.paperNode.getSize();
  606. var bodySize = $(document.body).getSize();
  607. if( this.paperNode.getPosition().y + pSize.y > bodySize.y ){
  608. var mobileActionNode = document.body.getElement(".o2_form_mobile_actions");
  609. logNode.inject( $(document.body) );
  610. logNode.setStyles({
  611. "display": "block",
  612. "position": "absolute",
  613. "width": "calc( 100% - 4px )",
  614. "max-width": "500px",
  615. "bottom": mobileActionNode ? (mobileActionNode.getSize().y+1+"px") : "1px",
  616. "left": "0px"
  617. });
  618. logNode.setStyle("left", (bodySize.x - logNode.getSize().x)/2 + "px");
  619. }else{
  620. logNode.inject( this.paperNode );
  621. logNode.setStyles({
  622. "display": "block",
  623. "position": "absolute",
  624. "width": "calc( 100% - 4px )",
  625. "max-width": "500px",
  626. "bottom": "1px",
  627. "left": "0px"
  628. });
  629. logNode.setStyle("left", (pSize.x - logNode.getSize().x)/2 + "px");
  630. }
  631. }else{
  632. var p = this.getlogNodePosition(activity, logNode, offset, psize);
  633. logNode.setPosition({"x": p.x, "y": p.y});
  634. }
  635. },
  636. hideCurrentWorklog: function(){
  637. if (this.currentWorklogNode){
  638. this.currentWorklogNode.setStyle("display", "none");
  639. this.currentWorklogNode = null;
  640. }
  641. },
  642. bindTabEvent: function(){
  643. if( this.module ){
  644. var tab = this.module.getParentModule();
  645. if( tab && tab.page ){
  646. tab.page.addEvent("postHide", function () {
  647. if(this.currentWorklogNode)this.currentWorklogNode.hide()
  648. }.bind(this))
  649. }
  650. }
  651. },
  652. createWorkLogNode: function(worklogs, activity){
  653. var node = new Element("div", {"styles": this.css.workLogNode});
  654. if (this.recordList){
  655. var logs = this.recordList.filter(function(r){
  656. return r.fromActivity === activity.data.id;
  657. });
  658. logs.each(function(log, idx){
  659. var workNode = new Element("div", {"styles": this.css.workLogWorkNode}).inject(node);
  660. if ((idx % 2)==0){
  661. workNode.setStyle("background-color", "#FFF");
  662. }else{
  663. workNode.setStyle("background-color", "#EEE");
  664. }
  665. var router, opinion, arrivedActivitys, arrivedUsers;
  666. arrivedActivitys = log.properties.nextManualList.map(function(o){
  667. return o.activityName;
  668. }).join(",");
  669. arrivedUsers = (log.properties.nextManualTaskIdentityList && log.properties.nextManualTaskIdentityList.length) ? o2.name.cns(log.properties.nextManualTaskIdentityList).join(",") : "";
  670. switch (log.type) {
  671. case "empower":
  672. router = MWF.xApplication.process.Xform.LP.empower;
  673. var empowerTo = (log.properties.nextManualTaskIdentityList && log.properties.nextManualTaskIdentityList.length) ? o2.name.cns(log.properties.nextManualTaskIdentityList).join(",") : "";
  674. opinion = MWF.xApplication.process.Xform.LP.empowerTo + empowerTo;
  675. break;
  676. case "retract":
  677. router = MWF.xApplication.process.Xform.LP.retract;
  678. opinion = MWF.xApplication.process.Xform.LP.retract;
  679. break;
  680. case "reroute":
  681. router = log.properties.routeName || MWF.xApplication.process.Xform.LP.reroute;
  682. opinion = log.properties.opinion || MWF.xApplication.process.Xform.LP.rerouteTo+": "+arrivedActivitys;
  683. break;
  684. case "rollback":
  685. router = log.properties.routeName || MWF.xApplication.process.Xform.LP.rollback;
  686. opinion = log.properties.opinion || MWF.xApplication.process.Xform.LP.rollbackTo+": "+log.arrivedActivityName;
  687. break;
  688. case "reset":
  689. var resetUser = log.properties.nextManualTaskIdentityList.erase(log.identity);
  690. resetUserText = o2.name.cns(resetUser).join(",");
  691. router = MWF.xApplication.process.Xform.LP.resetTo+":"+resetUserText;
  692. opinion = log.properties.opinion || ""
  693. break;
  694. case "appendTask":
  695. case "back":
  696. case "addSplit":
  697. case "urge":
  698. case "expire":
  699. case "read":
  700. default:
  701. router = log.properties.routeName || "";
  702. opinion = log.properties.opinion || "";
  703. }
  704. if (log.type==="currentTask"){
  705. var taskNode = new Element("div", {"styles": this.css.workLogTaskNode}).inject(workNode);
  706. var html = "<div style='font-weight: bold; color: red'>"+log.person.substring(0, log.person.indexOf("@"))+" "+MWF.xApplication.process.Xform.LP.processing+" </div>";
  707. taskNode.set("html", html);
  708. }else{
  709. var taskNode = new Element("div", {"styles": this.css.workLogTaskNode}).inject(workNode);
  710. var html = "<div style='font-weight: bold'>"+log.person.substring(0, log.person.indexOf("@"))+": </div>";
  711. html += "<div style='margin-left: 10px'>["+router+"] "+o2.txt(opinion)+"</div>";
  712. html += "<div style='text-align: right'>"+log.recordTime+"</div>";
  713. taskNode.set("html", html);
  714. }
  715. }.bind(this));
  716. }else{
  717. worklogs.each(function(log, idx){
  718. var workNode = new Element("div", {"styles": this.css.workLogWorkNode}).inject(node);
  719. if ((idx % 2)==0){
  720. workNode.setStyle("background-color", "#FFF");
  721. }else{
  722. workNode.setStyle("background-color", "#EEE");
  723. }
  724. if (log.taskCompletedList.length+log.taskList.length<1){
  725. if (log.connected){
  726. var taskNode = new Element("div", {"styles": this.css.workLogTaskNode}).inject(workNode);
  727. var html = "<div style='font-weight: bold'>"+MWF.xApplication.process.Xform.LP.systemProcess+" </div>";
  728. html += "<div style='text-align: right'>"+log.arrivedTime+"</div>";
  729. taskNode.set("html", html);
  730. }else{
  731. var taskNode = new Element("div", {"styles": this.css.workLogTaskNode}).inject(workNode);
  732. var html = "<div style='font-weight: bold; color: red'>"+MWF.xApplication.process.Xform.LP.systemProcess+" </div>";
  733. taskNode.set("html", html);
  734. }
  735. }else{
  736. log.taskCompletedList.each(function(task){
  737. var taskNode = new Element("div", {"styles": this.css.workLogTaskNode}).inject(workNode);
  738. var html = "<div style='font-weight: bold'>"+task.person.substring(0, task.person.indexOf("@"))+": </div>";
  739. html += "<div style='margin-left: 10px'>["+(task.routeName || "")+"] "+o2.txt(task.opinion)+"</div>";
  740. html += "<div style='text-align: right'>"+task.completedTime+"</div>";
  741. taskNode.set("html", html);
  742. }.bind(this));
  743. log.taskList.each(function(task){
  744. var taskNode = new Element("div", {"styles": this.css.workLogTaskNode}).inject(workNode);
  745. var html = "<div style='font-weight: bold; color: red'>"+task.person.substring(0, task.person.indexOf("@"))+" "+MWF.xApplication.process.Xform.LP.processing+" </div>";
  746. taskNode.set("html", html);
  747. }.bind(this));
  748. }
  749. }.bind(this));
  750. }
  751. node.inject(this.paperNode);
  752. return node;
  753. }
  754. });
  755. MWF.xApplication.process.Xform.widget.Monitor.Animation = new Class({
  756. Implements: [Events],
  757. initialize: function(monitor, log){
  758. }
  759. });