ค้นหาเว็บไซต์

javascript - อัปเดตจำนวนผลลัพธ์ที่ค้นหาและเปลี่ยนการเลือกตามจำนวนครั้งที่ผู้ใช้ค้นหาในอาร์เรย์ของวัตถุ


ฉันอยากเพิ่มฟังก์ชันที่ผู้ใช้สามารถไปยังผลการค้นหาถัดไปได้ ขอบคุณ @ggorlen สำหรับความช่วยเหลือเกี่ยวกับการค้นหาแบบวนซ้ำ

ฉันมีฟังก์ชันการค้นหาแบบเรียกซ้ำที่ให้ค่าตัวแรกและทำให้พวกมัน selected=true และถ้าอยู่ในอาร์เรย์ซ้อนก็ทำให้ showTree=true

  • ฉันจะเพิ่มฟังก์ชันที่เมื่อผู้ใช้คลิกที่บันทึกการค้นหาถัดไป ตัวเลือก selected: true จะถูกตั้งค่าให้กับผลลัพธ์ถัดไปและลบออกจากผลลัพธ์ก่อนหน้าได้อย่างไร?

  • และตามผลลัพธ์ใหม่ showTree จะเปลี่ยนไป

  • วิธีเพิ่มตัวแปรซึ่งได้รับการอัปเดตตามจำนวนครั้งที่มีการเรียกการค้นหา...

  • ตัวเลือกบันทึกก่อนหน้านี้เพื่อให้ผู้ใช้สามารถย้อนกลับไปยังผลลัพธ์ก่อนหน้า

const expandPath = (nodes, targetLabel) => {
  for (const node of nodes) {
    if (node.label.includes(targetLabel)) {
      return (node.selected = true);
    } else if (expandPath(node.item, targetLabel)) {
      return (node.showTree = true);
    }
  }
};

// Output

expandPath(testData, 'ch');

//// add variable for count  example: 1 of 25

console.log(testData);

//if user click on nextrecord after search


//nextrecord(){
//logic to remove the selected true from current and add for next
//update showtree
//update recordNumber of totalValue example: 2 of 25
//}


//child3 should get selected true and remove child1 selected true and showtree
//same add showTree= true based on selected value

//if user click on previous record after search

//previousrecord(){
//logic to remove the selected true from current and add for previous
//update showtree
//update recordNumber of totalValue example: 1 of 25
//}



console.log(testData);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script>
// Test Data
const testData = [
  {
    id: 1,
    label: 'parent1',
    item: [
      {
        id: 21,
        label: 'child1',
        item: [
          {
            id: 211,
            label: 'child31',
            item: [
              {
                id: 2111,
                label: 'child2211',
                item: [{ id: 21111, label: 'child22111' }]
              }
            ]
          },
          { id: 222, label: 'child32' }
        ]
      },
      {
        id: 22,
        label: 'child2',
        item: [
          {
            id: 221,
            label: 'child421',
            item: [{ id: 2211, label: 'child2211' }]
          },
          { id: 222, label: 'child222' }
        ]
      }
    ]
  },
  {
    id: 2,
    label: 'parent2',
    item: [
      {
        id: 21,
        label: 'child2',
        item: [
          {
            id: 511,
            label: 'child51',
            item: [
              {
                id: 5111,
                label: 'child5211',
                item: [{ id: 51111, label: 'child52111' }]
              }
            ]
          },
          { id: 522, label: 'child352' }
        ]
      }
    ]
  }
];
</script>

คำตอบ #1

คุณสามารถอ้างอิงรหัสต่อไปนี้

    const testData = [
  {
    id: 1,
    label: 'parent1',
    item: [
      {
        id: 21,
        label: 'child1',
        item: [
          {
            id: 211,
            label: 'child31',
            item: [
              {
                id: 2111,
                label: 'child2211',
                item: [{ id: 21111, label: 'child22111' }]
              }
            ]
          },
          { id: 222, label: 'child32' }
        ]
      },
      {
        id: 22,
        label: 'child2',
        item: [
          {
            id: 221,
            label: 'child421',
            item: [{ id: 2211, label: 'child2211' }]
          },
          { id: 222, label: 'child222' }
        ]
      }
    ]
  },
  {
    id: 2,
    label: 'parent2',
    item: [
      {
        id: 21,
        label: 'child2',
        item: [
          {
            id: 511,
            label: 'child51',
            item: [
              {
                id: 5111,
                label: 'child5211',
                item: [{ id: 51111, label: 'child52111' }]
              }
            ]
          },
          { id: 522, label: 'child352' }
        ]
      }
    ]
  }
];

