PageRenderTime 60ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/fangofmongo/static/fom/js/fangofmongo_ui.js

https://github.com/zinnie/Fang-of-Mongo
JavaScript | 1021 lines | 592 code | 141 blank | 288 comment | 48 complexity | 7a94213ca4a877aa428310ebba738b23 MD5 | raw file
  1. /* Fang of Mongo init function */
  2. function fom_init_mongo_ui()
  3. /*
  4. Base class for all fom objects
  5. */
  6. {
  7. $(function() {
  8. /*
  9. Base class for fom objects
  10. */
  11. $.widget("ui.fom_object", {
  12. _init: function() {
  13. // init code for mywidget
  14. var defaults = {
  15. };
  16. this.options = $.extend({}, defaults, this.options);
  17. //alert('d:'+this.options.disabled);
  18. // can use this.options
  19. },
  20. //set_enabled(enabled) {}
  21. //value: function(a) { return a; },
  22. //length: function ( ) { return this.listeners.length; },
  23. signal: function(signal_name, signal_source, signal_data ) {
  24. },
  25. destroy: function() {
  26. $.widget.prototype.apply(this, arguments); // default destroy
  27. // now do other stuff particular to this widget
  28. }
  29. });
  30. $.extend($.ui.fom_object, {
  31. getters: "value length",
  32. /*defaults: {
  33. //hidden: true
  34. }*/
  35. });
  36. //end of fom_object
  37. /*
  38. * Plugin interface
  39. *
  40. */
  41. Fom_plugin = $.extend({}, $.ui.fom_object.prototype,{
  42. _init: function(){
  43. $.ui.fom_object.prototype._init.call(this); // call the original function
  44. },
  45. });
  46. $.widget("ui.fom_plugin", Fom_plugin);
  47. /*
  48. * Query builder elemen
  49. */
  50. Fom_query_builder = $.extend({}, $.ui.fom_object.prototype,{
  51. _init: function(){
  52. var defaults = {
  53. autocomplete: true,
  54. completion_source: [],
  55. layout: 'vertical', //horizontal or vertical
  56. };
  57. this.options = $.extend({}, defaults, this.options);
  58. $.ui.fom_object.prototype._init.call(this); // call the original function
  59. var this_obj = this;
  60. this.condition_count = 0;
  61. this.div = $('#' + this.options['div_id']);
  62. $(this.div).addClass('fom_query_builder');
  63. //$(this.div).append('<table><tr><td><button class="fom_query_builder_btn_add" title="add condition">+</button></td><td><button class="fom_query_builder_btn_del" title="remove condition">-</button></td></tr></table>');
  64. $(this.div).append('<table></table>');
  65. this.table = $(this.div).children()[0];
  66. /*$(this.table).find('.fom_query_builder_btn_add').click( function() {
  67. this_obj.add_query();
  68. });
  69. $(this.table).find('.fom_query_builder_btn_del').click( function() {
  70. this_obj.del_query();
  71. });*/
  72. this.add_query();
  73. },
  74. add_query: function() {
  75. var this_obj = this;
  76. var qb_field_condition = $('\
  77. <select class="fom_query_builder_field_condition">\
  78. <option value="_ignore">(ignore)</option>\
  79. <option value="$equals">equals</option>\
  80. <option value="$ne">is not equal</option>\
  81. <option value="$exists">exists</option>\
  82. <option value="$nexists">does not exists</option>\
  83. <option value="$gt">greather</option>\
  84. <option value="$gte">greather or equal</option>\
  85. <option value="$lt">lower</option>\
  86. <option value="$lte">lower or equal</option>\
  87. <option value="$in">is any of</option>\
  88. <option value="$nin">is not any of</option>\
  89. <option value="$all">contains all of</option>\
  90. <option value="$size">is of size</option>\
  91. <option value="$type">is of type</option>\
  92. <option value="$re">matches regular expression</option>\
  93. <option value="$elemMatch">matches element</option>\
  94. <option value="$where">matches condition ($where)</option>\
  95. </select>\
  96. ');
  97. var qb_field_name = $('<input type="text" value="" class="fom_query_builder_field_name"/>')
  98. .autocomplete({ minLength:0, source:this.options.completion_source})
  99. .css('display','inline');
  100. var qb_field_btn = $("<button>&nbsp;</button>")
  101. .attr("tabIndex", -1)
  102. .attr("title", "Show all field names")
  103. .button({
  104. icons: {
  105. primary: "ui-icon-triangle-1-s"
  106. },
  107. text: false
  108. }).removeClass("ui-corner-all")
  109. .addClass("ui-corner-right ui-button-icon")
  110. .click(function() {
  111. // close if already visible
  112. if (qb_field_name.autocomplete("widget").is(":visible")) {
  113. qb_field_name.autocomplete("close");
  114. return;
  115. }
  116. // pass empty string as value to search for, displaying all results
  117. qb_field_name.autocomplete("search", "");
  118. qb_field_name.focus();
  119. });
  120. var qb_field_value = $('<input type="text" class="fom_query_builder_field_value"/>');
  121. if (this.condition_count == 0)
  122. var qb_condition_btn = $('<button title="Add more condition to query" />')
  123. .html('More conditions')
  124. .click( function() { this_obj.add_query(); } );
  125. else
  126. var qb_condition_btn = $('<button title="Remove this condition" />')
  127. .html('x')
  128. .click( function() { $(this).parent().parent().remove(); } );
  129. var new_row = $('<tr></tr>').html(
  130. $('<td/>').html('Field')
  131. .add( $('<td/>').html($(qb_field_name).add(qb_field_btn)))
  132. .add( $('<td/>').html(qb_field_condition))
  133. .add( $('<td/>').html(qb_field_value))
  134. .add( $('<td/>').html(qb_condition_btn))
  135. );
  136. //$(this.table).find('tr').last().before(new_row);
  137. $(this.table).append(new_row);
  138. this.condition_count++;
  139. this.build_query();
  140. },
  141. clear_query: function() {
  142. while(rows = $(this.table).find('tr'), rows.length > 1) {
  143. rows.last().remove();
  144. }
  145. $(rows.last().children('td')[1]).children('input').val('');
  146. $(rows.last().children('td')[2]).children('select').get(0).selectedIndex=0;
  147. $(rows.last().children('td')[3]).children('input').val('');
  148. this.condition_count = 1;
  149. },
  150. del_query: function() {
  151. if (this.condition_count > 1) {
  152. $(this.table).find('tr').last().prev().remove();
  153. this.condition_count--;
  154. }
  155. },
  156. build_query: function() {
  157. /*
  158. FIXME: detect if adding new query condition conflicts with existing ones
  159. function enhance_query(q, f, cond){
  160. if (!(f in q)) {
  161. q[f] = cond;
  162. } else {
  163. //check conflicting queries
  164. };
  165. return q;
  166. }*/
  167. var field_names = $(this.table).find('.fom_query_builder_field_name');
  168. var field_conditions = $(this.table).find('.fom_query_builder_field_condition');
  169. var field_values = $(this.table).find('.fom_query_builder_field_value');
  170. var rows = $(this.table).find('tr');
  171. var query = {};
  172. for(var i=0; i<field_names.length; i++)
  173. {
  174. var field = $(field_names[i]).val();
  175. var condition = $(field_conditions[i]).val();
  176. var value = $(field_values[i]).val();
  177. try {
  178. if (value != "")
  179. value = $('#fom_utils').fom_utils('json_to_strict', eval('res=' + value));
  180. } catch(e) {
  181. alert('query parsing error:' + e + ' for value:' + value )
  182. throw(e);
  183. };
  184. if ((field == "" && condition != "$where") || condition =="_ignore") continue;
  185. switch(condition) {
  186. case '$exists':
  187. q = {}
  188. q[field]={$exists: true}
  189. $.extend(true, query, q);
  190. break;
  191. case '$nexists':
  192. q = {}
  193. q[field]={$exists: false}
  194. $.extend(true, query, q);
  195. break;
  196. case '$equals':
  197. //query[field] = value;
  198. q = {}
  199. q[field]=value
  200. $.extend(true, query, q);
  201. break;
  202. case '$ne':
  203. q = {}
  204. q[field] = {$ne:value};
  205. $.extend(true, query, q);
  206. break;
  207. case '$gt' :
  208. case '$gte':
  209. case '$lt' :
  210. case '$lte':
  211. q = {}
  212. q[field] = {};
  213. q[field][condition] = value;
  214. $.extend(true, query, q);
  215. break;
  216. case '$in':
  217. case '$nin':
  218. q = {}
  219. q[field] = {};
  220. q[field][condition] = value;
  221. $.extend(true, query, q);
  222. break;
  223. case '$all':
  224. q = {}
  225. q[field] = {$all: value};
  226. $.extend(true, query, q);
  227. break;
  228. case '$size':
  229. q = {}
  230. q[field] = {$size: value};
  231. $.extend(true, query, q);
  232. break;
  233. case '$type':
  234. q = {}
  235. q[field] = {$type: value};
  236. $.extend(true, query, q);
  237. break;
  238. case '$re':
  239. q = {}
  240. q[field] = value;//{$regex:value};
  241. $.extend(true, query, q);
  242. break;
  243. case '$elemMatch':
  244. //alert('val:' + JSON.stringify(value));
  245. q = {}
  246. q[field] = {$elemMatch: value};
  247. //query[field] = q;
  248. $.extend(true, query, q);
  249. break;
  250. case '$where':
  251. q = {$where: value};
  252. $.extend(true, query, q);
  253. break;
  254. };
  255. };
  256. //alert(JSON.stringify(query));
  257. return query;
  258. },
  259. /*
  260. pass array of values to field name autocomplete widget
  261. */
  262. completion_source: function(completions) {
  263. this.options.completion_source = completions;
  264. $(this.table).find('tr td input.fom_query_builder_field_name').autocomplete({minLength:0, source: completions});
  265. },
  266. });
  267. $.widget("ui.fom_query_builder", Fom_query_builder);
  268. /**
  269. *
  270. * Message bus
  271. *
  272. */
  273. Fom_bus = $.extend({}, $.ui.fom_object.prototype,{
  274. _init: function(){
  275. $.ui.fom_object.prototype._init.call(this); // call the original function
  276. this.listeners = new Array();
  277. },
  278. length: function ( ) { return this.listeners.length; },
  279. /* add listeners
  280. params:
  281. listener: fom_object
  282. */
  283. add_listener: function(listener) {
  284. this.listeners[this.listeners.length] = listener;
  285. },
  286. /* send signal
  287. params:
  288. signal_name: name of the signal
  289. signal_source: fom_object instance originating the signal
  290. signal_data: json data related to signal (content depends on signal)
  291. */
  292. signal: function(signal_name, signal_source, signal_data ) {
  293. $.ui.fom_object.prototype.signal.call(this);
  294. for ( var obj in this.listeners)
  295. {
  296. this.listeners[obj].signal(signal_name, signal_source, signal_data);
  297. };
  298. },
  299. });
  300. $.widget("ui.fom_bus", Fom_bus);
  301. //end of message bus
  302. /**
  303. *
  304. * Console ui object - commented out, but I'LL BE BACK)
  305. *
  306. */
  307. /*
  308. Fom_ui_console = $.extend({}, $.ui.fom_object.prototype,{
  309. _init: function(){
  310. $.ui.fom_object.prototype._init.call(this); // call the original function
  311. this.dialog_id = this.options['div_id'] + '_dialog';
  312. this.console_id = this.options['div_id'] + '_console_div';
  313. this.input_id = this.options['div_id'] + '_input';
  314. this.button_id = this.options['div_id'] + '_button';
  315. $('#' + this.options['div_id']).append("<div id='" + this.dialog_id + "'><input type='text' name='" + this.input_id +"' id='" + this.input_id + "'/><button id='" + this.button_id + "'>Run</button><div id='" + this.console_id + "'></div><div></div></div>");
  316. var my_id = '#' + this.options['div_id'];
  317. var input_id = this.input_id;
  318. $('#' + this.button_id).click(function() { $(my_id).trigger('console_exec', [$('#' + input_id).get(0).value]) } );
  319. $('#' + this.input_id).keypress(function(event) { if (event.keyCode == 13) { $(my_id).trigger('console_exec', [$('#' + input_id).get(0).value]) }} );
  320. //dialog - item list
  321. $('#' + this.options['div_id'] + '_dialog').dialog({
  322. autoOpen: true,
  323. height: 500,
  324. width: 400,
  325. modal: false,
  326. closeOnEscape: false,
  327. buttons: {},
  328. title: this.options['title'],
  329. position : [220,100],
  330. }); //end of dialog
  331. $('#' + this.dialog_id).dialog('open');
  332. var dialog_id = this.dialog_id;
  333. //$('#' + this.options['tool_button_id']).click(function () { $('#' + dialog_id).dialog('isOpen')? $('#' + dialog_id).dialog('close') : $('#' + dialog_id).dialog('open');});
  334. },
  335. response_error : function (err) {
  336. }, //end of reponse_error
  337. response : function (data) {
  338. //alert(data);
  339. if (data.type == 'html') {
  340. $('#' + this.console_id).prepend('<div class="fom_console_message">' + data.data + '</div>')
  341. };
  342. }, //end of reponse_error
  343. });
  344. $.widget("ui.fom_ui_console", Fom_ui_console);
  345. //end of console ui object
  346. */
  347. /**
  348. *
  349. * Console object
  350. *
  351. */
  352. /*
  353. Fom_console = $.extend({}, $.ui.fom_object.prototype, {
  354. _init: function(){
  355. $.ui.fom_object.prototype._init.call(this); // call the original function
  356. $('#mongo_ui_header_tools_bus').fom_bus('add_listener', this);
  357. $('#mongo_ui_container').append("<div id='mongo_ui_console'></div>");
  358. $('#mongo_ui_console').fom_ui_console({'title':'Mongo console', 'div_id': 'mongo_ui_console', 'tool_button_id' : 'mongo_ui_header_tools_console' });
  359. var this_obj = this;
  360. $('#mongo_ui_console').bind('console_exec', function(e, cmd){ this_obj.exec_cmd(cmd); });
  361. },
  362. signal: function(signal_name, signal_source, signal_data ) {
  363. if (signal_name == 'app_init')
  364. {
  365. }
  366. else if ( signal_name == 'database_selected')
  367. {
  368. $('#mongo_ui_console_dialog').dialog('option','title','Mongo console [' + signal_data['database'] + ']');
  369. //$('#mongo_ui_database_list').fom_ui_list('set_list', signal_data['data'], signal_data['search'], signal_data['method']);
  370. }
  371. else if ( signal_name == 'collection_selected')
  372. {
  373. var db_name = $('#mongo_ajax').fom_object_mongo_ajax('option','database');
  374. $('#mongo_ui_console_dialog').dialog('option','title','Mongo console [' + db_name + ' -> ' + signal_data['collection'] + ']');
  375. }
  376. },
  377. exec_cmd: function(cmd){
  378. cmd = cmd.trim();
  379. if (cmd.length == 0) {
  380. return;
  381. }
  382. var my_console_instance = this;
  383. if (cmd[0] == ':') { //server command
  384. $('#mongo_ajax').fom_object_mongo_ajax('exec_cmd', my_console_instance, cmd);
  385. } else {
  386. alert('Unknown command: ' + cmd);
  387. }
  388. //alert('cmd:'+ cmd);
  389. },
  390. //process cmd response
  391. process_response: function(data){
  392. if (data.error) {
  393. $('#mongo_ui_console').fom_ui_console('response_error',data.error);
  394. } else {
  395. $('#mongo_ui_console').fom_ui_console('response', data);
  396. }
  397. },
  398. destroy: function(){
  399. $.ui.fom_object.prototype.destroy.call(this); // call the original function
  400. },
  401. });
  402. $.widget("ui.fom_console", Fom_console);
  403. //end of console
  404. */
  405. /**
  406. *
  407. * Item list ui object
  408. * - dialog displaying list of items, with ability to search
  409. */
  410. Fom_item_list = $.extend({}, $.ui.fom_object.prototype,{
  411. _init: function(){
  412. $.ui.fom_object.prototype._init.call(this); // call the original function
  413. this.options['title_prefix'] = this.options['title'];
  414. this.options['has_selected'] = false;
  415. this.dialog_id = this.options['div_id'] + '_dialog';
  416. this.item_list_id = this.options['div_id'] + '_list';
  417. this.input_id = this.options['div_id'] + '_input';
  418. this.search_id = this.options['div_id'] + '_search';
  419. this.clear_id = this.options['div_id'] + '_clear';
  420. var this_obj = this;
  421. $('#' + this.options['div_id']).append("\
  422. <div id='" + this.dialog_id + "'>\
  423. <div style='width: 99%; height: 99%; display: table;'>\
  424. <div style='display: table-row; height: auto;'>\
  425. <div style=' display: table-cell; height: 99%; '>\
  426. <div class='fom_ui_note'></div>\
  427. <div class='fom_ui_list_items'>\
  428. <div style='width: 99%;' id='" + this.item_list_id + "'></div>\
  429. </div>\
  430. </div>\
  431. </div>\
  432. <div style='display: table-row; height: auto;'>\
  433. <div class='search_toolbox' style=' height: auto; display: table-cell;'>\
  434. <input type='text' name='" + this.input_id +"' id='" + this.input_id + "'/>\
  435. <button id='" + this.search_id + "'>Search</button>\
  436. <button id='" + this.clear_id + "'>Clear</button>\
  437. </div>\
  438. </div>\
  439. <div style='display: table-row; height: auto;'>\
  440. <div class='toolbox' style='height: auto; display: table-cell;'></div>\
  441. </div>\
  442. </div>\
  443. </div>");
  444. var my_id = '#' + this.options['div_id'];
  445. var search_id = this.search_id;
  446. var clear_id = this.clear_id;
  447. var input_id = this.input_id;
  448. this.toolbox = $('#'+this_obj.dialog_id).find('.toolbox').get(0);
  449. this.search_toolbox = $('#'+this_obj.dialog_id).find('.search_toolbox').get(0);
  450. $(this.toolbox).hide();
  451. $(this.search_toolbox).hide();
  452. //dialog - item list
  453. $('#' + this.options['div_id'] + '_dialog').dialog({
  454. autoOpen: true,
  455. height: 300,
  456. width: 200,
  457. modal: false,
  458. closeOnEscape: false,
  459. title: this.options['title'],
  460. buttons: {},
  461. position : this.options['position'],
  462. close: function() {$(my_id).trigger('close', []);},
  463. }); //end of dialog
  464. //show/hide toolbox (set of icons witl operations on selected element)
  465. $('#' + this.dialog_id).hover(function(event, ui) {
  466. if(! this_obj.options['disabled'])
  467. $(this_obj.search_toolbox).show();
  468. $(this_obj.toolbox).show();
  469. });
  470. $('#' + this.dialog_id).mouseleave(function(event, ui) {
  471. //if(! this_obj.options['disabled'])
  472. $(this_obj.search_toolbox).hide();
  473. $(this_obj.toolbox).hide();
  474. });
  475. $('#' + this.dialog_id).dialog('open');
  476. var dialog_id = this.dialog_id;
  477. $('#' + this.options['tool_button_id']).click(function () {
  478. $('#' + dialog_id).dialog('isOpen')? $('#' + dialog_id).dialog('close') : $('#' + dialog_id).dialog('open');
  479. });
  480. $('#' + this.search_id).button();
  481. $('#' + this.clear_id).button();
  482. //set title properly when appending filter there
  483. $('#' + dialog_id).dialog('option','title_prefix',this.options['title']);
  484. $('#' + search_id).click(function() {
  485. search_term = $('#' + input_id).get(0).value.trim();
  486. if (search_term != '')
  487. dialog_title = $('#' + dialog_id).dialog('option','title_prefix')+' ~' + search_term;
  488. else
  489. dialog_title = $('#' + dialog_id).dialog('option','title_prefix');
  490. $('#' + dialog_id).dialog('option','title', dialog_title); $(my_id).trigger('search', [$('#' + input_id).get(0).value])
  491. });
  492. $('#' + clear_id).click(function() {
  493. $('#' + dialog_id).dialog('option','title',$('#' + dialog_id).dialog('option','title_prefix'));
  494. $('#' + input_id).get(0).value = '';
  495. $(my_id).trigger('search', [''])
  496. });
  497. $('#' + input_id).keyup(function(event) {
  498. if (event.keyCode == 13) {
  499. $('#' + search_id).click();
  500. }
  501. })
  502. if (this.options.disabled) {
  503. this.disable();
  504. };
  505. }, //end of _init
  506. /*
  507. Set list of items
  508. */
  509. set_list: function(item_list, search, method){
  510. var id_name = '#' + this.item_list_id;
  511. var this_obj = this;
  512. this.options['has_selected'] = false;
  513. $('#' + this.item_list_id).empty();
  514. $.each(item_list, function(){
  515. var dn = document.createElement('div');
  516. dn.fom_db = this;
  517. $(dn).addClass('fom_ui_list_item');
  518. dn.innerHTML = $('#fom_utils').fom_utils('escape_html', this);
  519. $(id_name).append( dn );
  520. });
  521. var my_id = '#' + this.options['div_id'];
  522. $('#' + this.item_list_id).children().click(function(){
  523. $(id_name).children().each(function() {
  524. $(this).removeClass('fom_ui_list_item_selected');
  525. });
  526. $(this).addClass('fom_ui_list_item_selected');
  527. this_obj.options['has_selected'] = true;
  528. $(my_id).trigger('fom_item_selected', [this.fom_db]);
  529. });
  530. }, //end of set_list
  531. get_ui_element: function(element) {
  532. switch(element) {
  533. case 'search_input': return $('#' + this.input_id);
  534. case 'search_btn': return $('#' + this.search_id);
  535. case 'clear_btn': return $('#' + this.clear_id);
  536. case 'toolbox': return $(this.toolbox);
  537. default: return null;
  538. };
  539. },
  540. /*
  541. * Clear items
  542. */
  543. clear: function() {
  544. this.options['has_selected'] = false;
  545. $('#' + this.item_list_id).empty();
  546. },
  547. enable: function() {
  548. this.set_enabled(true);
  549. },
  550. disable: function() {
  551. this.set_enabled(false);
  552. },
  553. /*
  554. Check if database has selected items
  555. */
  556. has_selected: function(){
  557. return this.options['has_selected'];
  558. },
  559. /*
  560. Helper: single function for enabling/disabling
  561. */
  562. set_enabled: function(enabled) {
  563. if (enabled) {
  564. $.ui.fom_object.prototype.enable.call(this); // call the original function
  565. method = 'enable';
  566. } else {
  567. method = 'disable';
  568. $.ui.fom_object.prototype.disable.call(this); // call the original function
  569. }
  570. $('#' + this.dialog_id ).dialog(method);
  571. $('#' + this.search_id).button(method);
  572. $('#' + this.clear_id).button(method);
  573. $('#' + this.input_id).attr('disabled', !enabled);
  574. },
  575. destroy: function(){
  576. $.ui.fom_object.prototype.destroy.call(this); // call the original function
  577. },
  578. });
  579. $.widget("ui.fom_ui_list", Fom_item_list);
  580. //end of item list ui object
  581. /*
  582. DATABASE ACCESS
  583. class which allows to access mongodb via ajax calls
  584. */
  585. Fom_mongo_ajax = $.extend({}, $.ui.fom_object.prototype, {
  586. _init: function() {
  587. $('#mongo_ui_header_tools_bus').fom_bus('add_listener', this);
  588. //this.host = null;
  589. //this.port = null;
  590. //this.collection = null;
  591. //this.database = null; },
  592. },
  593. // process server response to exec_cmd
  594. process_response: function(caller_id, data) {
  595. caller_id.process_response(data);
  596. }, // end of process_reponse
  597. /* //this is intended to be use for console plugin
  598. exec_cmd: function(console_obj, cmd){
  599. var url = '/fangofmongo/rest/mongo/cmd/';
  600. var caller_id = console_obj;
  601. var my_console = this;
  602. $.post(url, {'cmd':'help'}, function(data){ my_console.process_response(caller_id, data); }, "json");
  603. }, //end of exec_cmd:*/
  604. /*
  605. * run command against database
  606. * params:
  607. * command: Object with command to perform
  608. */
  609. run_command: function(database, command, callback){
  610. var url = '/fangofmongo/rest/mongo/' + encodeURIComponent(this.options['host']) + '/' + encodeURIComponent(this.options['port']) + '/';
  611. url += 'database/' + encodeURIComponent(database) + '/cmd/'
  612. $.getJSON( url,
  613. {cmd:JSON.stringify(command)},
  614. function(data){
  615. if ( 'error' in data ) { alert('error: ' + data['error']); return data; }
  616. //alert(JSON.stringify(data));
  617. callback(data);
  618. });
  619. }, //end of run_command
  620. /* Get list of databases from mongo server
  621. params:
  622. search (string, optional): text to search
  623. method (string, optional): search method, either null (text search) or 're' (search will be interpreted as regular expression)
  624. */
  625. get_db_list: function(search, method){
  626. this.run_command('admin', //database
  627. {listDatabases : 1}, //command
  628. function(data) { // callback
  629. if ( 'error' in data ) { alert('error: ' + data['error']); return; }
  630. var db_list = Array();
  631. for(obj in data['data']['databases'])
  632. {
  633. db_list.push(data['data']['databases'][obj]['name']);
  634. }
  635. db_list.sort();
  636. if(search) {
  637. db_list = $('#fom_utils').fom_utils('filter_list',db_list, search, method);
  638. }
  639. $('#mongo_ui_header_tools_bus').fom_bus('signal', 'database_list_received', this, {'search':search, 'method':method, 'data' : db_list } );
  640. }
  641. );
  642. }, //end of get_db_list:
  643. /* Get list of collections from mongo server
  644. params:
  645. search (string, optional): text to search
  646. method (string, optional): search method, either null (text search) or 're' (search will be interpreted as regular expression)
  647. */
  648. get_collection_list: function(search, method){
  649. this.get_data(
  650. {$where :'this.name.indexOf("' + this.options['database'] + '.") == 0 && this.name.indexOf("$") == -1'},
  651. {
  652. sort: [['name',1]],
  653. callback: function(data){
  654. if ( 'error' in data ) { alert('error: ' + data['error']); return; }
  655. var coll_list = Array();
  656. for(obj in data['data'])
  657. coll_list.push(data['data'][obj]['name'].substr(this.options['database'].length+1)); //strip database_name and dot
  658. if (search)
  659. coll_list = $('#fom_utils').fom_utils('filter_list',coll_list, search, method);
  660. $('#mongo_ui_header_tools_bus').fom_bus('signal', 'collection_list_received', this, {'search':search, 'method':method, 'data' : coll_list } );
  661. },
  662. context: this,
  663. database: this.options['database'],
  664. collection: 'system.namespaces'
  665. }
  666. );
  667. }, // end of get_collection_list
  668. /*
  669. save document
  670. options:
  671. document: json data in strict format
  672. callback: function to call when we have response
  673. context
  674. */
  675. save_document: function(options) {
  676. var url = '/fangofmongo/rest/mongo/' + this.options['host'] + '/' + this.options['port'] + '/';
  677. if (!("document" in options)) {
  678. throw("save_document: Missing document");
  679. }
  680. try {
  681. $.ajax({
  682. type: 'POST',
  683. url: url + 'collection/' + encodeURIComponent(this.options['database']) +'/' + encodeURIComponent(this.options['collection']) + '/save_document/',
  684. data: {document: JSON.stringify(options["document"])},
  685. dataType: 'json',
  686. context: ('context' in options) ? options['context'] : null,
  687. success: function(data){
  688. if ( 'error' in data ) { alert('error: ' + data['error']); };
  689. if ('callback' in options)
  690. options['callback'](data);
  691. },
  692. error: function(XMLHttpRequest, textStatus, errorThrown) {
  693. alert('save_document failed status' + textStatus + ' error:' + errorThrown);
  694. },
  695. }); //end of $.ajax
  696. } catch(e) {alert(e); throw(e);};
  697. }, //end of save_document
  698. /*
  699. retrieve collection statistics for selected collection
  700. */
  701. get_collection_stats: function(){
  702. var url = '/fangofmongo/rest/mongo/' + encodeURIComponent(this.options['host']) + '/' + encodeURIComponent(this.options['port']) + '/';
  703. var params = '';
  704. if (params != '') { params = '?' + params; };
  705. try{
  706. $.getJSON( url + 'collection/' + encodeURIComponent(this.options['database']) +'/' + encodeURIComponent(this.options['collection']) + '/stats/' + params,
  707. function(data){
  708. if ( 'error' in data ) { alert('error: ' + data['error']); return; }
  709. $('#mongo_ui_header_tools_bus').fom_bus('signal', 'collection_stats_received', this, {'data' : data['data'] } );
  710. }
  711. ); //end of $.getJSON
  712. } catch(e) {alert(e); throw(e);};
  713. }, // end of get_collection_stats
  714. /*
  715. retrieve collection indexes for selected collection
  716. */
  717. get_collection_indexes: function(){
  718. var url = '/fangofmongo/rest/mongo/' + encodeURIComponent(this.options['host']) + '/' + encodeURIComponent(this.options['port']) + '/';
  719. var params = '';
  720. if (params != '') { params = '?' + params; };
  721. try{
  722. $.getJSON( url + 'collection/' + encodeURIComponent(this.options['database']) +'/' + encodeURIComponent(this.options['collection']) + '/indexes/' + params,
  723. function(data){
  724. if ( 'error' in data ) { alert('error: ' + data['error']); return; }
  725. $('#mongo_ui_header_tools_bus').fom_bus('signal', 'collection_indexes_received', this, {'data' : data['data'] } );
  726. }
  727. ); //end of $.getJSON
  728. } catch(e) {alert(e);};
  729. }, // end of get_collection_stats
  730. /*
  731. get documents matching given criteria
  732. params:
  733. query: JSON representing query
  734. options: dictionary with:
  735. limit: number of documents to retrieve
  736. skip: how many documents ommit from results
  737. sort: sort order, in mongo format: array of arrays ["fieldname", "ordering"], for example: [["_id",1]]
  738. callback: callback function
  739. context: context object
  740. returns JSON with results
  741. */
  742. get_data: function(query, options){
  743. var url = '/fangofmongo/rest/mongo/' + encodeURIComponent(this.options['host']) + '/' + encodeURIComponent(this.options['port']) + '/';
  744. var params = '';
  745. query_data = {
  746. q: JSON.stringify(query),
  747. limit: options['limit'],
  748. skip: options['skip']
  749. };
  750. var db = 'database' in options ? options['database'] : this.options['database'];
  751. var coll = 'collection' in options ? options['collection'] : this.options['collection'];
  752. if (options['sort'])
  753. query_data['sort'] = JSON.stringify(options['sort']);
  754. $.ajax({
  755. url: url + 'collection/' + encodeURIComponent(db) + '/' + encodeURIComponent(coll) + '/query/' + params,
  756. dataType: 'json',
  757. data: query_data,
  758. success: options['callback'],
  759. context: ('context' in options) ? options['context'] : null,
  760. error: function(XMLHttpRequest, textStatus, errorThrown) {
  761. alert('get_data failed status' + textStatus + ' error:' + errorThrown);
  762. },
  763. });
  764. }, //end of get_data
  765. /*
  766. Perform operation on mongodb
  767. params:
  768. options: dictionary with options. Available options depend on the operation
  769. operation: name of the operations
  770. subject: one of: server, database, collection, document
  771. callback: function to perform when operation is complete
  772. context: context object passed to callback
  773. */
  774. operation : function(options) {
  775. if (!('operation' in options) || !('subject' in options)) {
  776. throw 'operation: missing params';
  777. }
  778. var url = '/fangofmongo/rest/mongo/' + encodeURIComponent(this.options['host']) + '/' + encodeURIComponent(this.options['port']) + '/cmd/';
  779. var data = {};
  780. switch(options['subject']) {
  781. case 'server':
  782. switch(options['operation']) {
  783. case 'create_database':
  784. data['cmd'] = 'create_database';
  785. data['database_name'] = options['database_name'];
  786. break;
  787. case 'drop_database':
  788. data['cmd'] = 'drop_database';
  789. data['database_name'] = options['database_name'];
  790. break;
  791. default: throw ('operation: incorrect params');
  792. }
  793. break;
  794. case 'database':
  795. switch(options['operation']) {
  796. case 'create_collection':
  797. data['cmd'] = 'create_collection';
  798. data['database'] = options['database']
  799. data['collection_name'] = options['collection_name'];
  800. break;
  801. case 'drop_collection':
  802. data['cmd'] = 'drop_collection';
  803. data['database'] = options['database']
  804. data['collection_name'] = options['collection_name'];
  805. break;
  806. default: throw ('operation: incorrect params');
  807. }
  808. break;
  809. default: throw ('operation: incorrect params');
  810. }
  811. $.ajax({
  812. url: url,
  813. type: 'POST',
  814. success: options['callback'],
  815. data: data,
  816. dataType: 'json',
  817. context: ('context' in options) ? options['context'] : null,
  818. error: function(XMLHttpRequest, textStatus, errorThrown) {
  819. alert('operation failed status: ' + textStatus + ' error:' + errorThrown);
  820. },
  821. });
  822. },
  823. signal: function(signal_name, signal_source, signal_data ) {
  824. if (signal_name == 'database_selected')
  825. {
  826. this.options['database'] = signal_data['database'];
  827. }
  828. if (signal_name == 'collection_selected')
  829. {
  830. this.options['collection'] = signal_data['collection'];
  831. }
  832. },
  833. }); //end of widget ui.fom_object.db
  834. $.widget("ui.fom_object_mongo_ajax", Fom_mongo_ajax);
  835. /**
  836. *
  837. * Init UI objects
  838. *
  839. */
  840. //init utils
  841. $('#fom_utils').fom_utils();
  842. //init bus
  843. $('#mongo_ui_header_tools_bus').fom_bus();
  844. $('#mongo_ui_container').append("<div id='mongo_ajax'></div>");
  845. $('#mongo_ajax').fom_object_mongo_ajax({'host':connection_params['host'], 'port': connection_params['port'], 'database' : null, 'collection' : null });
  846. //init console
  847. //$('#mongo_ui_container').append("<div id='mongo_console'></div>");
  848. //$('#mongo_console').fom_console();
  849. //set locale
  850. $.format.locale({
  851. number: {
  852. groupingSeparator: ' ',
  853. decimalSeparator: '.'
  854. }
  855. });
  856. //initialize all plugins
  857. fom_init_plugins();
  858. //tell everybody we are starting the party
  859. $(window).load( function() {
  860. $('#mongo_ui_header_tools_bus').fom_bus('signal', 'app_init', this, {} );
  861. });
  862. //hide error msg
  863. $('#errormsg').hide();
  864. }); //end of function
  865. } //end of fom_init_mongo_ui