Formulario de comentarios rápidos con PHP y jQuery

Al lanzar un producto web, no hay nada más beneficioso que recibir comentarios tempranos de sus usuarios. Desafortunadamente, muchos sitios web dificultan innecesariamente el envío de sus comentarios o carecen de esta funcionalidad

Hoy estamos haciendo una solución simple a este problema. Desarrollado por jQuery, PHP y la clase PHPMailer, este formulario envía las sugerencias de los usuarios directamente a su buzón.

El HTML

Comencemos con el marcado HTML. La hoja de estilo se incluye en la parte superior del documento y los archivos fuente de JavaScript en la parte inferior. Esto mejora el rendimiento percibido de la página, ya que los scripts se cargan en último lugar, lo que permite mostrar el diseño del sitio.

comentarios.html

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Quick Feedback Form w/ PHP and jQuery | Tutorialzine Demo</title>

<link rel="stylesheet" type="text/css" href="styles.css" />

</head>

<body>

<div id="feedback">

    <!-- Five color spans, floated to the left of each other -->

    <span class="color color-1"></span>
    <span class="color color-2"></span>
    <span class="color color-3"></span>
    <span class="color color-4"></span>
    <span class="color color-5"></span>

    <div class="section">

        <!-- The arrow span is floated to the right -->
        <h6><span class="arrow up"></span>Feedback</h6>

        <p class="message">Please include your contact information if you'd like to receive a reply.</p>

        <textarea></textarea>

        <a class="submit" href="">Submit</a>
    </div>
</div> 

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script src="script.js"></script>
</body>
</html>

Dentro del cuerpo puedes ver el #feedback división Está anclado en la parte inferior derecha de la ventana con una posición fija, como verá en la siguiente sección del tutorial.

En su interior residen los cinco tramos de color. Estos tienen un 20% de ancho y flotan hacia la izquierda. De esta manera, llenan el ancho exacto de la división #feedback.

Por último está la .sección contenedor, que contiene el encabezado, el área de texto y el botón.

El CSS

Pasando al estilo del formulario, primero tenemos que decir un par de palabras sobre cómo está estructurada la hoja de estilo. Como puede ver en las definiciones de CSS a continuación, cada regla comienza con #feedback . De esta manera logramos el equivalente CSS de los espacios de nombres, lo que facilita agregar el código a un sitio existente sin conflictos.

estilos.css - Parte 1

#feedback{
    background-color:#9db09f;
    width:310px;
    height:330px;
    position:fixed;
    bottom:0;
    right:120px;
    margin-bottom:-270px;
    z-index:10000;
}

#feedback .section{
    background:url('img/bg.png') repeat-x top left;
    border:1px solid #808f81;
    border-bottom:none;
    padding:10px 25px 25px;
}

#feedback .color{
    float:left;
    height:4px;
    width:20%;
    overflow:hidden;
}

#feedback .color-1{ background-color:#d3b112;}
#feedback .color-2{ background-color:#12b6d3;}
#feedback .color-3{ background-color:#8fd317;}
#feedback .color-4{ background-color:#ca57df;}
#feedback .color-5{ background-color:#8ecbe7;}

#feedback h6{
    background:url("img/feedback.png") no-repeat;
    height:38px;
    margin:5px 0 12px;
    text-indent:-99999px;
    cursor:pointer;
}

#feedback textarea{
    background-color:#fff;
    border:none;
    color:#666666;
    font:13px 'Lucida Sans',Arial,sans-serif;
    height:100px;
    padding:10px;
    width:236px;

    -moz-box-shadow:4px 4px 0 #8a9b8c;
    -webkit-box-shadow:4px 4px 0 #8a9b8c;
    box-shadow:4px 4px 0 #8a9b8c;
}

El primer elemento al que se le aplicará estilo es el #feedback. división Se aplica un posicionamiento fijo y se ancla a la ventana del navegador. Después de esto viene la definición de la .sección div, y los cinco intervalos de color. Estos tramos difieren solo en sus colores de fondo, que se asignan por separado para cada clase.

