window_management.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819
  1. /* This file is part of AToMPM - A Tool for Multi-Paradigm Modelling
  2. * Copyright 2011 by the AToMPM team and licensed under the LGPL
  3. * See COPYING.lesser and README.md in the root of this project for full details
  4. */
  5. ///////////////////////////////////////////////////////////////////////////////
  6. // DEPRECATED FUNCTIONS
  7. ///////////////////////////////////////////////////////////////////////////////
  8. function _openDialog(type, args, callback){
  9. AtomPMClient.alertDeprecatedFunctionCall("_openDialog");
  10. WindowManagement.openDialog(type, args, callback);
  11. }
  12. function _spawnClient(fname,callbackURL){
  13. AtomPMClient.alertDeprecatedFunctionCall("_spawnClient");
  14. WindowManagement.spawnClient(fname, callbackURL);
  15. }
  16. function _spawnHeadlessClient(context,onready,onchlog){
  17. AtomPMClient.alertDeprecatedFunctionCall("_spawnHeadlessClient");
  18. WindowManagement.spawnHeadlessClient(context, onready, onchlog);
  19. }
  20. function __showDialog(){
  21. alert(AtomPMClient);
  22. AtomPMClient.alertDeprecatedFunctionCall("__showDialog");
  23. WindowManagement.showDialog();
  24. }
  25. function __closeDialog(){
  26. AtomPMClient.alertDeprecatedFunctionCall("__closeDialog");
  27. WindowManagement.closeDialog();
  28. }
  29. ///////////////////////////////////////////////////////////////////////////////
  30. //DEPRECATED FUNCTIONS
  31. ///////////////////////////////////////////////////////////////////////////////
  32. var __dialog_stack = [];
  33. WindowManagement = function(){
  34. /**
  35. * Hides the login screen
  36. */
  37. this.hideLoginScreen = function()
  38. {
  39. //$('#div_login').style.display = 'none';
  40. $('#div_login').css('display', 'none');
  41. __setCanvasScrolling(true);
  42. };
  43. /**
  44. * Shows the login screen
  45. */
  46. this.showLoginScreen = function()
  47. {
  48. //$('#div_login').style.display = 'inline';
  49. $('#div_login').css('display', 'inline');
  50. __setCanvasScrolling(false);
  51. };
  52. this.showAboutDialog = function () {
  53. let create_about = function (status, text) {
  54. let version = null;
  55. let time_at = null;
  56. if (utils.isHttpSuccessCode(status)) {
  57. let resp = JSON.parse(text);
  58. version = resp['tag_name'];
  59. time_at = resp['published_at'];
  60. time_at = time_at.split("T")[0];
  61. }
  62. let title = "About AToMPM";
  63. let elements = [];
  64. let website = "<a href= '" + __WEBPAGE__ + "' target='_blank'>Website and Tutorials</a>";
  65. elements.push(GUIUtils.getTextSpan(website));
  66. let doc_website = "<a href= '" + __DOC_WEBPAGE__ + "' target='_blank'>Documentation</a>";
  67. elements.push(GUIUtils.getTextSpan(doc_website));
  68. let curr_version_str = "Current Version: " + __VERSION__;
  69. elements.push(GUIUtils.getTextSpan(curr_version_str));
  70. elements.push(GUIUtils.getTextSpan("\n"));
  71. if (version != null) {
  72. let new_version_str = "Newest Version: " + version;
  73. elements.push(GUIUtils.getTextSpan(new_version_str));
  74. let time_at_str = "Released on: " + time_at;
  75. elements.push(GUIUtils.getTextSpan(time_at_str));
  76. }
  77. GUIUtils.setupAndShowDialog(
  78. elements,
  79. null,
  80. __ONE_BUTTON,
  81. title,
  82. null);
  83. };
  84. HttpUtils.httpReq("GET", "https://api.github.com/repos/AToMPM/atompm/releases/latest", null, create_about);
  85. };
  86. //Todo: Shred this function into smaller functions, as this should
  87. // really just amount to a switch statement
  88. //TBI: complete comments about each dialog (copy from user's manual)
  89. /**
  90. * Opens a general dialog window
  91. */
  92. this.openDialog = function(type,args,callback)
  93. {
  94. args = args || {};
  95. function error(err,fatal)
  96. {
  97. console.error("Error! " + err);
  98. GUIUtils.setupAndShowDialog(
  99. [GUIUtils.getTextSpan(
  100. err,
  101. 'error')],
  102. undefined,
  103. (fatal ? __NO_BUTTONS : __ONE_BUTTON),
  104. (fatal ? 'FATAL ERROR (restart required)' : 'ERROR'));
  105. //console.error(err,args);
  106. }
  107. // TODO: Fix this, convert to JQuery
  108. if( type == _CLOUD_DATA_MANAGER )
  109. /* args: extensions,readonly,title */
  110. {
  111. HttpUtils.httpReq(
  112. 'GET',
  113. HttpUtils.url('/filelist',__NO_WID),
  114. undefined,
  115. function(statusCode,resp){
  116. var fnames = __localizeFilenames(
  117. __filterFilenamesByExtension(
  118. resp.split('\n'),
  119. args['extensions'] || ['.*'])).sort(),
  120. maxFnameLength =
  121. utils.max(fnames, function(_) {
  122. return _.length;
  123. }),
  124. fileb = FileBrowser.getFileBrowser(fnames,true),
  125. feedbackarea = $('<div>'),
  126. feedback = GUIUtils.getTextSpan(''),
  127. progressbar = $('<div>'),
  128. progressfill = $('<div>'),
  129. download = $('<div>'),
  130. trash = $('<div>'),
  131. div_dldel = $('<div>'),
  132. hldropzone =
  133. /* highlight or unhighlight the dropzone */
  134. function(zone)
  135. {
  136. if( zone == undefined )
  137. {
  138. fileb['filepane']().attr('class', 'fileb_pane');
  139. download.attr('class', 'dropzone');
  140. trash.attr('class', 'dropzone');
  141. }
  142. else if( zone == 'upload' )
  143. {
  144. var filepane = fileb['filepane']();
  145. filepane.attr('class', 'fileb_pane droppable');
  146. filepane.get(0).ondrop = onfilepanedrop;
  147. }
  148. else if( zone == 'dl/del' )
  149. {
  150. download.attr('class', 'dropzone droppable');
  151. trash.attr('class', 'dropzone droppable');
  152. }
  153. },
  154. cancelevt =
  155. /* prevent event bubbling */
  156. function(event)
  157. {
  158. event.stopPropagation();
  159. event.preventDefault();
  160. return false;
  161. },
  162. ondownloaddrop =
  163. function(event)
  164. {
  165. cancelevt(event);
  166. hldropzone();
  167. window.location.assign(event.dataTransfer.getData('uri'));
  168. },
  169. ontrashdrop =
  170. function(event)
  171. {
  172. cancelevt(event);
  173. hldropzone();
  174. var uri = event.dataTransfer.getData('uri');
  175. DataUtils.deleteFromCloud(uri,
  176. function(statusCode,resp)
  177. {
  178. if( ! utils.isHttpSuccessCode(statusCode) )
  179. return error(resp);
  180. feedback.html('deleted '+uri.match(/.*\/(.+)\.file/)[1]);
  181. });
  182. },
  183. onfilepanedrop =
  184. /* react to file drop from desktop
  185. 1. exit with error if non-zip files
  186. 2. move to handleFiles() otherwise */
  187. function(event)
  188. {
  189. cancelevt(event);
  190. hldropzone();
  191. var files = event.dataTransfer.files;
  192. for( var i=0; i<files.length; i++ )
  193. if( files[i].type != 'application/zip' )
  194. return error('uploaded files must zip archives');
  195. handleFiles(event.dataTransfer.files,0);
  196. },
  197. handleFiles =
  198. /* handle each dropped file from desktop
  199. 1. retrieve next file to handle
  200. 2. update feedback message and show progress bar
  201. 3. init file reader event handlers
  202. . onprogress updates progress bar
  203. . onload reacts to upload completion by adjusting
  204. feedback message, hiding progress bar and sending
  205. file to backend
  206. 4. start upload */
  207. function(files,i)
  208. {
  209. if( i >= files.length)
  210. return;
  211. var file = files[i];
  212. feedback.html('uploading '+file.name);
  213. progressbar.css("display", 'inline-block');
  214. var reader = new FileReader();
  215. reader.onprogress =
  216. function(event)
  217. {
  218. if( event.lengthComputable )
  219. progressfill.css("width",
  220. (100*event.loaded/event.total)+'%');
  221. };
  222. reader.onload =
  223. function(event)
  224. {
  225. progressfill.css("width", '100%');
  226. feedback.html('processing '+file.name+' ...');
  227. progressbar.css("display", 'none');
  228. DataUtils.uploadToCloud(
  229. fileb['getcurrfolder'](),
  230. event.target.result,
  231. function(statusCode,resp)
  232. {
  233. if( ! utils.isHttpSuccessCode(statusCode) )
  234. return error(resp);
  235. feedback.html('successfully processed '+file.name);
  236. handleFiles(files,++i);
  237. });
  238. };
  239. reader.readAsBinaryString(file);
  240. },
  241. cloudmgrClosed =
  242. function()
  243. {
  244. return fileb['filebrowser'].parent() == null;
  245. };
  246. document.body.ondragenter =
  247. /* show dropzone when file drag from desktop enters window */
  248. function(event)
  249. {
  250. if(cloudmgrClosed()) return true;
  251. cancelevt(event);
  252. hldropzone(
  253. (event.dataTransfer.effectAllowed == 'copyMove' ? 'dl/del' : 'upload'));
  254. return false;
  255. };
  256. document.body.ondragleave =
  257. /* hide dropzone when file drag from desktop leaves window (which
  258. causes event.pageX == 0) */
  259. function(event)
  260. {
  261. if(cloudmgrClosed()) return true;
  262. cancelevt(event);
  263. if( event.pageX == 0 )
  264. hldropzone();
  265. return false;
  266. };
  267. document.body.ondrop =
  268. function(event)
  269. {
  270. if(cloudmgrClosed()) return true;
  271. cancelevt(event);
  272. hldropzone();
  273. console.warn('non-dropzone drops are ignored');
  274. return false;
  275. };
  276. fileb['filebrowser'].attr('title',
  277. 'drag\'n\'drop files to file pane to upload\n'+
  278. '(close and re-open dialog to observe effects)');
  279. download.attr('title', 'drag\'n\'drop files from file pane to download');
  280. trash.attr('title', 'drag\'n\'drop files from file pane to delete\n'+
  281. '(close and re-open dialog to observe effects)');
  282. progressfill.attr('class', 'progress_fill');
  283. progressfill.html('&nbsp;');
  284. progressbar.attr('class', 'progress_bar');
  285. progressbar.append(progressfill);
  286. progressbar.css("display", 'none');
  287. feedbackarea.append(feedback);
  288. feedbackarea.append(progressbar);
  289. download.css("backgroundImage", 'url(client/media/download.png)');
  290. trash.css("backgroundImage", 'url(client/media/trash.png)');
  291. download.attr('class', 'dropzone');
  292. trash.attr('class', 'dropzone');
  293. download.css("cssFloat", 'left');
  294. trash.css("cssFloat", 'right');
  295. download.get(0).ondragover = cancelevt;
  296. trash.get(0).ondragover = cancelevt;
  297. download.get(0).ondrop = ondownloaddrop;
  298. trash.get(0).ondrop = ontrashdrop;
  299. div_dldel.append(download);
  300. div_dldel.append(trash);
  301. if( args['readonly'] )
  302. trash.css("display", 'none');
  303. GUIUtils.setupAndShowDialog(
  304. [fileb['filebrowser'],div_dldel,feedbackarea],
  305. undefined,
  306. __ONE_BUTTON,
  307. args['title'] ||
  308. 'manage your cloud data\n(note:: you must close and re-open '+
  309. 'dialog to view upload and deletion effects)');
  310. });
  311. }
  312. else if( type == _CUSTOM )
  313. /* args: widgets, title
  314. 'widgets' must be a list where each entry is either
  315. ['id':___,'type':'input','label':___,'default':___], or
  316. ['id':___,'type':'select','choices':___,'multipleChoice':___] */
  317. {
  318. var elements = [],
  319. getinputs = [];
  320. args['widgets'].forEach(
  321. function(w)
  322. {
  323. if( w['type'] == 'select' )
  324. {
  325. var select = GUIUtils.getSelector(w['choices'],w['multipleChoice']);
  326. getinputs.push(function(_)
  327. {
  328. _[w['id']] = HttpUtils.getSelectorSelection(select);
  329. });
  330. elements.push(select);
  331. }
  332. else if( w['type'] == 'input' )
  333. {
  334. var label = GUIUtils.getTextSpan(w['label'] || ''),
  335. input = GUIUtils.getStringInput(w['default'] || '');
  336. getinputs.push(function(_)
  337. {
  338. _[w['id']] = input[0].value;
  339. });
  340. elements.push(label,input);
  341. }
  342. });
  343. GUIUtils.setupAndShowDialog(
  344. elements,
  345. function()
  346. {
  347. var values = {};
  348. getinputs.forEach( function(gi) {gi(values);} );
  349. return values;
  350. },
  351. __TWO_BUTTONS,
  352. args['title'],
  353. callback);
  354. }
  355. else if( type == _ENTITY_EDITOR )
  356. /* args: uri */
  357. {
  358. var uri = (args['uri'] || __selection['items'][0]),
  359. matches = uri.match(/.*\/(.*)Icon\/(.*)\.instance/) ||
  360. uri.match(/.*\/(.*)Link\/(.*)\.instance/),
  361. type = matches[1],
  362. id = matches[2];
  363. HttpUtils.httpReq(
  364. 'GET',
  365. HttpUtils.url(uri),
  366. undefined,
  367. function(statusCode,resp)
  368. {
  369. if( ! utils.isHttpSuccessCode(statusCode) )
  370. return error(resp);
  371. return openDialog(
  372. _DICTIONARY_EDITOR,
  373. {'data': utils.jsonp( utils.jsonp(resp)['data'] ),
  374. 'ignoreKey':
  375. function(attr,val)
  376. {
  377. return attr.charAt(0) == '$' || val == undefined;
  378. },
  379. 'keepEverything':
  380. function()
  381. {
  382. return __changed(uri);
  383. },
  384. 'title':'edit '+type+' #'+id},
  385. callback || function(changes) {DataUtils.update(uri,changes);});
  386. });
  387. }
  388. else if( type == _ERROR )
  389. error(args);
  390. else if( type == __FATAL_ERROR )
  391. error(args,true);
  392. else if( type == _FILE_BROWSER )
  393. /* args: extensions,manualInput,title,startDir */
  394. {
  395. FileBrowser.buildFileBrowser(args['extensions'], args['manualInput'], args['title'], args['startDir'], callback);
  396. }
  397. else if( type == _LEGAL_CONNECTIONS )
  398. /* args: uri1, uri2, ctype, forceCallback */
  399. {
  400. var legalConnections = __legalConnections(args['uri1'],args['uri2'],args['ctype']);
  401. if( legalConnections.length == 0 )
  402. {
  403. var err = 'no valid connection between selected types';
  404. if( args['forceCallback'] )
  405. callback({'$err':err});
  406. else
  407. error(err);
  408. }
  409. else if( legalConnections.length == 1 )
  410. callback( legalConnections[0]+'Link.type' );
  411. else
  412. {
  413. var select = GUIUtils.getSelector(legalConnections);
  414. GUIUtils.setupAndShowDialog(
  415. [select],
  416. function() {return HttpUtils.getSelectorSelection(select)+'Link.type';},
  417. __TWO_BUTTONS,
  418. 'choose connection type',
  419. callback);
  420. }
  421. }
  422. else if( type == _LOADED_TOOLBARS )
  423. /* args: multipleChoice, type, title */
  424. {
  425. var choosableToolbars = [];
  426. for( var tb in __loadedToolbars )
  427. {
  428. if( (args['type'] == undefined &&
  429. (__isIconMetamodel(tb) || __isButtonModel(tb))) ||
  430. (args['type'] == 'metamodels' &&
  431. __isIconMetamodel(tb)) ||
  432. (args['type'] == 'buttons' &&
  433. __isButtonModel(tb)) )
  434. choosableToolbars.push(tb);
  435. }
  436. var select = GUIUtils.getSelector(choosableToolbars,args['multipleChoice']);
  437. GUIUtils.setupAndShowDialog(
  438. [select],
  439. function() {return HttpUtils.getSelectorSelection(select);},
  440. __TWO_BUTTONS,
  441. args['title'],
  442. callback);
  443. }
  444. else if( type == _DICTIONARY_EDITOR )
  445. /* args: data, ignoreKey, keepEverything, title */
  446. {
  447. var form = $('<form>'),
  448. table = $('<table>'),
  449. attrs2ii = {};
  450. form.onsubmit = function() {return false;};
  451. form.append(table);
  452. for( var attr in args['data'] )
  453. {
  454. if( args['ignoreKey'] != undefined &&
  455. args['ignoreKey'](attr,args['data'][attr]['value']) )
  456. continue;
  457. var tr = $('<tr>');
  458. tr.attr("id", "tr_" + attr);
  459. var ii = null;
  460. try {
  461. ii = GUIUtils.getInputField(
  462. args['data'][attr]['type'],
  463. args['data'][attr]['value']);
  464. } catch (err) {
  465. console.log(args['data'][attr]);
  466. WindowManagement.openDialog(
  467. _ERROR,
  468. 'unexpected error in editing mode ::\n ' + err + '\n' + utils.jsons(args['data'][attr]));
  469. }
  470. // var tr = table.append( $('<tr>') ),
  471. // ii = GUIUtils.getInputField(
  472. // args['data'][attr]['type'],
  473. // args['data'][attr]['value']);
  474. tr.append( $('<td>').append( GUIUtils.getTextSpan(attr)) );
  475. tr.append( $('<td>').append(ii.input) );
  476. if (ii.input.extra_el) tr.append( $('<td>').append(ii.input.extra_el) );
  477. attrs2ii[attr] = ii;
  478. table.append( tr );
  479. }
  480. GUIUtils.setupAndShowDialog(
  481. [form],
  482. function()
  483. {
  484. var changes = {},
  485. keepAll = (args['keepEverything'] != undefined &&
  486. args['keepEverything']());
  487. for( var attr in attrs2ii )
  488. {
  489. var am = attrs2ii[attr];
  490. var newVal = am['getinput'](am['input']);
  491. if( keepAll ||
  492. utils.jsons(newVal) != utils.jsons(am['oldVal']) )
  493. changes[attr] = newVal;
  494. }
  495. return changes;
  496. },
  497. __TWO_BUTTONS,
  498. args['title'],
  499. callback);
  500. }
  501. else if( type == __SVG_TEXT_EDITOR )
  502. {
  503. if( args.tagName != 'tspan' )
  504. {
  505. console.warn('SVG text editing only works on "Text" VisualObjects');
  506. return;
  507. }
  508. var vobj = args.parentNode,
  509. vobjuri = vobj.getAttribute('__vobjuri'),
  510. iconuri = __vobj2uri(vobj),
  511. lines = [];
  512. for( var i=0; i < vobj.children.length; i++ )
  513. if( vobj.children[i].tagName == 'tspan' )
  514. lines.push(vobj.children[i].textContent);
  515. var input =
  516. GUIUtils.getTextInput(
  517. lines.join('\n'),
  518. undefined,
  519. Math.min(lines.length,__MAX_TEXTAREA_LINES) );
  520. GUIUtils.setupAndShowDialog(
  521. [input],
  522. function() {return input.value;},
  523. __TWO_BUTTONS,
  524. 'enter new text',
  525. function(newVal)
  526. {
  527. DataUtils.update(
  528. iconuri+'/'+vobjuri+'.vobject',{'textContent':newVal});
  529. });
  530. }
  531. };
  532. /* spawn a new instance of atompm... if a model is specified (as 'fname'), it is
  533. loaded into the new instance... if a callback url is specified, critical
  534. information about the new instance is POSTed to it
  535. NOTE:: window.open returns a reference to the created window... however, this
  536. reference is not always complete (e.g. body.onload has not necessarily
  537. run its course)... for this reason, before proceeding with handling
  538. 'fname' and 'callbackURL', we poll the reference to ensure its
  539. completion */
  540. this.spawnClient = function (fname,callbackURL)
  541. {
  542. let c = window.open(window.location.href, '_blank');
  543. if (c == undefined){
  544. WindowManagement.openDialog(_ERROR, "Failed to open new window. Are pop-ups blocked?");
  545. return;
  546. }
  547. let onspawn =
  548. function()
  549. {
  550. if( (fname || callbackURL) &&
  551. (c.__wid == undefined ||
  552. c.__aswid == undefined ||
  553. c._loadModel == undefined) )
  554. return window.setTimeout(onspawn,250);
  555. c.__user = __user;
  556. if( fname )
  557. c._loadModel(fname);
  558. if( callbackURL )
  559. _httpReq(
  560. 'POST',
  561. callbackURL,
  562. {'aswid':c.__aswid,
  563. 'cswid':c.__wid,
  564. 'fname':fname,
  565. 'host':window.location.host});
  566. };
  567. onspawn();
  568. };
  569. /* NOTE:: Automating activities
  570. spawn a new instance of atompm... if a model is specified (as 'fname'), it is
  571. loaded into the new instance, if a toolbar is especified (as 'tbname'), it's loaded
  572. into the new instance, if a message is especified a popup message will show in
  573. the instance*/
  574. this.spawnClientOption = function (fname,tbname,option,trafo,msg)
  575. {
  576. let c = window.open(window.location.href, '_blank');
  577. if (c == undefined) {
  578. WindowManagement.openDialog(_ERROR, "Failed to open new window. Are pop-ups blocked?\n" +
  579. "Please reload the workflow model after allowing pop-ups.");
  580. return;
  581. }
  582. let onspawn =
  583. function()
  584. {
  585. if( (fname|| tbname) &&
  586. (c.__wid == undefined ||
  587. c.__aswid == undefined ||
  588. c._loadModel == undefined ||
  589. c._loadToolbar == undefined) )
  590. return window.setTimeout(onspawn,250);
  591. c.__user = __user;
  592. c.__name = fname;
  593. c.__option = option;
  594. c.__trafo = trafo;
  595. c.__msg = msg;
  596. if (trafo == undefined){
  597. trafo = option;
  598. }
  599. if (tbname) {
  600. let toolbars = tbname.split(",");
  601. for (let toolbar of toolbars) {
  602. c._loadToolbar(toolbar);
  603. }
  604. }
  605. if( fname ){
  606. c.__saveas = fname;
  607. if( option.length > 2 ){
  608. c._loadModel(fname);
  609. }
  610. }
  611. };
  612. onspawn();
  613. };
  614. /* initialize a headless client, i.e. a client with a proper backend but whose
  615. socket-message handling code is user-defined
  616. 1. setup new backend csworker and subscribe to it
  617. 2. call 'onready'
  618. 3. from this point on, all incoming socket messages are dispatched to
  619. 'onchlog'
  620. NOTE:: this code and the above comments are simplified versions of what's in
  621. initClient() (TBI:: merge this function with initClient()??)
  622. NOTE:: the context object gets populated with the headless client's wids and
  623. with a pointer to a function that closes it (as 'close') */
  624. this.spawnHeadlessClient = function (context,onready,onchlog)
  625. {
  626. var socket = io.connect(
  627. window.location.hostname,
  628. {'port':8124,'reconnect':false,'force new connection':true});
  629. socket.on('message',
  630. function(msg)
  631. {
  632. console.debug(' >>> '+utils.jsons(msg));
  633. if( msg['statusCode'] != undefined )
  634. {
  635. if( msg['statusCode'] == 201 )
  636. {
  637. HttpUtils.httpReq(
  638. 'PUT',
  639. '/aswSubscription?wid='+context.__wid,
  640. undefined,
  641. function(statusCode,resp)
  642. {
  643. context.__aswid = utils.jsonp(resp)['data'];
  644. onready();
  645. });
  646. context.close = socket.socket.disconnect;
  647. }
  648. else
  649. console.error('headless client failed to connect to back-end');
  650. }
  651. else
  652. onchlog(
  653. msg['data']['changelog'],
  654. msg['data']['sequence#'],
  655. msg['data']['hitchhiker']);
  656. });
  657. socket.on('disconnect',
  658. function()
  659. {
  660. console.debug('headless client lost connection to back-end');
  661. });
  662. socket.on('connect',
  663. function()
  664. {
  665. HttpUtils.httpReq(
  666. 'POST',
  667. '/csworker',
  668. undefined,
  669. function(statusCode,resp)
  670. {
  671. console.debug("Connect!");
  672. console.debug(statusCode);
  673. console.debug(resp);
  674. context.__wid = resp;
  675. socket.emit(
  676. 'message',
  677. {'method':'POST','url':'/changeListener?wid='+context.__wid});
  678. });
  679. });
  680. };
  681. /**
  682. * Sets whether to update the window title or not
  683. * @param changed whether or not the title has changed
  684. */
  685. this.setWindowTitle = function(changed)
  686. {
  687. if( __saveas == undefined )
  688. document.title =
  689. __TITLE +' - '+
  690. (changed ? '+ ' :'')+
  691. '[Unnamed]';
  692. else
  693. document.title =
  694. __TITLE+' - '+
  695. (changed ? '+ ' :'')+
  696. __saveas.match(/(.*\/){0,1}(.*)\.model/)[2]+' - '+
  697. __saveas;
  698. };
  699. /**
  700. * Displays the modal dialog
  701. */
  702. this.showDialog = function()
  703. {
  704. var dialog = __dialog_stack[__dialog_stack.length-1],
  705. dim_bg = $('#div_dim_bg');
  706. dim_bg.css("display", 'inline');
  707. dialog.css("display", 'block');
  708. dialog.css("left", document.body.scrollLeft +
  709. window.innerWidth/2 -
  710. dialog.width()/2 + "px");
  711. dialog.css("top", document.body.scrollTop +
  712. window.innerHeight/2 -
  713. dialog.height()/2 + "px");
  714. __setCanvasScrolling(false);
  715. };
  716. /**
  717. * Closes the modal dialog if it is currently opened (with arg js event)
  718. * Huseyin Ergin
  719. * HUSEYIN-ENTER
  720. */
  721. this.closeDialog = function(ev)
  722. {
  723. if(ev!=null && ev.keyCode==13) {
  724. $('#div_dialog_' + (__dialog_stack.length-1).toString() + " .okbutton").click();
  725. }
  726. __dialog_stack.pop();
  727. var dialog = $('#div_dialog_'+__dialog_stack.length);
  728. dialog.remove();
  729. if (!__dialog_stack.length) {
  730. __setCanvasScrolling(true);
  731. $('#div_dim_bg').css("display", 'none');
  732. BehaviorManager.setActiveBehaviourStatechart(__SC_CANVAS);
  733. }
  734. };
  735. return this;
  736. }();