Как сделать голосовалку для сайта

Андрей
Андрей
13K
10
Содержание:
  1. Комментарии
Приветствую
Возникло желание разместить на сайте небольшую голосовалку. Возможно, ли это реализовать на простом html сайте (без использования движка)? Если да, то как?

Комментарии:

  1. Константин
    Константин
    02.02.2021, 17:38
    Приветствую, спасибо за скрипт. единственный вопрос с накруткой голосов, COOKIE не очень хорошо работают, может возможно добавить защиту по IP?
    1. Daler
      Daler
      03.01.2018, 03:44
      Добрый день. Переменная $current — отвечает за то какой pool — опрос отображается. Не подскажите как сделать переключатель ввиде далее между опросами? И как добавить больше вопросов и ответов в 1 опрос, буду очень признателен
      1. Александр Мальцев
        Александр Мальцев
        12.04.2017, 04:25
        Как можно создать опросы на сайте, которые сохраняют данные не в базу, а в обычный текстовый файл...
        Данная инструкция пригодиться не только тем, у кого нет CMS, но и тем, у кого она есть. Кроме этого данный вариант может также пригодиться тем, у кого имеются высоконагруженные сайты, т.к. предложенная голосовалка для сайта практически не будет создавать нагрузку на процессор, а базу данных она вообще не использует.
        Работать созданная система опроса на сайте будет через AJAX и использовать COOKIE (для защиты от накрутки).

        Скриншоты, т.е. как будет выглядеть блока опроса и его результаты на сайте:
        Форма для голосования -1Результаты формы для голосования -1
        Форма для опроса -2Результаты формы для голосования -2

        Формат хранения результатов на сервере (JSON):
        {"pool-1":[3,2,5,2],"pool-2":[0,2,3,1,0]}
        
        Как подключить голосовалку к страницам сайта:
        1. Вставить в необходимую часть страницы следующий HTML-код голосовалки (оформление формы выполнено с помощью стилей Bootstrap):
        <section class="panel panel-danger">
          <div class="panel-heading">
            <h3 class="panel-title">
              Голосование
            </h3>
          </div>
          <div class="panel-body"> 
            <!-- HTML-структура голосовалки -->
            <div class="question"></div>
            <hr>
            <div id="vote-section">              
              <form id="vote" action="poll-vote.php" method="POST">
                <div class="answers"></div>
                <button type="submit" class="btn btn-default" disabled="disabled">Голосовать</button>
              </form>
            </div>
            <!-- конец HTML-структура -->
          </div>
        </section>
        
        Внимание: В HTML коде необходимо указать путь к файлу poll-vote.php (если конечно он не находится в той же директории, в которой расположена и страница).
        Если на сайте не используется Bootstrap, то тогда необходимо написать стили для оформления опроса и результатов голосования.
        2. Вставить следующий фрагмент сценария JavaScript на страницу (после подключения jQuery):
        <script>
          $(function(){
          
            var pathToPolls = 'polls.php';
            
            var vote = {};
            $.get(pathToPolls, function(data) {
              
              var data = JSON.parse(data);
              vote['id']=data['id'];
              vote['question']=data['question'];
              vote['answers']=data['answers'];
        
              if (data.hasOwnProperty('result')) {
                $('#vote').parent().parent().find('.question').text(vote['question']);
                var _answers = vote['answers'];
                var output = '';
                var result = data['result'];
                var totalvotes = 0;
                for (var i=0; i <= result.length-1; i++) {
                  totalvotes += result[i];
                }
                for (var i=0; i <= result.length-1; i++) {
                  output += '<p style="margin:0px;">'+_answers[i]+'</p>'+
                    '<p class="text-right" style="margin:0px;"><b>'+((result[i]/totalvotes)*100).toFixed(1)+'%</b> (Голосов: '+result[i]+')</p>'+
                    '<div class="progress">'+
                      '<div class="progress-bar progress-bar-info progress-bar-striped" role="progressbar" aria-valuenow="'+(result[i]/totalvotes)*100+'" aria-valuemin="0" aria-valuemax="100" style="width: '+(result[i]/totalvotes)*100+'%">'+
                        '<span class="sr-only">'+(result[i]/totalvotes)*100+'%</span>'+
                      '</div>'+
                    '</div>';
                }
                $('#vote-section').html(output);
              } else {          
                processPoll();
              }
            });    
        
            var processPoll = function() {        
              var _id = vote['id'];
              var _answers = vote['answers'];
              var form = $('#vote');
              form.parent().parent().find('.question').text(vote['question']);
              form.prepend('<input type="hidden" name="count" value="'+vote['answers'].length+'">');
              form.prepend('<input type="hidden" name="id" value="'+vote['id']+'">');
              var answers = form.find('.answers');
              for (var i=0; i<=vote['answers'].length-1;i++) {
                answers.append('<div class="radio">'+
                    '<label>'+
                      '<input type="radio" name="poll" value="'+(i+1)+'">'+
                      vote['answers'][i]+
                    '</label>'+
                  '</div>');
              }
              if (form.find('button[type="submit"]:disabled')) { 
                form.find('input[type="radio"]').click(function(){
                  form.find('button[type="submit"]').prop('disabled',false);
                  form.find('input[type="radio"]').off('click');  
                });          
              };
              
              form.submit(function(e) {
                //отмена действия по умолчанию для кнопки submit
                e.preventDefault();
                $.post(form.attr('action'), form.serializeArray(), function(data) {
                  if (data) {
                    var data = JSON.parse(data);
                    var output = '';
                    var result = data[_id];
                    var totalvotes = 0;
                    for (var i=0; i <= result.length-1; i++) {
                      totalvotes += result[i];
                    }
                    for (var i=0; i <= result.length-1; i++) {
                      output += '<p style="margin:0px;">'+_answers[i]+'</p>'+
                        '<p class="text-right" style="margin:0px;"><b>'+((result[i]/totalvotes)*100).toFixed(1)+'%</b> (Голосов: '+result[i]+')</p>'+
                        '<div class="progress">'+
                          '<div class="progress-bar progress-bar-info progress-bar-striped" role="progressbar" aria-valuenow="'+(result[i]/totalvotes)*100+'" aria-valuemin="0" aria-valuemax="100" style="width: '+(result[i]/totalvotes)*100+'%">'+
                            '<span class="sr-only">'+(result[i]/totalvotes)*100+'%</span>'+
                          '</div>'+
                        '</div>';
                    }
                    $('#vote-section').html(output);
                  }
                }); 
              });
            };
        
          });
        </script>
        
        В переменной pathToPolls указать путь к файлу polls.php.
        3. На сервере…
        На сервере используются 2 файла php (polls.php и poll-vote.php).

        В файле polls.php хранятся все опросы в формате ассоциативного массива (каждый опрос – это объект).
        Синтаксис опроса:
        // pool-1
        $key = 'pool-1';
        $value = new stdClass();
        $value->id = $key;
        $value->question = 'Какая стихия вам ближе?';
        $value->answers = array('Огонь','Воздух','Вода','Земля');
        $votes[$key]=$value;
        
        Для того чтобы добавить новый опрос, необходимо продублировать этот код и ввести необходимые значения в соответствующие переменные.
        Установка, какой опрос показывать на страницах управляется с помощью значения переменной $current.
        $current = 'pool-1';
        
        Это очень удобно, т.к. ничего не надо править на страницах. Т.е. для того чтобы установить показ другого опроса на всех страницах сайта достаточно будет просто указать необходимый ключ опроса в качестве значения этой переменной.
        Также этот файл возвращает результаты, если пользователь уже проголосовал на сайте (для этого используются COOKIE).

        Второй файл (poll-vote.php) записывает данные голосования в файл poll-results.txt, который создаётся по умолчанию в той же директории, в которой расположены эти 2 php файла. В качестве формата данных используется ассоциативный массив. Кроме этого данный файл после того как пользователь проголосовал ещё возвращает результаты голосования (в качестве ответа).

        Код файла polls.php:
        <?php
        $nameFile = 'poll-results.txt';
        $current = 'pool-2';
        
        $votes = array();
        
        // pool-1
        $key = 'pool-1';
        $value = new stdClass();
        $value->id = $key;
        $value->question = 'Какая стихия вам ближе?';
        $value->answers = array('Огонь','Воздух','Вода','Земля');
        $votes[$key]=$value;
        
        // pool-2
        $key = 'pool-2';
        $value = new stdClass();
        $value->id = $key;
        $value->question = 'Какой ваш любимый цвет?';
        $value->answers = array('Красный','Оранжевый','Зелёный','Синий','Нет, другой');
        $votes[$key]=$value;
        
        
        /* блок для вывода результатов если пользователь проголосовал */
        if (isset($_COOKIE['polls'])) {
          $arrayPolls = explode(',',$_COOKIE['polls']);
          if (in_array($current, $arrayPolls)) {
            // получаем содержимое файла
            $output = file_get_contents(dirname(__FILE__).'/'.$nameFile);
            // декодируем содержимое в массив
            $output = json_decode($output, true);
            // проверяем есть если указанный ключ голосования в ассоциативном массиве
            if (array_key_exists($current, $output)) {
              // получаем значение, связанное с указанным ключом
              $votes[$current]->result = $output[$current];
            }
          }
        }
        
        echo json_encode($votes[$current]);
        
        exit();
        
        Код файла poll-vote.php:
        <?php
        // Если  запрос не AJAX (XMLHttpRequest), то завершить работу
        if (empty($_SERVER['HTTP_X_REQUESTED_WITH']) || $_SERVER['HTTP_X_REQUESTED_WITH'] != 'XMLHttpRequest') {return;}
        
        if (empty($_POST['id'])) {exit();}
        
        $nameFile = 'poll-results.txt';
        
        $id = $_POST['id'];
        $answer = $_POST['poll'];
        $count = $_POST['count'];
        
        if (isset($_COOKIE['polls'])) {
          $arrayPolls = explode(',',$_COOKIE['polls']);
          if (in_array($id, $arrayPolls)) {
            exit();
          }
        }
        
        
        // массив, который будем возвращать клиенту
        $result = array();
        
        // если файлами с результатами нет
        if (!file_exists($nameFile)) {
          // результирующий массив
          $output = array();
          // массив для хранения ответов
          $answers = array();
          // заполняем массив нулями
          for ($i=0; $i<=$count-1; $i++) {
            $answers[$i] = 0;
          }
          // увеличиваем в массиве полученный элемент на 1
          $answers[$answer-1] = $answers[$answer-1] + 1;
          // связываем id опроса с ответами   
          $output[$id] = $answers;
          // кодируем ассоциативный массив в JSON
          $output = json_encode($output);
          // записываем в файл
          file_put_contents(dirname(__FILE__).'/'.$nameFile, $output, LOCK_EX);
        } else {
          // получаем содержимое файла
          $output = file_get_contents(dirname(__FILE__).'/'.$nameFile);
          // декодируем содержимое в массив
          $output = json_decode($output, true);
          // проверяем есть если указанный ключ голосования в ассоциативном массиве
          if (array_key_exists($id, $output)) {
            // получаем значение, связанное с указанным ключом
            $answers = $output[$id];
            // увеличиваем в массиве полученный элемент на 1
            $answers[$answer-1] = $answers[$answer-1] + 1;
            // перезеписываем массив ответов, связанных с ключом
            $output[$id] = $answers;
          } else {
            /* если не найден переданный ключ в массиве */
            // массив для хранения ответов
            $answers = array();
            // заполняем массив нулями
            for ($i=0; $i<=$count-1; $i++) {
              $answers[$i] = 0;
            }
            // увеличиваем в массиве полученный элемент на 1
            $answers[$answer-1] = $answers[$answer-1] + 1;
            // добавляем в результирующий массив ключом и связанный с ним ассоциативный массив
            $output[$id] = $answers;
          }
          // кодируем ассоциативный массив в JSON
          $output = json_encode($output);
          // записываем в файл
          file_put_contents(dirname(__FILE__).'/'.$nameFile, $output, LOCK_EX);
        }
        
        if (isset($_COOKIE['polls'])) {
          $arrayPolls = explode(',',$_COOKIE['polls']);
        } else {
          $arrayPolls = array();
        }
        array_push($arrayPolls,$id);
        setcookie('polls', implode(',',$arrayPolls),time() + (86400 * 365),'/');   
        
        $result[$id] = $answers;
        $result = json_encode($result);  
        echo $result;
        exit();
        ?>
        
        Скачать готовый пример можно с Яндекс Диска.
        Проект на Githib: github.com/itchief/simple-poll
        1. Иван Шеин
          Иван Шеин
          28.07.2021, 19:25
          А так же вопрос касаемо тайминга. Т.е. мне надо, чтобы опросы сбрасывались во вторник после 20:00, в четверг после 20:00 и в субботу. Так же после 20:00.
          Если это, конечно, возможно.
          1. Иван Шеин
            Иван Шеин
            28.07.2021, 19:21
            Здравствуйте. Такой вопрос — можно ли сделать так, чтобы, помимо того, чтобы записывалось в текстовый файл, ещё скидывался результат на указанную почту? Ну или вместо файла результаты на почту.
            Я предполагаю, что для этого надо в php файле poll-vote.php изменить или добавить параметры для отправки на почту.
            Но к сожалению знаний мне для этого ещё не достаточно. Подскажите, мои рассуждения верны? И, если верны, прошу подсказать, что и куда вписать)
            1. Александр Мальцев
              Александр Мальцев
              04.08.2021, 04:53
              Привет! Чтобы это реализовать, лучше создать новый php-файл, который будет брать данные из «poll-results.txt», формировать нужное тело письма и отправлять его адресатам. Запускать этот файл можно через планировщика cron (обычно имеется на всех виртуальных хостингах), указав в нём нужные дни и нужное время.
              1. Иван Шеин
                Иван Шеин
                04.08.2021, 06:38
                А подскажете, как это сделать? А то я недавно в программировании. Освоил пока HTML, по нужде залез в CSS, но Java и php для меня пока тёмный лес(
            2. Андрей
              Андрей
              12.04.2017, 12:21
              Александр спасибо, отличный вариант. Обязательно попробую в действии.
            3. Александр Мальцев
              Александр Мальцев
              10.04.2017, 15:39
              Здравствуйте! Простую голосовалку можно реализовать и без движка. Но всё равно потребуется написать серверный скрипт и выбрать хранилище, в котором сохранять данные голосования (как минимум текстовый файл).
              1. Андрей
                Андрей
                10.04.2017, 15:45
                Приветствую Александр. Я как раз и думал о простом текстовом файле для сохранения данных голосования. Подскажите, по скрипту есть какие-то шаблоны? Где можно узнать поподробнее?
              Войдите, пожалуйста, в аккаунт, чтобы оставить комментарий.