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

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

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

  1. Константин
    Константин
    2021-02-02 17:38:00
    Приветствую, спасибо за скрипт. единственный вопрос с накруткой голосов, COOKIE не очень хорошо работают, может возможно добавить защиту по IP?
  1. Daler
    Daler
    2018-01-03 03:44:32
    Добрый день. Переменная $current — отвечает за то какой pool — опрос отображается. Не подскажите как сделать переключатель ввиде далее между опросами? И как добавить больше вопросов и ответов в 1 опрос, буду очень признателен
    1. Александр Мальцев
      Александр Мальцев
      2017-04-12 04:25:15
      Как можно создать опросы на сайте, которые сохраняют данные не в базу, а в обычный текстовый файл...
      Данная инструкция пригодиться не только тем, у кого нет 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. Андрей
        Андрей
        2017-04-12 12:21:23
        Александр спасибо, отличный вариант. Обязательно попробую в действии.
      2. Иван Шеин
        Иван Шеин
        2021-07-28 19:21:06
        Здравствуйте. Такой вопрос — можно ли сделать так, чтобы, помимо того, чтобы записывалось в текстовый файл, ещё скидывался результат на указанную почту? Ну или вместо файла результаты на почту.
        Я предполагаю, что для этого надо в php файле poll-vote.php изменить или добавить параметры для отправки на почту.
        Но к сожалению знаний мне для этого ещё не достаточно. Подскажите, мои рассуждения верны? И, если верны, прошу подсказать, что и куда вписать)
      3. Иван Шеин
        Иван Шеин
        2021-07-28 19:25:18
        А так же вопрос касаемо тайминга. Т.е. мне надо, чтобы опросы сбрасывались во вторник после 20:00, в четверг после 20:00 и в субботу. Так же после 20:00.
        Если это, конечно, возможно.
      4. Александр Мальцев
        Александр Мальцев
        2021-08-04 04:53:36
        Привет! Чтобы это реализовать, лучше создать новый php-файл, который будет брать данные из «poll-results.txt», формировать нужное тело письма и отправлять его адресатам. Запускать этот файл можно через планировщика cron (обычно имеется на всех виртуальных хостингах), указав в нём нужные дни и нужное время.
      5. Иван Шеин
        Иван Шеин
        2021-08-04 06:38:38
        А подскажете, как это сделать? А то я недавно в программировании. Освоил пока HTML, по нужде залез в CSS, но Java и php для меня пока тёмный лес(
    2. Александр Мальцев
      Александр Мальцев
      2017-04-10 15:39:18
      Здравствуйте! Простую голосовалку можно реализовать и без движка. Но всё равно потребуется написать серверный скрипт и выбрать хранилище, в котором сохранять данные голосования (как минимум текстовый файл).
      1. Андрей
        Андрей
        2017-04-10 15:45:11
        Приветствую Александр. Я как раз и думал о простом текстовом файле для сохранения данных голосования. Подскажите, по скрипту есть какие-то шаблоны? Где можно узнать поподробнее?