vakata / jstree

jquery tree plugin
http://jstree.com
MIT License
5.15k stars 1.38k forks source link

SUGGESTION: Add option for unique plugin which disables name validation between nodes of different type #2440

Closed kgrishchenyuk closed 4 years ago

kgrishchenyuk commented 4 years ago

In my case, I have nodes of two types: folders and files, I'm making a file explorer. When unique plugin is enabled, it doesn't allow me to create a folder if a file with the same name already exists. I solved that issue by patching the 'check' function in the plugin. It is most likely not optimal, but here is what I got:

this.check = function (chk, obj, par, pos, more) {
  if(parent.check.call(this, chk, obj, par, pos, more) === false) { return false; }
  obj = obj && obj.id ? obj : this.get_node(obj);
  par = par && par.id ? par : this.get_node(par);
  if(!par || !par.children) { return true; }
  var n = { 'text': chk === "rename_node" ? pos : obj.text, 'type': obj.type },
    c = [],
    s = this.settings.unique.case_sensitive,
    w = this.settings.unique.trim_whitespace,
    m = this._model.data, i, j, t;
  for(i = 0, j = par.children.length; i < j; i++) {
    t = m[par.children[i]].text;
    if (!s) {
      t = t.toLowerCase();
    }
    if (w) {
      t = t.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
    }
    c.push({'text': t, 'type': m[par.children[i]].type});
  }
  if(!s) { n.text = n.text.toLowerCase(); }
  if (w) { n.text = n.text.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); }
  switch(chk) {
    case "delete_node":
    return true;
    case "rename_node":
    t = obj.text || '';
    if (!s) {
      t = t.toLowerCase();
    }
    if (w) {
      t = t.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
    }
    i = (c.findIndex(e => e.text == n.text && e.type == n.type) === -1 || (obj.text && t === n.text));
    if(!i) {
      this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_01', 'reason' : 'Child with name ' + n.text + ' 
            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 }) };
    }
    return i;
     case "create_node":
        i = (c.findIndex(e => e.text == n.text && e.type == n.type) === -1);
    if(!i) {
      this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_04', 'reason' : 'Child with name ' + n.text + ' 
            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 }) };
    }
    return i;
     case "copy_node":
    i = (c.findIndex(e => e.text == n.text && e.type == n.type) === -1);
    if(!i) {
      this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_02', 'reason' : 'Child with name ' + n.text + ' 
            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 }) };
    }
    return i;
     case "move_node":
    i = ( (obj.parent === par.id && (!more || !more.is_multi)) || c.findIndex(e => e.text == n.text && e.type == n.type) === -1);
    if(!i) {
      this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_03', 'reason' : 'Child with name ' + n.text + ' a 
            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 }) };
    }
    return i;
  }
  return true;
}

As you can see here, in the beginnig I'm forming an object including node's type and name instead of just string for futher operations with it.

So, can we have an in-built option for making validation only type-level?

vakata commented 4 years ago

The only complete solution would be a custom callback, but I try to keep this plugin simple. So the correct solution is to wrap this function in your own (third party) plugin. If you do that I will include it with all useful third party plugins in this repo.

kgrishchenyuk commented 4 years ago

Sorry, but I'm just a beginner, I'm afraid I won't be able to make a whole plugin correctly. Maybe later. But thanks for the reply anyway!