Список пользователей

1
Админ
Постов: 288
2
VIP
Постов: 75
3
Элита
Постов: 62
4
Проверенные
Постов: 46
5
Проверенные
Постов: 45
6
Проверенные
Постов: 39
7
VIP
Постов: 36
8
VIP
Постов: 35

  • Страница 1 из 1
  • 1
Интерактивная форма публикации V 5.0 для uCoz стиль Май 2026
Дата: Среда, 13.05.2026, 23:19 | Сообщение # 1 | | Написал: Известный
Автор темы
Мурчанн не в сети
        Сообщений:288
         Регистрация:20.10.2016
За уважение окружающих За уважение окружающих За хорошее поведение За преданность форуму За любовь народа

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

Фон внутри окна изменён на более стеклянный тёмно-серый стиль. Подобный визуальный эффект отчасти напоминает оформление некоторых тем Windows XP, но в более современном исполнении.

Также были доработаны элементы интерфейса: иконка календаря стала более выразительной и заметной.

Добавлены анимационные эффекты при нажатии кнопок «комментарии», «закрепить» и «скрыть» теперь они сопровождаются эффектом схлопывания.

Скрипт был полностью переработан, а логика работы улучшена, что повысило стабильность и отзывчивость интерфейса.

В дальнейшем планируется добавить опцию отображения панели BB-кодов под полем краткого описания.

Нужно будет ещё хорошо подумать над тем, что можно улучшить или изменить в дальнейшем. Однако это уже будет реализовано в других стилях и, возможно, в отдельной теме. Принципиально логика работы скрипта меняться не будет возможны только добавления новых функций. Наверняка ещё есть элементы, которые можно улучшить, но при этом стоит помнить, что новое не всегда означает более надёжное. Иногда старые, проверенные решения работают стабильнее.

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



Исходник

Код
<!-- система интерактивное окно-->
<div id="siteWrapper" style="position: relative; max-width: 1200px; margin: 0 auto; background: #f5f5f5; min-height: 100vh;">
<link rel="stylesheet" href="https://bro.usite.pro/css/vk-pubmodal03.css" media="all">

<!-- Кнопка "Send Message" -->
<a href="javascript:void(0);" id="openArticleForm" style="
position: absolute;
right: -450px;
top: 50%;
background: #3b5998;
color: #fff;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;
font-size: 14px;
font-weight: 500;
padding: 11px 30px;
border-radius: 8px 0 0 8px;
text-decoration: none;
box-shadow: 0 6px 16px rgba(76,117,163,0.45);
transition: all 0.3s ease;
z-index: 9999;
"
onmouseover="
this.style.background='#3f6691';
this.style.paddingRight='115px';
this.style.boxShadow='0 10px 24px rgba(76,117,163,0.55)';
"
onmouseout="
this.style.background='#3b5998';
this.style.paddingRight='30px';
this.style.boxShadow='0 6px 16px rgba(76,117,163,0.45)';
"
>
💬 Send Message
</a>

</div>

<?if($USER_ID$>0)?>

<div id="publOverlay">
<div id="publModal">

<!-- HEADER -->
<div class="publHeader">
<span>📝 Новая публикация</span>
<span id="closePubl">✕</span>
</div>

<div id="p_status"></div>

<div class="publBody">

<div class="field">
<input type="text" id="p_title" required>
<label>Заголовок *</label>
</div>

<div class="field">
<select id="p_cat">
<option value="1">Стена</option>
</select>
</div>

<!-- OPTIONS -->
<div class="publOptions">

<div class="opt active" data-key="coms">
💬 Комментарии
</div>

<div class="opt" data-key="ontop">
📌 Закрепить
</div>

<div class="opt" data-key="hidden">
<span class="bigEye">👁</span> Скрыть
</div>

</div>

<div class="field">
<textarea id="p_brief" required></textarea>

<label>Краткое описание *</label>

<div class="emojiWrap">

