jstree.unique.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /**
  2. * ### Unique plugin
  3. *
  4. * Enforces that no nodes with the same name can coexist as siblings.
  5. */
  6. /*globals jQuery, define, exports, require */
  7. (function (factory) {
  8. "use strict";
  9. if (typeof define === 'function' && define.amd) {
  10. define('jstree.unique', ['jquery','jstree'], factory);
  11. }
  12. else if(typeof exports === 'object') {
  13. factory(require('jquery'), require('jstree'));
  14. }
  15. else {
  16. factory(jQuery, jQuery.jstree);
  17. }
  18. }(function ($, jstree, undefined) {
  19. "use strict";
  20. if($.jstree.plugins.unique) { return; }
  21. /**
  22. * stores all defaults for the unique plugin
  23. * @name $.jstree.defaults.unique
  24. * @plugin unique
  25. */
  26. $.jstree.defaults.unique = {
  27. /**
  28. * Indicates if the comparison should be case sensitive. Default is `false`.
  29. * @name $.jstree.defaults.unique.case_sensitive
  30. * @plugin unique
  31. */
  32. case_sensitive : false,
  33. /**
  34. * Indicates if white space should be trimmed before the comparison. Default is `false`.
  35. * @name $.jstree.defaults.unique.trim_whitespace
  36. * @plugin unique
  37. */
  38. trim_whitespace : false,
  39. /**
  40. * A callback executed in the instance's scope when a new node is created and the name is already taken, the two arguments are the conflicting name and the counter. The default will produce results like `New node (2)`.
  41. * @name $.jstree.defaults.unique.duplicate
  42. * @plugin unique
  43. */
  44. duplicate : function (name, counter) {
  45. return name + ' (' + counter + ')';
  46. }
  47. };
  48. $.jstree.plugins.unique = function (options, parent) {
  49. this.check = function (chk, obj, par, pos, more) {
  50. if(parent.check.call(this, chk, obj, par, pos, more) === false) { return false; }
  51. obj = obj && obj.id ? obj : this.get_node(obj);
  52. par = par && par.id ? par : this.get_node(par);
  53. if(!par || !par.children) { return true; }
  54. var n = chk === "rename_node" ? pos : obj.text,
  55. c = [],
  56. s = this.settings.unique.case_sensitive,
  57. w = this.settings.unique.trim_whitespace,
  58. m = this._model.data, i, j, t;
  59. for(i = 0, j = par.children.length; i < j; i++) {
  60. t = m[par.children[i]].text;
  61. if (!s) {
  62. t = t.toLowerCase();
  63. }
  64. if (w) {
  65. t = t.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
  66. }
  67. c.push(t);
  68. }
  69. if(!s) { n = n.toLowerCase(); }
  70. if (w) { n = n.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); }
  71. switch(chk) {
  72. case "delete_node":
  73. return true;
  74. case "rename_node":
  75. t = obj.text || '';
  76. if (!s) {
  77. t = t.toLowerCase();
  78. }
  79. if (w) {
  80. t = t.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
  81. }
  82. i = ($.inArray(n, c) === -1 || (obj.text && t === n));
  83. if(!i) {
  84. this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_01', 'reason' : 'Child with name ' + n + ' already exists. Preventing: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) };
  85. }
  86. return i;
  87. case "create_node":
  88. i = ($.inArray(n, c) === -1);
  89. if(!i) {
  90. this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_04', 'reason' : 'Child with name ' + n + ' already exists. Preventing: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) };
  91. }
  92. return i;
  93. case "copy_node":
  94. i = ($.inArray(n, c) === -1);
  95. if(!i) {
  96. this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_02', 'reason' : 'Child with name ' + n + ' already exists. Preventing: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) };
  97. }
  98. return i;
  99. case "move_node":
  100. i = ( (obj.parent === par.id && (!more || !more.is_multi)) || $.inArray(n, c) === -1);
  101. if(!i) {
  102. this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_03', 'reason' : 'Child with name ' + n + ' already exists. Preventing: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) };
  103. }
  104. return i;
  105. }
  106. return true;
  107. };
  108. this.create_node = function (par, node, pos, callback, is_loaded) {
  109. if(!node || node.text === undefined) {
  110. if(par === null) {
  111. par = $.jstree.root;
  112. }
  113. par = this.get_node(par);
  114. if(!par) {
  115. return parent.create_node.call(this, par, node, pos, callback, is_loaded);
  116. }
  117. pos = pos === undefined ? "last" : pos;
  118. if(!pos.toString().match(/^(before|after)$/) && !is_loaded && !this.is_loaded(par)) {
  119. return parent.create_node.call(this, par, node, pos, callback, is_loaded);
  120. }
  121. if(!node) { node = {}; }
  122. var tmp, n, dpc, i, j, m = this._model.data, s = this.settings.unique.case_sensitive, w = this.settings.unique.trim_whitespace, cb = this.settings.unique.duplicate, t;
  123. n = tmp = this.get_string('New node');
  124. dpc = [];
  125. for(i = 0, j = par.children.length; i < j; i++) {
  126. t = m[par.children[i]].text;
  127. if (!s) {
  128. t = t.toLowerCase();
  129. }
  130. if (w) {
  131. t = t.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
  132. }
  133. dpc.push(t);
  134. }
  135. i = 1;
  136. t = n;
  137. if (!s) {
  138. t = t.toLowerCase();
  139. }
  140. if (w) {
  141. t = t.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
  142. }
  143. while($.inArray(t, dpc) !== -1) {
  144. n = cb.call(this, tmp, (++i)).toString();
  145. t = n;
  146. if (!s) {
  147. t = t.toLowerCase();
  148. }
  149. if (w) {
  150. t = t.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
  151. }
  152. }
  153. node.text = n;
  154. }
  155. return parent.create_node.call(this, par, node, pos, callback, is_loaded);
  156. };
  157. };
  158. // include the unique plugin by default
  159. // $.jstree.defaults.plugins.push("unique");
  160. }));