Tunda panggilan ajax di bidang teks untuk memungkinkan pengetikan

8

Saya ingin menunda ajax dari menembak dengan cara yang sama bahwa autocomplete tampaknya berfungsi. Misalnya, jika pengguna mengetik, ajax tidak akan berjalan hingga 500ms telah berlalu sejak keyup terakhir.

Saat ini saya sedang melihat drupal.behaviors tetapi tidak dapat membuatnya berfungsi.

Drupal.behaviors.mymodule = {
  attach: function(context, settings) { 
    $('input.andtimer', context).delay(500).ajaxStart();
  }
};

Ini adalah elemen bentuk tempat perilaku dilampirkan.

$form['my_input'] = array(
  '#type' => 'textfield',
  '#default_value' => $value,
  '#ajax' => array(
    'callback' => 'my_callback',        
    'event' => 'keyup',
    'wrapper' => 'my_wrapper',  
    'trigger_as' => array(
      'name' =>  'my_button',
  ),
  'progress' => array('type' => 'none'),
  ),
  '#attributes' => array(
    'class' => array('andtimer'),
  ),                      
);

Jsfiddle ini menunjukkan apa yang saya coba capai.

Apakah Cara mengganti Drupal.ajax.prototype.beforeSend? menjadi rute untuk mencatat ini?

Berikut ini berfungsi untuk 'set' input pertama dengan class .andtimer. Itu tidak bekerja untuk set lain, ajax selalu berlanjut dengan set pertama. Ada ide bagaimana cara memperbaikinya?

(function($, Drupal) {
    Drupal.behaviors.bform = {
        attach : function(context, settings) {

            var events = $('.andtimer').clone(true).data('events');
            $('.andtimer').unbind('keyup');
            var typingTimer;
            var doneTypingInterval = 300;
            $('.andtimer').keyup(function() {
                clearTimeout(typingTimer);
                typingTimer = setTimeout(doneTyping, doneTypingInterval);
                function doneTyping() {
                    $.each(events.keyup, function() {
                        this.handler();
                    });
                }

                return false;
            });
        }
    };
})(jQuery, Drupal); 

Menggunakan $ form ['my_input'] ['# ajax'] ['event'] = 'finishedinput' seperti yang disarankan dan

var typingTimer;
var doneTypingInterval = 600;

$('.andtimer').on('keyup', function (e) {
  clearTimeout(typingTimer);
  if ($(this).val) {
    var trigid = $(this);
    typingTimer = setTimeout(function(){                    
      trigid.triggerHandler('finishedinput');
    }, doneTypingInterval);
  }
});

Berfungsi untuk setiap 'kelompok' input di mana jumlah input yang diisi perlu diperoleh.

Inigo Montoya
sumber
Kode itu tidak ada hubungannya dengan keyup / keydown atau peristiwa yang Anda singgung - dapatkah Anda menambahkan kode Anda yang sebenarnya? Ingatlah bahwa jika Anda hanya mencari bantuan javascript umum, ini bukan tempat untuk menemukannya. Aturannya adalah: membuatnya bekerja di luar Drupal terlebih dahulu, dan jika Anda tidak bisa membuatnya bekerja di dalam Drupal, tanyakan di sini
Clive
Terima kasih Clive, saya telah menambahkan kode untuk membangun input. Saya langsung mencoba dan membuatnya bekerja di Drupal. Masih belajar. Saya akan mencobanya di luar dan melihat apakah saya tidak bisa mengklarifikasi masalahnya sedikit lebih banyak di kepala saya.
Inigo Montoya
Saya berbicara terlalu cepat, tidak menyadari betapa terikatnya Anda pada Drupal untuk mencoba membuat ini. Ini membuat masalah yang cukup menarik :)
Clive
1
Cuplikan kode bawah berfungsi baik untuk saya, kecuali setelah memecat acara, bidang tersebut kehilangan fokus. Bagaimana saya bisa membuatnya begitu fokus tetap pada elemen setelah menembak.
VanD

Jawaban:

7

Salah satu opsi adalah menggunakan acara jQuery khusus, mis. sesuatu seperti selesai input . Tetapkan $form['my_input']['#ajax']['event'] = 'finishedinput'dan sediakan beberapa JS untuk memicu acara khusus Anda setelah penundaan yang sesuai (mirip dengan JS dalam biola).

Andy
sumber
Luar biasa! Saya benar-benar mencari itu :) Terima kasih banyak. Namun, jika saya bisa mendapatkan tip tentang cara menerapkan ini saat Anda mengubah input dari formulir yang dilihat. Jika saya tidak menetapkan panggilan balik ke $ form ['my_input'] ['# ajax'] tidak ada yang terjadi, jika saya menambahkan formulir kirim pandangan yang terbuka, ajukan fn sebagai panggilan balik (atau apa pun yang lain) itu berfungsi tetapi mengembalikan indeks yang tidak ditentukan: form_build_id. .. Dan saya tidak tahu bagaimana dan di mana menambahkan $ form_state ['rebuild'] = BENAR Terima kasih sebelumnya
Kojo
1
@ Kojo Bisakah Anda mengajukan pertanyaan baru tentang ini dan memasukkan deskripsi pengaturan Views AJAX, filter yang terbuka, kode kustom apa pun yang Anda gunakan, dan masalah yang terjadi? Btw CTools autosubmit sudah memiliki (hardcoded) penundaan pengiriman dari bidang teks 0,5s ( lihat auto-submit.js ).
Andy
Ah bagus, ini tempatnya! Apakah tidak mungkin untuk memodifikasinya "on the fly" untuk input tertentu? Jika tidak sederhana, saya akan memposting pertanyaan :) Terima kasih atas bantuan Anda!
Kojo
1
@ Kojo Tidak semudah yang seharusnya! Jika itu saya, saya mungkin hanya akan membuat auto-submit.js saya sendiri dan menggunakannya hook_js_alter()untuk memastikan itu digunakan sebagai pengganti yang asli. (Tapi benar-benar imho kode ctools harus menggunakan Drupal.settings daripada nilai hard-coded.)
Andy
1
@ Kojo Juga lihat drupal.org/node/2023705 yaitu tentang meningkatkan pengalaman autosubmit (bukan hanya untuk input teks). Ada tambalan yang mungkin cukup untuk Anda. Sunting: dan jika Anda mencoba menggunakannya, jangan lupa untuk memberikan komentar pada masalah yang mengatakan apakah itu berhasil.
Andy
0

