Jak sprawić, by przyciski formularza wywoływały tylko javascript?

9

Eksperymentuję z formularzami JavaScript i Drupal. Obecnie próbuję utworzyć przycisk w formie administracyjnej modułu, który będzie wykorzystywał JavaScript do dodawania opcji do listy wyboru. Problem, na który napotykam, polega na tym, że po kliknięciu przycisku JavaScript jest wywoływany, ale cały formularz jest odświeżany. Spojrzałem na odniesienie do interfejsu API formularzy, myśląc, że istnieje pewien rodzaj atrybutu, który mogę ustawić na przycisku, aby go zatrzymać, ale nic nie znalazłem. Czy jest jakiś sposób, aby zatrzymać przycisk odświeżania strony, czy jest to ślepy zaułek?

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

Mój końcowy kod:

<?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
źródło

Odpowiedzi:

4

Najłatwiejszym sposobem na osiągnięcie tego jest po prostu zwrócenie false w kodzie 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;
  }
}

lub lepszym sposobem jest użycie zachowań:

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

    //whatever you want here
    return false;
  });
}
Gnuget
źródło
1
Dzięki za wskazanie mi zachowań, czytam o tym teraz. I z jakiegoś powodu zwracanie wartości false nie działa dla mnie; strona jest wciąż odświeżana = /. W przypadku kolejnego pytania, w jaki sposób należy postępować z użytkownikami, którzy blokują / wyłączają JavaScript?
Sathariel,
Jeśli umieścisz przycisk na zewnątrz w tagu <form> </form>, nie zostanie on przesłany, ale nie jest to zalecane, bardziej konwencjonalnym sposobem jest użycie javascript. Jeśli formularz jest nadal odświeżany, sprawdź, czy jest jakiś inny kod JavaScript, który wyświetla błąd lub coś w tym rodzaju.
Gnuget,
Gdzie umieścić kod Drupal.Behaviors? w pliku javascript?
7

poniższa definicja przycisku formularza działa dla mnie, #after_build jest przydatny do ładowania w javascript, który może dołączyć moduł obsługi kliknięć.

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

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

Następnie mój JavaScript, który jest ładowany do osobnego pliku przez funkcję po kompilacji, wygląda mniej więcej tak:

Drupal.behaviors.[module_name] = function(context) {
  $('#edit-add-button').click(function() {
   ...Do something here
  });
};
Malks
źródło
After_build nie działa dla mnie. Zgłasza mi błąd krytyczny: Wywołanie niezdefiniowanej funkcji [nazwa_modułu] _after_build (). Jeśli zdefiniuję metodę [nazwa_modułu] _after_build () z pustym ciałem, formularz nie będzie renderowany. Czy możesz wyjaśnić nieco więcej, jak go używać?
sumanchalki
Niestety, nie widziałem tego pytania ... Zakładam, że zastępujesz [nazwa_modułu] rzeczywistą nazwą swojego modułu?
Malks
$ form ['# after_build'] służy do dodawania funkcji po stronie serwera (PHP) - nie służy do określania javascript po kompilacji. api.drupal.org/api/drupal/…
Christian
3

Możesz po prostu dodać return falseinstrukcję po wywołaniu funkcji, wewnątrz linii atrybutu elementu formularza przycisku:

'#attributes' => array(
   'onclick' => "add_to_list(this.form.sellist, 'Append' + this.form.sellist.length); return false",
),
Sandokan
źródło
Wydaje mi się, że lepszym rozwiązaniem jest dodanie zewnętrznego detektora zdarzeń niż umieszczenie tego wszystkiego we wbudowanym zdarzeniu onclick.
Christian
0

Idealnie, przeczytaj własne umiejętności postaci AJAX (lub AHAH) Drupala. Naprawdę podstawowe wprowadzenie tutaj http://drupal.org/node/752056

W przeciwnym razie jestem zaskoczony, że odświeża stronę, ponieważ jest to tylko „przycisk”, a nie przesłanie lub cokolwiek innego.

Czy potrzebuje javascript do zwrócenia false, tak jak w przypadku linku, aby zatrzymać przeskakiwanie z powrotem na górę strony?

joevallender
źródło
W rzeczywistości starałem się unikać korzystania z AJAX, ponieważ staram się przede wszystkim po stronie klienta. Serwer potrzebuje danych dopiero po przesłaniu formularza. Jeśli chodzi o zwracanie rzeczy w JavaScript, próbowałem zwrócić true, false i null bez różnicy.
Sathariel,