🍪 Мы используем cookie-файлы, в том числе для аналитики и рекламы. Продолжая использовать сайт, вы соглашаетесь на обработку персональных данных. Подробнее — в политике конфиденциальности.
OK
Блог
Мануалы

Изменение CRM формы Битрикс24 для опросов

Изменение строкового поля в форме.

Проблема: Стандартные поля input[type="string"] не подходили для ввода большого текста, нужно добавить перенос текста по строкам, если он не помещается в поле, а также возможность изменить его размер.
Решение: Добавить код, которые ищет все input[type="string"] на странице, скрывает его и создает новый элемент textarea. Оба этих элемента связываются уникальным dataset, через который настроена передача данных.
function replaceStringInputsWithTextareas() {
    const stringInputs = document.querySelectorAll('input[type="string"]');
 
    stringInputs.forEach((input) => {
      if (input.dataset.textareaReplaced) return;
      const linkId =
     "textarea_" + Date.now() + "_" + Math.random().toString(8).substr(2, 4);
      input.dataset.textareaLinkId = linkId;
      input.dataset.textareaReplaced = "true";
      const textarea = document.createElement("textarea");
      textarea.dataset.linkedInputId = linkId;
      textarea.className = input.className;
      textarea.value = input.value || "";
      textarea.style.resize = "vertical";
      input.style.display = "none";
 const container = document.createElement("div");
      container.className = linkId;
      input.parentNode.insertBefore(container, input);
      container.appendChild(textarea);
      container.appendChild(input);
      textarea.addEventListener("input", function () {
        input.value = this.value;
        input.dispatchEvent(new Event("input", { bubbles: true }));
      });
    });
  }
  document.addEventListener("DOMContentLoaded", function () {
    setTimeout(function () {
      replaceStringInputsWithTextareas();
    }, 200);
  });

Было (Текст в 1 строку , просто исчезает если не влазит)
Стало (Текст переносится, можно расширить поле, если он не влазит)

Улучшение интерфейса формы

