Main.js 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049
  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);
  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);
  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. Implements: [Options, Events],
  608. options: {
  609. "background": null,
  610. "zoom": 1
  611. },
  612. initialize: function (editor, minder, options) {
  613. this.setOptions(options);
  614. this.editor = editor;
  615. this.minder = minder;
  616. },
  617. toPng: function (width, height, callback, failure) {
  618. var img;
  619. this.toCanvas(width, height, function (canvas) {
  620. try{
  621. var src = canvas.toDataURL("image/png");
  622. var base64Code = src.split(',')[1];
  623. if (!base64Code) {
  624. img = null;
  625. return;
  626. }
  627. base64Code = window.atob(base64Code);
  628. var ia = new Uint8Array(base64Code.length);
  629. for (var i = 0; i < base64Code.length; i++) {
  630. ia[i] = base64Code.charCodeAt(i);
  631. }
  632. img = new Blob([ia], {type: "image/png"});
  633. if(callback)callback( img );
  634. }catch(e){
  635. if(failure)failure();
  636. //debugger;
  637. //var pr = new MWF.xApplication.MinderEditor.PreviewConverter(this.editor, this.minder, width, height);
  638. //pr.toPng(width, height, callback, failure );
  639. }
  640. }.bind(this))
  641. },
  642. toCanvas: function (width, height, callback, svg) {
  643. this.loadCanvgResource(function () {
  644. if( !svg )svg = this.editor.contentNode.get("html");
  645. var coordinates = this.getSvgCoordinates();
  646. var offsetLeft = Math.abs(coordinates.left), offsetTop = Math.abs(coordinates.top);
  647. var contentWidth = coordinates.x, contentHeight = coordinates.y;
  648. if( !width )width = contentWidth + offsetLeft;
  649. if( !height )height = contentHeight + offsetTop;
  650. var matrix;
  651. if (width && height) {
  652. if ((width > coordinates.x) && (height > coordinates.y)) {
  653. //如果宽度比指定宽度小,设置偏移量
  654. if (width > coordinates.x) {
  655. offsetLeft += ( width - coordinates.x ) / 2;
  656. contentWidth = width;
  657. }
  658. //如果高度比指定高度小,设置偏移量
  659. if (height > coordinates.y) {
  660. offsetTop += ( height - coordinates.y ) / 2;
  661. contentHeight = height;
  662. }
  663. }
  664. //如果宽度比指定宽度大,进行缩小
  665. var xRatio, yRatio, ox, oy, zoom;
  666. if (width < coordinates.x) {
  667. xRatio = width / coordinates.x;
  668. }
  669. //如果高度比指定高度大,进行缩小
  670. if (height < coordinates.y) {
  671. yRatio = height / coordinates.y;
  672. }
  673. if( this.options.zoom && this.options.zoom !== 1 ){
  674. var z = parseFloat( this.options.zoom );
  675. xRatio = xRatio ? xRatio * z : z;
  676. yRatio = yRatio ? yRatio * z : z;
  677. width = width * z;
  678. height = height * z;
  679. }
  680. if (xRatio || yRatio) {
  681. contentWidth = width;
  682. contentHeight = height;
  683. xRatio = xRatio || 1;
  684. yRatio = yRatio || 1;
  685. if( xRatio >= yRatio ){
  686. zoom = yRatio;
  687. ox = (width - zoom * coordinates.x)/2;
  688. oy = 0;
  689. }else{
  690. zoom = xRatio;
  691. ox = 0;
  692. oy = ( height - zoom * coordinates.y )/2;
  693. }
  694. if( this.options.zoom && this.options.zoom !== 1 ) {
  695. matrix = zoom + " 0 0 " + zoom + " " + 0 + " " + 0;
  696. }else{
  697. matrix = zoom + " 0 0 " + zoom + " " + ox + " " + oy;
  698. }
  699. }
  700. }
  701. var regex = /<svg.*?>(.*?)<\/svg>/ig;
  702. svg = "<svg width=\"" + contentWidth + "\" height=\"" + contentHeight + "\">" + regex.exec(svg)[1] + "</svg>";
  703. var arr1 = svg.split("</defs>");
  704. var arr2 = svg.split("<g id=\"minder_connect_group");
  705. svg = arr1[0] + "</defs>"
  706. + "<g transform=\"" + ( matrix ? "matrix(" + matrix + ")" : "translate(0.5 0.5)") + "\">"
  707. + "<g transform=\"translate(" + offsetLeft + " " + offsetTop + ")\" text-rendering=\"" + ( matrix ? "geometricPrecision" : "optimize-speed") + "\">"
  708. + "<g id=\"minder_connect_group" + arr2[1];
  709. var canvas = new Element("canvas", {
  710. width: contentWidth, height: contentHeight,
  711. styles: {width: contentWidth + "px", height: contentHeight + "px"}
  712. }).inject(this.editor.node);
  713. // if( this.options.background ){
  714. // var ctx = canvas.getContext("2d");
  715. // ctx.fillStyle = this.options.background;
  716. // ctx.fillRect(0, 0, canvas.width, canvas.height);
  717. // }
  718. canvg(canvas, svg, {
  719. useCORS : true, log: true, renderCallback: function (dom) {
  720. if (callback)callback(canvas);
  721. }
  722. });
  723. }.bind(this))
  724. },
  725. loadCanvgResource: function (callback) {
  726. var canvgPath = "../o2_lib/canvg/";
  727. COMMON.AjaxModule.load(canvgPath + "canvg.js", function () {
  728. if (callback)callback();
  729. }.bind(this))
  730. },
  731. getSvgCoordinates: function () {
  732. var topBox = {top: 0, left: 0, right: 0, bottom: 0};
  733. var leftBox = {top: 0, left: 0, right: 0, bottom: 0};
  734. var rightBox = {top: 0, left: 0, right: 0, bottom: 0};
  735. var bottomBox = {top: 0, left: 0, right: 0, bottom: 0};
  736. this.minder.getRoot().traverse(function (node) {
  737. var renderBox = node.getLayoutBox();
  738. if (renderBox.top < topBox.top) {
  739. topBox = renderBox;
  740. }
  741. if (renderBox.left < leftBox.left) {
  742. leftBox = renderBox;
  743. }
  744. if (renderBox.right > rightBox.right) {
  745. rightBox = renderBox;
  746. }
  747. if (renderBox.bottom > bottomBox.bottom) {
  748. bottomBox = renderBox;
  749. }
  750. }.bind(this));
  751. return {
  752. top: topBox.top,
  753. right: rightBox.right,
  754. bottom: bottomBox.bottom,
  755. left: leftBox.left,
  756. width: rightBox.right - leftBox.left + 1,
  757. height: bottomBox.bottom - topBox.top + 1,
  758. x: rightBox.right - leftBox.left + 1,
  759. y: bottomBox.bottom - topBox.top + 1
  760. };
  761. }
  762. });
  763. MWF.xApplication.MinderEditor.PreviewConverter = new Class({
  764. initialize: function (editor, minder, width, height) {
  765. this.editor = editor;
  766. this.minder = minder;
  767. this.previewer = new Element("div",{ "styles" : {
  768. width : width, height : height
  769. }}).inject( this.editor.content );
  770. this.initPreViewer();
  771. this.draw();
  772. },
  773. initPreViewer: function(){
  774. // 画布,渲染缩略图
  775. this.paper = new kity.Paper( this.previewer );
  776. // 用两个路径来挥之节点和连线的缩略图
  777. this.nodeThumb = this.paper.put(new kity.Path());
  778. this.connectionThumb = this.paper.put(new kity.Path());
  779. /**
  780. * 增加一个对天盘图情况缩略图的处理,
  781. * @Editor: Naixor line 104~129
  782. * @Date: 2015.11.3
  783. */
  784. this.pathHandler = this.getPathHandler(this.minder.getTheme());
  785. },
  786. getPathHandler: function (theme) {
  787. switch (theme) {
  788. case "tianpan":
  789. case "tianpan-compact":
  790. return function(nodePathData, x, y, width, height) {
  791. var r = width >> 1;
  792. nodePathData.push('M', x, y + r,
  793. 'a', r, r, 0, 1, 1, 0, 0.01,
  794. 'z');
  795. };
  796. default: {
  797. return function(nodePathData, x, y, width, height) {
  798. nodePathData.push('M', x, y,
  799. 'h', width, 'v', height,
  800. 'h', -width, 'z');
  801. }
  802. }
  803. }
  804. },
  805. draw : function(){
  806. var view = this.minder.getRenderContainer().getBoundaryBox();
  807. var padding = 30;
  808. this.paper.setViewBox(
  809. view.x - padding - 0.5,
  810. view.y - padding - 0.5,
  811. view.width + padding * 2 + 1,
  812. view.height + padding * 2 + 1);
  813. var nodePathData = [];
  814. var connectionThumbData = [];
  815. this.minder.getRoot().traverse(function(node) {
  816. var box = node.getLayoutBox();
  817. this.pathHandler(nodePathData, box.x, box.y, box.width, box.height);
  818. if (node.getConnection() && node.parent && node.parent.isExpanded()) {
  819. connectionThumbData.push(node.getConnection().getPathData());
  820. }
  821. }.bind(this));
  822. this.paper.setStyle('background', this.minder.getStyle('background'));
  823. if (nodePathData.length) {
  824. this.nodeThumb
  825. .fill(this.minder.getStyle('root-background'))
  826. .setPathData(nodePathData);
  827. } else {
  828. this.nodeThumb.setPathData(null);
  829. }
  830. if (connectionThumbData.length) {
  831. this.connectionThumb
  832. .stroke(this.minder.getStyle('connect-color'), '0.5%')
  833. .setPathData(connectionThumbData);
  834. } else {
  835. this.connectionThumb.setPathData(null);
  836. }
  837. },
  838. toPng: function (width, height, callback, failure, svg) {
  839. var img;
  840. this.toCanvas(width, height, function (canvas) {
  841. try{
  842. var src = canvas.toDataURL("image/png");
  843. var base64Code = src.split(',')[1];
  844. if (!base64Code) {
  845. img = null;
  846. return;
  847. }
  848. base64Code = window.atob(base64Code);
  849. var ia = new Uint8Array(base64Code.length);
  850. for (var i = 0; i < base64Code.length; i++) {
  851. ia[i] = base64Code.charCodeAt(i);
  852. }
  853. img = new Blob([ia], {type: "image/png"});
  854. if(callback)callback( img );
  855. }catch(e){
  856. if(failure)failure( );
  857. }
  858. }.bind(this), svg)
  859. },
  860. toCanvas: function (width, height, callback, svg ) {
  861. this.loadCanvgResource(function () {
  862. if(!svg)svg = this.previewer.get("html");
  863. var coordinates = this.getSvgCoordinates();
  864. var offsetLeft = Math.abs(coordinates.left), offsetTop = Math.abs(coordinates.top);
  865. var contentWidth = coordinates.x, contentHeight = coordinates.y;
  866. var matrix;
  867. if (width && height) {
  868. if ((width > coordinates.x) && (height > coordinates.y)) {
  869. //如果宽度比指定宽度小,设置偏移量
  870. if (width > coordinates.x) {
  871. offsetLeft += ( width - coordinates.x ) / 2;
  872. contentWidth = width;
  873. }
  874. //如果高度比指定高度小,设置偏移量
  875. if (height > coordinates.y) {
  876. offsetTop += ( height - coordinates.y ) / 2;
  877. contentHeight = height;
  878. }
  879. }
  880. //如果宽度比指定宽度大,进行缩小
  881. var xRatio, yRatio, ox, oy, zoom;
  882. if (width < coordinates.x) {
  883. xRatio = width / coordinates.x;
  884. }
  885. //如果高度比指定高度大,进行缩小
  886. if (height < coordinates.y) {
  887. yRatio = height / coordinates.y;
  888. }
  889. if (xRatio || yRatio) {
  890. contentWidth = width;
  891. contentHeight = height;
  892. xRatio = xRatio || 1;
  893. yRatio = yRatio || 1;
  894. if( xRatio >= yRatio ){
  895. zoom = yRatio;
  896. ox = (width - zoom * coordinates.x)/2;
  897. oy = 0;
  898. }else{
  899. zoom = xRatio;
  900. ox = 0;
  901. oy = ( height - zoom * coordinates.y )/2;
  902. }
  903. matrix = zoom + " 0 0 " + zoom + " " + ox + " " + oy;
  904. }
  905. }
  906. var regex = /<svg.*?>(.*?)<\/svg>/ig;
  907. svg = "<svg width=\"" + contentWidth + "\" height=\"" + contentHeight + "\">" + regex.exec(svg)[1] + "</svg>";
  908. var arr1 = svg.split("</defs>");
  909. var arr2 = svg.split("<g id=\"minder_connect_group");
  910. svg = arr1[0] + "</defs>"
  911. + "<g transform=\"" + ( matrix ? "matrix(" + matrix + ")" : "translate(0.5 0.5)") + "\">"
  912. + "<g transform=\"translate(" + offsetLeft + " " + offsetTop + ")\" text-rendering=\"" + ( matrix ? "geometricPrecision" : "optimize-speed") + "\">"
  913. + "<g id=\"minder_connect_group" + arr2[1];
  914. var canvas = new Element("canvas", {
  915. width: contentWidth, height: contentHeight,
  916. styles: {width: contentWidth + "px", height: contentHeight + "px"}
  917. }).inject(this.editor.node);
  918. canvg(canvas, svg, {
  919. useCORS : true, log: true, renderCallback: function (dom) {
  920. if (callback)callback(canvas);
  921. }
  922. });
  923. }.bind(this))
  924. },
  925. loadCanvgResource: function (callback) {
  926. var canvgPath = "../o2_lib/canvg/";
  927. COMMON.AjaxModule.load(canvgPath + "canvg.js", function () {
  928. if (callback)callback();
  929. }.bind(this))
  930. },
  931. getSvgCoordinates: function () {
  932. var topBox = {top: 0, left: 0, right: 0, bottom: 0};
  933. var leftBox = {top: 0, left: 0, right: 0, bottom: 0};
  934. var rightBox = {top: 0, left: 0, right: 0, bottom: 0};
  935. var bottomBox = {top: 0, left: 0, right: 0, bottom: 0};
  936. this.paper.getRoot().traverse(function (node) {
  937. var renderBox = node.getLayoutBox();
  938. if (renderBox.top < topBox.top) {
  939. topBox = renderBox;
  940. }
  941. if (renderBox.left < leftBox.left) {
  942. leftBox = renderBox;
  943. }
  944. if (renderBox.right > rightBox.right) {
  945. rightBox = renderBox;
  946. }
  947. if (renderBox.bottom > bottomBox.bottom) {
  948. bottomBox = renderBox;
  949. }
  950. }.bind(this));
  951. return {
  952. top: topBox.top,
  953. right: rightBox.right,
  954. bottom: bottomBox.bottom,
  955. left: leftBox.left,
  956. width: rightBox.right - leftBox.left + 1,
  957. height: bottomBox.bottom - topBox.top + 1,
  958. x: rightBox.right - leftBox.left + 1,
  959. y: bottomBox.bottom - topBox.top + 1
  960. };
  961. },
  962. destory : function(){
  963. this.paper.remove();
  964. this.previewer.destroy();
  965. }
  966. });