Editor de FormQuestion de Javascript Ajax -- javascript campo con jquery campo con object-oriented campo con ajax camp codereview Relacionados El problema

JavaScript ajax formquestion editor


3
vote

problema

Español

Este es el archivo JavaScript que utilizo para mi editor que permite a las personas editar preguntas de un formulario.

Me pregunto si este tipo de enfoque para usar los objetos JavaScript es bueno o que me pierdo el punto aquí?

  red3  

Esta es la plantilla PHP / HTML con la que funciona (no está destinado a ser el enfoque de esta revisión):

  red4  
Original en ingles

This is the JavaScript file that i use for my editor that allows people to edit questions from a form.

I'm wondering if this sort of approach to use JavaScript objects is good or that I kind of miss the point here?

$(document).ready(function() {     manager = new Customerformquestionmanager();     manager.formId = firstFormId;     manager.getCategorys();       $('#formSelect').change(function() {         manager.getCategorys();     });      $('#categorySelect').change(function() {         manager.categoryId = $(this).val();         manager.getQuestions();     });      $('.dataTable').on('click', '.editBtn', function() {         parent = $(this).parent();         id = parent.find('.rowId').html();         question = parent.find('.rowQuestion').html();         type = parent.find('.rowType').html();         answers = parent.find('.rowAnswer').html();         customType = parent.find('.rowCustomType').html();           $('#editId').val(id)         $('#editQuestion').val(question);         $('#editType').val(type);         $('#editAnswers').val(answers);         $('#editCustomType').val(customType);     });      $('#saveBtn').click(function() {         questionObj = {             question: $('#editQuestion').val(),             type: $('#editType').val(),             custom_answers: $('#editAnswers').val(),             custom_type: $('#editCustomType').val()         };          if($('#editId').val() != '') {             questionObj.id = $('#editId').val();         }          manager.saveQuestion(questionObj);     }); });  function Customerformquestionmanager() {     this.formId = false;     this.currentQuestionId = false;     this.categoryId = false;     this.categorySelect = $('#categorySelect');     this.dataTable = $('.datatTable');     this.handler = '/handlers/backend/customerformhandler'; }  Customerformquestionmanager.prototype.getCategorys = function() {     if(this.formId) {         obj = this;         $.ajax({             'url': this.handler,             'type': 'POST',             'data': {                 'method': 'getcategorysbyformid',                 'id': this.formId             }         }).done(function(data) {             if(typeof data != 'undefined')                 data = JSON.parse(data);             if(typeof data != 'undefined') {                 obj.categorySelect.find('option').remove();                  length = data.length;                 for(i = 0; i < length; i++) {                     selected = '';                     if(i == 0) {                         obj.categoryId = data[0].id;                         selected = 'selected="selected"';                         obj.getQuestions();                     }                     obj.categorySelect.append('<option' + selected + ' value="' + data[i].id + '">' + data[i].title + ' (id: ' + data[i].id + ')</option>');                 }             }         });     } }  Customerformquestionmanager.prototype.getQuestions = function() {     if(this.categoryId) {         obj = this;         $.ajax({             'url': this.handler,             'type': 'POST',             'data': {                 'method': 'getquestionsbycategoryid',                 'id': this.categoryId             }         }).done(function(data) {             obj.dataTable.find('tr').not(':first').remove();             if(typeof data !== 'undefined' && data)                  data = JSON.parse(data);             if(typeof data !== 'undefined') {                 length = data.length;                 for(i = 0; i < length; i++) {                     obj.dataTable.append(                         '<tr id="category' + data[i].id + '">' +                             '<td class="rowId">' + data[i].id + '</td>' +                             '<td class="rowQuestion">' + data[i].question + '</td>' +                             '<td class="rowType">' + data[i].type + '</td>' +                             '<td class="rowAnswer">' + data[i].custom_answers + '</td>' +                             '<td class="rowCustomType">' + data[i].custom_type + '</td>' +                             '<td class="editBtn">edit</td>' +                             '<td class="redClickable">delete</td>' +                         '</tr>'                     );                 }             }         });     } }  Customerformquestionmanager.prototype.saveQuestion = function(dataobj) {     if(typeof dataobj != 'undefined') {         dataobj.method = 'savequestion';         dataobj.category_id = this.categoryId;         obj = this;         if(typeof dataobj.id !== 'undefined')             this.currentQuestionId = dataobj.id;         $.ajax({             'url': this.handler,             'type': 'POST',             'data': dataobj         }).done(function(data) {             if(typeof data !== 'undefined' && data) {                 data = JSON.parse(data);                 if(typeof data !== 'undefined') {                     obj.dataTable.append(                         '<tr id="category' + data.id + '">' +                             '<td class="rowId">' + data.id + '</td>' +                             '<td class="rowQuestion">' + dataobj.question + '</td>' +                             '<td class="rowType">' + dataobj.type + '</td>' +                             '<td class="rowAnswer">' + dataobj.custom_answers + '</td>' +                             '<td class="rowCustomType">' + dataobj.custom_type + '</td>' +                             '<td class="editBtn">edit</td>' +                             '<td class="redClickable">delete</td>' +                         '</tr>'                     );                     alert('question added');                 }             }             else {                 $('category' + obj.currentQuestionId + ' .rowQuestion').html(dataobj.question);                 $('category' + obj.currentQuestionId + ' .rowType').html(dataobj.type);                 $('category' + obj.currentQuestionId + ' .rowAnswer').html(dataobj.answers);                 $('category' + obj.currentQuestionId + ' .rowCustomType').html(dataobj.custom_type);                                  alert('question saved');             }          });     } } 