Pendekatan ini memiliki kelebihan dan kekurangan diterapkan untuk semua peristiwa AJAX yang dipicu keyup pada halaman mana pun skrip ini berjalan.

!function ($) {
  const originalMethod = Drupal.ajax.prototype.eventResponse,
        timeoutDelay   = 500;

  var timeoutId;

  // Override the default event handler
  Drupal.ajax.prototype.eventResponse = function (element, event) {
    const self = this;
    clearTimeout(timeoutId);

    if ('keyup' === this.event) {
      // Fire the original event handler with a delay
      timeoutId = setTimeout(function (element, event) {
        originalMethod.apply(self, [element, event]);
      }, timeoutDelay, element, event);
    }
    else {
      // Fire the original event handler immediately
      originalMethod.apply(this, [element, event]);
    }
  };
}(jQuery);
tvanc
sumber
-1

Ini adalah kode yang saya tulis:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pt-br" lang="pt-br">
<head><title>Submit after typing finished</title>
<script language="javascript" type="text/javascript">
function DelayedSubmission() {
    var date = new Date();
    initial_time = date.getTime();
    if (typeof setInverval_Variable == 'undefined') {
            setInverval_Variable = setInterval(DelayedSubmission_Check, 50);
    } 
}
function DelayedSubmission_Check() {
    var date = new Date();
    check_time = date.getTime();
    var limit_ms=check_time-initial_time;
    if (limit_ms > 800) { //Change value in milliseconds
        alert("insert your function"); //Insert your function
        clearInterval(setInverval_Variable);
        delete setInverval_Variable;
    }
}

</script>
</head>
<body>

<input type="search" onkeyup="DelayedSubmission()" id="field_id" style="WIDTH: 100px; HEIGHT: 25px;" />

</body>
</html>
Alfredo Lingoist Jr.
sumber
3
Selamat Datang di Jawaban Drupal. Anda dapat meningkatkan jawaban Anda dengan menulis paragraf pendek yang menjelaskan apa yang dilakukan cide, dan bagaimana hal itu akan menyelesaikan masalah OPs.
Radikal Gratis
-1

Saya juga mencoba "mengirim dulu" tanpa banyak keberuntungan. Saya kemudian menemukan "beforeSubmit" dan itu berhasil bagi saya. Anda dapat menggunakan strategi ini untuk menghubungkan ke metode prototipe ajax Drupal lainnya juga (lihat /misc/ajax.js untuk semua metode asli):

(function($, Drupal) {
    var delayedTimeoutId;
    var delayInterval = 500;

    /**
     * Modify form values prior to form submission.
     */
    Drupal.ajax.prototype.original_beforeSubmit = Drupal.ajax.prototype.beforeSubmit;
    Drupal.ajax.prototype.beforeSubmit = function (form_values, element, options) {
        // Some console stuff for info purposes:
        if(window.console) {
            console.log('beforeSubmit args:');
            console.log(this); // contains stuff like PHP AJAX callback, triggering selector, etc.
            console.log(form_values); // the form data
            console.log(element); // the triggering element
            console.log(options); // ajax options
        }

        // If it is the triggering selector or callback I want to delay, then do the delay:
        if(this.selector == '#my-text-input-id' || this.callback == '_my_module_ajax_callback') {
            // Clear timeout if it exists;
            clearTimeout(delayedTimeoutId);
            // Start waiting:
            delayedTimeoutId = setTimeout(function(drupalAjax, form_values, element, options) {
                delayedTimeoutId = null;
                // Execute original beforeSubmit:
                drupalAjax.original_beforeSubmit(form_values, element, options);
            }, delayInterval, this, form_values, element, options)
        } else {
            // Continue with original beforeSubmit:
            this.original_beforeSubmit(form_values, element, options);
        }
    };
}(jQuery, Drupal));
jduhl
sumber
Drupal.ajax.prototype.beforeSubmit adalah fungsi kosong secara default sehingga kode ini tidak benar-benar melakukan apa pun. Itu hanya memanggil kosong dengan atau tanpa penundaan.
tvanc
RE: fungsi kosong - Ini benar. Itu kosong untuk saat ini. Tetapi API Drupal bisa berubah dan mungkin tidak lagi kosong. Ini adalah penggantian yang aman. Selain itu, saat ini tidak melakukan apa-apa karena terserah OP untuk memasukkan nilai apa pun yang ingin mereka timpa.
jduhls
Drupal bahkan mengatakannya dalam kode untuk mengabaikan fungsi ini: / ** * Memodifikasi nilai formulir sebelum pengiriman formulir. * / Drupal.ajax.prototype.beforeSubmit = fungsi (form_values, elemen, options) {// Fungsi ini dibiarkan kosong untuk memudahkan menimpa modul // yang ingin menambah fungsionalitas di sini. };
jduhls