Перебирая все div внутри контейнера div, используя jQuery - PullRequest
0 голосов
/ 18 января 2020

Я пытаюсь сделать что-то вроде системы выставления счетов, и html выглядит так:

<invoice>
  <headers>
    <div date contenteditable>15-Jan-2020</div>
    <div buyer contenteditable>McDonalds</div>
    <div order contenteditable>145632</div>
  </headers>
  <item>
    <div name contenteditable>Big Mac</div>
    <div quantity contenteditable>5</div>
    <div rate contenteditable>20.00</div>
  </item>
  <item>
    <div name contenteditable>Small Mac</div>
    <div quantity contenteditable>10</div>
    <div rate contenteditable>10.00</div>
  </item>
</invoice>

<button>Loop</button>

Мне нужно l oop через каждый <invoice> и получить подробности от <headers> и <item>, поэтому конечные результаты выглядят следующим образом.

date : 15-Jan-2020 buyer : McDonalds order:145632
item : Big Mac quantity : 5 rate : 20.00
item : Small Mac quantity : 10 rate : 10.00

Я планирую отправить эти данные как json в PHP сценарий для обработки.

проблема в том, что <headers>, <items> не будут единственными контейнерами в каждом счете. Там может быть <address>, <transporter> et c. но они все будут внутри каждого <invoice>.

В таком случае, как я могу oop пройти через каждый контейнер и получить его данные?

Вот jQuery Я пытался:

var button = $("button")

button.on("click", function() {
  $('invoice').each(function() {
    alert('It works');

  });
});

Скрипка здесь

Ответы [ 3 ]

1 голос
/ 18 января 2020

Вы можете использовать l oop - div и использовать data-attribute для названия, как показано ниже

$('invoice>headers>div, invoice>item>div').each(function(index,item) {

  console.log($(this).attr('data-name'),  $(this).text());

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<invoice>
  <headers>
    <div date contenteditable data-name="date">15-Jan-2020</div>
    <div buyer contenteditable  data-name="buyer">McDonalds</div>
    <div order contenteditable  data-name="order">145632</div>
  </headers>
  <item>
    <div name contenteditable data-name="name">Big Mac</div>
    <div quantity contenteditable data-name="quantity">5</div>
    <div rate contenteditable data-name="rate">20.00</div>
  </item>
  <item>
    <div name contenteditable data-name="name">Small Mac</div>
    <div quantity contenteditable data-name="quantity">10</div>
    <div rate contenteditable data-name="rate">10.00</div>
  </item>
</invoice>
1 голос
/ 18 января 2020

Кажется, ваш HTML недействителен HTML. Spe c не определяет такие элементы, как <invoice>, <headers> и <item>. Кроме того, атрибуты на элементах почти всегда напоминают пары ключ-значение, то есть вы должны объявить свои атрибуты name, buyer, order, quantity и rate в качестве значений существующих атрибутов. Атрибут contenteditable является логическим атрибутом, который можно оставить без изменений.

Вот исправленный и рабочий пример:

var button = $('#read-invoice');

// readLine :: [String] -> (HTMLElement -> String)
function readLine(fields) {
  return function (el) {
    return fields.reduce(function (txt, field) {
      var data = $('.' + field, el).text();
      return txt === ''
        ? field + ': ' + data
        : txt + '; ' + field + ': ' + data
    }, '');
  }
}

// readBlock :: { (HTMLElement -> String) } -> (HTMLElement -> String)
function readBlock(readers) {
  return function (el) {
    var rtype = el.className;
    if (typeof readers[rtype] === 'function') {
      return readers[rtype](el);
    }
    return '';
  }
}

// autoRead :: HTMLElement -> String
var autoRead = readBlock({
  headers: readLine(['date', 'buyer', 'order']),
  item: readLine(['name', 'quantity', 'rate'])
  // ... address, etc.
});

button.on('click', function () {
  var result = $('.invoice').
    children().
    toArray().
    reduce(function (txt, el) {
      var line = autoRead(el);
      return line === ''
        ? txt
        : txt + line + '\n';
    }, '');
    
  console.log(result);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="invoice">
  <div class="headers">
    <div class="date" contenteditable>15-Jan-2020</div>
    <div class="buyer" contenteditable>McDonalds</div>
    <div class="order" contenteditable>145632</div>
  </div>
  <div class="item">
    <div class="name" contenteditable>Big Mac</div>
    <div class="quantity" contenteditable>5</div>
    <div class="rate" contenteditable>20.00</div>
  </div>
  <div class="item">
    <div class="name" contenteditable>Small Mac</div>
    <div class="quantity" contenteditable>10</div>
    <div class="rate" contenteditable>10.00</div>
  </div>
</div>

<button id="read-invoice">Loop</button>

JS объяснение

Функция readLine принимает Array String с, где каждый String напоминает имя класса одного из внутренних <div> элементов. Он возвращает функцию, которая ожидает элемент «блок» (например, <div class="headers">) и считывает содержимое содержащихся в нем <div> в один String. Давайте назовем возвращенную функцию reader .

Функция readBlock берет Object функций считывателя и возвращает функцию, содержащую элемент "block". Возвращаемая функция определяет, какой тип «блока» она получила, и вызывает соответствующую функцию чтения с элементом в качестве аргумента. Если ни один читатель не соответствует типу блока, он возвращает пустое значение String.

. В конце концов, autoRead становится единственной функцией, принимающей целый элемент «блока» и возвращающей все его содержимое в виде строки. текста.

Обработчик клика button ищет элемент <div class="invoice">, пересекает его дерево DOM до его дочерних элементов (наших элементов "блока") и передает каждый "блок" в autoRead, наращивание результата String. Окончательный результат заносится в консоль.

Расширение

Чтобы добавить новые типы «блоков», просто определите для них новый считыватель и добавьте его в Object передано readBlock. Например, добавить читатель <div class="address">, который читает информацию "name", "street", "zip" и "city":

var autoRead = readBlock({
  headers: readLine(['date', 'buyer', 'order']),
  item: readLine(['name', 'quantity', 'rate']),
  address: readLine(['name', 'street', 'zip', 'city']) // <<< new
}); 

Расширить поля, которые читает определенный читатель, также просто, просто добавить название поля следующего содержания:

var autoRead = readBlock({
  headers: readLine(['date', 'buyer', 'order']),
  item: readLine(['name', 'quantity', 'rate', 'currency']) // <<< added "currency"
});
1 голос
/ 18 января 2020
$('headers > div, item > div').each(function(item) {
  console.log('item');
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...