tree-suggest.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. /**
  2. * Copyright © Magento, Inc. All rights reserved.
  3. * See COPYING.txt for license details.
  4. */
  5. (function (root, factory) {
  6. 'use strict';
  7. if (typeof define === 'function' && define.amd) {
  8. define([
  9. 'jquery',
  10. 'jquery/ui',
  11. 'jquery/jstree/jquery.jstree',
  12. 'mage/backend/suggest'
  13. ], factory);
  14. } else {
  15. factory(root.jQuery);
  16. }
  17. }(this, function ($) {
  18. 'use strict';
  19. /* jscs:disable requireCamelCaseOrUpperCaseIdentifiers */
  20. var hover_node, dehover_node, select_node, init;
  21. $.extend(true, $, {
  22. // @TODO: Move method 'treeToList' in file with utility functions
  23. mage: {
  24. /**
  25. * @param {Array} list
  26. * @param {Object} nodes
  27. * @param {*} level
  28. * @param {*} path
  29. * @return {*}
  30. */
  31. treeToList: function (list, nodes, level, path) {
  32. $.each(nodes, function () {
  33. if ($.type(this) === 'object') {
  34. list.push({
  35. label: this.label,
  36. id: this.id,
  37. level: level,
  38. item: this,
  39. path: path + this.label
  40. });
  41. if (this.children) {
  42. $.mage.treeToList(list, this.children, level + 1, path + this.label + ' / ');
  43. }
  44. }
  45. });
  46. return list;
  47. }
  48. }
  49. });
  50. hover_node = $.jstree._instance.prototype.hover_node;
  51. dehover_node = $.jstree._instance.prototype.dehover_node;
  52. select_node = $.jstree._instance.prototype.select_node;
  53. init = $.jstree._instance.prototype.init;
  54. $.extend(true, $.jstree._instance.prototype, {
  55. /**
  56. * @override
  57. */
  58. init: function () {
  59. this.get_container()
  60. .show()
  61. .on('keydown', $.proxy(function (e) {
  62. var o;
  63. if (e.keyCode === $.ui.keyCode.ENTER) {
  64. o = this.data.ui.hovered || this.data.ui.last_selected || -1;
  65. this.select_node(o, true);
  66. }
  67. }, this));
  68. init.call(this);
  69. },
  70. /**
  71. * @override
  72. */
  73. hover_node: function (obj) {
  74. hover_node.apply(this, arguments);
  75. obj = this._get_node(obj);
  76. if (!obj.length) {
  77. return false;
  78. }
  79. this.get_container().trigger('hover_node', [{
  80. item: obj.find('a:first')
  81. }]);
  82. },
  83. /**
  84. * @override
  85. */
  86. dehover_node: function () {
  87. dehover_node.call(this);
  88. this.get_container().trigger('dehover_node');
  89. },
  90. /**
  91. * @override
  92. */
  93. select_node: function (o) {
  94. var node;
  95. select_node.apply(this, arguments);
  96. node = this._get_node(o);
  97. (node ? $(node) : this.data.ui.last_selected)
  98. .trigger('select_tree_node');
  99. }
  100. });
  101. $.widget('mage.treeSuggest', $.mage.suggest, {
  102. widgetEventPrefix: 'suggest',
  103. options: {
  104. template:
  105. '<% if (data.items.length) { %>' +
  106. '<% if (data.allShown()) { %>' +
  107. '<% if (typeof data.nested === "undefined") { %>' +
  108. '<div style="display:none;" data-mage-init="{&quot;jstree&quot;:{&quot;plugins&quot;:[&quot;themes&quot;,&quot;html_data&quot;,&quot;ui&quot;,&quot;hotkeys&quot;],&quot;themes&quot;:{&quot;theme&quot;:&quot;default&quot;,&quot;dots&quot;:false,&quot;icons&quot;:false}}}">' + //eslint-disable-line max-len
  109. '<% } %>' +
  110. '<ul>' +
  111. '<% _.each(data.items, function(value) { %>' +
  112. '<li class="<% if (data.itemSelected(value)) { %>mage-suggest-selected<% } %>' +
  113. ' <% if (value.is_active == 0) { %> mage-suggest-not-active<% } %>">' +
  114. '<a href="#" <%= data.optionData(value) %>><%- value.label %></a>' +
  115. '<% if (value.children && value.children.length) { %>' +
  116. '<%= data.renderTreeLevel(value.children) %>' +
  117. '<% } %>' +
  118. '</li>' +
  119. '<% }); %>' +
  120. '</ul>' +
  121. '<% if (typeof data.nested === "undefined") { %>' +
  122. '</div>' +
  123. '<% } %>' +
  124. '<% } else { %>' +
  125. '<ul data-mage-init="{&quot;menu&quot;:[]}">' +
  126. '<% _.each(data.items, function(value) { %>' +
  127. '<% if (!data.itemSelected(value)) {%>' +
  128. '<li <%= data.optionData(value) %>>' +
  129. '<a href="#">' +
  130. '<span class="category-label"><%- value.label %></span>' +
  131. '<span class="category-path"><%- value.path %></span>' +
  132. '</a>' +
  133. '</li>' +
  134. '<% } %>' +
  135. '<% }); %>' +
  136. '</ul>' +
  137. '<% } %>' +
  138. '<% } else { %>' +
  139. '<span class="mage-suggest-no-records"><%- data.noRecordsText %></span>' +
  140. '<% } %>',
  141. controls: {
  142. selector: ':ui-menu, :mage-menu, .jstree',
  143. eventsMap: {
  144. focus: ['menufocus', 'hover_node'],
  145. blur: ['menublur', 'dehover_node'],
  146. select: ['menuselect', 'select_tree_node']
  147. }
  148. }
  149. },
  150. /**
  151. * @override
  152. */
  153. _bind: function () {
  154. this._super();
  155. this._on({
  156. /**
  157. * @param {jQuery.Event} event
  158. */
  159. keydown: function (event) {
  160. var keyCode = $.ui.keyCode;
  161. switch (event.keyCode) {
  162. case keyCode.LEFT:
  163. case keyCode.RIGHT:
  164. if (this.isDropdownShown()) {
  165. event.preventDefault();
  166. this._proxyEvents(event);
  167. }
  168. break;
  169. }
  170. }
  171. });
  172. },
  173. /**
  174. * @override
  175. */
  176. close: function (e) {
  177. var eType = e ? e.type : null;
  178. if (eType === 'select_tree_node') {
  179. this.element.focus();
  180. } else {
  181. this._superApply(arguments);
  182. }
  183. },
  184. /**
  185. * @override
  186. */
  187. _filterSelected: function (items, context) {
  188. if (context._allShown) {
  189. return items;
  190. }
  191. return this._superApply(arguments);
  192. },
  193. /**
  194. * @override
  195. */
  196. _prepareDropdownContext: function () {
  197. var context = this._superApply(arguments),
  198. optionData = context.optionData,
  199. templates = this.templates,
  200. tmplName = this.templateName;
  201. /**
  202. * @param {Object} item
  203. * @return {*|String}
  204. */
  205. context.optionData = function (item) {
  206. item = $.extend({}, item);
  207. delete item.children;
  208. return optionData(item);
  209. };
  210. return $.extend(context, {
  211. /**
  212. * @param {*} children
  213. * @return {*|jQuery}
  214. */
  215. renderTreeLevel: function (children) {
  216. var _context = $.extend({}, this, {
  217. items: children,
  218. nested: true
  219. }),
  220. tmpl = templates[tmplName];
  221. tmpl = tmpl({
  222. data: _context
  223. });
  224. return $('<div>').append($(tmpl)).html();
  225. }
  226. });
  227. },
  228. /**
  229. * @override
  230. */
  231. _processResponse: function (e, items, context) {
  232. var control;
  233. if (context && !context._allShown) {
  234. items = this.filter($.mage.treeToList([], items, 0, ''), this._term);
  235. }
  236. control = this.dropdown.find(this._control.selector);
  237. if (control.length && control.hasClass('jstree')) {
  238. control.jstree('destroy');
  239. }
  240. this._superApply([e, items, context]);
  241. }
  242. });
  243. return $.mage.treeSuggest;
  244. }));