¿Cómo hacer que los botones de formulario llamen solo javascript?

9

Estoy experimentando con JavaScript y formularios Drupal. Actualmente estoy tratando de hacer un botón en la forma de administración de un módulo que usará JavaScript para agregar opciones a una lista de selección. El problema con el que me encuentro es que cuando hago clic en el botón, se llama a mi JavaScript pero se actualiza todo el formulario. Miré la referencia de Forms API pensando que había algún tipo de atributo que puedo configurar en el botón para detenerlo, pero no encontré nada. ¿Hay alguna forma de evitar que el botón actualice la página o es un callejón sin salida?

$form['#attached']['js'] = array(
  drupal_get_path('module', 'test').'/js/test.js',
);

$form['list'] = array(
  '#type' => 'select',
  '#options' => array(),
  '#attributes' => array(
    'name' => 'sellist',
  ),
  '#size' => 4,
);

$form['add_button'] = array(
  '#type' => 'button',
  '#value' => 'Add',
  '#attributes' => array(
    'onclick' => "add_to_list(this.form.sellist, 'Append' + this.form.sellist.length);",
  ),
);

//JavaScript
function add_to_list(list, text) {
  try {
    list.add(new Option(text, list.length), null) //add new option to end of "sample"
  }
  catch(e) {
    list.add(new Option(text, list.length));
  }
}

Mi codigo final:

<?php
function jstest_menu() {
  $items['admin/config/content/jstest'] = array(
    'title' => 'JavaScript Test',
      'description' => 'Configuration for Administration Test',
      'page callback' => 'drupal_get_form',
      'page arguments' => array('_jstest_form'),
      'access arguments' => array('access administration pages'),
      'type' => MENU_NORMAL_ITEM,
  );

  return $items;
}

function _jstest_form($form, &$form_state) {
  $form['list'] = array(
    '#type' => 'select',
    '#options' => array(),
    '#size' => 4,
  );

  $form['text'] = array(
    '#type' => 'textfield',
  );

  $form['add_button'] = array (
    '#type' => 'button',
    '#value' => t("Add"),
    '#after_build' => array('_jstest_after_build'),
  );
  return $form;
}

function _jstest_after_build($form, &$form_state) {
  drupal_add_js(drupal_get_path('module', 'jstest').'/js/jstest.js');
  return $form;
}

JavaScript
(function ($) {
  Drupal.behaviors.snmpModule = {
    attach: function (context, settings) {
      $('#edit-add-button', context).click(function () {
        var list = document.getElementById('edit-list');
        var text = document.getElementById('edit-text');

        if (text.value != '')
        {
          try {
            list.add(new Option(text.value, list.length), null);
          }
          catch(e) {
            list.add(new Option(text.value, list.length));
          }

          text.value = '';
        }

        return false;
      });
      $('#edit-list', context).click(function () {
        var list = document.getElementById('edit-list');

        if (list.selectedIndex != -1)
          list.remove(list.selectedIndex);

        return false;
      });
    }
  };
}(jQuery));
Sathariel
fuente

Respuestas:

4

La forma más fácil de lograr esto es simplemente devolver falso en su código javascript:

function add_to_list(list, text) {
  try {
    list.add(new Option(text, list.length), null);
    return false;
  } catch(e) {
    list.add(new Option(text, list.length));   
    return false;
  }
}

o una mejor manera es usar comportamientos:

Drupal.behaviors.some_action = function(context) {
  $('#id-button:not(.button-processed)',context)
  .addClass('button-processed').each(function() {

    //whatever you want here
    return false;
  });
}
Gnuget
fuente
1
Gracias por señalarme a los comportamientos, de hecho lo estoy leyendo. Y por alguna razón devolver falso no funciona para mí; la página aún se está actualizando = /. Para una pregunta de seguimiento, ¿cómo debe manejar a los usuarios que bloquean / deshabilitan JavaScript?
Sathariel
Si coloca el botón afuera de una etiqueta <form> </form>, esto no se enviará pero no se recomienda, la forma más convencional de hacerlo es con javascript. Si su formulario aún se está actualizando, verifique si hay algún otro JavaScript que muestre un error o algo así.
Gnuget
¿Dónde poner el código Drupal.Behaviors? en el archivo javascript?
Sí, eche un vistazo a esto: amazeelabs.com/en/blog/drupal-behaviors-quick-how
Gnuget
7

la definición del botón de formulario a continuación me funciona, el #after_build es útil para cargar en JavaScript que puede adjuntar el controlador de clic.

$form['add_button'] = array (
  '#type' => 'button',
  '#attributes' => array('onclick' => 'return (false);'),
  '#value' => t("Add"),
);

$form['#after_build'] = array('[module_name]_after_build');

Entonces mi javascript que se carga en un archivo separado por la función de compilación posterior, se parece a:

Drupal.behaviors.[module_name] = function(context) {
  $('#edit-add-button').click(function() {
   ...Do something here
  });
};
Malks
fuente
After_build no funciona para mí. Me arroja un error fatal: Llamar a la función indefinida [nombre_módulo] _after_build (). Si defino el método [nombre_módulo] _after_build () con cuerpo vacío, el formulario no se procesa. ¿Puedes aclarar un poco más cómo usarlo?
sumanchalki
Lo siento, no vi esta pregunta ... ¿Asumo que estás reemplazando [nombre_módulo] con el nombre real de tu módulo?
Malks
$ form ['# after_build'] es para agregar una función del lado del servidor (PHP); no es para especificar javascript post build. api.drupal.org/api/drupal/…
Christian
3

Simplemente puede agregar la return falsedeclaración después de su llamada a la función, dentro de la línea de atributo del elemento de forma de botón:

'#attributes' => array(
   'onclick' => "add_to_list(this.form.sellist, 'Append' + this.form.sellist.length); return false",
),
Sandokan
fuente
Creo que una mejor opción es agregar un detector de eventos externo en lugar de ponerlo todo en el evento onclick en línea.
Christian
0

Idealmente, lea las habilidades de forma AJAX (o AHAH) de Drupal. Introducción realmente básica aquí http://drupal.org/node/752056

De lo contrario, me sorprende que esté actualizando la página, ya que es solo un "botón", no un envío ni nada.

¿Necesita el javascript para devolver falso, como en un enlace para evitar que vuelva a la parte superior de la página?

joevallender
fuente
En realidad, estaba tratando de evitar el uso de AJAX ya que lo que intento hacer es principalmente en el lado del cliente. No es hasta que se envía el formulario que el servidor necesita los datos. En cuanto a devolver cosas en JavaScript, he intentado devolver verdadero, falso y nulo sin diferencia.
Sathariel