<button type="button" id="emojiToggle">
<img src="https://bro.usite.pro/img/yksmile.webp" alt="">
</button>

<div id="emojiPopup">

<span class="emojiItem">😀</span>
<span class="emojiItem">😂</span>
<span class="emojiItem">😎</span>
<span class="emojiItem">🔥</span>
<span class="emojiItem">❤️</span>
<span class="emojiItem">👍</span>
<span class="emojiItem">🎉</span>
<span class="emojiItem">🤖</span>
<span class="emojiItem">😏</span>
<span class="emojiItem">😭</span>
<span class="emojiItem">😍</span>
<span class="emojiItem">🥶</span>

</div>
</div>

</div>

<script>
document.addEventListener('DOMContentLoaded', function () {

  const btn = document.getElementById('emojiToggle');
  const popup = document.getElementById('emojiPopup');
  const textarea = document.getElementById('p_brief');

  if (!btn || !popup || !textarea) return;

  btn.onclick = function (e) {
    e.stopPropagation();
    popup.classList.toggle('active');
  };

  document.querySelectorAll('.emojiItem').forEach(function (el) {
    el.onclick = function () {
      const emoji = this.textContent;

      const start = textarea.selectionStart;
      const end = textarea.selectionEnd;

      textarea.value =
        textarea.value.substring(0, start) +
        emoji +
        textarea.value.substring(end);

      textarea.focus();
      textarea.selectionStart = textarea.selectionEnd = start + emoji.length;
    };
  });

  document.addEventListener('click', function () {
    popup.classList.remove('active');
  });

});
</script>

<button type="button" id="toggleTextBtn" class="miniBtn">
➕ Добавить полный текст
</button>

<div id="textContainer" style="display:none;">
<div class="field">
<textarea id="p_text"></textarea>
<label>Полный текст</label>
</div>
</div>

<div class="field dateWrap">
  <input type="datetime-local" id="p_datetime" name="p_datetime" placeholder=" ">
  <label>Дата публикации</label>

  <span class="calendarIcon" id="openCalendar">
    <img src="https://www.emojiall.com/images/60/microsoft/1f4c5.png" alt="calendar">
  </span>
</div>

<div class="publishActions">

  <!--  КОЛОКОЛ / ПОДПИСКА -->
  <div class="opt notifyOpt" data-key="notify">
    <span class="bell">🔔</span>
    <span class="notifyText">Подписаться</span>

    <!-- скрытый чекбокс состояния -->
    <input type="checkbox" id="sbsc" name="sbcr" value="1" hidden>

    <!-- зелёный индикатор -->
    <span class="notifyDot"></span>
  </div>

  <!--  КНОПКА ОТПРАВКИ -->
  <button id="p_send">Создать запись</button>

</div>

</div>
</div>
</div>

<iframe id="ssidFrame" src="/publ/1-0-0-0-1" style="display:none;"></iframe>
<script src="https://bro.usite.pro/js/ssid_ucodes04.js"></script>

<?endif?>




Скрипт

