Ответы пользователя по тегу JavaScript
  • Как сложить старое и новое значение в одном input?

    <input type="text" id="number" value="100">
    document.getElementById("number").onblur = function(){
    	this.value = parseInt(this.defaultValue) + parseInt(this.value);
      this.defaultValue = this.value;
    }


    PS: при потере фокуса происходит перерасчет значения и запись обратно и в defaultValue

    Ответ написан
  • Как обработать массивы?

    const al   = "АБВГДЕЁЖЗИКЛМНОПРСТУФХЦЧШЩЫЬЭЮЯ "; // Алфавит
    let key1 = "ПЕРВЫЙ"; // первый ключ
    let key2 = "БУКВА"; // второй ключ
    let open_str = "ЭТО СТРОКА ОТКРЫТОГО ИСХОДНОГО ТЕКСТА"; // кодируемый текст
    
    // т.к. в алфавите нет букв Й и Ъ, то производим соответствующую замену:
    key1 = key1.replace("Й","И").replace("Ъ","Ь");
    key2 = key2.replace("Й","И").replace("Ъ","Ь");
    open_str = open_str.replace("Й","И").replace("Ъ","Ь");
    
    // кодируем текст
    let encoded_str = ([...open_str]).map( (e,i) => al[(al.indexOf(e) + al.indexOf(key1[i%key1.length]) + al.indexOf(key2[i%key2.length])) % 32] ).join("");
    
    console.log(encoded_str);


    PS:
    к строке по сути можно обращаться как к массиву - str[index]
    про .map смотрим здесь - https://developer.mozilla.org/en-US/docs/Web/JavaS...
    если вам надо прям вот на МАССИВАХ, то просто сделайте соответствующие переменные "массивами"
    строку в массив можно разбить так str.split("") или [...str]

    по скрипту
    al - строка / массив букв алфавита
    al.indexOf(char) - получаем индекс буквы в алфавите
    по выбору символа из ключа - т.к. ключ у нас заитерирован, то берем остаток от деления индекса кодируемого символа на длину ключа , это и будет символ из ключа - key1[i%key1.length], далее получаем его код по алфавиту - al.indexOf(key1[i%key1.length])

    и у вас много ошибок в таблице, например в третьей строке - конечный символ не И, а З
    и т.д.

    Ответ написан
  • Какая нужна регулярка чтобы проверка проходила на номера одного оператора?

    Вот еще вариант, проверяет номер написанный в любом формате со скобками вокруг кода и без с пробелами и с тире и с + в начале и без

    var str = '90553334849';
    alert(/^\+?9[ -]?\(?05[58]\)?[ -]?\d{3}[ -]?\d{2}[ -]?\d{2}$/.test(str));


    UPD:
    вот проверка (одной регуляркой в одну строку) по массиву кодов

    var str = '9(055)3334849';
    var allow = ['055','058'];
    alert((new RegExp('^\\+?9[ -]?\\(?('+allow.join('|')+')\\)?[ -]?\\d{3}[ -]?\\d{2}[ -]?\\d{2}$')).test(str));


    UPD3:
    Почитайте: https://developer.mozilla.org/en-US/docs/Web/JavaS...
    в разделе "Special characters in regular expressions." расписаны все спецсимволы, которые используются в регулярных выражениях.
    про конструктор new RegExp там тоже есть...

    кокретно в последнем примере:
    т.к. регулярку нам надо создавать "динамически", то используется конструктор new RegExp , который из строки создает и возвращает регулярку и уже у нее вызывается метод .test()
    про строку - в строке спецсимволы \ необходимо экранировать (предварять) символом \
    в строку регулярки мы вставляем все коды из массива allow склеенные через символ |
    регулярка вида (одно|второе|третье) читается как одно ИЛИ второе ИЛИ третье
    в данном случае массив склеивается и реглярка читается как 055 или 058

    ну, как-то так... )
    Ответ написан
  • Как правильно вывести объект в html?

    Во-первых, вы непонятно излагаете свои мысли:
    и как сравнить значение, если например 0 - соотв. этому .item добавляем класс

    значит ли это что класс необходимо выставлять элементу в котором значение равно искомому, в данном случае 0 ?

    Во-вторых, вы неправильно берете количество/значение из str
    посмотрите как вы ее заполняете... в ней будет
    0: 1,
    1: 4,
    2: 2,
    3: 4,
    4: 4,
    5: 2,


    после разбивки split'ом
    str.split(', ')[i]
    в count вы присваете ПАРУ значение: количество !
    и это сравниваете с 0 ???
    эту пару необходимо еще раз разбить и взять либо ЗНАЧЕНИЕ, либо КОЛИЧЕСТВО, смотря что вам надо??

    ну и
    если например 0
    то почему у вас стоит условие < 0 ???

    for (let i = 0; i < item.length; i++) {
    	let pair = str.split(', ')[i];
      if (pair.split(': ')[0] == 0) {
        item[i].classList.add('zero');
      }
      item[i].textContent = pair;
    }


    PS: а если количество элементов в массиве изменится??
    может стоит добавлять элементы динамически?
    см. Node.appendChild()

    UPDATE:


    UPDATE 2:
    с добавлением класса:
    Ответ написан
  • Как обновлять таймер по клику?

    странная логика заложена у вас.

    1. контейнер для таймер можно/нужно добавить в нужное место в HTML, а не добавлять каждый раз по клику, либо добавлять его по условию (что он еще не создан).

    2. вы безусловно добавляете элементы, а потом лишнее удаляете, зачем?

    3. зачем-то создали специально объект, хотя можно просто работать с массивом и удалять его элементы, массив это тот же объект.
    const items = [];
    items["one"]=1;
    items["two"]=1;
    if(items["one"]) console.log("Есть"); else console.log("Нет");
    delete items["one"];
    if(items["one"]) console.log("Есть"); else console.log("Нет");
    
    // либо
    items["one"]=0;
    if(items["one"]) console.log("Есть"); else console.log("Нет");


    4.
    Мне нужно сделать так, что если человек постоянно кликает по кнопке, то обновлять таймер

    у вас собственно вообще нет обработки повторного клика на туже кнопку, вместо этого у вас
    удаление излишне созданного контейнера, т.к. он выше добавляется безусловно:
    if (index > 0) {
              $(this).remove();
           }

    и возврат из обработчика если есть элемент (т.е. ранее был клик):
    if (items[name]) return;

    5. для возобновления таймера, вам надо написать обработчик повторного нажатия а не выходить из обработчика по условию
    if (items[name]) return;

    т.е. так:
    if (items[name]) {
    // остановка анимации таймера и запуск заново
    } else {
    // код первого запуска таймера.
    }


    остановка анимации, см. метод .stop

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

    как-то так.

    UPDATE:

    Ответ написан
  • Как автоматически задать высоту фрейма?

    Про Размеры и прокрутка страницы
    Про Общение между окнами

    Политика «Одинакового источника» говорит, что:

    • если у нас есть ссылка на другой объект window, например, на всплывающее окно, созданное с помощью window.open или на window из и у этого окна тот же источник, то к нему будет полный доступ.
    • в противном случае, если у него другой источник, мы не сможем обращаться к его переменным, объекту document и так далее. Единственное исключение – объект location: его можно изменять (таким образом перенаправляя пользователя). Но нельзя читать location (нельзя узнать, где находится пользователь, чтобы не было никаких утечек информации).



    и есть решение по кроссдоменным iframe
    Автоматическая кросс-доменная установка высоты Iframe

    PS: но скрипты должны интегрироваться на обе стороны, на странице хосте и на странице в ифрейме.

    PPS:
    <iframe src="<?= $link ?>?partnerID=<?= $partnerID ?>" width="100%" height="100%" scroll="no" marginheight="0" frameborder="0" id="<?=$code?>" name="<?=$code?>"></iframe>

    если размеры известны, то их можно и задать в пикселях.
    Ответ написан
  • Как оптимизировать создание элемента?

    • В аттрибут src элемента script нельзя записывать массив!
    • Вы передаете два параметра (адреса), соответственно необходимо создать два элемента script и оба добавить в body


    как-то так:

    function loadScripts(arrScr) {
      arrScr.forEach((src) => {
        var scr = document.createElement('script');
        scr.src = src;
        document.body.appendChild(scr);
      })
    }
    
    if (window.location.href.indexOf('index') != -1) {
         loadScripts(['js/scripts.js', 'js/scripts2.js']);
    }
    Ответ написан
  • Можно ли в JQuery (или чистом JS) создать переменную, которая будет соответствовать DOM? То есть, если элемента больше нет в DOM, то и length равен 0?

    // Выдает 1, а должно 0.


    Не должно!
    Потому что .remove()
    Remove the set of matched elements from the DOM.
    т.е. удаляет набор соответствующих элементов из DOM

    что успешно и выполняется.
    но т.к. вы сделали ссылку на этот элемент
    let $elem_1 = $('.elem-2').prev();
    он продолжает существовать и будет удален когда исчезнет последняя ссылка на него.

    нужно удалить ссылку на объект, например так:
    $elem_1 = null;

    т.е. при удалении из DOM, удалять так же и ссылку из переменной:
    $('.elem-1').remove();
    $elem_1 = null;


    так же, если вы объявите саму переменную как свойство какого либо объекта, то ее можно удалить.
    если за функцией то достаточно это сделать без var или let/const, тогда эта переменная будет свойством window
    либо в функции как window.$elem_1
    см. delete

    т.е. в коде вы должны удалять не только из DOM методом .remove(), но и само свойство ("переменную").

    $(function() {
      window.$elem_1 = $('.elem-2').prev();
    
      delete window.$elem_1;
      $('.elem-1').remove();
    
      console.log(window.$elem_1.length);
      // TypeError: window.$elem_1 is undefined
    });


    PS: можно создать объект с соответствующими свойствами и методами и пользоваться методами этого объекта.

    например как-то так:

    $obj = {
    	$elem: null,
      set: function (el) {
      	this.$elem = el;
      },
      del: function() {
      	$(this.$elem).remove();
      	delete this.$elem;
      },
      isExists: function() {
      	return !!this.$elem;
      }
    }
    
    $obj.set( $('.elem-2').prev() );
    
    console.log($obj.isExists(), $obj.$elem.text());
    
    $obj.del();
    
    console.log($obj.isExists());


    объект можно переделать и хранить массив элементов, соответственно переделать и методы манипуляции.

    похожие механизмы реализованы например в React.js
    там есть свой виртуальный DOM с которым и производится манипуляция, которая в последствии переносится на реальный DOM методом render
    Ответ написан
  • Как в регулярном выражении исключить слова JS?

    Имхо, желательно делать проверку полнее, т.к. ну чисто теоретически такие слова могут быть в имени пользователя например, так же не делать инверсию результата, т.к. метод все же называется isInvalid

    isInvalid: function(input) {
      return /@(gmail|yahoo)\.[a-z]+$/.test(input.value.trim().toLowerCase());
    }


    PS: если проверка НА валидность, то поставить !
    Ответ написан
  • Можно ли это как то упростить?

    Ок, если вам не интересно просто подумать, то примерно так:

    function recountItem(el_summ, el_quantity, n_price, e) {
      action = e ? e.target.className.match(/\w+_+(\w+)/)[1] : '';
      n_quantity = parseInt(el_quantity.text());
      switch(action){
        case 'plus':
        case 'increment':
          n_quantity ++;
          break;
        case 'minus':
        case 'decrement':
          n_quantity = n_quantity > 1 ? n_quantity - 1 : n_quantity;
          break;
      }
      el_quantity.text(n_quantity);
      el_summ.text(n_quantity * n_price + ' грн.');
    };
    
    //order
    
    $('.order__block').each(function() {
      var $e = $(this),
          el_quantity = $e.find('.order__value'),
          el_summ = $e.find('.order__sum'),
          n_price = $e.find('.order__value').attr('data-number');
    
      $e.find('.order__plus').click(function(e) {
        recountItem(el_summ, el_quantity, n_price, e)
      });
    
      $e.find('.order__minus').click(function(e) {
        recountItem(el_summ, el_quantity, n_price, e)
      });
    
      recountItem(el_summ, el_quantity, n_price);
    });
    
    //single
    
    $('.single__row').each(function() {
      var $e = $(this),
          el_quantity = $e.find('.single__count'),
          el_summ = $e.find('.single__price'),
          n_price = $e.find('.single__count').attr('data-price');
    
      $e.find('.single__increment').click(function(e) {
        recountItem(el_summ, el_quantity, n_price, e)
      });
    
      $e.find('.single__decrement').click(function(e) {
        recountItem(el_summ, el_quantity, n_price, e)
      });
    
      recountItem(el_summ, el_quantity, n_price);
    });
    
    //basket
    
    $('.basket__item').each(function() {
      var $e = $(this),
          el_quantity = $e.find('.basket__value> span'),
          el_summ = $e.find('.basket__sum'),
          n_price = $e.find('.basket__single').text();
    
      $e.find('.single__increment').click(function(e) {
        recountItem(el_summ, el_quantity, n_price, e);
        updateBasketTotalSum();
      });
    
      $e.find('.single__decrement').click(function(e) {
        recountItem(el_summ, el_quantity, n_price, e);
        updateBasketTotalSum();
      });
    
      recountItem(el_summ, el_quantity, n_price);
      updateBasketTotalSum();
    });
    
    function updateBasketTotalSum() {
      var sum = 0;
      $('.basket__sum').each(function() {
         sum += parseInt($(this).text());
       });
      $('.basket__count').text(sum + ' грн.');
    }
    
    $('.basket__close').on('click', function() {
      $(this).parent().parent().remove();
    });


    если нигде в синтаксисе не ошибся, то должно работать вроде как.

    PS: все повторяющиеся действия вынесены в ОДНУ функцию, тем более что у вас во все функции передавались ссылки на html элементы и действия абсолютно одинаковые. А action определяется по className элемента, который берется из event'а

    PPS: только какой профит с готового решения??
    Ответ написан
  • Как сделать импорт в js другой js в chrome extention?

    Вы это читали?
    https://developer.chrome.com/extensions/content_sc...

    Declaratively injected scripts are registered in the manifest under the "content_scripts" field. They can include JavaScript files, CSS files or both. All auto-run content scripts must specify match patterns.

    {
    "name": "My extension",
    ...
    "content_scripts": [
    {
    "matches": ["http://*.nytimes.com/*"],
    "css": ["myStyles.css"],
    "js": ["contentScript.js"]
    }
    ],
    ...
    }


    js array of strings Optional. The list of JavaScript files to be injected into matching pages. These are injected in the order they appear in this array.

    тоже самое и с секцией background
    https://developer.chrome.com/extensions/background...

    {
    "name": "Awesome Test Extension",
    ...
    "background": {
    "scripts": [
    "backgroundContextMenus.js",
    "backgroundOmniBox.js",
    "backgroundOauth.js"
    ],
    "persistent": false
    },
    ...
    }

    PS: в popup они вставляются через тег script как в обычном HTML файле.
    Ответ написан
  • Как на чистом js копировать html элемент со всеми его дочерними элементами?

    такое мне кажется все делают по разному, что правильно выбираете сами.
    варианты:
    1. блок с работами имеет фиксированную высоту с overflow: hidden
    при нажатии на кнопку высота блока увеличивается, блок с кнопкой скрывается.
    можно это дело анимировать, ну чтоб плавно высота увеличивалась.
    2. блок с работами состоит из нескольких блоков, по умолчанию показывается первый, при нажатии на кнопку появляется второй блок (меняем ему display), блок с кнопкой скрывается.
    3. добавлять элементы скриптом, через .appendChild(childElement) например:
    document.querySelector(".works__more__btn").addEventListener("click", function() {
      var elem = document.createElement("div");
      elem.setAttribute("class", "works__content__smallRow");
      elem.innerHTML = `
                    <img src="https://www.placehold.it/375x327/25" class="works__content__smallRow__item">
                    <img src="https://www.placehold.it/375x327/50" class="works__content__smallRow__item">
                    <img src="https://www.placehold.it/375x327/75" class="works__content__smallRow__item">
                    <img src="https://www.placehold.it/375x327/100" class="works__content__smallRow__item">
    `;
      document.querySelector(".works__content").appendChild(elem);
      document.querySelector(".works__more").style.display = "none";
    });


    как-то так...

    UPD:
    собственно копирование:

    вы правильно сделали cloneNode, но!!!
    см. Метод Node.cloneNode()
    если вы хотите копировать с дочерними элементами, то необходимо передать параметр "deep" = true

    Т.е. вот так:
    document.querySelector(".works__more__btn").addEventListener("click", function() {
      document.querySelector(".works__content").appendChild(document.querySelector(".works__content").cloneNode(true));
      document.querySelector(".works__more").style.display = "none";
    });
    Ответ написан
  • Почему не работает проверка при отправке формы?

    Дело в том что у вас проверка email выполняется только в том случае если не выполняется условие по имени:
    if ($('#name').val().length >= 3) {
          $(this).find('#name').css("border", "1px solid rgb(169, 169, 169)");
      } else if ($('#email').val().length > 10 && $('#email').val().search(pattern) == 0) {
        $(this).find('#email').css("border", "1px solid rgb(169, 169, 169)");
      }


    else if

    надо без else, тогда оба условия будут проверяться независимо.
    if ($('#name').val().length >= 3) {
        $(this).find('#name').css("border", "1px solid rgb(169, 169, 169)");
    }
    if ($('#email').val().length > 10 && $('#email').val().search(pattern) == 0) {
        $(this).find('#email').css("border", "1px solid rgb(169, 169, 169)");
    }


    и т.д.
    Ответ написан
  • Как выводить в одном модальном окне данные из разных карточек товара по клику на кнопку?

    Ну например переписывать содержимое карточки в модальное окно перед его отображением.
    как-то то так:
    btn.onclick = function() {
    modal.innerHTML = btn.innerHTML;
    modal.style.display = "flex";
    }
    Ответ написан
  • Как пробросить UTM-метку из реферрера и поставить в адресную строку?

    см.:
    -> document.referrer
    -> document.location

    -> javascript работа со строками
    -> javascript работа с массивами
    -> javascript разбор url

    ну и например можно вот так:
    document.location.href += "&" + document.referrer
                                    .split("?")[1]
                                    .split("#")[0]
                                    .split("&")
                                    .filter(str => str.indexOf("utm_") > -1)
                                    .join("&");


    .split
    .filter
    .join

    Upd:
    на случай если у реферера нет параметров, сделать проверку

    document.location.href += document.referrer.indexOf("?") > -1 ?
                "&" + document.referrer
                .split("?")[1]
                .split("#")[0]
                .split("&")
                .filter(str => str.indexOf("utm_") > -1)
                .join("&") : "";
    Ответ написан
  • Как заставить реагировать объект?

    пересечение / совпадение элементов определяется сопоставлением координат углов элементов.
    и решение(я) находятся поиском - javascript определить перекрытие элементов

    в итого можно написать объект checker с методами проверки collide и inside
    var checker = {
      // получить координаты углов объекта
    	getRectangle: function (el) {
        return {
          left: el.offsetLeft,
          top: el.offsetTop,
          right: el.offsetLeft + el.offsetWidth,
          bottom: el.offsetTop + el.offsetHeight
        }
      },
      // проверка на пересечение
      collide: function (el1, el2) {
        var rect1 = this.getRectangle(el1);
        var rect2 = this.getRectangle(el2);
        
        return !(
          rect1.top > rect2.bottom ||
          rect1.right < rect2.left ||
          rect1.bottom < rect2.top ||
          rect1.left > rect2.right
        );
      },
      // проверка на совпадение
      inside: function (el1, el2) {
        var rect1 = this.getRectangle(el1);
        var rect2 = this.getRectangle(el2);
    
        return (
          ((rect2.top <= rect1.top) && (rect1.top <= rect2.bottom)) &&
          ((rect2.top <= rect1.bottom) && (rect1.bottom <= rect2.bottom)) &&
          ((rect2.left <= rect1.left) && (rect1.left <= rect2.right)) &&
          ((rect2.left <= rect1.right) && (rect1.right <= rect2.right))
        );
      }
    }


    ниже все вместе + некоторые исправления:

    https://codepen.io/sazakharov/pen/LYPBmNM?editors=0010
    Ответ написан
  • Как реализовать открытие и закрытие всех спойлеров разом на веб странице?

    попробуйте
    либо в начале JavaScript'a удалить
    jQuery(".sp-body.folded").hide();

    и/или

    в конце JavaScript'a перед последней });
    вставить:

    jQuery(".sp-head").each(function(){
      $this = jQuery(this);
      $this.addClass("unfolded");
      $this.next().slideDown("fast");
      $this.next().removeClass("folded");
      $this.prop('title', title.folded);
    });


    UPD:
    а, если действие-переключение надо производить по кнопке, то
    сделать кнопку, на onclick повесить функцию toggleSpoilers()

    добавить в JS в самом конце
    var isUnfolded = false;
    
    function toggleSpoilers() {
      jQuery(".sp-head").each(function(){
        $this = jQuery(this);
        if(isUnfolded) {
          $this.removeClass("unfolded");
          $this.next().slideUp("fast");
          $this.next().addClass("folded");
          $this.prop('title', title.unfolded);
        } else {
          $this.addClass("unfolded");
          $this.next().slideDown("fast");
          $this.next().removeClass("folded");
          $this.prop('title', title.folded);
        }
      });
      isUnfolded = !isUnfolded;
    }


    как-то так...
    Ответ написан