Main.js 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021
  1. MWF.xApplication.MinderEditor = MWF.xApplication.MinderEditor || {};
  2. //MWF.xDesktop.requireApp("Minder", "Actions.RestActions", null, false);
  3. MWF.xDesktop.requireApp("MinderEditor", "Tools", null, false);
  4. MWF.xDesktop.requireApp("MinderEditor", "RuntimeInCommon", null, false);
  5. MWF.xDesktop.requireApp("MinderEditor", "WidgetInCommon", null, false);
  6. MWF.xDesktop.requireApp("MinderEditor", "Commands", null, false);
  7. MWF.xDesktop.requireApp("MinderEditor", "LeftToolbar", null, false);
  8. //脑图,数据样式如下:
  9. //{
  10. // "root": {
  11. // "data": {
  12. // "text": "level_1"
  13. // },
  14. // "children": [
  15. // {
  16. // "data": {
  17. // "id": "blc4k0w350cg",
  18. // "created": 1525849642649,
  19. // "text": "level_2.1"
  20. // },
  21. // "children": []
  22. // },
  23. // {
  24. // "data": {
  25. // "id": "blc4k10mh0cg",
  26. // "created": 1525849642923,
  27. // "text": "level_2.2"
  28. // },
  29. // "children": []
  30. // }
  31. // ]
  32. //},
  33. // "template": "structure",
  34. // "theme": "fresh-blue",
  35. // "version": "1.4.33"
  36. //}
  37. MWF.xApplication.MinderEditor.options = {
  38. multitask: true,
  39. executable: true
  40. };
  41. MWF.xApplication.MinderEditor.Main = new Class({
  42. Extends: MWF.xApplication.Common.Main,
  43. Implements: [Options, Events],
  44. options: {
  45. "isEdited" : false,
  46. "style": "default",
  47. "name": "MinderEditor",
  48. "icon": "icon.png",
  49. "width": "1200",
  50. "height": "700",
  51. "isResize": false,
  52. "isMax": true,
  53. "title": MWF.xApplication.MinderEditor.LP.title,
  54. "align": "center",
  55. "folderId" : "root",
  56. "minderName" : "",
  57. "menuAction" : "",
  58. "id" : "",
  59. "defaultTheme" : "fresh-blue",
  60. "defaultTemplate" : "default",
  61. "isSetDataWhenExpand" : false,
  62. "leftToolbarEnable" : true,
  63. "notePreviewerEnable" : true,
  64. "tools" : {
  65. "top" : [ "menu", "|", "save", "|", "undoredo", "|", "append", "|", "arrange", "|", "edit_remove", "|", "hyperLink", "image", "priority", "progress", "|", "style", "help" ],
  66. "left" : [ "zoom", "camera", "resetlayout", "move", "expandLevel", "selectAll", "preview", "template" , "theme", "search" ],
  67. "right" : [ "font", "resource", "note" ]
  68. },
  69. "disableTools" : [],
  70. "template" : [],
  71. "theme" : [],
  72. //dataMode参数,restful 通过MWF.xApplication.Minder.Actions.RestActions获取数据,
  73. //outer 打开应用的时候直接设置数据
  74. "dataMode" : "restful"
  75. },
  76. onQueryLoad: function () {
  77. this.lp = MWF.xApplication.MinderEditor.LP;
  78. },
  79. loadApplication: function (callback) {
  80. this.autoSaveInter = 3 * 60 * 1000;
  81. this.userName = layout.desktop.session.user.distinguishedName || layout.desktop.session.user.name;
  82. this.restActions = MWF.Actions.get("x_mind_assemble_control"); //new MWF.xApplication.Minder.Actions.RestActions();
  83. if( this.status ){
  84. this.options.isEdited = this.status.isEdited || false;
  85. this.options.isNew = this.status.isNew || false;
  86. this.options.dataMode = this.status.dataMode;
  87. }
  88. if( this.options.isEdited ){
  89. MWF.xDesktop.requireApp("MinderEditor", "RuntimeInEditMode", null, false);
  90. MWF.xDesktop.requireApp("MinderEditor", "WidgetInEditMode", null, false);
  91. MWF.xDesktop.requireApp("MinderEditor", "ToolbarInEditMode", null, false);
  92. MWF.xDesktop.requireApp("MinderEditor", "PopMenu", null, false);
  93. }else{
  94. MWF.xDesktop.requireApp("MinderEditor", "RuntimeInReadMode", null, false);
  95. }
  96. this.createNode();
  97. this.getData( function(){
  98. var name = this.data.name || this.options.title || "新建脑图";
  99. name = name.length > 30 ? name.substr(0,30) : name;
  100. this.setTitle( name );
  101. this.loadApplicationContent();
  102. }.bind(this));
  103. if( this.options.noticeText )this.notice( this.options.noticeText , "info");
  104. },
  105. getData : function( callback ){
  106. var id;
  107. if( this.options.dataMode == "outer" || (this.status && this.status.dataMode == "outer") ){
  108. if( this.status && this.status.data ){
  109. this.data = this.status.data
  110. }
  111. }else{
  112. if( this.status && this.status.id ){
  113. id = this.status.id;
  114. }else if( this.options.id ){
  115. id = this.options.id
  116. }else if( this.data && this.data.id ){
  117. id = this.data.id;
  118. }
  119. }
  120. if( id ) {
  121. this.restActions.getMind(id, function (json) {
  122. this.data = json.data;
  123. this.data.content = JSON.parse(this.data.content);
  124. if (callback)callback();
  125. }.bind(this))
  126. }else if( this.data ){
  127. if( this.data.content ){
  128. if( typeOf( this.data.content ) == "string" ){
  129. this.data.content = JSON.parse(this.data.content);
  130. }
  131. }else{
  132. this.data.content = { data : {} };
  133. }
  134. if(callback)callback();
  135. }else{
  136. this.data = { content : { data : {} } };
  137. if(callback)callback();
  138. }
  139. },
  140. createNode: function () {
  141. this.content.setStyle("overflow", "hidden");
  142. this.node = new Element("div.node", {
  143. "styles": {"width": "100%", "height": "100%", "overflow": "hidden"}
  144. }).inject(this.content);
  145. this._createNode()
  146. },
  147. _createNode : function(){
  148. if( this.options.isEdited ){
  149. this.topToolbarNode = new Element("div.topToolbar").inject(this.node);
  150. this.topToolbarNode.setStyles( this.css.topToolbar );
  151. }
  152. this.contentNode = new Element("div.contentNode").inject(this.node);
  153. this.contentNode.classList.add("km-editor");
  154. if( this.options.isEdited ){
  155. this.rightToolbarNode = new Element("div.rightToolbar").inject( this.node );
  156. this.rightToolbarNode.setStyles( this.css.rightToolbar );
  157. }
  158. this.Content_Offset_Top = this.contentNode.getCoordinates( this.node).top;
  159. this.resizeContentFun = this.resizeContent.bind(this);
  160. this.addEvent("resize", this.resizeContentFun);
  161. this.resizeContent();
  162. },
  163. loadApplicationContent: function () {
  164. this.loadResource(function () {
  165. this.loadKityMinder(this.data.content);
  166. this.debug = new MWF.xApplication.MinderEditor.Debug(true);
  167. this.key = new MWF.xApplication.MinderEditor.Key();
  168. this.fsm = new MWF.xApplication.MinderEditor.FSM('normal');
  169. this.receiver = new MWF.xApplication.MinderEditor.Receiver(this);
  170. if( this.options.isEdited ){
  171. this.popmenu = new MWF.xApplication.MinderEditor.PopMenu(this.content, this, this.minder, this);
  172. this.input = new MWF.xApplication.MinderEditor.Input(this);
  173. if (this.minder.supportClipboardEvent && !kity.Browser.gecko) {
  174. this.MimeType = new MWF.xApplication.MinderEditor.ClipboardMimeType();
  175. this.clipboard = new MWF.xApplication.MinderEditor.Clipboard(this);
  176. }
  177. this.history = new MWF.xApplication.MinderEditor.History(this.minder);
  178. this.commands = new MWF.xApplication.MinderEditor.Commands( this );
  179. this.commands.load();
  180. this.topToolbar = new MWF.xApplication.MinderEditor.TopToolbar( this, this.topToolbarNode );
  181. this.topToolbar.load();
  182. this.rightToolbar = new MWF.xApplication.MinderEditor.RightToolbar( this, this.rightToolbarNode );
  183. this.rightToolbar.load();
  184. this.drag = new MWF.xApplication.MinderEditor.Drag(this);
  185. MWF.xApplication.MinderEditor.JumpingInEditMode(this);
  186. if( this.status && this.status.autoSave ){
  187. this.startAutoSave();
  188. }
  189. }else{
  190. this.commands = new MWF.xApplication.MinderEditor.Commands( this );
  191. this.commands.load();
  192. this.drag = new MWF.xApplication.MinderEditor.Drag(this);
  193. MWF.xApplication.MinderEditor.JumpingInReadMode(this);
  194. }
  195. //this.loadNavi();
  196. if( this.options.notePreviewerEnable )new MWF.xApplication.MinderEditor.NotePrviewer( this );
  197. //this.attachEvent();
  198. }.bind(this));
  199. },
  200. openMainMenu : function( actionName ){
  201. var menuNode = this.topToolbar.getCommandNode("menu");
  202. menuNode.click();
  203. this.commands.mainMenu.show( actionName );
  204. },
  205. loadResource: function (callback) {
  206. var kityminderPath = "../o2_lib/kityminder/";
  207. COMMON.AjaxModule.loadCss("../x_component_MinderEditor/$Main/default/kityminder.editor.css", function () {
  208. COMMON.AjaxModule.loadCss(kityminderPath + "core/src/kityminder.css", function () {
  209. COMMON.AjaxModule.load("kity", function () {
  210. COMMON.AjaxModule.load("kityminder", function () {
  211. if (callback)callback();
  212. }.bind(this));
  213. }.bind(this))
  214. }.bind(this))
  215. }.bind(this))
  216. },
  217. loadExtentResource : function (callback) {
  218. var kityminderPath = "../o2_lib/kityminder/";
  219. COMMON.AjaxModule.load("../o2_lib/jquery/jquery-2.2.4.min.js", function () {
  220. COMMON.AjaxModule.load(kityminderPath + "core/dist/kityminder.core.extend.js", function () {
  221. var jquery = jQuery.noConflict();
  222. if (callback)callback();
  223. }.bind(this));
  224. }.bind(this))
  225. },
  226. loadKityMinder: function (data) {
  227. var _self = this;
  228. this.isMovingCenter = true;
  229. // 创建 km 实例
  230. /* global kityminder */
  231. var km = this.minder = new kityminder.Minder();
  232. //var target = document.querySelector('#minder-view');
  233. km.renderTo(this.contentNode);
  234. data.theme = data.theme || this.options.defaultTheme;
  235. data.template = data.template || this.options.defaultTemplate;
  236. this.deepestLevel = 0;
  237. km.on('contentchange', function(){
  238. this.updateTime = new Date();
  239. }.bind(this));
  240. km.on("import", function (e) {
  241. if (!_self.alreadyBind) {
  242. var nodes = km.getAllNode();
  243. nodes.forEach(function (node) {
  244. _self._loadMinderNode(node);
  245. });
  246. _self.alreadyBind = true;
  247. if (_self.options.leftToolbarEnable)_self.loadLeftToolbar();
  248. _self.fireEvent("postLoadMinder", _self);
  249. }
  250. });
  251. km.on("execCommand", function (e) {
  252. if (e.commandName === "template") {
  253. _self.moveToCenter();
  254. }
  255. });
  256. km.on("layoutallfinish", function () {
  257. if (_self.templateChanged || _self.isMovingCenter) {
  258. _self.moveToCenter();
  259. _self.templateChanged = false;
  260. _self.isMovingCenter = false;
  261. }
  262. });
  263. km.importJson(data);
  264. },
  265. _loadMinderNode : function( node ){
  266. var level = node.getLevel();
  267. this.deepestLevel = level > this.deepestLevel ? level : this.deepestLevel;
  268. this.fireEvent("postLoadMinderNode", node);
  269. },
  270. addMinderNodeEvents : function(minderNode, events){
  271. var cNode = minderNode.getRenderContainer().node;
  272. for( var key in events ){
  273. cNode.addEventListener( key, function ( ev ) {
  274. var coordinate = minderNode.getRenderBox('screen');
  275. events[this]( ev, minderNode, coordinate );
  276. }.bind(key));
  277. }
  278. },
  279. addMinderNoteIconEvents : function( minderNode, events ){
  280. var iconRenderer = minderNode.getRenderer('NoteIconRenderer');
  281. if( iconRenderer && iconRenderer.getRenderShape() ){
  282. var icon = iconRenderer.getRenderShape();
  283. for( var key in events ){
  284. icon.addEventListener( key, function ( ev ) {
  285. var coordinate = minderNode.getRenderBox('screen');
  286. events[this]( ev, minderNode, coordinate );
  287. }.bind(key));
  288. //icon.addEventListener("mouseover", function ( ev ) {
  289. // _self.tooltipTimer = setTimeout(function() {
  290. // var c = this.getRenderBox('screen');
  291. // _self.loadTooltip( this.getData(), c );
  292. // }.bind(this), 300);
  293. //}.bind(minderNode));
  294. }
  295. }
  296. },
  297. onExpandMinderNode : function( minderNode, callback ){
  298. var expanderNode = minderNode.getRenderer('ExpanderRenderer').getRenderShape();
  299. if( expanderNode ){
  300. expanderNode.addEventListener("mousedown", function(ev){
  301. var coordinate = minderNode.getRenderBox('screen');
  302. if(callback)callback(ev, minderNode, coordinate);
  303. }.bind(minderNode));
  304. }
  305. },
  306. replaceMinderNodeWithData : function(minderNode, data){
  307. var km = this.minder;
  308. while (minderNode.getChildren().length){
  309. var node = minderNode.getChildren()[0];
  310. km.removeNode(node)
  311. }
  312. km.importNode(minderNode, data );
  313. km.refresh();
  314. setTimeout( function(){
  315. var nodes = minderNode.getChildren();
  316. if( nodes.length ){
  317. nodes.forEach(function (node) {
  318. this._loadMinderNode(node);
  319. }.bind(this));
  320. }
  321. }.bind(this), 100)
  322. },
  323. resizeContent: function () {
  324. var size = this.content.getSize();
  325. this.contentNode.setStyles({
  326. "height": (size.y - this.Content_Offset_Top ) + "px"
  327. });
  328. if( this.rightToolbar ){
  329. this.rightToolbar.setTooltipsSize();
  330. }
  331. if( this.minder ){
  332. this.moveToCenter();
  333. }
  334. },
  335. loadLeftToolbar: function () {
  336. this.leftToolbar = new MWF.xApplication.MinderEditor.LeftToolbar(this.node, this, this.minder, this);
  337. this.leftToolbar.load();
  338. //this.navi.setMoveOpen(false);
  339. },
  340. moveToCenter: function () {
  341. //setTimeout( this._moveToCenter.bind(this) , 100 );
  342. this._moveToCenter();
  343. },
  344. _moveToCenter: function () {
  345. if (this.options.align != "center")return;
  346. //图形居中
  347. var minderView = this.minder.getRenderContainer().getRenderBox('screen'); //.getBoundaryBox();
  348. var containerView = this.contentNode.getCoordinates();
  349. var root = this.minder.getRoot();
  350. var rootView = root.getRenderContainer().getRenderBox('screen'); //getRenderBox('top');
  351. var rootClientTop = rootView.top - minderView.top;
  352. var rootClientLeft = rootView.left - minderView.left;
  353. var rootChildrenLength = root.getChildren().length;
  354. var template = this.minder.queryCommandValue("template");
  355. var left, top, isCamera = false;
  356. if (minderView.width > containerView.width) { //如果图形宽度大于容器宽度
  357. if (template == "fish-bone" || rootChildrenLength < 2) {
  358. left = 50;
  359. } else {
  360. isCamera = true;
  361. }
  362. } else {
  363. left = parseInt(( containerView.width - minderView.width ) / 2 + rootClientLeft + 50);
  364. }
  365. if (minderView.height > containerView.height) { //如果图形高度大于容器高度
  366. if (rootClientTop > containerView.height) {
  367. if (template == "fish-bone") {
  368. top = containerView.height - rootView.height
  369. } else if (rootChildrenLength < 2) {
  370. top = parseInt(containerView.width / 2);
  371. } else {
  372. isCamera = true;
  373. }
  374. } else {
  375. top = rootClientTop + 50;
  376. }
  377. } else {
  378. top = parseInt(( containerView.height - minderView.height ) / 2) + rootClientTop;
  379. }
  380. if (isCamera) {
  381. this.minder.execCommand('camera', this.minder.getRoot(), 600);
  382. } else {
  383. var dragger = this.minder.getViewDragger();
  384. dragger.moveTo(new kity.Point(left, top), 300);
  385. }
  386. },
  387. recordStatus: function () {
  388. var status = {
  389. id : this.data ? this.data.id : "",
  390. autoSave : this.autoSave,
  391. isEdited : this.options.isEdited,
  392. isNew : this.options.isNew,
  393. dataMode : this.options.dataMode
  394. };
  395. if( this.options.dataMode == "outer" ){
  396. status.data = this.data;
  397. }
  398. if( this.rightToolbar ){
  399. status.styleActive = this.rightToolbar.styleActive;
  400. status.noteActive = this.rightToolbar.noteActive;
  401. status.resourceActive = this.rightToolbar.resourceActive;
  402. }
  403. return status;
  404. },
  405. startAutoSave : function(){
  406. this.notice("开启自动保存");
  407. this.autoSave = true;
  408. this.autosaveInterval = setInterval( function(){
  409. if( this.updateTime ){
  410. if( !this.saveTime || this.saveTime < this.updateTime ){
  411. this.save( "自动保存成功" );
  412. this.saveTime = this.updateTime.clone();
  413. }
  414. }
  415. }.bind(this), this.autoSaveInter )
  416. },
  417. stopAutoSave : function(){
  418. this.notice("关闭自动保存");
  419. this.autoSave = false;
  420. if( this.autosaveInterval ){
  421. clearInterval( this.autosaveInterval );
  422. }
  423. },
  424. saveAs : function ( folder, newName ) {
  425. var content = this.minder.exportJson();
  426. var contentStr = JSON.stringify( content );
  427. var title = this.minder.getRoot().getText();
  428. var data = {
  429. content : contentStr,
  430. name : newName || title,
  431. folderId : folder || this.options.folderId,
  432. description : ""
  433. };
  434. this.restActions.saveMind( data, function(json){
  435. var id = json.data.id;
  436. this.restActions.getMind( id, function( json2 ){
  437. var converter = new MWF.xApplication.MinderEditor.Converter(this, this.minder, this);
  438. converter.toPng(180, 130, function( img ){
  439. var formData = new FormData();
  440. formData.append('file', img, "untitled.png");
  441. formData.append('site', id);
  442. //this.restActions.uploadMindIcon( id, 180, function(){
  443. // this.notice( "另存成功" );
  444. //}.bind(this), null,formData, img, false )
  445. MWF.xDesktop.uploadImage( id, "mindInfo", formData, img,
  446. function(json3){
  447. data.id = id;
  448. data.icon = json3.data.id;
  449. this.restActions.saveMind( data, function(json4){
  450. this.notice( "另存成功" );
  451. }.bind(this))
  452. }.bind(this)
  453. );
  454. }.bind(this), function(){
  455. this.notice( "另存成功,但由于脑图中有外网图片,浏览器无法生成缩略图" );
  456. }.bind(this))
  457. }.bind(this))
  458. }.bind(this));
  459. },
  460. setNewName: function( newname ){
  461. this.save( "重命名成功", newname, null )
  462. },
  463. save: function ( noticetText, newName , folder) {
  464. var content = this.minder.exportJson();
  465. var contentStr = JSON.stringify( content );
  466. var title = this.minder.getRoot().getText();
  467. var callback_save = function(id, flag, toPngFail){
  468. this.data.content = contentStr;
  469. var text = toPngFail ? "另存成功,但由于脑图中有外网图片,浏览器无法生成缩略图" : "保存成功";
  470. this.restActions.saveMind( this.data, function(json4){
  471. if( flag ){
  472. this.restActions.getMind( id, function( json5 ){
  473. this.data = json5.data;
  474. this.data.content = content;
  475. if( newName )this.setTitle(newName);
  476. this.notice( noticetText || text );
  477. }.bind(this))
  478. }else{
  479. this.data.content = content;
  480. if( newName )this.setTitle(newName);
  481. this.notice( noticetText || text );
  482. }
  483. }.bind(this))
  484. }.bind(this);
  485. var callback = function( id, flag ){
  486. var converter = new MWF.xApplication.MinderEditor.Converter(this, this.minder, this);
  487. converter.toPng(180, 130, function( img ){
  488. var formData = new FormData();
  489. formData.append('file', img, "untitled.png");
  490. formData.append('site', id);
  491. //this.restActions.uploadMindIcon( id, 180, function(){
  492. // if( newName )this.setTitle(newName);
  493. // this.notice( noticetText || "保存成功" );
  494. //}.bind(this), null,formData, img, false )
  495. MWF.xDesktop.uploadImage( id, "mindInfo", formData, img,
  496. function(json3){
  497. this.data.icon = json3.data.id;
  498. callback_save(id, flag)
  499. }.bind(this)
  500. );
  501. }.bind(this), function(){
  502. this.data.icon = "";
  503. callback_save(id, flag, true);
  504. }.bind(this))
  505. }.bind(this);
  506. if( this.data && this.data.id){
  507. this.data.content = contentStr;
  508. if( newName ){ this.data.name = newName; }
  509. if( folder ){ this.data.folderId = folder; }
  510. callback(this.data.id);
  511. }else{
  512. this.data = {
  513. content : contentStr,
  514. name : newName || title,
  515. folderId : folder || this.options.folderId,
  516. description : ""
  517. };
  518. this.restActions.saveMind( this.data, function(json){
  519. var id = this.options.id = json.data.id;
  520. callback(id, true);
  521. }.bind(this));
  522. }
  523. },
  524. openSaveAsDialog : function(){
  525. var form = new MWF.xApplication.MinderEditor.SaveAsForm(this, {
  526. newname : (this.data ? this.data.name : "")
  527. }, {}, {
  528. app: this
  529. });
  530. form.edit()
  531. },
  532. openRenameDialog : function(){
  533. var form = new MWF.xApplication.MinderEditor.NewNameForm(this, {
  534. newname : (this.data ? this.data.name : "")
  535. }, {}, {
  536. app: this
  537. });
  538. form.edit()
  539. },
  540. openShareDialog : function(){
  541. MWF.xDesktop.requireApp("Minder", "Common", null, false);
  542. var form = new MWF.xApplication.Minder.ShareForm({ app : this }, {}, {
  543. }, {
  544. app: this
  545. });
  546. form.checkedItemData = [this.data];
  547. form.edit();
  548. },
  549. openExportDialog : function(){
  550. var form = new MWF.xApplication.MinderEditor.ExportForm({ app : this }, this.data, {
  551. }, {
  552. app: this
  553. });
  554. form.edit();
  555. },
  556. openNewMinderDialog : function(){
  557. MWF.xDesktop.requireApp("Minder", "Common", null, false);
  558. var form = new MWF.xApplication.Minder.NewNameForm({ app : this }, {}, {
  559. }, {
  560. app: this
  561. });
  562. form.edit();
  563. },
  564. loadCodeMirror : function( callback ){
  565. if( window.CodeMirror ){
  566. if( callback )callback();
  567. return;
  568. }
  569. var codeMirrorPath = "../o2_lib/codemirror";
  570. var markedPath = "../o2_lib/marked";
  571. var jsModules = {
  572. codemirror : codeMirrorPath + "/lib/codemirror.js",
  573. codemirror_xml : codeMirrorPath + "/mode/xml/xml.js",
  574. codemirror_javascript : codeMirrorPath + "/mode/javascript/javascript.js",
  575. codemirror_css : codeMirrorPath + "/mode/css/css.js",
  576. codemirror_htmlmixed : codeMirrorPath + "/mode/htmlmixed/htmlmixed.js",
  577. codemirror_markdown: codeMirrorPath + "/mode/markdown/markdown.js",
  578. codemirror_overlay: codeMirrorPath + "/addon/mode/overlay.js",
  579. codemirror_gfm: codeMirrorPath + "/mode/gfm/gfm.js",
  580. codemirror_marked: markedPath + "/lib/marked.js"
  581. };
  582. //var modules = [];
  583. //for( var key in jsModules ){
  584. // if( !COMMON.AjaxModule[ key ] ){
  585. // COMMON.AjaxModule[ key ] = jsModules[key];
  586. // }
  587. // modules.push( key );
  588. //}
  589. COMMON.AjaxModule.loadCss(codeMirrorPath + "/lib/codemirror.css", function () {
  590. o2.load( Object.values(jsModules), function () {
  591. marked.setOptions({
  592. gfm: true,
  593. tables: true,
  594. breaks: true,
  595. pedantic: false,
  596. sanitize: true,
  597. smartLists: true,
  598. smartypants: false
  599. });
  600. //this.codeMirrorLoaded = true;
  601. if(callback)callback();
  602. }.bind(this))
  603. }.bind(this))
  604. }
  605. });
  606. MWF.xApplication.MinderEditor.Converter = new Class({
  607. initialize: function (editor, minder) {
  608. this.editor = editor;
  609. this.minder = minder;
  610. },
  611. toPng: function (width, height, callback, failure) {
  612. var img;
  613. this.toCanvas(width, height, function (canvas) {
  614. try{
  615. var src = canvas.toDataURL("image/png");
  616. var base64Code = src.split(',')[1];
  617. if (!base64Code) {
  618. img = null;
  619. return;
  620. }
  621. base64Code = window.atob(base64Code);
  622. var ia = new Uint8Array(base64Code.length);
  623. for (var i = 0; i < base64Code.length; i++) {
  624. ia[i] = base64Code.charCodeAt(i);
  625. }
  626. img = new Blob([ia], {type: "image/png"});
  627. if(callback)callback( img );
  628. }catch(e){
  629. if(failure)failure();
  630. //debugger;
  631. //var pr = new MWF.xApplication.MinderEditor.PreviewConverter(this.editor, this.minder, width, height);
  632. //pr.toPng(width, height, callback, failure );
  633. }
  634. }.bind(this))
  635. },
  636. toCanvas: function (width, height, callback, svg) {
  637. this.loadCanvgResource(function () {
  638. if( !svg )svg = this.editor.contentNode.get("html");
  639. var coordinates = this.getSvgCoordinates();
  640. var offsetLeft = Math.abs(coordinates.left), offsetTop = Math.abs(coordinates.top);
  641. var contentWidth = coordinates.x, contentHeight = coordinates.y;
  642. var matrix;
  643. if (width && height) {
  644. if ((width > coordinates.x) && (height > coordinates.y)) {
  645. //如果宽度比指定宽度小,设置偏移量
  646. if (width > coordinates.x) {
  647. offsetLeft += ( width - coordinates.x ) / 2;
  648. contentWidth = width;
  649. }
  650. //如果高度比指定高度小,设置偏移量
  651. if (height > coordinates.y) {
  652. offsetTop += ( height - coordinates.y ) / 2;
  653. contentHeight = height;
  654. }
  655. }
  656. //如果宽度比指定宽度大,进行缩小
  657. var xRatio, yRatio, ox, oy, zoom;
  658. if (width < coordinates.x) {
  659. xRatio = width / coordinates.x;
  660. }
  661. //如果高度比指定高度大,进行缩小
  662. if (height < coordinates.y) {
  663. yRatio = height / coordinates.y;
  664. }
  665. if (xRatio || yRatio) {
  666. contentWidth = width;
  667. contentHeight = height;
  668. xRatio = xRatio || 1;
  669. yRatio = yRatio || 1;
  670. if( xRatio >= yRatio ){
  671. zoom = yRatio;
  672. ox = (width - zoom * coordinates.x)/2;
  673. oy = 0;
  674. }else{
  675. zoom = xRatio;
  676. ox = 0;
  677. oy = ( height - zoom * coordinates.y )/2;
  678. }
  679. matrix = zoom + " 0 0 " + zoom + " " + ox + " " + oy;
  680. }
  681. }
  682. var regex = /<svg.*?>(.*?)<\/svg>/ig;
  683. svg = "<svg width=\"" + contentWidth + "\" height=\"" + contentHeight + "\">" + regex.exec(svg)[1] + "</svg>";
  684. var arr1 = svg.split("</defs>");
  685. var arr2 = svg.split("<g id=\"minder_connect_group");
  686. svg = arr1[0] + "</defs>"
  687. + "<g transform=\"" + ( matrix ? "matrix(" + matrix + ")" : "translate(0.5 0.5)") + "\">"
  688. + "<g transform=\"translate(" + offsetLeft + " " + offsetTop + ")\" text-rendering=\"" + ( matrix ? "geometricPrecision" : "optimize-speed") + "\">"
  689. + "<g id=\"minder_connect_group" + arr2[1];
  690. var canvas = new Element("canvas", {
  691. width: contentWidth, height: contentHeight,
  692. styles: {width: contentWidth + "px", height: contentHeight + "px"}
  693. }).inject(this.editor.node);
  694. canvg(canvas, svg, {
  695. useCORS : true, log: true, renderCallback: function (dom) {
  696. if (callback)callback(canvas);
  697. }
  698. });
  699. }.bind(this))
  700. },
  701. loadCanvgResource: function (callback) {
  702. var canvgPath = "../o2_lib/canvg/";
  703. COMMON.AjaxModule.load(canvgPath + "canvg.js", function () {
  704. if (callback)callback();
  705. }.bind(this))
  706. },
  707. getSvgCoordinates: function () {
  708. var topBox = {top: 0, left: 0, right: 0, bottom: 0};
  709. var leftBox = {top: 0, left: 0, right: 0, bottom: 0};
  710. var rightBox = {top: 0, left: 0, right: 0, bottom: 0};
  711. var bottomBox = {top: 0, left: 0, right: 0, bottom: 0};
  712. this.minder.getRoot().traverse(function (node) {
  713. var renderBox = node.getLayoutBox();
  714. if (renderBox.top < topBox.top) {
  715. topBox = renderBox;
  716. }
  717. if (renderBox.left < leftBox.left) {
  718. leftBox = renderBox;
  719. }
  720. if (renderBox.right > rightBox.right) {
  721. rightBox = renderBox;
  722. }
  723. if (renderBox.bottom > bottomBox.bottom) {
  724. bottomBox = renderBox;
  725. }
  726. }.bind(this));
  727. return {
  728. top: topBox.top,
  729. right: rightBox.right,
  730. bottom: bottomBox.bottom,
  731. left: leftBox.left,
  732. width: rightBox.right - leftBox.left + 1,
  733. height: bottomBox.bottom - topBox.top + 1,
  734. x: rightBox.right - leftBox.left + 1,
  735. y: bottomBox.bottom - topBox.top + 1
  736. };
  737. }
  738. });
  739. MWF.xApplication.MinderEditor.PreviewConverter = new Class({
  740. initialize: function (editor, minder, width, height) {
  741. this.editor = editor;
  742. this.minder = minder;
  743. this.previewer = new Element("div",{ "styles" : {
  744. width : width, height : height
  745. }}).inject( this.editor.content );
  746. this.initPreViewer();
  747. this.draw();
  748. },
  749. initPreViewer: function(){
  750. // 画布,渲染缩略图
  751. this.paper = new kity.Paper( this.previewer );
  752. // 用两个路径来挥之节点和连线的缩略图
  753. this.nodeThumb = this.paper.put(new kity.Path());
  754. this.connectionThumb = this.paper.put(new kity.Path());
  755. /**
  756. * 增加一个对天盘图情况缩略图的处理,
  757. * @Editor: Naixor line 104~129
  758. * @Date: 2015.11.3
  759. */
  760. this.pathHandler = this.getPathHandler(this.minder.getTheme());
  761. },
  762. getPathHandler: function (theme) {
  763. switch (theme) {
  764. case "tianpan":
  765. case "tianpan-compact":
  766. return function(nodePathData, x, y, width, height) {
  767. var r = width >> 1;
  768. nodePathData.push('M', x, y + r,
  769. 'a', r, r, 0, 1, 1, 0, 0.01,
  770. 'z');
  771. };
  772. default: {
  773. return function(nodePathData, x, y, width, height) {
  774. nodePathData.push('M', x, y,
  775. 'h', width, 'v', height,
  776. 'h', -width, 'z');
  777. }
  778. }
  779. }
  780. },
  781. draw : function(){
  782. var view = this.minder.getRenderContainer().getBoundaryBox();
  783. var padding = 30;
  784. this.paper.setViewBox(
  785. view.x - padding - 0.5,
  786. view.y - padding - 0.5,
  787. view.width + padding * 2 + 1,
  788. view.height + padding * 2 + 1);
  789. var nodePathData = [];
  790. var connectionThumbData = [];
  791. this.minder.getRoot().traverse(function(node) {
  792. var box = node.getLayoutBox();
  793. this.pathHandler(nodePathData, box.x, box.y, box.width, box.height);
  794. if (node.getConnection() && node.parent && node.parent.isExpanded()) {
  795. connectionThumbData.push(node.getConnection().getPathData());
  796. }
  797. }.bind(this));
  798. this.paper.setStyle('background', this.minder.getStyle('background'));
  799. if (nodePathData.length) {
  800. this.nodeThumb
  801. .fill(this.minder.getStyle('root-background'))
  802. .setPathData(nodePathData);
  803. } else {
  804. this.nodeThumb.setPathData(null);
  805. }
  806. if (connectionThumbData.length) {
  807. this.connectionThumb
  808. .stroke(this.minder.getStyle('connect-color'), '0.5%')
  809. .setPathData(connectionThumbData);
  810. } else {
  811. this.connectionThumb.setPathData(null);
  812. }
  813. },
  814. toPng: function (width, height, callback, failure, svg) {
  815. var img;
  816. this.toCanvas(width, height, function (canvas) {
  817. try{
  818. var src = canvas.toDataURL("image/png");
  819. var base64Code = src.split(',')[1];
  820. if (!base64Code) {
  821. img = null;
  822. return;
  823. }
  824. base64Code = window.atob(base64Code);
  825. var ia = new Uint8Array(base64Code.length);
  826. for (var i = 0; i < base64Code.length; i++) {
  827. ia[i] = base64Code.charCodeAt(i);
  828. }
  829. img = new Blob([ia], {type: "image/png"});
  830. if(callback)callback( img );
  831. }catch(e){
  832. if(failure)failure( );
  833. }
  834. }.bind(this), svg)
  835. },
  836. toCanvas: function (width, height, callback, svg ) {
  837. this.loadCanvgResource(function () {
  838. if(!svg)svg = this.previewer.get("html");
  839. var coordinates = this.getSvgCoordinates();
  840. var offsetLeft = Math.abs(coordinates.left), offsetTop = Math.abs(coordinates.top);
  841. var contentWidth = coordinates.x, contentHeight = coordinates.y;
  842. var matrix;
  843. if (width && height) {
  844. if ((width > coordinates.x) && (height > coordinates.y)) {
  845. //如果宽度比指定宽度小,设置偏移量
  846. if (width > coordinates.x) {
  847. offsetLeft += ( width - coordinates.x ) / 2;
  848. contentWidth = width;
  849. }
  850. //如果高度比指定高度小,设置偏移量
  851. if (height > coordinates.y) {
  852. offsetTop += ( height - coordinates.y ) / 2;
  853. contentHeight = height;
  854. }
  855. }
  856. //如果宽度比指定宽度大,进行缩小
  857. var xRatio, yRatio, ox, oy, zoom;
  858. if (width < coordinates.x) {
  859. xRatio = width / coordinates.x;
  860. }
  861. //如果高度比指定高度大,进行缩小
  862. if (height < coordinates.y) {
  863. yRatio = height / coordinates.y;
  864. }
  865. if (xRatio || yRatio) {
  866. contentWidth = width;
  867. contentHeight = height;
  868. xRatio = xRatio || 1;
  869. yRatio = yRatio || 1;
  870. if( xRatio >= yRatio ){
  871. zoom = yRatio;
  872. ox = (width - zoom * coordinates.x)/2;
  873. oy = 0;
  874. }else{
  875. zoom = xRatio;
  876. ox = 0;
  877. oy = ( height - zoom * coordinates.y )/2;
  878. }
  879. matrix = zoom + " 0 0 " + zoom + " " + ox + " " + oy;
  880. }
  881. }
  882. var regex = /<svg.*?>(.*?)<\/svg>/ig;
  883. svg = "<svg width=\"" + contentWidth + "\" height=\"" + contentHeight + "\">" + regex.exec(svg)[1] + "</svg>";
  884. var arr1 = svg.split("</defs>");
  885. var arr2 = svg.split("<g id=\"minder_connect_group");
  886. svg = arr1[0] + "</defs>"
  887. + "<g transform=\"" + ( matrix ? "matrix(" + matrix + ")" : "translate(0.5 0.5)") + "\">"
  888. + "<g transform=\"translate(" + offsetLeft + " " + offsetTop + ")\" text-rendering=\"" + ( matrix ? "geometricPrecision" : "optimize-speed") + "\">"
  889. + "<g id=\"minder_connect_group" + arr2[1];
  890. var canvas = new Element("canvas", {
  891. width: contentWidth, height: contentHeight,
  892. styles: {width: contentWidth + "px", height: contentHeight + "px"}
  893. }).inject(this.editor.node);
  894. canvg(canvas, svg, {
  895. useCORS : true, log: true, renderCallback: function (dom) {
  896. if (callback)callback(canvas);
  897. }
  898. });
  899. }.bind(this))
  900. },
  901. loadCanvgResource: function (callback) {
  902. var canvgPath = "../o2_lib/canvg/";
  903. COMMON.AjaxModule.load(canvgPath + "canvg.js", function () {
  904. if (callback)callback();
  905. }.bind(this))
  906. },
  907. getSvgCoordinates: function () {
  908. var topBox = {top: 0, left: 0, right: 0, bottom: 0};
  909. var leftBox = {top: 0, left: 0, right: 0, bottom: 0};
  910. var rightBox = {top: 0, left: 0, right: 0, bottom: 0};
  911. var bottomBox = {top: 0, left: 0, right: 0, bottom: 0};
  912. this.paper.getRoot().traverse(function (node) {
  913. var renderBox = node.getLayoutBox();
  914. if (renderBox.top < topBox.top) {
  915. topBox = renderBox;
  916. }
  917. if (renderBox.left < leftBox.left) {
  918. leftBox = renderBox;
  919. }
  920. if (renderBox.right > rightBox.right) {
  921. rightBox = renderBox;
  922. }
  923. if (renderBox.bottom > bottomBox.bottom) {
  924. bottomBox = renderBox;
  925. }
  926. }.bind(this));
  927. return {
  928. top: topBox.top,
  929. right: rightBox.right,
  930. bottom: bottomBox.bottom,
  931. left: leftBox.left,
  932. width: rightBox.right - leftBox.left + 1,
  933. height: bottomBox.bottom - topBox.top + 1,
  934. x: rightBox.right - leftBox.left + 1,
  935. y: bottomBox.bottom - topBox.top + 1
  936. };
  937. },
  938. destory : function(){
  939. this.paper.remove();
  940. this.previewer.destroy();
  941. }
  942. });