Javascript заменяет дочерние узлы, заставляя их изменяться на [object HTMLTableSectionElement]

Я пытаюсь преобразовать таблицу, чтобы программно удалить некоторые используемые теги, которые мне не нужны. Я написал рекурсивную функцию, которая вызывается для элемента таблицы и вызывает себя для всех дочерних элементов, составляя список этих дочерних элементов и заменяя текущие дочерние элементы этими очищенными дочерними элементами. Однако узлы не добавляются правильно, а вместо этого в выходных данных оказывается строковое представление [object HTMLTableSectionElement] или [object Text].

(Для тех, кто интересуется контекстом: я использую thead, tbody и пару пользовательских тегов для необычной таблицы, но я также хочу иметь возможность нажать кнопку, чтобы скопировать таблицу на страницы Википедии, которые не поддерживают эти теги, поэтому при копировании в буфер обмена мне приходится их удалять, иначе это будет выглядеть ужасно)

Это моя функция:

function prepHTMLforExport(element){
    //recursively goes into an HTML element, preparing it for export by:
    //removing thead and tbody statements but leaving their contents in the parent element
    //removing floattext tags
    //replacing hyperlink a tags with ...
    
    //go through child elements and prep each for export
    var newchildren = []
    var children = element.childNodes
    for (var i=0;i<children.length;i++){
        var newkid = prepHTMLforExport(children[i])
        
        //if the new kid is actually a list, concat the lists
        if (newkid instanceof Array){
            newchildren.concat(newkid)
        } else {
            newchildren.push(newkid)
        }
    }
    //if to be removed, return a list of children
    if (element.tagName in ["floattext", "table-body", "table-head"]){
        return newchildren
    } else {
        //else add children to self and return self
        if (newchildren.length > 0) {
            element.replaceChildren(newchildren)
        }
        return element
    }
}

Он должен работать практически с любой таблицей HTML.

Первоначально я подозревал, что проверяю не тех дочерних элементов или использую неправильный метод для их замены, поэтому я также попробовал это с помощью var children = element.children и посмотрел, есть ли другая функция для замены, например replaceWith, но при ближайшем рассмотрении я обнаружил, что это не помогло. Элементы уже преобразуются в неправильную форму в нодлисте своих родителей во время их обработки, а не только после того, как я заменил их очищенной версией. Чтобы проверить это, есть эта таблица:

<table>
  <th>sample text</th> 
  <th>some more sample text</th>
</table>

При прохождении кода, если код только что закончил подготовку первой ячейки, а теперь о рекурсии во вторую ячейку, если вы выполните console.info(element), это приведет к

<table>
  <th>[object Text]</th>
  <th>some more sample text</th>
</table>

Всякий раз, когда вы видите [object Object] или какой-либо другой [object Type], это означает, что ваш код преобразовал объект в строку. например let txt = "x" + obj

fdomn-m 15.05.2024 12:14

Вероятно, не по теме: array concat — возвращает новый массив, ваш код игнорирует это

fdomn-m 15.05.2024 12:17

Попробуйте изменить на newchildren = newchildren.concat(newkid); и element.replaceChildren(...newchildren) - похоже, работает (по крайней мере, без ошибок): jsfiddle.net/xfnjozhw/1 но вывод выглядит таким же, как ввод, поэтому я понятия не имею, сработало это или нет.

fdomn-m 15.05.2024 12:32

Хм, тогда возникает вопрос, где появляется эта строка и почему... Спасибо за примечание о concat, теперь я исправил это в своем коде.

Mennolt van Alten 15.05.2024 12:33

Ваша проблема в том, что .element.replaceChildren ожидает, что каждый дочерний элемент будет отдельным параметром, однако вы передаете массив. Попробуйте с element.replaceChildren(...newchildren)replaceChildren

fdomn-m 15.05.2024 12:34

@fdomn-m Это действительно работает! Фильтрации пока нет, но мне кажется, это другая проблема. Что именно делает...? это оператор распаковки, такой как python *?

Mennolt van Alten 15.05.2024 12:36

У меня был подготовлен подробный ответ, но я не знал, подойдет ли он вам. Это «остальные параметры», которые преобразуют массив в список параметров. В js также есть оператор распространения, который выглядит так же.

