Задать вопрос
  • Как решить задачу с Promise?

    0xD34F
    @0xD34F Куратор тега JavaScript
    В конструкторе создаём promise, делаем его свойством экземпляра, также делаем свойством экземпляра функцию, разрешающую promise; метод then - вызываем метод then у сохранённого promise, пробрасывая ему полученный параметр, результат вызова кладём на место сохранённого promise:

    class deferred {
      constructor() {
        this.promise = new Promise(resolve => this.resolve = resolve);
      }
    
      then(f) {
        this.promise = this.promise.then(f);
      }
    }

    Но вообще, можно добиться того же поведения и без использования promise. Сохраняем в массив все передаваемые в then функции, при вызове resolve перебираем этот массив, вызываем функции, результат вызова предыдущий используем как параметр следующей:

    class deferred {
      constructor() {
        this.callbacks = [];
      }
    
      then(f) {
        this.callbacks.push(f);
      }
    
      resolve(val) {
        this.callbacks.reduce((res, f) => f(res), val);
      }
    }
    Ответ написан
    1 комментарий
  • Как манипулировать svg, который подключен через тэг object?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Не получается обратиться к элементу по его id.

    А как вы это делаете? Вдруг неправильно? Почему не показали?

    Просто по id (или с помощью любого другого селектора) обращаться нельзя, у внешних SVG отдельное DOM-дерево, оно доступно через свойство contentDocument соответствующего object'а, т.е.:

    const svgDocument = document.querySelector('object').contentDocument;
    const element = svgDocument.querySelector('здесь указываете нужный id или что там вам надо');
    Ответ написан
    Комментировать
  • Как определить событие клика event.target элемента?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Замените click на mousedown. А то сейчас у вас получается так: нажали на выбранный пункт, фокус с .select-list ушёл, и к тому моменту, когда вы отпускаете кнопку мыши, список уже скрылся, соответственно, клик получается по элементу, который был под списком.
    Ответ написан
    Комментировать
  • Как объединить массивы?

    0xD34F
    @0xD34F
    function walk($data, $key, &$result) {
      foreach ($data as $k => $v) {
        if (!array_key_exists($k, $result)) {
          $result[$k] = [];
        }
    
        if (!is_array($v) || array_keys($v) === range(0, count($v) - 1)) {
          $result[$k][$key] = $v;
        } else {
          walk($v, $key, $result[$k]);
        }
      }
    }
    
    function merge(...$arrays) {
      $result = [];
    
      foreach ($arrays as $arr) {
        $key = array_keys($arr)[0];
        walk($arr[$key], $key, $result);
      }
    
      return $result;
    }
    
    $result = merge($array1, $array2);
    Ответ написан
    Комментировать
  • Как вывести массив?

    0xD34F
    @0xD34F
    Рекурсия же:

    $arr = [
      "raz" => [
        "qqq" => [ "6" ],
        "www" => [ 0 ]
      ],
      "dva" => [
        "qqq" => [ 0 ],
        "www" => [ 0 ]
      ]
    ];
    
    function printArr($arr, $path = '') {
      foreach ($arr as $key => $val) {
        if (is_array($val)) {
          printArr($val, $path."[$key]");
        } else {
          echo $path."[$val]<br>";
        }
      }
    }
    
    printArr($arr);
    Ответ написан
    2 комментария
  • Как сделать изначально невидимый до анимации SVG?

    0xD34F
    @0xD34F
    Группируем анимируемые элементы, через set управляем свойством visibility, анимацию запускаем по окончанию действия set'а. Типа так.
    Ответ написан
    Комментировать
  • Как скачать файлы по url?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Нет, так просто не получится - тянуть файлы со сторонних доменов через a[download] нельзя.

    Можно загрузить файл, перегнать его FileReader'ом в data url, и уже в таком виде подсунуть в ссылку. Как-то так.
    Ответ написан
    3 комментария
  • Как установить метки в Яндекс карте во Vue.js приложении?

    0xD34F
    @0xD34F Куратор тега Яндекс.Карты
    Нет гарантии, что карта загрузится быстрее, чем вы получите данные для меток (этого и не происходит, почему и возникает ошибка), поэтому выполнять запрос данных следует после того, как карта будет готова к использованию - т.е., в ymaps.ready.

    UPD. Вынесено из комментариев:

    Я так понял, вы предлагаете код, который находится в функции setMarkers() перенести в initializeYandexMap(), я прав?

    Нет, не правы. Подумайте ещё. Предположим, вы так сделали. Что будет, если карта загрузится раньше, чем данные? Вы ничего не увидите, потому что массив coordinates будет пустым в момент выполнения setMarkers.

    Ещё раз: выполняйте действия последовательно, а не параллельно - сначала загрузка карты, затем загрузка данных. Это самый простой вариант. Параллельная загрузка организовывается немного посложнее - надо обернуть ymaps.ready в промис, и воспользоваться Promise.all.

    Как это может выглядеть - первый вариант, второй (запрос заменён на setTimeout, но думаю суть понятна).
    Ответ написан
    3 комментария
  • Как пронумеровать список в textarea?

    0xD34F
    @0xD34F Куратор тега JavaScript
    textareaEl.addEventListener('paste', function() {
      setTimeout(() => {
        this.value = this.value.split('\n').map((n, i) => {
          const line = i + 1;
          return `${line}. ${n.replace(RegExp(`^${line}\\. `), '')}`;
        }).join('\n');
      });
    });
    Ответ написан
    1 комментарий
  • Как найти и удалить дубли leaflet?

    0xD34F
    @0xD34F
    Получаем массив маркеров, перебираем его, для каждого маркера проверяем наличие маркера с похожими координатами (абсолютное значение разности координат меньше определённого). Если найденный маркер не является тем же, что и текущий проверяемый - удаляем проверяемый. Собрал небольшую демку - можно порасставлять маркеры, вручную и случайно, настраивать допустимую разницу координат, удалять.
    Ответ написан
    1 комментарий
  • Как эмулировать клик по элементу после того, как он отрендерился?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Элемент - представленный в примере - это FileInput (кликать нужно на него, что бы вызвать диалог выбора файлов)

    Нет, ничего у вас не получится. Этот диалог может быть открыт только в результате настоящих действий пользователя (и то не всех: клик, нажатие клавиши - окей; скролл, движение мыши, вызов контекстного меню - нет), а не их имитации. По крайней мере, в Хроме. В Фаерфоксе имитировать можно.
    Ответ написан
  • Как написать такое регулярное выражение?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Не нужны здесь регулярные выражения:

    const imgs = document.querySelectorAll('img[src*="/test/"]');

    UPD. Оказывается, автор вопроса с первого раза не сумел рассказать, чего ему надо. Вынесено из комментариев:

    это не в dom, а в строке

    Всё равно регулярные выражения не нужны. Парсим строку, ищем нужные элементы, получаем их разметку:

    const div = document.createElement('div');
    div.innerHTML = str;
    const imgsStr = ''.concat(...[].map.call(
      div.querySelectorAll('img[src*="/test/"]'),
      n => n.outerHTML
    ));

    или

    const imgsStr = Array
      .from(
        new DOMParser().parseFromString(str, 'text/html').querySelectorAll('img[src*="/test/"]'),
        n => n.outerHTML)
      .join('');

    или

    const imgsStr = Array.prototype.reduce.call(
      document.createRange().createContextualFragment(str).querySelectorAll('img[src*="/test/"]'),
      (acc, n) => acc + n.outerHTML,
      ''
    );

    UPD. Нет, со второго раза тоже не получилось. Всплыли ещё подробности:

    мне нужно удалить из этой строки все картинки, которые...

    Удалить, так удалить:

    const div = document.createElement('div');
    div.innerHTML = str;
    const imgs = div.querySelectorAll('img[src*="/test/"]');
    for (let i = 0; i < imgs.length; i++) {
      imgs[i].outerHTML = '';
    }
    str = div.innerHTML;

    или

    const { body } = new DOMParser().parseFromString(str, 'text/html');
    body.querySelectorAll('img[src*="/test/"]').forEach(n => n.remove());
    str = body.innerHTML;

    или

    const fragment = document.createRange().createContextualFragment(str);
    for (const n of fragment.querySelectorAll('img[src*="/test/"]')) {
      n.parentNode.removeChild(n);
    }
    str = Array.from(fragment.childNodes, n => n.outerHTML || n.nodeValue).join('');
    Ответ написан
    6 комментариев
  • Как достать информацию с иерархического уровня по клику?

    0xD34F
    @0xD34F Куратор тега React
    Как программно получить индексы Ряда и Ячейки для строки кода
    this.showPillarHandler(p.data[индекс Ряда].data[индекс Ячейки]) ?

    А не надо никаких индексов получать. Передавайте нужный объект в обработчик в самом нижнем компоненте вашей иерархии.

    В компоненте Pillars делаете так: showMachine={this.showPillarHandler}.
    В PillarListItem так: showShelfMachine={showMachine}.
    И в ShelfListItem аналогично: showPlaceMachine={showShelfMachine}.
    Наконец, в PlaceListItem: onClick={() => showPlaceMachine(seat)}.

    P.S. Погуглите, что такое redux.
    Ответ написан
  • Как создать массив с объектами из другого массива?

    0xD34F
    @0xD34F Куратор тега Vue.js
    computed: {
      groupedPosts() {
        return this.posts.reduce((acc, n) => {
          (acc[n.category] = acc[n.category] || []).push(n);
          return acc;
        }, {});
      },
    },

    UPD. Чего на самом деле хотел автор вопроса, вынесено из комментариев:

    При нажатии на название категории хочу выводить посты и соответствующего массива.

    Добавляем ещё одно вычисляемое свойство - массив категорий:

    categories() {
      return Object.keys(this.groupedPosts);
    },

    И обычное свойство - выбранная категория:

    data: () => ({
      activeCategory: null,
      ...

    На основе массива категорий создаём кнопки, по нажатию на которые будет производиться выбор категории:

    <button
      v-for="n in categories"
      v-text="n"
      :class="{ active: n === activeCategory }"
      @click="activeCategory = n"
    ></button>

    Если категория выбрана - показываем соответствующие посты:

    <div v-if="activeCategory">
      <div v-for="n in groupedPosts[activeCategory]" class="post">
        ...

    https://jsfiddle.net/yxf50qg2/
    Ответ написан
  • Что такое public?

    0xD34F
    @0xD34F
    Я тут начинаю изучать php с фреймворка yii2

    Что в переводе на русский означает "собираюсь стать говнокодером".

    Может лучше вы забудете про yii на ближайшие полгода и начнёте изучать php c собственно php? Чтобы вот таких вот дурацких вопросов не задавать. На него и ответить-то нормально нельзя - учитывая ваши нулевые знания php, это всё равно что объяснять тригонометрию человеку, который складывать-вычитать не научился.
    Ответ написан
    1 комментарий
  • Как определить принадлежность элемента по data value?

    0xD34F
    @0xD34F Куратор тега JavaScript
    function onlyOne({ value, dataset: { group } }) {
      document.querySelectorAll(`[data-group="${group}"]`).forEach(n => {
        n.checked = n.checked && n.value === value;
      });
    }
    Ответ написан
    2 комментария
  • Почему дублируется вывод массива?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Потому что вы дополняете уже существующую разметку, вместо того, чтобы перезаписывать её полностью - несмотря на то, что при выводе списка вы каждый раз обрабатываете все элементы.

    Замените

    todoList.forEach(function(element) {
      document.getElementById('out').innerHTML += '<p>'+element+'</p>';
    });

    на

    document.getElementById('out').innerHTML = todoList.map(n => `<p>${n}</p>`).join('');
    Ответ написан
    3 комментария
  • Как удалить определённые html теги из строки?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Создать элементы на основе строки, найти и удалить ненужные, получить разметку оставшихся:

    const div = document.createElement('div');
    div.innerHTML = html;
    div.querySelectorAll('a[href*="/test/"]').forEach(n => n.outerHTML = '');
    html = div.innerHTML;

    или

    const { body } = new DOMParser().parseFromString(html, 'text/html');
    body.querySelectorAll('a[href*="/test/"]').forEach(n => n.remove());
    html = body.innerHTML;

    или

    const fragment = document.createRange().createContextualFragment(html);
    fragment.querySelectorAll('a[href*="/test/"]').forEach(n => n.parentNode.removeChild(n));
    html = Array.from(fragment.childNodes, n => n.outerHTML || n.nodeValue).join('');
    Ответ написан
    Комментировать
  • Как сортировать option по атрибуту?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Значения атрибутов - это строки. Надо при сравнении преобразовывать их в числа.

    UPD. Ну и в целом - многословно как-то у вас. Можно же гораздо короче:

    function sort(desc, attr) {
      const select = document.querySelector('#search-sort-field');
      select.append(...Array
        .from(select.children, n => [ n, n.getAttribute(attr) * (desc ? 1 : -1) ])
        .sort((a, b) => a[1] - b[1])
        .map(n => n[0])
      );
    }
    Ответ написан
    1 комментарий