corgis.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. _IMPORTED_DATASETS = {};
  2. _IMPORTED_COMPLETE_DATASETS = {};
  3. /**
  4. * Module that connects to the CORGIS datasets and manages interactions
  5. * with them. This includes loading in datasets at launch and on-the-fly.
  6. * Note that this has no presence on screen, so it does not have a tag.
  7. *
  8. * @constructor
  9. * @this {BlockPyCorgis}
  10. * @param {Object} main - The main BlockPy instance
  11. */
  12. function BlockPyCorgis(main) {
  13. this.main = main;
  14. this.loadedDatasets = [];
  15. this.loadDatasets();
  16. }
  17. BlockPyCorgis.prototype.loadDatasets = function (silently) {
  18. // Load in each the datasets
  19. var corgis = this,
  20. model = this.main.model,
  21. editor = this.main.components.editor,
  22. server = this.main.components.server;
  23. var imports = [];
  24. model.assignment.modules().forEach(function (name) {
  25. var post_prefix = name.substring(7).replace(/\s/g, '_').toLowerCase();
  26. if (!(name in BlockPyEditor.CATEGORY_MAP)) {
  27. imports.push.apply(imports, corgis.importDataset(post_prefix, name, silently));
  28. }
  29. });
  30. // When datasets are loaded, update the toolbox.
  31. // $.when.apply($, imports).done(function() {
  32. // if (model.settings.editor() == "Blocks") {
  33. // editor.updateBlocksFromModel();
  34. // }
  35. // editor.updateToolbox(true);
  36. // }).fail(function(e) {
  37. // console.error(e);
  38. // }).always(function() {
  39. // server.finalizeSubscriptions();
  40. // });
  41. }
  42. /**
  43. * Loads the definitions for a dataset into the environment, including
  44. * the dataset (as a JS file), the skulpt bindings, and the blockly
  45. * bindings. This requires access to a CORGIS server, and occurs
  46. * asynchronously. The requests are fired and their deferred objects
  47. * are returned - callers can use this information to perform an action
  48. * on completion of the import.
  49. *
  50. * @param {String} slug - The URL safe version of the dataset name
  51. * @param {String} name - The user-friendly version of the dataset name.
  52. * @returns {Array.<Deferred>} - Returns the async requests as deferred objects.
  53. */
  54. BlockPyCorgis.prototype.importDataset = function (slug, name, silently) {
  55. var url_retrievals = [];
  56. if (this.main.model.server_is_connected('import_datasets')) {
  57. var root = this.main.model.constants.urls.import_datasets + 'blockpy/' + slug + '/' + slug;
  58. this.main.model.status.dataset_loading.push(name);
  59. // Actually get data
  60. var get_dataset = $.getScript(root + '_dataset.js');
  61. var get_complete = $.getScript(root + '_complete.js');
  62. // Load get_complete silently in the background
  63. var get_skulpt = $.get(root + '_skulpt.js', function (data) {
  64. Sk.builtinFiles['files']['src/lib/' + slug + '/__init__.js'] = data;
  65. });
  66. var get_blockly = $.getScript(root + '_blockly.js');
  67. // On completion, update menus.
  68. var corgis = this;
  69. $.when(get_dataset, get_skulpt,
  70. get_blockly).done(function () {
  71. corgis.loadedDatasets.push(slug);
  72. if (silently) {
  73. corgis.main.model.settings.server_connected(false);
  74. corgis.main.model.assignment.modules.push(name);
  75. corgis.main.components.editor.addAvailableModule(name);
  76. corgis.main.model.settings.server_connected(true);
  77. } else {
  78. corgis.main.model.assignment.modules.push(name);
  79. corgis.main.components.editor.addAvailableModule(name);
  80. }
  81. corgis.main.model.status.dataset_loading.pop();
  82. });
  83. url_retrievals.push(get_dataset, get_skulpt, get_blockly);
  84. }
  85. return url_retrievals;
  86. }
  87. /**
  88. * Opens a dialog box to present the user with the datasets available
  89. * through the CORGIS server. This requires a call, so this method
  90. * completes asynchronously. The dialog is composed of a table with
  91. * buttons to load the datasets (More than one dataset can be loaded
  92. * from within the dialog at a time).
  93. *
  94. * @param {String} name - The name of the dataset to open. This is basically the user friendly version of the name, though it will be mangled into a slug.
  95. */
  96. BlockPyCorgis.prototype.openDialog = function (name) {
  97. var corgis = this;
  98. if (this.main.model.server_is_connected('import_datasets')) {
  99. var root = this.main.model.constants.urls.import_datasets;
  100. $.getJSON(root + 'index.json', function (data) {
  101. // Make up the Body
  102. var datasets = data.blockpy.datasets;
  103. var start = $("<p>Documentation is available at url</p>");
  104. var body = $('<table></table>', { 'class': 'table-bordered table-condensed table-striped' });
  105. Object.keys(datasets).sort().map(function (name) {
  106. var title_name = name;
  107. name = name.replace(/\s/g, '_').toLowerCase();
  108. var btn = $('<button type="button" class="btn btn-primary" data-toggle="button" aria-pressed="false" autocomplete="off">Load</button>');
  109. if (corgis.loadedDatasets.indexOf(name) > -1) {
  110. set_button_loaded(btn);
  111. } else {
  112. btn.click(function () {
  113. corgis.importDataset(name.toLowerCase(), 'Data - ' + title_name);
  114. set_button_loaded(btn);
  115. });
  116. }
  117. $("<tr></tr>")
  118. .append($("<td class='col-md-4'>" + title_name + "</td>"))
  119. .append($("<td>" + datasets[title_name]['short'] + "</td>"))
  120. .append($("<td class='col-md-2'></td>").append(btn))
  121. .appendTo(body);
  122. });
  123. // Show the actual dialog
  124. var editor = corgis.main.components.editor;
  125. corgis.main.components.dialog.show("Import Datasets", body, function () {
  126. if (editor.main.model.settings.editor() == "Blocks") {
  127. editor.updateBlocksFromModel();
  128. }
  129. });
  130. });
  131. }
  132. };
  133. /**
  134. * This is a very simplistic helper function that will transform
  135. * a given button into a "Loaded" state (disabled, pressed state, etc.).
  136. *
  137. * @param {HTMLElement} btn - An HTML element to change the text of.
  138. */
  139. var set_button_loaded = function (btn) {
  140. btn.addClass("active")
  141. .addClass('btn-success')
  142. .removeClass('btn-primary')
  143. .prop("disabled", true)
  144. .text("Loaded")
  145. .attr("aria-pressed", "true");
  146. }