En la parte inferior están las reglas CSS que definen el aspecto del área de texto.

estilos.css - Parte 2

#feedback a.submit{
    background:url("img/submit.png") no-repeat;
    border:none;
    display:block;
    height:34px;
    margin:20px auto 0;
    text-decoration:none;
    text-indent:-99999px;
    width:91px;
}

#feedback a.submit:hover{
    background-position:left bottom;
}

#feedback a.submit.working{
    background-position:top right !important;
    cursor:default;
}

#feedback .message{
    font-family:Corbel,Arial,sans-serif;
    color:#5a665b;
    text-shadow:1px 1px 0 #b3c2b5;
    margin-bottom:20px;
}

#feedback .arrow{
    background:url('img/arrows.png') no-repeat;
    float:right;
    width:23px;
    height:18px;
    position:relative;
    top:10px;
}

#feedback .arrow.down{ background-position:left top;}
#feedback h6:hover .down{ background-position:left bottom;}
#feedback .arrow.up{ background-position:right top;}
#feedback h6:hover .up{ background-position:right bottom;}

#feedback .response{
    font-size:21px;
    margin-top:70px;
    text-align:center;
    text-shadow:2px 2px 0 #889889;
    color:#FCFCFC;
}

En la segunda parte de la hoja de estilo, puede ver la definición del botón de envío. Tenga en cuenta que hay tres estados de botón, que están contenidos en la misma imagen de fondo:submit.png - y se muestra solo cuando es necesario. Estos son el estado predeterminado del botón, el estado de desplazamiento y el estado "Trabajando versión ". Cuando el botón está en su "funcionamiento ", el efecto de desplazamiento está deshabilitado.

JQuery

El formulario de comentarios tiene dos estados:minimizado y maximizado. Cuando se carga, por defecto se minimiza en la parte inferior derecha de la pantalla. Depende de jQuery maximizarlo cuando el usuario hace clic en el encabezado. Esto se hace vinculando un detector de eventos y ejecutando una animación simple, como puede ver en el código a continuación.

script.js - Parte 1

$(document).ready(function(){

    // The relative URL of the submit.php script.
    // You will probably have to change it.
    var submitURL = 'submit.php';

    // Caching the feedback object:
    var feedback = $('#feedback');

    $('#feedback h6').click(function(){

        // We are storing the values of the animated
        // properties in a separate object:

        var anim    = {
            mb : 0,            // Margin Bottom
            pt : 25            // Padding Top
        };

        var el = $(this).find('.arrow');

        if(el.hasClass('down')){
            anim = {
                mb : -270,
                pt : 10
            };
        }

        // The first animation moves the form up or down, and the second one
        // moves the "Feedback" heading, so it fits in the minimized version

        feedback.stop().animate({marginBottom: anim.mb});

        feedback.find('.section').stop().animate({paddingTop:anim.pt},function(){
            el.toggleClass('down up');
        });
    });

Para mantener el código limpio, moví las declaraciones if a la parte superior y creé el anim objeto, que contiene los valores alimentados al método de animación. Dependiendo de si el 'abajo ' existe en la flecha, maximizamos o minimizamos el formulario.

La segunda parte de script.js maneja las interacciones AJAX con submit.php .

script.js - Parte 2

    $('#feedback a.submit').live('click',function(){
        var button = $(this);
        var textarea = feedback.find('textarea');

        // We use the working class not only for styling the submit button,
        // but also as kind of a "lock" to prevent multiple submissions.

        if(button.hasClass('working') || textarea.val().length < 5){
            return false;
        }

        // Locking the form and changing the button style:
        button.addClass('working');

        $.ajax({
            url        : submitURL,
            type    : 'post',
            data    : { message : textarea.val()},
            complete    : function(xhr){

                var text = xhr.responseText;

                // This will help users troubleshoot their form:
                if(xhr.status == 404){
                    text = 'Your path to submit.php is incorrect.';
                }

                // Hiding the button and the textarea, after which
                // we are showing the received response from submit.php

                button.fadeOut();

                textarea.fadeOut(function(){
                    var span = $('<span>',{
                        className    : 'response',
                        html        : text
                    })
                    .hide()
                    .appendTo(feedback.find('.section'))
                    .show();
                }).val('');
            }
        });

        return false;
    });
});

