2015-03-04 2 views
1

Я написал функцию, которая взяла HTML-подборку и текст и итерации этой коллекции, ища узел с этим титлом. Затем он должен вернуть этот узел. Проблема в том, что он возвращается всегда неопределенным, даже когда он находит правильный узел: в коде вы видите, что есть console.log, который выводится, если текущий узел имеет этот заголовок. На консоли я вижу один «истинный», который я ожидаю, но цикл не останавливается на достигнутом, и функция ничего не возвращает.javascript поиск по названию в коллекции и вернуть его

function searchButtonbyText(group,text){ 
    for(var i=0;i<group.length;i++){ 
     for(var j=0; j< group[i].children.length; j++){ 
      var child = group[i].children[j]; 
      console.log(child.title == text); 
      if(child.title == text){ 
       console.log(child); 
       return child; 
      } 
     } 
    } 
} 

Я попытался с более простыми функциями, которые просто вернули определенный узел с коллекцией в качестве входных данных, и они работают правильно. Например

function tt(coll){ return coll[7].children[0]} 

Заранее спасибо.

EDIT

Я редактировал код, чтобы исправить ошибку. Теперь код работает, но подход к выбранному ответу намного лучше.

+2

'if (child.tite == text) {' возможно название ??? –

+0

@ JordiCastilla действительно хорошая добыча! –

+0

Если 'tite' был в этом случае, то как консоль регистрировала' true'? – Lepanto

ответ

2

Вот рекурсивный подход (демо enter link description here)

function searchButtonByText(element, text) { 
    var match; 
    if(element['title'] && element['title'] === text) { 
     return element; 
    } else { 
     for(var i = 0; i < element.children.length; i++) { 
      match = searchButtonByText(element.children[i], text); 
      if(match) { 
       break; 
      } 
     } 
     return match; 
    } 
} 

Со следующим HTML:

<ul id='Group'> 
    <li><button title='One'>One</button></li> 
    <li><button title='Two'>Two</button></li> 
    <li> 
     <ul> 
      <li><button title='A'>A</button></li> 
      <li><button title='B'>B</button></li> 
      <li><button title='C'>C</button></li> 
     </ul> 
    </li> 
    <li><button title='Three'>Three</button></li> 
</ul> 

Тогда вы можете вызвать его так:

console.log(searchButtonByText(document.getElementById('Group'), 'Two')); 

Он начинается любой произвольный узел, а затем просматривает каждый дочерний элемент до тех пор, пока не найдет совпадение (независимо от того, повторно). Или вы можете обобщить это еще дальше и сделать тест на обратный вызов, как это (demo):

function searchByFunction(element, matcher) { 
    var match; 
    if (matcher(element)) { 
     return element; 
    } else { 
     for (var i = 0; i < element.children.length; i++) { 
      match = searchByFunction(element.children[i], matcher); 
      if (match) { 
       break; 
      } 
     } 
     return match; 
    } 
} 

Тогда вам просто нужно передать функцию, которая возвращает истинное или ложное значение, основанное на какой-либо логики для Вас Завещание, как это :

console.log(searchByFunction(document.getElementById('Group'), function(element) { 
    return element['title'] && element['title'] === 'C'; 
})); 

Наконец обратиться требование работы с множеством элементов (которые каждый из них может иметь детей) здесь является осуществимым решением (demo):

function searchByFunction(element, matcher) { 
    var match, 
     i; 
    if(element.length) { 
     for (i = 0; i < element.length; i++) { 
      match = searchByFunction(element[i], matcher); 
      if (match) { 
       break; 
      } 
     } 
    } else { 
     if (matcher(element)) { 
      return element; 
     } else { 
      if(element.children) { 
       for (i = 0; i < element.children.length; i++) { 
        match = searchByFunction(element.children[i], matcher); 
        if (match) { 
         break; 
        } 
       } 
      } 
     } 
    } 
    return match; 
}; 

Наряду с вспомогательной функцией, чтобы генерировать соответствующие функции:

function buildTitleMatcher(title) { 
    return function(element) { 
     return element['title'] && element['title'] === title; 
    }; 
}; 

Вы можете использовать его с одним элементом, как это:

console.log(searchByFunction(document.getElementById('Group'), buildTitleMatcher('C'))); 

Или с массивом элементов, как это:

console.log(searchByFunction(document.getElementsByTagName('li'), buildTitleMatcher('B'))); 
+0

Большое спасибо Джейсону. Этот подход очень хорош! На самом деле это больше, чем я ожидал. Рекурсивные функции не являются одними из моих сильных сторон. Я добавлю его в репозиторий моих фрагментов. Я слышал, что JS очень медленный с рекурсивными функциями, поскольку производительность не является ключом к моему проекту, что вы знаете об этом? – Danielo515

+0

Привет, Джейсон. Рассмотрев ваше решение, я заметил, что он ожидает один элемент, так как мой подход повторял сборку HTML. Поэтому ваш пример должен быть изменен, чтобы соответствовать этой ситуации, вами или мной как изменением моего ответа. Спасибо – Danielo515

+0

Что касается моего последнего комментария вы можете использовать вспомогательную функцию: функция searchButtonInCollection (сбор, текст) { для (вар я = 0; я Danielo515

Смежные вопросы