This is the PHP/HTML template that it works with (not intended to be the focus of this review):

<?php      require_once __DIR__ . '/../classes/database.php';     require_once __DIR__ . '/../classes/security.php';     require_once __DIR__ . '/../includes/checkauth.php';     require_once __DIR__ . '/../includes/backendincludes.php';      $db = Database::getInstance();     $forms = $db->getAsArray('SELECT id, title FROM ea_customer_form');     $lastForm = end($forms);     $lastForm = $lastForm['id'];     reset($forms);  ?> <script type="text/javascript" src="/js/backend/customerformquestion.js"></script> <script type="text/javascript">var firstFormId = <?php echo $lastForm; ?>;</script> <div id="maincontent">     Select form:     <br />     <select id="formSelect">                 <?php              foreach($forms as $form) {                 echo '<option value="' . $form['id'] . '">' . $form['title'] . '</option>';             }         ?>     </select>     <br /><br />      Select category in form:<br />      <select id="categorySelect"></select>      <br /><br />         <input type="button" value="clear fields (back to add new)" id="clearBtn">      <br /><br /><hr><br />      Required:     <table>         <tr>             <td>Id: </td>             <td><input type="text" id="editId" readonly="readonly"></td>         </tr>         <tr>             <td>Question: </td>             <td><input type="text" id="editQuestion" style="width: 600px;"></td>         </tr>         <tr>             <td>Type: </td>             <td>                 <select id="editType">                     <option value="textarea">Text area</option>                     <option value="radio">Radio</option>                 </select>             </td>         </tr>     </table>     <br /><br />     Optional:      <table>         <tr>             <td>Answers: </td>             <td><input type="text" id="editAnswers" style="width: 600px;" placeholder="answers comma seperated (for example: yes,no,maybe)"></td>         </tr>         <tr>             <td>Custom type:</td>             <td>                 <select id="editCustomType">                     <option value="">none</option>                     <option value="grouped">Grouped</option>                 </select>             </td>         </tr>         <tr>             <td><input type="button" value="save" id="saveBtn"></td>         </tr>     </table>      <br /><br /><hr><br />      <table class="dataTable">         <tr>             <th>Id</th>             <th>Question</th>             <th>Type</th>             <th>Answers</th>             <th>Custom type</th>             <th>Edit</th>             <th>Delete</th>         </tr>     </table> </div> 
           

Lista de respuestas

1
 
vote
vote
La mejor respuesta
 

El punto principal de las clases es poder crear múltiples instancias independientemente entre sí. Entonces, si tuviera el mismo "widget" varias veces en su página, podrían funcionar sin necesidad de escribir código duplicado. El principal problema es que tiene cosas como las ID y las URL codificadas en su clase y tienen partes relevantes (a saber, los manipuladores de eventos) fuera de la clase.

Entonces, sí, te estás perdiendo el punto.

Si desea encapsular todo, debe eliminar las identificaciones y usar las clases (o 9988776655544337 Atributos) y colgar todo desde un elemento circundante, por ejemplo.:

  <form class="questioneditor">    <!-- put everything your widget need in here marked up with classes, not IDs --> </form>  $(".questioneditor").each(function() {    new Customerformquestionmanager(this); });   

Hay varios otros problemas (pequeños) con su código que podrían optimizarse. Aquí solo una visión general rápida:

  • Si tiene su script del lado del servidor JSON, devuelva la "aplicación / JSON" de tipo MIME correcto o al menos establezca la opción dataType: "json" en el password_hash()0 Llame, luego No es necesario analizar la respuesta del servidor. jquery password_hash()1 hará eso por su.
  • password_hash()2 es para las salidas de línea en cosas como poemas y direcciones, no para el diseño.
  • La forma en que genera las filas de tabla (que es un código duplicado por bTW) y lee los datos de ellos a los campos de entrada se ve muy peligroso. En lo general, te estás abriendo a los ataques de scripts de cruce. Al menos, probablemente conduzca a los dolores de cabeza con (ONU) que codifica HTML correctamente.

Editar: Infos a Scripts de sitio Cross:

Si sus datos contienen algún tipo de HTML (especialmente incluidos los scripts), solo adjuntándolo así password_hash()3 no se escapará y se olvidó 99887776555443314 , o Un extravío password_hash()5 romperá su diseño. Y, de alguna manera, un bucle infinito, como password_hash()6 GET, su sitio será inutilizable. En el peor script AJAX, podría ser contrabandeado y enviar datos personales a un sitio de terceros.

En su lugar, asegúrese de escapar de los datos creando nodos de texto adecuados. Con jQuery, por ejemplo, utilizando el método 99887776655443317 :

  password_hash()8  
 

The main point of classes is to be able to create multiple instances independently from each other. So if you had the same "widget" multiple times on your page, they could work without needing to write duplicate code. The main problem is that you have things like IDs and URLs hard-coded into your class, and have relevant parts (namely the event handlers) outside of the class.

So, yes, you are missing the point.

If you want to encapsulate everything, you should drop the IDs and use classes (or data- attributes) and hang up everything from a surrounding element, e.g.:

<form class="questioneditor">    <!-- put everything your widget need in here marked up with classes, not IDs --> </form>  $(".questioneditor").each(function() {    new Customerformquestionmanager(this); }); 

There are several other (small) problems with your code that could be optimized. Here just a quick overview:

  • If you have your JSON server-side script return the correct mime-type "application/json" or at least set the option dataType: "json" in the ajax() call, then you don't need to parse the server response yourself. jQuery ajax() will do that for your.
  • <br> is for line breaks in things like poems and addresses, not for layout.
  • The way you generate the table rows (which is duplicated code BTW) and read the data from them into the input fields looks very dangerous. At the very worst you are opening yourself up to cross-site scripting attacks. At the very least it will probably lead to to headaches with (un)encoding HTML properly.

EDIT: Infos to cross-site scripting:

If your data contains any kind of HTML (especially including scripts), then just appending it like this '<td class="rowQuestion">' + data[i].question + '</td>' it won't be escaped and a forgotten <, or a stray </table> will break your layout. And if somehow an infinite loop such as <script>while(1){alert();}</script> get's in, your site will be unusable. At the worst AJAX script could be smuggled in and send personal data to a third party site.

Instead make sure to escape the data by creating proper text nodes. With jQuery, for example, by using the .text() method:

$("<td>").addClass("rowQuestion").text(data[i].question); 
 
 
     
     

Relacionados problema

7  Plugin de paginación  ( Pagination plugin ) 
Este complemento está escrito en jQuery y se hace para admitir el marco de CodeIgniter . Es un complemento de paginación de tabla de AJAX diseñada para propo...

1  Actualización de una página web de DRUPAL con contenido basado en texto ingresado  ( Updating a drupal web page with content based on inputted text ) 
La intención es actualizar una página web de drupal existente con contenido basado en texto ingresado en un cuadro de texto. La página existente muestra dat...

2  Parámetros JavaScript - Mejores prácticas para configuraciones objeto / devolución de llamada  ( Javascript parameters best practices for settings object callback ) 
Tengo la siguiente función que se ejecuta como se esperaba y se define en el objeto 9988777665544339 .appedTo0 que funciona como se esperaba. Sin em...

8  Tema / Cambio de la piel ... Versión 2! (CSS-Drived)  ( Theme skin swap version 2 css driven ) 
Básicamente, tengo una piel de AJAX (HTML / CSS) que se carga en un elemento ficticio (ID = SkinContainer) cuando la página está cargada, y luego el contenido...

2  Llamada Ajax en JavaScript  ( Ajax call in javascript ) 
Sé que hay muchas bibliotecas con esto construido en $.get() , etc ... Pero como para escribir esto en Javascript puro ¿Cómo se ve esto? Cells0 ...

8  Escribiendo un widget de jquery: plantilla  ( Writing a jquery widget templating ) 
Estoy haciendo mi primer mayor desarrollo de jQuery. Es un widget para eventos recurrentes, y es como una bestia bastante compleja. El código completo está di...

3  MARCA DE TEXTBOX JavaScript de doble modo  ( Dual mode javascript textbox watermark ) 
Solo estaba tratando de hacer una marca de agua AJAX alternativa desde "Fecha de inserción" (primer modo) a "MM / DD / YYAY" (segundo modo). Después de algún ...

5  Validación del formulario AJAX  ( Ajax form validation ) 
Este es mi primer intento de la validación del formulario AJAX, y todo funciona como se esperaba, el ejemplo final final mantendrá muchos más campos de entrad...

8  Biblioteca básica de JavaScript  ( Basic javascript library ) 
Mi propio CMS está utilizando actualmente JQERY, pero como uno de los objetivos es que todo el proyecto sea muy pequeño, he decidido escribir mi propia biblio...

0  ¿Cómo puedo mostrar los resultados de mysql_fetch_assoc en una tabla dinámica?  ( How can i display the results of mysql fetch assoc in a dynamic table ) 
Tengo una base de datos MySQL con varias columnas y dos filas de datos, hasta ahora. Estoy usando mysql_fetch_assoc para devolver los datos en la base de dato...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos