writer.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. // iVProg - www.usp.br/line/ivprog
  2. // LInE - Free Education, Private Data
  3. import * as Models from "../ivprog_elements";
  4. import { LocalizedStrings } from "../../services/localizedStringsService";
  5. import * as VariableValueMenu from "./variable_value_menu";
  6. import * as VariableValueMenuManagement from "./variable_value_menu";
  7. import * as CommandsManagement from "../commands";
  8. import * as GenericExpressionManagement from "./generic_expression";
  9. import * as CodeGenerator from '../code_generator';
  10. export function createFloatingCommand () {
  11. var command_write = LocalizedStrings.getUI("text_command_write");
  12. //D console.log("js/visualUI/code_generator.js: createFloatingCommand(.): text_command_write=" + command_write);
  13. return $('<div class="ui writer created_element"> <i class="ui icon small upload"></i> <span> ' + command_write + ' var </span></div>');
  14. }
  15. // Interpret all function code
  16. export function renderCommand (command, function_obj) {
  17. const ret = '<div class="ui writer command_container"><i class="ui icon small upload command_drag"></i>' +
  18. '<i class="ui icon times red button_remove_command"></i>' +
  19. '<span class="span_command_spec">' + LocalizedStrings.getUI("text_command_write") + '(</span>' +
  20. '<div class="all_elements_write"></div> <span class="textual_expression"></span>' +
  21. '<span class="close_parentheses span_command_spec">)</span>' +
  22. '<img data-state="' + (command.newline ? 'on' : 'false') + '" src="' + (command.newline ? 'img/new_line.svg' : 'img/no_new_line.svg') + '"' +
  23. ' class="ivprog_newline_btn"/>' +
  24. '<i class="ui icon i cursor button_write_expression" style="margin-left: 3rem !important; margin-right: -1.1rem !important;"></i>' +
  25. '<i class="ui icon unlock button_alternate_expression"></i>' +
  26. '</div>' + "\n";
  27. const el = $(ret);
  28. el.data("command", command);
  29. //renderExpression (command, function_obj, div_to_render, expression_array)
  30. GenericExpressionManagement.renderExpression(command, function_obj, el.find(".all_elements_write"), command.content);
  31. addHandlers(command, function_obj, el);
  32. if (command.content && command.lockexpression) {
  33. try {
  34. var text = CodeGenerator.elementExpressionCode(command.content);
  35. if (text) {
  36. $(el.find('.all_elements_write')[0]).toggle();
  37. $(el.find('.textual_expression')[0]).text(text);
  38. $(el.find('.textual_expression')[0]).toggle();
  39. $(el.find('.button_alternate_expression')[0]).toggleClass('unlock').toggleClass('lock');
  40. }
  41. } catch (e) {
  42. command.lockexpression = false;
  43. }
  44. }
  45. el.find('.unlock').popup({
  46. content : LocalizedStrings.getUI("text_lock_expression"),
  47. delay: { show: 750, hide: 0 }
  48. });
  49. el.find('.lock').popup({
  50. content : LocalizedStrings.getUI("text_unlock_expression"),
  51. delay: { show: 750, hide: 0 }
  52. });
  53. el.find('.button_write_expression').popup({
  54. content : LocalizedStrings.getUI("text_edit_expression"),
  55. delay: { show: 750, hide: 0 }
  56. });
  57. return el;
  58. } // export function renderCommand(command, function_obj)
  59. function addHandlersManager (command, _function_obj, _writer_dom, item_div, content_element) {
  60. item_div.find(".times").on("click", function () {
  61. for (let i = 0; i < command.content.length; i++) {
  62. if (command.content[i] == content_element) {
  63. delete command.content[i];
  64. command.content.splice(i, 1);
  65. item_div.children().off();
  66. item_div.off();
  67. item_div.fadeOut();
  68. if (command.content.length > 0) {
  69. item_div.next(".icon_add_item_to_writer").fadeOut();
  70. }
  71. break;
  72. }
  73. }
  74. });
  75. }
  76. function addHandlers (command, function_obj, writer_dom) {
  77. $(writer_dom.find('.textual_expression')[0]).toggle();
  78. writer_dom.find('.button_write_expression').on('click', function() {
  79. window.expressionEdition = true;
  80. window.inputExpression = null;
  81. var afterWhichElement;
  82. var lockButton = $(writer_dom.find('.button_alternate_expression')[0]);
  83. var editButton = $(this);
  84. afterWhichElement = writer_dom.find('.all_elements_write');
  85. if (command.lockexpression) {
  86. afterWhichElement = writer_dom.find('.textual_expression');
  87. }
  88. var text = "";
  89. if (command.content) {
  90. if (command.content.length == 1 && command.content[0].content == null && !command.content[0].function_called) {
  91. text = "";
  92. } else {
  93. try {
  94. text = CodeGenerator.elementExpressionCode(command.content);
  95. } catch(ex) {
  96. text = "";
  97. }
  98. }
  99. }
  100. var ok_button = $('<i class="ui icon check circle expression-edit-confirm"></i>');
  101. var cancel_button = $('<i class="ui icon undo expression-edit-cancel"></i>');
  102. var input = $('<input type="text" spellcheck="false" autocomplete="off" class="input-expression-field" >');
  103. input.val(text);
  104. input.focusout(function(evt) {
  105. ok_button.click();
  106. evt.preventDefault();
  107. return true;
  108. });
  109. input.keyup(function(evt) {
  110. if (evt.keyCode == 27) { // esc
  111. cancel_button.click();
  112. }
  113. if (evt.keyCode == 13) { // enter
  114. ok_button.click();
  115. }
  116. });
  117. ok_button.click(function() {
  118. var parsed = null;
  119. parsed = GenericExpressionManagement.expressionParserToVisual(input.val(), function_obj, input);
  120. if (parsed) {
  121. window.expressionEdition = false;
  122. command.content = parsed;
  123. renderAlgorithm();
  124. }
  125. });
  126. cancel_button.mousedown(function(evt) {
  127. var parsed = GenericExpressionManagement.expressionParserToVisual(text, function_obj, input);
  128. if (parsed) {
  129. window.expressionEdition = false;
  130. command.content = parsed;
  131. renderAlgorithm();
  132. }
  133. });
  134. input.insertAfter(afterWhichElement);
  135. input.focus();
  136. cancel_button.insertAfter(input);
  137. ok_button.insertAfter(input);
  138. var len = text.length;
  139. input[0].setSelectionRange(len, len);
  140. afterWhichElement.css('display', 'none');
  141. lockButton.css('display', 'none');
  142. editButton.css('display', 'none');
  143. ok_button.popup({
  144. content : LocalizedStrings.getUI("text_edit_expression_confirm"),
  145. delay: { show: 750, hide: 0 }
  146. });
  147. cancel_button.popup({
  148. content : LocalizedStrings.getUI("text_edit_expression_cancel"),
  149. delay: { show: 750, hide: 0 }
  150. });
  151. });
  152. writer_dom.find('.button_alternate_expression').on('click', function() {
  153. if (command.content) {
  154. var text = CodeGenerator.elementExpressionCode(command.content);
  155. if (text) {
  156. $(writer_dom.find('.all_elements_write')[0]).toggle();
  157. $(writer_dom.find('.textual_expression')[0]).text(text);
  158. $(writer_dom.find('.textual_expression')[0]).toggle();
  159. $(this).toggleClass('unlock').toggleClass('lock');
  160. command.lockexpression = !command.lockexpression;
  161. }
  162. if (command.lockexpression) {
  163. writer_dom.find('.lock').popup({
  164. content : LocalizedStrings.getUI("text_unlock_expression"),
  165. delay: { show: 750, hide: 0 }
  166. });
  167. } else {
  168. writer_dom.find('.unlock').popup({
  169. content : LocalizedStrings.getUI("text_lock_expression"),
  170. delay: { show: 750, hide: 0 }
  171. });
  172. }
  173. }
  174. });
  175. writer_dom.find(".button_remove_command").on("click", function () {
  176. if (CommandsManagement.removeCommand(command, function_obj, writer_dom)) {
  177. writer_dom.fadeOut(400, function () {
  178. writer_dom.remove();
  179. });
  180. }
  181. });
  182. Sortable.create(writer_dom.find(".all_elements_write")[0], {
  183. handle: ".ellipsis",
  184. animation: 100,
  185. ghostClass: "ghost",
  186. group: "writer_" + Math.floor(Math.random() * 10000000),
  187. draggable: ".div_parent_handler",
  188. onEnd: function (evt) {
  189. command.content.splice(evt.newIndex, 0, command.content.splice(evt.oldIndex, 1)[0]);
  190. writer_dom.empty();
  191. writer_dom.replaceWith(renderCommand(command, function_obj));
  192. },
  193. });
  194. // Attach event handles for the newline button
  195. const newlineBtn = writer_dom.find(".ivprog_newline_btn");
  196. newlineBtn.on("click", function () {
  197. const state = this.dataset.state;
  198. if (state === "on") {
  199. this.dataset.state = "off";
  200. command.newline = false;
  201. this.setAttribute("src", "img/no_new_line.svg");
  202. } else {
  203. this.dataset.state = "on";
  204. command.newline = true;
  205. this.setAttribute("src", "img/new_line.svg");
  206. }
  207. writer_dom.data("command", command);
  208. setPopup(newlineBtn, command.newline);
  209. });
  210. // Attach jquery popup
  211. setPopup(newlineBtn, command.newline);
  212. }
  213. function setPopup (element, state) {
  214. if (element.popup("exists")) {
  215. element.popup("destroy");
  216. }
  217. const content = state ? LocalizedStrings.getUI("write_command_newline_on") : LocalizedStrings.getUI("write_command_newline_off");
  218. element.popup({
  219. content: content,
  220. delay: { show: 750, hide: 0, },
  221. });
  222. }
  223. function _addHandlerIconAdd (dom_object, command, function_obj, insert_after = false, after_which = null) {
  224. const icon_add_item = $('<i class="ui icon plus square outline icon_add_item_to_writer"></i> ');
  225. if (!insert_after) {
  226. dom_object.append(icon_add_item);
  227. } else {
  228. icon_add_item.insertAfter(after_which);
  229. }
  230. icon_add_item.on("click", function (_event) {
  231. const div_parent_with_handler = $('<div class="div_parent_handler" style="display:none;"></div>');
  232. const new_div_item = $('<div class="var_value_menu_div"></div>');
  233. div_parent_with_handler.append($('<i class="ui icon ellipsis vertical inverted handler"></i>'));
  234. div_parent_with_handler.append(new_div_item);
  235. div_parent_with_handler.append($('<i class="white inverted icon times handler"></i>'));
  236. div_parent_with_handler.insertAfter(icon_add_item);
  237. const new_related_menu = new Models.VariableValueMenu(VariableValueMenuManagement.VAR_OR_VALUE_TYPES.all, null, null, null, true);
  238. VariableValueMenu.renderMenu(command, new_related_menu, new_div_item, function_obj);
  239. addHandlerIconAdd(dom_object, command, function_obj, true, div_parent_with_handler);
  240. addHandlersManager(command, function_obj, dom_object, div_parent_with_handler, new_related_menu);
  241. let pos = 1;
  242. dom_object.find(".icon_add_item_to_writer").each(function () {
  243. if ($(this).get(0) === icon_add_item.get(0)) {
  244. command.content.splice(pos, 0, new_related_menu);
  245. } else {
  246. pos++;
  247. }
  248. });
  249. if (command.content.length == 1) {
  250. icon_add_item.remove();
  251. }
  252. div_parent_with_handler.fadeIn();
  253. });
  254. }
  255. export function addContent (command, _ref_object, dom_object, _menu_var_or_value, function_obj, _ref_object_content) {
  256. if (dom_object.hasClass("var_value_menu_div")) {
  257. const icon_add_item = $('<i class="ui icon plus square outline icon_add_item_to_writer"></i> ');
  258. icon_add_item.insertAfter(dom_object);
  259. icon_add_item.on("click", function (_event) {
  260. const div_parent_with_handler = $('<div class="div_parent_handler"></div>');
  261. div_parent_with_handler.append($('<i class="ui icon ellipsis vertical inverted handler"></i>'));
  262. div_parent_with_handler.append(new_div_item);
  263. div_parent_with_handler.append($('<i class="white inverted icon times handler"></i>'));
  264. div_parent_with_handler.insertAfter(icon_add_item);
  265. const new_related_menu = new Models.VariableValueMenu(VariableValueMenuManagement.VAR_OR_VALUE_TYPES.all, null, null, null, true);
  266. VariableValueMenu.renderMenu(command, new_related_menu, new_div_item, function_obj);
  267. addHandlersManager(command, function_obj, dom_object, div_parent_with_handler, new_related_menu);
  268. command.content.push(new_related_menu);
  269. if (command.content.length == 1) {
  270. icon_add_item.remove();
  271. }
  272. });
  273. }
  274. }