Код
$(function () {
    const $out = $('#p_status');
    const $modal = $('#publModal');
    const $overlay = $('#publOverlay');
    const $sendBtn = $('#p_send');

    // =========================
    // Инициализация даты
    // =========================
    const now = new Date();

    // Год
    const $year = $('#p_year');
    for (let y = 2022; y <= 2035; y++) {
        $year.append(`<option value="${y}">${y}</option>`);
    }

    // Месяцы
    const months = ['Январь','Февраль','Март','Апрель','Май','Июнь','Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь'];
    months.forEach((m, i) => {
        $('#p_month').append(`<option value="${i + 1}">${m}</option>`);
    });

    // Дни, часы, минуты
    const $day = $('#p_day');
    const $hour = $('#p_hour');
    const $minute = $('#p_minute');

    function populateDays(year, month) {
        const daysInMonth = new Date(year, month, 0).getDate();
        $day.empty();
        
        for (let d = 1; d <= daysInMonth; d++) {
            $day.append(`<option value="${d}">${d}</option>`);
        }
    }

    // Часы
    for (let h = 0; h <= 23; h++) {
        const hh = String(h).padStart(2, '0');
        $hour.append(`<option value="${hh}">${hh}</option>`);
    }

    // Минуты
    for (let m = 0; m <= 59; m++) {
        const mm = String(m).padStart(2, '0');
        $minute.append(`<option value="${mm}">${mm}</option>`);
    }

    // Устанавливаем текущую дату
    function setCurrentDate() {
        const y = now.getFullYear();
        const m = now.getMonth() + 1;
        
        $year.val(y);
        $('#p_month').val(m);
        populateDays(y, m);
        $day.val(now.getDate());
        $hour.val(String(now.getHours()).padStart(2, '0'));
        $minute.val(String(now.getMinutes()).padStart(2, '0'));
    }

    setCurrentDate();

    // Обновление дней при смене месяца/года
    $('#p_year, #p_month').on('change', function () {
        const year = parseInt($year.val());
        const month = parseInt($('#p_month').val());
        populateDays(year, month);
    });

  
// =========================
// Открытие календаря по иконке
// =========================
$('#openCalendar').on('click', function () {
    const input = document.getElementById('p_datetime');

    if (input.showPicker) {
        // современный метод (Chrome / Edge)
        input.showPicker();
    } else {
        // fallback
        input.focus();
        input.click();
    }
});
  
  
    // =========================
    // Модальное окно
    // =========================
    $('#openArticleForm').on('click', function () {
        $overlay.fadeIn(200);
        $modal.css({ transform: 'translateX(0)' });
        $out.text('').removeClass('error success');
    });

    function closeModal() {
        $modal.css({ transform: 'translateX(100%)' });
        setTimeout(() => $overlay.fadeOut(200), 250);
        $out.text('').removeClass('error success');
    }

    $('#closePubl, #publOverlay').on('click', function (e) {
        if (e.target.id === 'closePubl' || e.target.id === 'publOverlay') {
            closeModal();
        }
    });

    // =========================
    // Переключение полного текста
    // =========================
    $('#toggleTextBtn').on('click', function () {
        const $box = $('#textContainer');
        $box.stop(true, true).slideToggle(200);
        
        setTimeout(() => {
            $(this).text(
                $box.is(':visible')
                    ? 'Скрыть текст статьи'
                    : '➕ Добавить полный текст'
            );
        }, 10);
    });

  // =========================
  // ОПЦИИ + АНИМАЦИЯ КОЛОКОЛЬЧИКА
  // =========================
$(document).on('click', '.publOptions .opt', function () {

  const $el = $(this);
  const key = $el.data('key');

  if (key === 'notify') {

    $el.toggleClass('active');

    if ($el.hasClass('active')) {

      const bell = $el.find('.bell')[0]; //  ВАЖНО

      if (bell) {
        bell.animate([
          { transform: 'rotate(0deg) scale(1)' },
          { transform: 'rotate(-20deg) scale(1.2)' },
          { transform: 'rotate(20deg) scale(1.2)' },
          { transform: 'rotate(0deg) scale(1)' }
        ], {
          duration: 400,
          easing: 'ease-out'
        });
      }
    }

    return;
  }

  $el.toggleClass('active');
});

  // =========================
  // SSID
  // =========================
  function getSSID() {
    try {
      const iframe = document.getElementById('ssidFrame');
      return iframe.contentWindow.document
        .querySelector('input[name="ssid"]').value;
    } catch {
      return null;
    }
  }

  
    // =========================
   //  ПОДПИСКА (VK STYLE)
  // =========================
  const $notify = $('.notifyOpt');
  const $notifyText = $notify.find('.notifyText');
  const $checkbox = $('#sbsc');

  //  всегда старт выключен
  $checkbox.prop('checked', false);
  $notify.removeClass('active');
  $notifyText.text('Подписаться');

  $notify.on('click', function () {

    const isActive = !$notify.hasClass('active');

    $notify.toggleClass('active', isActive);
    $checkbox.prop('checked', isActive);

    $notifyText.text(isActive ? 'Подписан' : 'Подписаться');

    //  анимация колокола (если есть)
    const bell = $notify.find('.bell')[0];

    if (isActive && bell) {
      bell.animate([
        { transform: 'rotate(0deg) scale(1)' },
        { transform: 'rotate(-18deg) scale(1.2)' },
        { transform: 'rotate(18deg) scale(1.2)' },
        { transform: 'rotate(0deg) scale(1)' }
      ], {
        duration: 400,
        easing: 'ease-out'
      });
    }
  });
  

  
  // =========================
  // ОТПРАВКА
  // =========================
  $sendBtn.on('click', function () {

    const btn = $(this);

    const title = $('#p_title').val().trim();
    const brief = $('#p_brief').val().trim();
    const text  = $('#p_text').val().trim();
    const cat   = $('#p_cat').val();

    $out.text('').removeClass('error success');

    if (!title || !brief) {
      return $out.addClass('error').text('❌ Заполните поля');
    }

    const ssid = getSSID();
    if (!ssid) {
      return $out.addClass('error').text('❌ SSID не найден');
    }

    const d = new Date($('#p_datetime').val() || new Date());

    const data = {
      a: 12,
      ssid,
      ocat: cat,

      title,
      brief,
      message: text,

      edttbrief: 2,
      edttmessage: 2,

      ya: d.getFullYear(),
      ma: d.getMonth() + 1,
      da: d.getDate(),
      ha: String(d.getHours()).padStart(2,'0'),
      mia: String(d.getMinutes()).padStart(2,'0'),

      coms_allowed: $('.opt[data-key="coms"]').hasClass('active') ? 1 : 0,
      is_ontop: $('.opt[data-key="ontop"]').hasClass('active') ? 1 : 0,
      is_pending: $('.opt[data-key="hidden"]').hasClass('active') ? 1 : 0,
      sbcr: $('.opt[data-key="notify"]').hasClass('active') ? 1 : 0
    };

    btn.prop('disabled', true).text('Отправка...');

    $.post('/publ', data)

    .done(function (res) {

  if (/error|ошиб|fatal/i.test(String(res))) {
    $out.addClass('error').text('❌ Ошибка сервера');

    btn.prop('disabled', false).text('Создать запись');
    return;
  }

  // статус — показываем и ДАЁМ УВИДЕТЬ
  $out.addClass('success').text('✅ Пост опубликован');

  //  очистка формы
  $('#p_title, #p_brief, #p_text').val('');
  $('.publOptions .opt').removeClass('active');
  $('.opt[data-key="coms"]').addClass('active');

  const $notify = $('.notifyOpt');
  const $checkbox = $('#sbsc');
  const $text = $notify.find('.notifyText');

  $notify.removeClass('active');
  $checkbox.prop('checked', false);
  $text.text('Подписаться');

  // ⏱ сначала показываем результат
  setTimeout(() => {

    //  закрываем модалку
    $modal.css({ transform: 'translateX(100%)' });
    setTimeout(() => $overlay.fadeOut(200), 250);

    //  обновляем страницу ПОСЛЕ закрытия
    setTimeout(() => {
      location.reload();
    }, 300);

  }, 1500); //  ВОТ ГЛАВНОЕ — задержка

})

.fail(function () {
  $out.addClass('error').text('❌ Ошибка соединения');
})

.always(function () {
  btn.prop('disabled', false).text('Создать запись');
});

  });

});

Мурчанн

Признаюсь, не знаю почему, но глядя на звезды мне всегда хочется мечтать.
  • Страница 1 из 1
  • 1
Поиск: