js/CustomFields.js

  1. /**=====LICENSE STATEMENT START=====
  2. Translator++
  3. CAT (Computer-Assisted Translation) tools and framework to create quality
  4. translations and localizations efficiently.
  5. Copyright (C) 2018 Dreamsavior<dreamsavior@gmail.com>
  6. This program is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program. If not, see <https://www.gnu.org/licenses/>.
  16. =====LICENSE STATEMENT END=====*/
  17. // ===========================================================
  18. // Custom field class
  19. // ===========================================================
  20. /**
  21. * CustomFields class for handling custom form fields.
  22. * @extends require("www/js/BasicEventHandler.js")
  23. */
  24. class CustomFields extends require("www/js/BasicEventHandler.js") {
  25. /**
  26. * Constructor for CustomFields class.
  27. * @param {jQuery|Object} $form - jQuery object or object representing form.
  28. * @param {Object} [options={}] - Options for customization.
  29. */
  30. constructor($form, options = {}) {
  31. super($form);
  32. // Warns about creation
  33. console.log("Creating custom fields", arguments);
  34. // Handling different argument scenarios
  35. // if (arguments.length == 1 && typeof $form == "object" && $form.constructor.name !== "jQuery") {
  36. // options = {
  37. // jsonForm: $form
  38. // }
  39. // $form = $("<form></form>");
  40. // $form.submit(false);
  41. // }
  42. if (arguments.length == 1) {
  43. options = CustomFields.sanitize(arguments[0]);
  44. $form = $("<form class='autogenerateForm'></form>");
  45. } else {
  46. options = CustomFields.sanitize(options);
  47. $form ||= $("<form></form>");
  48. }
  49. /**
  50. * jQuery form element.
  51. * @type {jQuery}
  52. */
  53. this.$elm = $form;
  54. this.$elm.on("submit", (e)=> {
  55. e.preventDefault();
  56. });
  57. this.getElm = function() {
  58. return this.$elm;
  59. }
  60. /**
  61. * Initialize the CustomFields instance.
  62. */
  63. this.init = (value) => {
  64. this.$elm.empty();
  65. if (value) {
  66. if (options.jsonForm) {
  67. options.jsonForm.value = value;
  68. }
  69. }
  70. if (options.jsonForm) this.addJSONForm(options.jsonForm);
  71. if (options.html) this.addHTML(options.html);
  72. console.warn("CustomFields rendered", this);
  73. this.resolveState("ready");
  74. };
  75. this.init();
  76. }
  77. /**
  78. * Adds JSON form to the form element.
  79. * @param {Object} [settings={}] - Settings for the JSON form.
  80. */
  81. addJSONForm(settings = {}) {
  82. console.log("Adding jsonform", settings);
  83. try {
  84. this.$elm.jsonForm(settings);
  85. CustomFields.bindExternalLinks(this.$elm[0]);
  86. } catch (e) {
  87. console.warn("Invalid jsonForm options", e);
  88. }
  89. }
  90. /**
  91. * Gets the JSON form tree.
  92. * @returns {Object} - JSON form tree data.
  93. */
  94. getJsonFormTree() {
  95. return this.$elm.data("jsonformTree");
  96. }
  97. /**
  98. * Validates the form.
  99. * @returns {boolean} - Validation result.
  100. */
  101. validate() {
  102. const ft = this.getJsonFormTree();
  103. if (!ft) return;
  104. return ft.validate();
  105. }
  106. /**
  107. * Adds HTML content to the form.
  108. * @param {jQuery} $elm - jQuery object representing HTML content.
  109. */
  110. addHTML($elm) {
  111. this.$elm.append($elm);
  112. }
  113. /**
  114. * Gets values from the form.
  115. * @returns {Object} - Form field values.
  116. */
  117. getValues() {
  118. let fd = new FormData(this.$elm[0]);
  119. return Object.fromEntries(fd);
  120. }
  121. /**
  122. * set values from the form.
  123. * @param {Object} values - Form field values.
  124. */
  125. setValues(values) {
  126. if (!values) return;
  127. this.init(values);
  128. }
  129. /**
  130. * Gets JSONForm's value.
  131. * @returns {Object} - Form field values.
  132. */
  133. getFormValues() {
  134. const jsonForm = this.getJsonFormTree();
  135. if (!jsonForm) throw new Error("Not a jsonform");
  136. return jsonForm.root.getFormValues()
  137. }
  138. /**
  139. * Sets value for a field by its name.
  140. * @param {string} name - Name of the field.
  141. * @param {any} val - Value to set.
  142. */
  143. setValueByName(name, val) {
  144. console.log("Updating value", name, val, "of", this);
  145. const $fld = this.$elm.find(`[name="${name}"]`);
  146. $fld.val(val);
  147. }
  148. }
  149. /**
  150. * Sanitizes options for CustomFields class.
  151. * @param {Object} option - Options object.
  152. * @returns {Object} - Sanitized options.
  153. */
  154. CustomFields.sanitize = function(option) {
  155. console.log("CustomFields - sanitizing option", option);
  156. if (typeof option == "function") {
  157. option = option();
  158. }
  159. if (common.isHTMLNode(option)) return {
  160. html: option
  161. }
  162. if (CustomFields.isJsonForm(option)) return {
  163. jsonForm: option
  164. }
  165. return option;
  166. };
  167. /**
  168. * Checks if the data represents a JSON form.
  169. * @param {Object|string|function} [data={}] - Data to check.
  170. * @returns {boolean} - Whether the data represents a JSON form.
  171. */
  172. CustomFields.isJsonForm = function(data = {}) {
  173. if (typeof data == "string") {
  174. if (common.isJSON(data)) data = JSON.parse(data);
  175. } else if (typeof data == "function") {
  176. data = data() || {};
  177. }
  178. if (!data) return false;
  179. if (data.constructor.name !== "Object") return false;
  180. if (!data?.schema && !data?.form) return false;
  181. return true;
  182. };
  183. CustomFields.bindExternalLinks = function(parentElement) {
  184. // Select all elements with the 'help-block' class within the parentElement
  185. var helpBlocks = parentElement.querySelectorAll('.help-block');
  186. // Iterate over each 'help-block' element
  187. helpBlocks.forEach(function(helpBlock) {
  188. // Use a regular expression to find URL-like text
  189. var urlPattern = /https?:\/\/[^\s]+/g;
  190. var text = helpBlock.textContent;
  191. var urls = text.match(urlPattern);
  192. // If URLs are found, create clickable elements
  193. if (urls) {
  194. urls.forEach(function(url) {
  195. var link = document.createElement('a');
  196. link.href = "#";
  197. link.textContent = url;
  198. $(link).attr('data-url', url);
  199. $(link).attr("external", true);
  200. // Bind the click event to open the URL externally
  201. // Replace the URL text with the clickable link
  202. helpBlock.innerHTML = helpBlock.innerHTML.replace(url, link.outerHTML);
  203. $(helpBlock).find("a[external]").on("click", function(e) {
  204. e.preventDefault(); // Prevent the default link behavior
  205. $(this).addClass("externalRendered");
  206. console.log("opening external link", $(this).attr("data-url"));
  207. nw.Shell.openExternal($(this).attr("data-url")); // Open the URL in the system's browser
  208. });
  209. });
  210. }
  211. });
  212. $(parentElement).find("a[external]").not(".externalRendered").on("click", function(e) {
  213. $(this).addClass("externalRendered");
  214. e.preventDefault(); // Prevent the default link behavior
  215. console.log("opening external link", $(this).attr("href"));
  216. nw.Shell.openExternal($(this).attr("href")); // Open the URL in the system's browser
  217. });
  218. $(parentElement).find("a.externalLink").not(".externalRendered").on("click", function(e) {
  219. $(this).addClass("externalRendered");
  220. e.preventDefault(); // Prevent the default link behavior
  221. console.log("opening external link", $(this).attr("href"));
  222. nw.Shell.openExternal($(this).attr("href")); // Open the URL in the system's browser
  223. });
  224. }
  225. CustomFields.loadJSONForm = async function() {
  226. // load the main jsonform module
  227. await common.loadDomScript("/www/modules/jsonform/lib/jsonform.js");
  228. // load extended jsonform modules
  229. await common.loadDomScript("/www/js/jsonform.ext.js");
  230. }
  231. module.exports = CustomFields;