Main.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741
  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. }.bind(this));
  446. }.bind(this))
  447. }.bind(this));
  448. },
  449. setNewName: function( newname ){
  450. this.save( "重命名成功", newname, null )
  451. },
  452. save: function ( noticetText, newName , folder) {
  453. var content = this.minder.exportJson();
  454. var contentStr = JSON.stringify( content );
  455. var title = this.minder.getRoot().getText();
  456. if( this.data && this.data.id){
  457. this.data.content = contentStr;
  458. if( newName ){ this.data.name = newName; }
  459. if( folder ){ this.data.folderId = folder; }
  460. }else{
  461. this.data = {
  462. content : contentStr,
  463. name : newName || title,
  464. folderId : folder || this.options.folderId,
  465. description : ""
  466. }
  467. }
  468. this.restActions.saveMind( this.data, function(json){
  469. var id = this.options.id = json.data.id;
  470. this.restActions.getMind( id, function( json2 ){
  471. this.data = json2.data;
  472. this.data.content = content;
  473. var converter = new MWF.xApplication.MinderEditor.Converter(this, this.minder, this);
  474. converter.toPng(180, 130, function( img ){
  475. var formData = new FormData();
  476. formData.append('file', img, "untitled.png");
  477. formData.append('site', id);
  478. this.restActions.uploadMindIcon( id, 180, function(){
  479. if( newName )this.setTitle(newName);
  480. this.notice( noticetText || "保存成功" );
  481. }.bind(this), null,formData, img, false )
  482. }.bind(this));
  483. }.bind(this))
  484. }.bind(this));
  485. },
  486. openSaveAsDialog : function(){
  487. var form = new MWF.xApplication.MinderEditor.SaveAsForm(this, {
  488. newname : (this.data ? this.data.name : "")
  489. }, {}, {
  490. app: this
  491. });
  492. form.edit()
  493. },
  494. openRenameDialog : function(){
  495. var form = new MWF.xApplication.MinderEditor.NewNameForm(this, {
  496. newname : (this.data ? this.data.name : "")
  497. }, {}, {
  498. app: this
  499. });
  500. form.edit()
  501. },
  502. openShareDialog : function(){
  503. MWF.xDesktop.requireApp("Minder", "Common", null, false);
  504. var form = new MWF.xApplication.Minder.ShareForm({ app : this }, {}, {
  505. }, {
  506. app: this
  507. });
  508. form.checkedItemData = [this.data];
  509. form.edit();
  510. },
  511. openExportDialog : function(){
  512. var form = new MWF.xApplication.MinderEditor.ExportForm({ app : this }, this.data, {
  513. }, {
  514. app: this
  515. });
  516. form.edit();
  517. },
  518. openNewMinderDialog : function(){
  519. MWF.xDesktop.requireApp("Minder", "Common", null, false);
  520. var form = new MWF.xApplication.Minder.NewNameForm({ app : this }, {}, {
  521. }, {
  522. app: this
  523. });
  524. form.edit();
  525. },
  526. loadCodeMirror : function( callback ){
  527. if( window.CodeMirror ){
  528. if( callback )callback();
  529. return;
  530. }
  531. var codeMirrorPath = "/o2_lib/codemirror";
  532. var markedPath = "/o2_lib/marked";
  533. var jsModules = {
  534. codemirror : codeMirrorPath + "/lib/codemirror.js",
  535. codemirror_xml : codeMirrorPath + "/mode/xml/xml.js",
  536. codemirror_javascript : codeMirrorPath + "/mode/javascript/javascript.js",
  537. codemirror_css : codeMirrorPath + "/mode/css/css.js",
  538. codemirror_htmlmixed : codeMirrorPath + "/mode/htmlmixed/htmlmixed.js",
  539. codemirror_markdown: codeMirrorPath + "/mode/markdown/markdown.js",
  540. codemirror_overlay: codeMirrorPath + "/addon/mode/overlay.js",
  541. codemirror_gfm: codeMirrorPath + "/mode/gfm/gfm.js",
  542. codemirror_marked: markedPath + "/lib/marked.js"
  543. };
  544. var modules = [];
  545. for( var key in jsModules ){
  546. if( !COMMON.AjaxModule[ key ] ){
  547. COMMON.AjaxModule[ key ] = jsModules[key];
  548. }
  549. modules.push( key );
  550. }
  551. COMMON.AjaxModule.loadCss(codeMirrorPath + "/lib/codemirror.css", function () {
  552. COMMON.AjaxModule.load( modules, function () {
  553. marked.setOptions({
  554. gfm: true,
  555. tables: true,
  556. breaks: true,
  557. pedantic: false,
  558. sanitize: true,
  559. smartLists: true,
  560. smartypants: false
  561. });
  562. //this.codeMirrorLoaded = true;
  563. if(callback)callback();
  564. }.bind(this))
  565. }.bind(this))
  566. }
  567. });
  568. MWF.xApplication.MinderEditor.Converter = new Class({
  569. initialize: function (editor, minder) {
  570. this.editor = editor;
  571. this.minder = minder;
  572. },
  573. toPng: function (width, height, callback) {
  574. var img;
  575. this.toCanvas(width, height, function (canvas) {
  576. var src = canvas.toDataURL("image/png");
  577. var base64Code = src.split(',')[1];
  578. if (!base64Code) {
  579. img = null;
  580. return;
  581. }
  582. base64Code = window.atob(base64Code);
  583. var ia = new Uint8Array(base64Code.length);
  584. for (var i = 0; i < base64Code.length; i++) {
  585. ia[i] = base64Code.charCodeAt(i);
  586. }
  587. img = new Blob([ia], {type: "image/png"});
  588. if(callback)callback( img );
  589. }.bind(this))
  590. },
  591. toCanvas: function (width, height, callback) {
  592. this.loadCanvgResource(function () {
  593. var svg = this.editor.contentNode.get("html");
  594. var coordinates = this.getSvgCoordinates();
  595. var offsetLeft = Math.abs(coordinates.left), offsetTop = Math.abs(coordinates.top);
  596. var contentWidth = coordinates.x, contentHeight = coordinates.y;
  597. var matrix;
  598. if (width && height) {
  599. if ((width > coordinates.x) && (height > coordinates.y)) {
  600. //如果宽度比指定宽度小,设置偏移量
  601. if (width > coordinates.x) {
  602. offsetLeft += ( width - coordinates.x ) / 2;
  603. contentWidth = width;
  604. }
  605. //如果高度比指定高度小,设置偏移量
  606. if (height > coordinates.y) {
  607. offsetTop += ( height - coordinates.y ) / 2;
  608. contentHeight = height;
  609. }
  610. }
  611. //如果宽度比指定宽度大,进行缩小
  612. var xRatio, yRatio, ox, oy, zoom;
  613. if (width < coordinates.x) {
  614. xRatio = width / coordinates.x;
  615. }
  616. //如果高度比指定高度大,进行缩小
  617. if (height < coordinates.y) {
  618. yRatio = height / coordinates.y;
  619. }
  620. if (xRatio || yRatio) {
  621. contentWidth = width;
  622. contentHeight = height;
  623. xRatio = xRatio || 1;
  624. yRatio = yRatio || 1;
  625. if( xRatio >= yRatio ){
  626. zoom = yRatio;
  627. ox = (width - zoom * coordinates.x)/2;
  628. oy = 0;
  629. }else{
  630. zoom = xRatio;
  631. ox = 0;
  632. oy = ( height - zoom * coordinates.y )/2;
  633. }
  634. matrix = zoom + " 0 0 " + zoom + " " + ox + " " + oy;
  635. }
  636. }
  637. var regex = /<svg.*?>(.*?)<\/svg>/ig;
  638. svg = "<svg width=\"" + contentWidth + "\" height=\"" + contentHeight + "\">" + regex.exec(svg)[1] + "</svg>";
  639. var arr1 = svg.split("</defs>");
  640. var arr2 = svg.split("<g id=\"minder_connect_group");
  641. svg = arr1[0] + "</defs>"
  642. + "<g transform=\"" + ( matrix ? "matrix(" + matrix + ")" : "translate(0.5 0.5)") + "\">"
  643. + "<g transform=\"translate(" + offsetLeft + " " + offsetTop + ")\" text-rendering=\"" + ( matrix ? "geometricPrecision" : "optimize-speed") + "\">"
  644. + "<g id=\"minder_connect_group" + arr2[1];
  645. var canvas = new Element("canvas", {
  646. width: contentWidth, height: contentHeight,
  647. styles: {width: contentWidth + "px", height: contentHeight + "px"}
  648. }).inject(this.editor.node);
  649. canvg(canvas, svg, {
  650. log: true, renderCallback: function (dom) {
  651. if (callback)callback(canvas);
  652. }
  653. });
  654. }.bind(this))
  655. },
  656. loadCanvgResource: function (callback) {
  657. var canvgPath = "/o2_lib/framework/canvg/";
  658. COMMON.AjaxModule.load(canvgPath + "canvg.js", function () {
  659. if (callback)callback();
  660. }.bind(this))
  661. },
  662. getSvgCoordinates: function () {
  663. var topBox = {top: 0, left: 0, right: 0, bottom: 0};
  664. var leftBox = {top: 0, left: 0, right: 0, bottom: 0};
  665. var rightBox = {top: 0, left: 0, right: 0, bottom: 0};
  666. var bottomBox = {top: 0, left: 0, right: 0, bottom: 0};
  667. this.minder.getRoot().traverse(function (node) {
  668. var renderBox = node.getLayoutBox();
  669. if (renderBox.top < topBox.top) {
  670. topBox = renderBox;
  671. }
  672. if (renderBox.left < leftBox.left) {
  673. leftBox = renderBox;
  674. }
  675. if (renderBox.right > rightBox.right) {
  676. rightBox = renderBox;
  677. }
  678. if (renderBox.bottom > bottomBox.bottom) {
  679. bottomBox = renderBox;
  680. }
  681. }.bind(this));
  682. return {
  683. top: topBox.top,
  684. right: rightBox.right,
  685. bottom: bottomBox.bottom,
  686. left: leftBox.left,
  687. width: rightBox.right - leftBox.left + 1,
  688. height: bottomBox.bottom - topBox.top + 1,
  689. x: rightBox.right - leftBox.left + 1,
  690. y: bottomBox.bottom - topBox.top + 1
  691. };
  692. }
  693. });