Проблема: При изменении стандартных полей всегда возникают ошибки в интерфейсе, название поля не работает, подсказки для поля уплывают. Также в стандартном интерфейсе подсказки для поля пишутся снизу, что неудобно для чтения, если в него пишутся большие вопросы.
Решение: Изменении логики названия полей, теперь они находятся над полями, а также изменение структуры формы, при наличии подсказки для поля она переносится под вопрос, над полем.
function organizeFieldsSafe() {
    const containers = document.querySelectorAll(
      ".b24-form-control-string, .b24-form-control-list, .b24-form-control-text"
    );
    containers.forEach((container) => {
      if (container.dataset.organized) return;
      const label = container.querySelector(".b24-form-control-label");
      const comment = container.querySelector(".b24-form-control-comment");
      if (label) {
        container.prepend(label);
      }
      if (comment && label) {
        label.insertAdjacentElement("afterend", comment);
      }
      container.dataset.organized = "true";
    });
  document.addEventListener("DOMContentLoaded", function () {
    setTimeout(function () {
      organizeFieldsSafe();
   }, 200);
  });
<style>
  .b24-form-control-label {
    margin-bottom: 8px !important;
    display: block !important;
    font-weight: 600 !important;
    color: #333 !important;
    position: relative !important;
    left: 0 !important;
    transform: translateY(0%) !important;
    right: 0 !important;
    white-space: normal !important;
    padding-left: 0 !important;
  }

Было: (Названия полей внутри, подсказки для поля под полем)
Стало: (Названия и подсказки для полей вынесены над полем)

Автоматическое удаление повторных названий в множественных полях

Проблема: В множественных полях есть функция «Добавить еще», в которой можно добавить дополнительные значения, но так как названия в полях были вынесены над поля, это ломает интерфейс.
Решение: Находить множественные поля и проверять количество названий. Все кроме первого удалять.
function removeExtraLabels() {
    const containers = document.querySelectorAll(".b24-form-control-string, .b24-form-control-list, .b24-form-control-text");
    let totalRemoved = 0;
    containers.forEach((container, containerIndex) => {
      const labels = container.querySelectorAll(".b24-form-control-label");
      const fields = container.querySelectorAll("input, textarea, select");
      if (fields.length > 1 && labels.length > 1) {
        for (let i = labels.length - 1; i >= 1; i--) {
          labels[i].remove();
          totalRemoved++;
        }
      }
    });
return totalRemoved;
  }
  document.addEventListener("DOMContentLoaded", function () {
    setTimeout(function () {
      removeExtraLabels();
    }, 200);
  });
  setInterval(removeExtraLabels, 1000);

Было: (Названия множественного поля находятся в поле, поэтому дублируются)
Стало: (Названия сверху, удаляются при добавлении новых вариантов ответа)

Изменение названия формы на ФИО оцениваемого сотрудника

Проблема: При оценке необходимо понимать какого сотрудника мы оцениваем, нужно вывести его ФИО в название формы
Решение: При отправке URL формы, необходимо добавить параметр name, в котором передать ФИО оцениваемого сотрудника, после чего записать ФИО в название формы
ffunction getNameFromUrl() {
    const urlParams = new URLSearchParams(window.location.search);
    return urlParams.get("name");
  }
  function updateFormTitle() {
    const name = getNameFromUrl();
    if (name) {
      const formTitle = document.querySelector(".b24-form-header-title");
      formTitle.textContent = name;
    }
  }
  document.addEventListener("DOMContentLoaded", function () {
    setTimeout(function () {
      updateFormTitle();
    }, 200);
  });

Было: (Название формы вынесено перед ней, статичное)
Стало: (Изменяется в зависимости от параметра name, переданного в ссылке)

Общий код для всех настроек:

<script>
  function replaceStringInputsWithTextareas() {
    const stringInputs = document.querySelectorAll('input[type="string"]');
 
    stringInputs.forEach((input) => {
      if (input.dataset.textareaReplaced) return;
 
      const linkId =
        "textarea_" + Date.now() + "_" + Math.random().toString(8).substr(2, 4);
      input.dataset.textareaLinkId = linkId;
      input.dataset.textareaReplaced = "true";
 
      const textarea = document.createElement("textarea");
      textarea.dataset.linkedInputId = linkId;
      textarea.className = input.className;
      textarea.value = input.value || "";
      textarea.style.resize = "vertical";
 
      input.style.display = "none";
 
      const container = document.createElement("div");
      container.className = linkId;
            input.parentNode.insertBefore(container, input);
      container.appendChild(textarea);
      container.appendChild(input);
 
      textarea.addEventListener("input", function () {
        input.value = this.value;
        input.dispatchEvent(new Event("input", { bubbles: true }));
      });
    });
  }
  function organizeFieldsSafe() {
    const containers = document.querySelectorAll(
      ".b24-form-control-string, .b24-form-control-list, .b24-form-control-text"
    );
    containers.forEach((container) => {
      if (container.dataset.organized) return;
      const label = container.querySelector(".b24-form-control-label");
      const comment = container.querySelector(".b24-form-control-comment");
      if (label) {
        container.prepend(label);
      }
      if (comment && label) {
        label.insertAdjacentElement("afterend", comment);
      }
      container.dataset.organized = "true";
    });
  }
  function removeExtraLabels() {
    const containers = document.querySelectorAll(
      ".b24-form-control-string, .b24-form-control-list, .b24-form-control-text"
    );
    let totalRemoved = 0;
    containers.forEach((container, containerIndex) => {
      const labels = container.querySelectorAll(".b24-form-control-label");
      const fields = container.querySelectorAll("input, textarea, select");
 
      if (fields.length > 1 && labels.length > 1) {
        // Удаляем все лейблы кроме первого (сохраняем индекс 0)
        for (let i = labels.length - 1; i >= 1; i--) {
          labels[i].remove();
          totalRemoved++;
        }
      }
    });
    return totalRemoved;
  }
  function getNameFromUrl() {
    const urlParams = new URLSearchParams(window.location.search);
        return urlParams.get("name");
  }
  function updateFormTitle() {
    const name = getNameFromUrl();
    if (name) {
      const formTitle = document.querySelector(".b24-form-header-title");
      formTitle.textContent = name;
    }
  }
  document.addEventListener("DOMContentLoaded", function () {
    setTimeout(function () {
      replaceStringInputsWithTextareas();
      organizeFieldsSafe();
      removeExtraLabels();
      updateFormTitle();
    }, 500);
  });
 
  setInterval(removeExtraLabels, 1000);
</script>
 
<style>
  .b24-form-control-label {
    margin-bottom: 8px !important;
        display: block !important;
    font-weight: 600 !important;
    color: #333 !important;
    position: relative !important;
    left: 0 !important;
    transform: translateY(0%) !important;
    right: 0 !important;
    white-space: normal !important;
    padding-left: 0 !important;
  }
  .b24-form-control-comment {
    margin-bottom: 4px !important;
    display: block !important;
    font-size: 12px !important;
    color: #666 !important;
  }
  .b24-form-control-list
    .b24-form-control-icon-after
    .b24-form-control-not-empty.b24-form-control,
  .b24-form-control-list
    .b24-form-control-icon-after
    .b24-form-control-not-empty.b24-form-control-label {
    padding: 0 80px 0 15px;
  }
  textarea.b24-form-control {
    min-height: 80px;
    resize: vertical;
    width: 100%;
    box-sizing: border-box;
    padding: 12px;
    border: 1px solid #c6cdd3;
    border-radius: 2px;
  }
</style>