Estamos utilizando el método AJAX de nivel inferior de jQuery - $.ajax() , para interactuar con submit.php . Este método nos da un poco más de control sobre la conexión que $.get() y $.post() envoltorios.

Un beneficio de usar este método es visible en la función de devolución de llamada "completa". Allí hacemos coincidir el estado de respuesta para el error 404 no encontrado y envía un mensaje de error amigable al usuario recordándole que verifique su submitURL camino.

Ahora continuemos con la parte final del tutorial:el paso de PHP.

El PHP

PHP maneja los datos, los pasa con AJAX, los desinfecta y envía un mensaje de correo electrónico a su dirección de correo electrónico.

enviar.php

// Enter your email address below
$emailAddress = '[email protected]';

// Using session to prevent flooding:

session_name('quickFeedback');
session_start();

// If the last form submit was less than 10 seconds ago,
// or the user has already sent 10 messages in the last hour

if( $_SESSION['lastSubmit'] && ( time() - $_SESSION['lastSubmit'] < 10 || $_SESSION['submitsLastHour'][date('d-m-Y-H')] > 10 )){
    die('Please wait for a few minutes before sending again.');
}

$_SESSION['lastSubmit'] = time();
$_SESSION['submitsLastHour'][date('d-m-Y-H')]++;

require "phpmailer/class.phpmailer.php";

if(ini_get('magic_quotes_gpc')){
    // If magic quotes are enabled, strip them
    $_POST['message'] = stripslashes($_POST['message']);
}

if(mb_strlen($_POST['message'],'utf-8') < 5){
    die('Your feedback body is too short.');
}

$msg = nl2br(strip_tags($_POST['message']));

// Using the PHPMailer class

$mail = new PHPMailer();
$mail->IsMail();

// Adding the receiving email address
$mail->AddAddress($emailAddress);

$mail->Subject = 'New Quick Feedback Form Submission';
$mail->MsgHTML($msg);

$mail->AddReplyTo('[email protected]'.$_SERVER['HTTP_HOST'], 'Quick Feedback Form');
$mail->SetFrom('[email protected]'.$_SERVER['HTTP_HOST'], 'Quick Feedback Form');

$mail->Send();

echo 'Thank you!';

Primero usamos la gestión de sesión de PHP para realizar un seguimiento de cuántas veces el usuario ha enviado el formulario en la última hora y la marca de tiempo del último envío. Si la diferencia entre el envío del último formulario y el actual es inferior a 10 segundos, o si el usuario ha enviado más de 10 mensajes en la última hora, se le muestra un mensaje de error.

Los correos electrónicos se envían con la clase PHPMailer. Solo funciona con PHP5, por lo que para usar el formulario debe ejecutar esa versión de PHP.

Se utilizan varios métodos de PHPMailer para configurar el correo electrónico saliente. Con IsMail() le estamos diciendo a la clase que debe usar el mail() interno Función PHP. AñadirDirección() anuncia las direcciones de correo electrónico receptoras (puede agregar más de un receptor con llamadas adicionales al método). Después de agregar el asunto y el cuerpo, especificamos la dirección de respuesta y enviamos el mensaje.

¡Con esto nuestro formulario de comentarios rápidos está completo!

Palabras finales

Puede usar este formulario para recopilar comentarios rápidos de sus visitantes. Con una barrera de entrada tan baja, simplemente llenando un solo cuadro de texto, hará que sea considerablemente más fácil para los usuarios compartir sus opiniones y dar ideas. El script también está estructurado para que sea fácil de personalizar y tenga un impacto mínimo en su página.