Como fazer botões de formulário chamar apenas javascript?

9

Estou experimentando formulários JavaScript e Drupal. Atualmente, estou tentando criar um botão no formulário de administração de um módulo que usará o JavaScript para anexar opções a uma lista de seleção. O problema que encontro é que, quando clico no botão, meu JavaScript é chamado, mas todo o formulário é atualizado. Eu olhei para a referência da API de formulários pensando que havia algum tipo de atributo que posso definir no botão para impedi-lo, mas não encontrei nada. Existe alguma maneira de impedir que o botão atualize a página ou isso é um beco sem saída?

$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));
  }
}

Meu código 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
fonte

Respostas:

4

A maneira mais fácil de fazer isso é simplesmente retornar false no seu 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;
  }
}

ou uma maneira melhor é usar comportamentos:

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

    //whatever you want here
    return false;
  });
}
Gnuget
fonte
11
Obrigado por me indicar comportamentos, eu estou lendo isso agora, na verdade. E, por algum motivo, retornar falso não está funcionando para mim; a página ainda está atualizando = /. Para uma pergunta de acompanhamento, como você deve lidar com usuários que bloqueiam / desabilitam o javascript?
precisa saber é o seguinte
Se você colocar o botão fora de uma tag <form> </form>, isso não será enviado, mas isso não é recomendado, a maneira mais convencional de fazer isso é com javascript. Se o formulário ainda estiver atualizando, verifique se há algum outro javascript que esteja exibindo um erro ou algo parecido.
Gnuget
Onde colocar o código Drupal.Behaviors? no arquivo javascript?
Sim, dê uma olhada nisso: amazeelabs.com/en/blog/drupal-behaviors-quick-how
Gnuget
7

a definição do botão de formulário abaixo funciona para mim, o #after_build é útil para carregar em javascript que pode anexar o manipulador de cliques.

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

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

Então meu javascript, carregado em um arquivo separado pela função after build, se parece com:

Drupal.behaviors.[module_name] = function(context) {
  $('#edit-add-button').click(function() {
   ...Do something here
  });
};
Malks
fonte
After_build não está funcionando para mim. Isso gera um erro fatal: Chame a função indefinida [module_name] _after_build (). Se eu definir o método [module_name] _after_build () com corpo vazio, o formulário não será renderizado. Você pode esclarecer um pouco mais como usá-lo?
sumanchalki
Desculpe, eu não vi essa pergunta ... Presumo que você esteja substituindo [module_name] pelo nome real do seu módulo?
Malks
$ form ['# after_build'] é para adicionar uma função do lado do servidor (PHP) - não é para especificar javascript pós-compilação. api.drupal.org/api/drupal/…
Christian
3

Você pode simplesmente adicionar a return falseinstrução após sua chamada de função, dentro da linha de atributo do elemento do formulário do botão:

'#attributes' => array(
   'onclick' => "add_to_list(this.form.sellist, 'Append' + this.form.sellist.length); return false",
),
Sandokan
fonte
Eu acho que uma opção melhor é adicionar um ouvinte de evento externo ao invés de colocar tudo no evento onclick inline.
Christian
0

Idealmente, leia as habilidades de forma AJAX (ou AHAH) do Drupal. Introdução realmente básica aqui http://drupal.org/node/752056

Caso contrário, estou surpreso ao atualizar a página, pois é apenas um 'botão', não um envio ou algo assim.

Ele precisa que o javascript retorne false, como em um link para impedi-lo de voltar ao topo da página?

joevallender
fonte
Na verdade, eu estava tentando evitar o uso do AJAX, pois o que estou tentando fazer é principalmente no cliente. Não é até que o formulário seja enviado que o servidor precisa dos dados. Quanto a retornar as coisas no JavaScript, tentei retornar true, false e null sem nenhuma diferença.
precisa saber é o seguinte