Trì hoãn cuộc gọi ajax trên trường văn bản để cho phép nhập


8

Tôi muốn trì hoãn ajax bắn theo cùng một cách mà tự động hoàn thành dường như hoạt động. Ví dụ: nếu người dùng gõ, ajax sẽ không chạy cho đến khi hết 500ms kể từ lần khóa cuối cùng.

Tôi hiện đang xem drupal.behaviors nhưng không thể làm cho nó hoạt động.

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

Đây là yếu tố hình thức mà hành vi được đính kèm.

$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 này cho thấy những gì tôi đang cố gắng để đạt được.

Would Làm thế nào để ghi đè Drupal.ajax.prototype.beforeSend? là một tuyến đường để đưa điều này xuống?

Các công việc sau đây cho 'bộ' đầu vào đầu tiên với lớp .andtimer. Nó không hoạt động cho bất kỳ bộ nào khác, ajax luôn tiếp tục với bộ đầu tiên. Bất kỳ ý tưởng làm thế nào để sửa lỗi này?

(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); 

Sử dụng $ form ['my_input'] ['# ajax'] ['event'] = 'finishinput' như đề xuất và

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

Hoạt động cho từng 'nhóm' đầu vào trong đó cần phải thu được số lượng đầu vào đầy.


Mã đó không liên quan gì đến keyup / keydown hoặc sự kiện ràng buộc mà bạn đang ám chỉ - bạn có thể thêm mã thực tế của mình không? Hãy nhớ rằng nếu bạn chỉ tìm kiếm trợ giúp javascript chung, đây không phải là nơi để tìm thấy nó. Quy tắc là: làm cho nó hoạt động bên ngoài Drupal trước và nếu bạn không thể khiến nó hoạt động bên trong Drupal, hãy hỏi tại đây
Clive

Cảm ơn Clive, tôi đã thêm mã để xây dựng đầu vào. Tôi đã đi thẳng để thử và làm cho nó hoạt động trong Drupal. Vẫn đang học. Tôi sẽ cho nó ra ngoài và xem liệu tôi không thể làm rõ đầu dò thêm một chút trong đầu.
Inigo Montoya

Tôi đã nói quá sớm, không nhận ra mình bị ràng buộc với Drupal như thế nào. Điều này làm cho một vấn đề khá thú vị :)
Clive

1
Đoạn mã dưới cùng hoạt động tốt với tôi, ngoại trừ sau khi bắn sự kiện, trường mất tiêu điểm. Làm thế nào tôi có thể thực hiện được để tập trung vào yếu tố sau khi bắn.
VanD

Câu trả lời:


7

Một tùy chọn là sử dụng một sự kiện jQuery tùy chỉnh, ví dụ. một cái gì đó giống như hoàn thành . Đặt $form['my_input']['#ajax']['event'] = 'finishedinput'và cung cấp một số JS để kích hoạt sự kiện tùy chỉnh của bạn sau một độ trễ thích hợp (tương tự như JS trong fiddle).


Kinh ngạc ! Tôi đã chính xác tìm kiếm điều đó :) Cảm ơn rất nhiều. Tuy nhiên, nếu tôi có thể có một mẹo về cách áp dụng điều này khi bạn thay đổi đầu vào của biểu mẫu hiển thị. Nếu tôi không đặt gọi lại thành $ form ['my_input'] ['# ajax'] thì không có gì xảy ra, nếu tôi thêm biểu mẫu hiển thị, hãy gửi fn dưới dạng gọi lại (hoặc bất cứ điều gì khác), nó hoạt động nhưng trả về chỉ mục không xác định: form_build_id. .. Và tôi cũng không biết cách và nơi để thêm $ form_state ['xây dựng lại]] = TRUE Cảm ơn trước
Kojo

1
@Kojo Bạn có thể hỏi một câu hỏi mới về vấn đề này và bao gồm các mô tả về cài đặt AJAX của Chế độ xem, bộ lọc được hiển thị, bất kỳ mã tùy chỉnh nào bạn đang sử dụng và các sự cố xảy ra không? Btw CTools autosubmit đã có độ trễ (mã hóa cứng) khi gửi từ các trường văn bản là 0,5 giây ( xem auto-submit.js ).
Andy

Ah tuyệt vời, đây là các thiết lập! Không thể sửa đổi nó "nhanh chóng" cho một đầu vào cụ thể? Nếu nó không đơn giản, tôi sẽ gửi một câu hỏi :) Cảm ơn sự giúp đỡ của bạn!
Kojo

1
@Kojo Không dễ như mong muốn! Nếu là tôi, có lẽ tôi chỉ cần tạo auto-submit.js của riêng mình và sử dụng hook_js_alter()để đảm bảo nó được sử dụng thay cho bản gốc. (Nhưng thực sự imho mã ctools nên sử dụng Drupal.sinstall chứ không phải là giá trị được mã hóa cứng.)
Andy

1
@Kojo Cũng hãy xem drupal.org/node/2023705 , đó là về việc cải thiện trải nghiệm tự động gửi (không chỉ cho nhập văn bản). Có một bản vá có thể là đủ cho bạn. EDIT: và nếu bạn cố gắng sử dụng nó, đừng quên bình luận về vấn đề này cho biết liệu nó có hiệu quả hay không.
Andy

0

Cách tiếp cận này có cả ưu điểm và nhược điểm của việc áp dụng cho tất cả các sự kiện AJAX được kích hoạt bằng khóa trên bất kỳ trang nào có tập lệnh này chạy.

!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);

-1

Đây là mã tôi đã viết:

<!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>

3
Chào mừng đến với câu trả lời của Drupal. Bạn có thể cải thiện câu trả lời của mình bằng cách viết một đoạn văn ngắn giải thích những gì cide làm và cách nó sẽ giải quyết vấn đề OP.
Cấp tiến miễn phí

-1

Tôi cũng đã thử "beforeSend" mà không gặp nhiều may mắn. Sau đó, tôi tình cờ phát hiện ra "beforeSubmit" và đó là mẹo cho tôi. Bạn cũng có thể sử dụng chiến lược này để nối vào các phương thức nguyên mẫu Drupal ajax khác (xem /misc/ajax.js cho tất cả các phương thức ban đầu):

(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));

Drupal.ajax.prototype.b BeforeSubmit theo mặc định là một hàm trống nên mã này không thực sự làm gì cả. Nó chỉ gọi một khoảng trống có hoặc không có độ trễ.
tvanc

RE: hàm rỗng - Điều này đúng. Nó trống rỗng bây giờ. Nhưng API Drupal có thể thay đổi và nó có thể không còn trống. Đây là một ghi đè an toàn. Ngoài ra, hiện tại nó không làm gì cả vì tùy thuộc vào OP để chèn bất kỳ giá trị nào họ muốn ghi đè.
jduhls

Drupal thậm chí còn nói nó trong mã để ghi đè chức năng này: / ** * Sửa đổi giá trị biểu mẫu trước khi gửi biểu mẫu. * / Drupal.ajax.prototype.b BeforeSubmit = function (form_values, phần tử, tùy chọn) {// Hàm này được để trống để đơn giản ghi đè lên các mô-đun // muốn thêm chức năng ở đây. };
jduhls
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.