Source: select.js

  1. /**
  2. * Select Dropdown Component
  3. * <BR><BR><img src=/tk/lib/components/w/img/select.png width=70% style="border:1px lime dashed";>
  4. * <BR><BR><a href="/tk/lib/components/w/html/select.html">DEMO</a>
  5. */
  6. class Select extends HTMLElement {
  7. constructor() {
  8. wc.group("Select.constructor")
  9. super();
  10. wc.groupEnd();
  11. };
  12. /**
  13. * Set observable values here. When Changed, attributeChangedCallback is invoked
  14. * @observedAttributes
  15. */
  16. static get observedAttributes() {
  17. wc.group("Select.observedAttributes");
  18. this.observables = ["searchable"];
  19. wc.groupEnd();
  20. return this.observables;
  21. };
  22. /**
  23. * This function is called when this is attached to DOM
  24. * @connectedCallback.
  25. */
  26. connectedCallback() {
  27. wc.group("Select.connectedCallback")
  28. let self = this;
  29. // GET PROPERTIES AND INTERESTING ELEMENTS
  30. this._initialize();
  31. let cols = this.properties.columns.split(',');
  32. let id = this.id;
  33. let c1 = "col-md-" + cols[0];
  34. let c2 = "col-md-" + cols[1];
  35. let lbl = this.properties.label || "";
  36. let hlp = this.properties.help || "";
  37. let name = $(this).attr("name");
  38. if (typeof name === "undefined") {name = id;}
  39. let tmp = id.toCamelCase()
  40. // REPLACE CONTENT IF NECESSARY WITH NEW STUFF
  41. this.innerHTML = `
  42. <div class="form-group clearfix">
  43. <div class="row">
  44. <div class="${c1}">
  45. <label id="${this.id}-label" for="${this.id}-label" class="btn-control col-form-label">${lbl}</label>
  46. </div>
  47. <div class="${c2}">
  48. <select name="${name}" class="form-control ${this.properties.class}" id="${tmp}-input">
  49. ${this.dom.content}>
  50. </select>
  51. <span class="glyphicon form-control-feedback" aria-hidden="true"></span>
  52. <small id='${this.id}-help' class='help-block with-errors text-muted'>${hlp}</small>
  53. </div>
  54. </div>
  55. </div>`
  56. // TRANSFER ALL ATTRIBUTES NOW (below is an example)
  57. let widget = this.querySelector("select");
  58. for (var key in this.propertiesW) {
  59. if (key != "class" && key != "id") {
  60. this.removeAttribute(key);
  61. widget.setAttribute(key, this.properties[key]);
  62. }
  63. }
  64. this.select = this.querySelector("select");
  65. if(this.properties.searchable == "true") {
  66. var search = 1
  67. } else {
  68. var search = Infinity
  69. }
  70. $(this.select).select2({
  71. minimumResultsForSearch: search, // HIDE SEARCH
  72. theme: 'bootstrap4',
  73. width: 'style',
  74. placeholder: $(this).attr('placeholder'),
  75. allowClear: false,
  76. });
  77. //containerCssClass: "wc-select2-container-class",
  78. //dropdownCssClass: "wc-select2-dropdown-class"
  79. // USE THIS CLASS TO CUSTOMIZE
  80. let s2 = $(this.select).next(".select2")
  81. $(s2).addClass("wc-select2-custom");
  82. // ADD STATS AND OTHER FINAL STUFF
  83. this._finalize();
  84. // PUBLISH INTERESTING EVENTS
  85. this._publish();
  86. // SHOW IT NOW (NO FLICKERS)
  87. this.style.visibility = "visible";
  88. wc.groupEnd();
  89. };
  90. /**
  91. * Publish all events
  92. * @private
  93. * @_publish
  94. */
  95. _publish() {
  96. wc.group("Select._publish");
  97. let widget = this.querySelector("select");
  98. let id = $(widget).attr("id");
  99. $("#" + id).on("change", e => {
  100. this._change(id)
  101. });
  102. // NOT WORKING
  103. // widget.addEventListener("change", e => {
  104. // this._change(id);
  105. // });
  106. wc.groupEnd();
  107. return true;
  108. }
  109. /**
  110. * A sample callback usage function - see connectedCallback()
  111. * @private
  112. * @_onChange
  113. */
  114. _change(id) {
  115. wc.group("Select._change:", id);
  116. let val = $("#" + id).val();
  117. wc.publish("wc-select", {
  118. time: new Date().getTime(),
  119. action: "change",
  120. id: id,
  121. val: val,
  122. uparam: this.properties.uparam
  123. });
  124. wc.groupEnd();
  125. };
  126. /**
  127. * Invoked When component is removed. Usually with a .remove() function call
  128. * @disconnectedCallback
  129. */
  130. disconnectedCallback() {
  131. wc.group("Select.disconnectedCallback")
  132. /* CLEAN UP NOW */
  133. wc.groupEnd();
  134. };
  135. /**
  136. * Called with .setAttribute(...) function call
  137. * @attributeChangedCallback
  138. */
  139. attributeChangedCallback(attr, oldval, newval) {
  140. wc.group("Select.attributeChangedCallback:", attr, oldval, newval);
  141. this.properties = this.properties || [];
  142. let obs = Select.observedAttributes;
  143. for (let i = 0; i < obs.length; i++) {
  144. if (newval) {
  145. this.properties[obs[i]] = newval;
  146. // YOUR CODE FOR CHANGES GO HERE
  147. }
  148. }
  149. wc.log("=====", this.properties);
  150. wc.groupEnd();
  151. };
  152. /**
  153. * Stores DOM elements of interest for future use
  154. * @private
  155. * @_fetchElements
  156. */
  157. _fetchElements() {
  158. wc.group("Select._fetchElements");
  159. this.dom = this.dom || [];
  160. this.dom.content = this.innerHTML;
  161. wc.groupEnd();
  162. };
  163. /**
  164. * Component attributes are _fetched and defaults are set if undefined
  165. * @private
  166. * @_fetchAttributes
  167. * @param {string} [searchable=false]
  168. */
  169. _fetchAttributes() {
  170. wc.group("Select._fetchAttributes");
  171. this.properties = {
  172. "cname" : "Select",
  173. "author" : "Mel Heravi",
  174. "version" : "1.0",
  175. "columns" : "12,12",
  176. "searchable" : "false"
  177. };
  178. // SAVE WIDGET SPECIFIC PROPERTIES
  179. this.propertiesW = [];
  180. // SAVE ALL OTHER PROPERTIES
  181. let attrs = wc.getAttributes(this)
  182. for (var key in attrs) {
  183. this.properties[key] = this.getAttribute(key);
  184. this.propertiesW[key] = this.getAttribute(key);
  185. wc.log(key + ": " + attrs[key]);
  186. }
  187. this.properties.placeholder = this.properties.placeholder || "";
  188. wc.log("---------", this.properties);
  189. wc.groupEnd();
  190. };
  191. /**
  192. * Destroy the instance object and artifacts
  193. * @private
  194. * @_destroy
  195. */
  196. destroy() {
  197. wc.group("Select.destroy:", this.id);
  198. // FREE POINTER
  199. delete this;
  200. // REMOVE ITEM FROM DOM
  201. this.parentNode.removeChild(this);
  202. wc.groupEnd();
  203. };
  204. /**
  205. * SAVE DATA FOR ANALYTICS
  206. * @private
  207. * @_initialize
  208. */
  209. _initialize() {
  210. wc.group("Select._initialize:", this.id);
  211. // FETCH ALL INTERESTING ELEMENTS
  212. this._fetchElements();
  213. // FETCH ALL ATTRIBUTES
  214. this._fetchAttributes();
  215. wc.groupEnd();
  216. };
  217. /**
  218. * SAVE DATA FOR ANALYTICS
  219. * @private
  220. * @_finalize
  221. */
  222. _finalize() {
  223. wc.group("Select._finalize:", this.id);
  224. this.classList.add("wc");
  225. // ADD ANALYTICS HERE
  226. wc.setStats(this, this.properties.cname, this.properties.version);
  227. wc.groupEnd();
  228. };
  229. /**
  230. * FOR TESTING PURPOSES
  231. * @test
  232. */
  233. static test() {
  234. wc.group("Select.test");
  235. wc.log("testing results will be printed here...");
  236. wc.groupEnd();
  237. return true;
  238. }
  239. /**
  240. * configure the instance object and artifacts
  241. * @configure
  242. * @param {string} data use data if exist else use 'this.properties.cfg' parameter
  243. */
  244. configure(data) {
  245. wc.group("Select.configure:", data);
  246. // IF JSON VARIABLE (data) IS PROVIDED
  247. if (data) {
  248. this._process(data);
  249. } else {
  250. let self = this;
  251. $.getJSON(this.properties.cfg, function(data) {
  252. self._process(data);
  253. }).fail(function(jqXHR, textStatus, errorThrown) {
  254. alert("ERROR: INCOMING TEXT " + jqXHR.responseText);
  255. });
  256. }
  257. wc.groupEnd();
  258. };
  259. /**
  260. * _process the instance object and artifacts
  261. * @private
  262. * @_process
  263. */
  264. _process(data) {
  265. wc.group("Select._process:", data);
  266. let w = this.querySelector("select");
  267. for (var i = 0; i < data.length; i++) {
  268. var opt = document.createElement('option');
  269. opt.value = data[i].value;
  270. opt.innerHTML = data[i].name;
  271. w.appendChild(opt);
  272. }
  273. wc.groupEnd();
  274. };
  275. }
  276. window.customElements.define('wc-select', Select);
  277. // SO I CAN CALL THE STATIC METHOD GLOBALLY
  278. window.Select = Select;