// flatten down tree to array and add parent pointer
const flatten = (data) => {
  let flattenData = [data]
  if (data.item) {
    for (const item of data.item) {
      item.parent = data;
      flattenData = flattenData.concat(flatten(item));
    }
  }
  return flattenData;
}

let flattenData = [];

// flatten down the test data
for (const data of testData) {
  flattenData = flattenData.concat(flatten(data));
}

// to update showTree flag
const toggle = (item, expand = true) => {
  const parent = item.parent;
  if (parent) {
    parent.showTree = expand;
    if (parent.parent) {
      return toggle(parent, expand);
    }
    return parent;
  }
  return item;
}

/**
 * 
 * @param {targetLabel} query 
 * @returns function navigate with param forward flag
 */
const seach = (query) => {
  let index = -1;
  const items = flattenData.filter(x => x.label.includes(query));
  return (forward = true) => {
    if (index > -1) {
      items[index].selected = false;
      toggle(items[index], false);
    }
    index = index + (forward ? 1 : -1);
    let item = null;
    if (index > -1 && index < items.length) {
      items[index].selected = true;
      item = toggle(items[index], true);
    }
    return {
      item,
      index,
      length: items.length
    }
  }
}

const navigate = seach('child5211');

// next result
let result = navigate();

// previous result
result = navigate(false);

// result will look like this
/**
 * {
 *  item: root of current item with showTree and selected falgs or null if out of bound,
 *  index: current match,
 *  length: total match
 * }
 * 
 */

คำตอบ #2

จัดการทีละเรื่องตรงนี้ คุณสามารถได้ฟังก์ชัน 'ถัดไป' ที่ต้องการได้อย่างรวดเร็วโดยการแปลงการค้นหาแบบเรียกซ้ำของคุณให้เป็นฟังก์ชันตัวสร้าง:

function* expandPath(nodes, targetLabel) {
  for (const node of nodes) {
    if (node.label.includes(targetLabel)) {
      yield (node.selected = true);
    } else if (expandPath(node.item, targetLabel)) {
      yield (node.showTree = true);
    }
  }
};

const gen = expandPath(mynodes, "thisTargetLabel");
gen.next()
gen.next() //<-- the next one

มันค่อนข้างยากที่จะตอบคำถามอื่น ๆ โดยไม่รู้บริบทของคุณมากขึ้น แต่สิ่งที่ดูเหมือนว่าคุณต้องการที่นี่คือ state และ class (es6) เป็นวิธีที่ดีในการสร้างสิ่งนี้:

class Searcher {
  constructor(mynodes, mylabel){
    this.count=0;
    this.nodes=mynodes;
    this.label=mylabel;
    this.generateMatches(this.nodes);
    this.selectNode(this.matches[0]); // select the first node
  }

  generateMatches(nodes){
      this.matches=[];
    for (const node of nodes) {
      if (node.label.includes(this.label)) {
        this.matches.push(node);
      } else {
        this.generateMatches(nodes.node) 
      }
    }
  }

  updateTreeById(id, node){
    this.nodes.forEach(n=>n.showTree = false);
    for (const node of this.nodes) {
      if (node.id === id) {
        //noop but we are here
      } else if(this.updateTreeById(id, this.nodes.node)) {
        node.showTree = true;
      }
    }
  }

  selectNode(i){
    const index =  i % this.matches.length;
    this.currNodeId =  this.matches[index].id;
    this.matches[index].selected = true // we are wrapping around
    this.count = i; // setting your current count
    this.updateTreeById(this.matches[index].id)
    // update logic, reset trees
  }

  nextNode(){
    this.selectNode(this.count + 1)
  }
  prevNode(){
    this.selectNode(this.count - 1)
  }
}