mardi 2 octobre 2018

Ember one focus active list - recursive problem

I am building a multi-select checkdown group item list. The goal is to have only ONE active group at a time. So the user can select parents - but if they select a child item, that child group becomes the focus and the selected parents become unchecked.

<div class="checkboxhandler">
  <input 
    type="checkbox" 
    checked=
    onclick=
  >
  <label> -- checked: </label>

  
    

       <CheckboxGroup @item= @onClick= />

    
  
</div>

I've got as far with the checkboxes with recursive helper checks.

This is the helper tree - where the logic to deselect takes place. This application also needs to hold the array for selectedItems - but needs to clear those array's as well as the checkboxes.

const toggle = value => !value;
const disable = () => false;

// the roots / siblings are contained by arrays
export function check(tree, id, transform = toggle) {
  if (tree === undefined) return undefined;

  if (Array.isArray(tree)) {
    return tree.map(t => check(t, id, transform));
  } 

  if (tree.id === id || id === 'all') {
    return checkNode(tree, id, transform);
  }

  if (tree.children) {
    return checkChildren(tree, id, transform);
  }

  return tree;
}

function selectOnlySubtree(tree, id, transform) {
  return tree.map(subTree => {
    const newTree = check(subTree, id, transform);

    if (!newTree.children || (transform !== disable && didChange(newTree, subTree))) {
      return newTree;
    } 

    return disableTree(subTree);
  });
}

function isTargetAtThisLevel(tree, id) {
  return tree.map(t => t.id).includes(id);
}

function checkNode(tree, id, transform) {
  return { 
    ...tree, 
    checked: transform(tree.checked),
    children: disableTree(tree.children)
  };
}

function disableTree(tree) {
  return check(tree, 'all', disable);
}

function checkChildren(tree, id, transform) {
  const newChildren = check(tree.children, id, transform);
  const changed = didChange(tree.children, newChildren);
  const checked = changed ? false : (
    id === 'all' ? transform(tree.checked) : tree.checked
  );

    return { 
        ...tree, 
        checked: checked,
    children: check(tree.children, id, transform) 
  };
}

export function didChange(treeA, treeB) {
  const rootsChanged = treeA.checked !== treeB.checked;

  if (rootsChanged) return true;

  if (Array.isArray(treeA) && Array.isArray(treeB)) {
    return didChangeList(treeA, treeB);
  }

  if (treeA.children && treeB.children) {
        return didChangeList(treeA.children, treeB.children);
  }

  return false;
}

function didChangeList(a, b) {
  const compares = a.map((childA, index) => {
    return didChange(childA, b[index]);
  });

  const nothingChanged = compares.every(v => v === false);

  return !nothingChanged;
}

//latest ember fiddle https://canary.ember-twiddle.com/468a737efbbf447966dd83ac734f62ad?openFiles=tests.unit.utils.tree-helper-test.js%2C

so these are valid conditions -- just parents selected enter image description here

-- just children selected enter image description here

but the current bugs are occuring

  1. currently - I can select chilli - then burger - and no decheck of chilli occurs - so that's a bug
  2. currently - I can select coffee maker - then pickle - and no decheck of coffee maker occurs - so that's a bug
  3. currently - I can select filter - then chilli - and no decheck of filter occurs - so that's a bug

//illustration of error 1 - so only burger should remain selected in this instance enter image description here

//illustration of error 2 - so only pickle should remain selected in this instance enter image description here

//illustration of problem 3 - so only chilli should remain selected in this instance enter image description here




Aucun commentaire:

Enregistrer un commentaire