fdomn-m 15.05.2024 12:51
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
7
75
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Ваша проблема в том, что .element.replaceChildren ожидает, что каждый дочерний элемент будет отдельным параметром, однако вы передаете массив.

Итак, .replaceChildren преобразует массив в строку, давая

[object Text],[object HTMLTableSectionElement]

лишняя запятая , посередине — это дополнительный намек на то, что это был массив, преобразованный в строку.

Вы можете преобразовать массив в параметры, используя остальные параметры — эта строка вашего кода станет:

element.replaceChildren(...newchildren)

Обновленный фрагмент:

function prepHTMLforExport(element) {
  //recursively goes into an HTML element, preparing it for export by:
  //removing thead and tbody statements but leaving their contents in the parent element
  //removing floattext tags
  //replacing hyperlink a tags with ...

  //go through child elements and prep each for export
  var newchildren = []
  var children = element.childNodes
  for (let i = 0; i < children.length; i++) {
    var newkid = prepHTMLforExport(children[i])

    //if the new kid is actually a list, concat the lists
    if (newkid instanceof Array) {
      newchildren = newchildren.concat(newkid);
    } else {
      newchildren.push(newkid)
    }
  }
  //if to be removed, return a list of children
  if (element.tagName in ["floattext", "table-body", "table-head"]) {
    return newchildren
  } else {
    //else add children to self and return self
    if (newchildren.length > 0) {
      element.replaceChildren(...newchildren);
    }
    return element
  }
}

prepHTMLforExport(document.getElementById("tbl"));
<table id='tbl'>
  <th>sample text</th>
  <th>some more sample text</th>
</table>

Помимо массива, упомянутого @fdomn-m в его ответе, я вижу еще три проблемы.

Использование element.childNodes может возвращать текстовые узлы, такие как " " или "\n", а не только узлы элементов. Использование element.children исправит это.

element.tagNames возвращает теги в верхнем регистре, а вы сравниваете их со строками в нижнем регистре.

Наконец, вы сравниваете теги «table-head» и «table-body». Я предполагаю, что вы имели в виду «голова» и «тело». Я не знаю, что такое floattext, который вы проверяете.

Обновлено: Как вы можете видеть в комментариях к коду, я также изменил ваш

в [] быть [].includes()

Вот ваш код со всеми тремя этими изменениями.

function fancyTableOnClick( event ) {
      prepHTMLforExport( FancyTableID )
    }


    function prepHTMLforExport(element){
    //recursively goes into an HTML element, preparing it for export by:
    //removing thead and tbody statements but leaving their contents in the parent element
    //removing floattext tags
    //replacing hyperlink a tags with ...

    //go through child elements and prep each for export
    var newchildren = []
    // var children = element.childNodes
    var children = element.children  // Just elements, no text nodes
    for (var i=0;i<children.length;i++){
        var newkid = prepHTMLforExport(children[i])

        //if the new kid is actually a list, concat the lists
        if (newkid instanceof Array){
            newchildren = newchildren.concat(newkid)
        } else {
            newchildren.push(newkid)
        }
    }
    //if to be removed, return a list of children
    // if (element.tagName in ["floattext", "table-body", "table-head"]){
    if (["FLOATTEXT", "TBODY", "THEAD"].includes(element.tagName)){  // [].includes() not "in []"
        return newchildren
    } else {
        //else add children to self and return self
        if (newchildren.length > 0) {
            // element.replaceChildren(newchildren)
            element.replaceChildren(...newchildren)  // Takes individual elements, not an array
        }
        return element
    }
}
table {
  border: 2px solid red;
}
th {
  border: 1px solid black;
  padding: 0px 4px;
}
tbody {
  background-color: green;
}
thead {
  background-color: cyan;
}
<button type = "button" onclick = "fancyTableOnClick(event)">Fix Table</button>

      <table id = "FancyTableID">
        <thead>
          <th>sample text</th>
          <th>Something</th>
        </thead>
        <tbody>
          <h>Table body</th>
          <th>some more sample text</th>
        </tbody>
      </table>

Другие вопросы по теме