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

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

Комментарии ()

  1. Константин
    02 февраля 2021, 17:38
    Приветствую, спасибо за скрипт. единственный вопрос с накруткой голосов, COOKIE не очень хорошо работают, может возможно добавить защиту по IP?
    1. Daler
      03 января 2018, 03:44
      Добрый день. Переменная $current — отвечает за то какой pool — опрос отображается. Не подскажите как сделать переключатель ввиде далее между опросами? И как добавить больше вопросов и ответов в 1 опрос, буду очень признателен
      1. Александр Мальцев
        12 апреля 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. Андрей
          12 апреля 2017, 12:21
          Александр спасибо, отличный вариант. Обязательно попробую в действии.
        2. Александр Мальцев
          10 апреля 2017, 15:39
          Здравствуйте! Простую голосовалку можно реализовать и без движка. Но всё равно потребуется написать серверный скрипт и выбрать хранилище, в котором сохранять данные голосования (как минимум текстовый файл).
          1. Андрей
            10 апреля 2017, 15:45
            Приветствую Александр. Я как раз и думал о простом текстовом файле для сохранения данных голосования. Подскажите, по скрипту есть какие-то шаблоны? Где можно узнать поподробнее?
          Войдите, пожайлуста, в аккаунт, чтобы оставить комментарий.