Задержка вызова AJAX на текстовое поле, чтобы позволить набирать

8

Я хотел бы отложить запуск ajax таким же образом, как кажется, что автозаполнение работает. Например, если пользователь печатает, ajax не будет работать, пока не истечет 500 мс с момента последнего нажатия клавиш.

В настоящее время я смотрю на drupal.behaviors, но не могу заставить его работать.

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

Это элемент формы, к которому привязано поведение.

$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 показывает, чего я пытаюсь достичь.

Будет ли переопределить Drupal.ajax.prototype.beforeSend? быть маршрутом, чтобы снять это?

Следующее работает для первого «набора» входов с классом .andtimer. Это не работает для любого другого набора, ajax всегда продолжается с первого набора. Любые идеи, как это исправить?

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

Используя $ form ['my_input'] ['# ajax'] ['event'] = 'finishinput', как предложено, и

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

Работает для каждой «группы» входов, где необходимо получить количество заполненных входов.

Иниго Монтойя
источник
Этот код не имеет ничего общего с keyup / keydown или привязкой к событию, на которую вы ссылаетесь - пожалуйста, не могли бы вы добавить свой реальный код? Имейте в виду, что если вы просто ищете общую справку по JavaScript, это не место, где ее можно найти. Правило таково: сначала сделайте так, чтобы он работал вне Drupal, и если вы не можете заставить его работать внутри Drupal, спросите здесь
Clive
Спасибо Клайв, я добавил код для создания ввода. Я пошел прямо на попытку и заставить это работать в Drupal. Все еще изучаю. Я выхожу на улицу и посмотрю, не смогу ли я немного прояснить проблему в моей голове.
Иниго Монтойя
Я говорил слишком рано, не понимая, как вы привязаны к Drupal, вы пытаетесь это сделать. Это делает довольно интересную проблему :)
Клайв
1
Нижний фрагмент кода работает хорошо для меня, за исключением того, что после запуска события поле теряет фокус. Как можно сделать так, чтобы фокус оставался на элементе после стрельбы.
VanD

Ответы:

7

Одним из вариантов является использование пользовательского события jQuery, например. что-то вроде готового ввода . Установите $form['my_input']['#ajax']['event'] = 'finishedinput'и предоставьте JS для запуска вашего пользовательского события после соответствующей задержки (аналогично JS в скрипке).

Энди
источник
Удивительно ! Я точно искал это :) Большое спасибо. Тем не менее, если бы я мог дать совет о том, как применить это, когда вы изменяете ввод представленной формы представления. Если я не установлю функцию обратного вызова в $ form ['my_input'] ['# ajax'], то ничего не произойдет, если я добавлю открытую форму представления представлений, отправим fn как функцию обратного вызова (или что-то еще), она будет работать, но вернет неопределенный индекс: form_build_id. .. И я не знаю ни как, ни где добавить $ form_state ['rebuild'] = TRUE Заранее спасибо
Kojo
1
@Kojo Не могли бы вы задать новый вопрос по этому поводу и включить описания настроек AJAX Views, открытого фильтра, любого пользовательского кода, который вы используете, и возникающих проблем? Кстати, автоматическая отправка CTools уже имеет (жестко заданную) задержку при отправке из текстовых полей 0,5 с ( см. Auto-submit.js ).
Энди
Ах, здорово, вот обстановка! Разве нельзя изменить его «на лету» для конкретного ввода? Если не все просто, я напишу вопрос :) Спасибо за помощь!
Кожо
1
@ Kojo Не так легко, как должно быть! Если бы это был я, я бы, вероятно, просто создал свой собственный auto-submit.js и использовал его, hook_js_alter()чтобы убедиться, что он используется вместо оригинала. (Но на самом деле имхо код ctools должен использовать Drupal.settings, а не жестко запрограммированное значение.)
Энди
1
@Kojo Также взгляните на drupal.org/node/2023705, который посвящен улучшению процесса автоматической отправки (не только для ввода текста). Есть патч, который может быть достаточно для вас. РЕДАКТИРОВАТЬ: и если вы пытаетесь использовать его, не забудьте оставить комментарий по этому вопросу, говоря, сработало ли это.
Энди
0

Этот подход имеет как преимущество, так и недостаток, поскольку он применяется ко всем событиям AJAX, запускаемым с помощью ключа, на любой странице, где выполняется этот сценарий.

!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
источник
-1

Это код, который я написал:

<!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
Добро пожаловать в ответы Drupal. Вы можете улучшить свой ответ, написав короткий параграф, объясняющий, что делает cide и как он решит проблему с OP.
Свободное Радикальное
-1

Я также попытался "beforeSend" без особой удачи. Затем я наткнулся на «beforeSubmit», и это помогает мне. Вы можете использовать эту стратегию для подключения других методов-прототипов Drupal ajax (см. /Misc/ajax.js для всех оригинальных методов):

(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));
jduhls
источник
Drupal.ajax.prototype.beforeSubmit по умолчанию является пустой функцией, поэтому этот код фактически ничего не делает. Это просто вызывает пустое с задержкой или без.
tvanc
RE: пустая функция - это правда. Пока пусто. Но API Drupal может измениться, и он может больше не быть пустым. Это безопасное переопределение. Кроме того, в настоящее время он ничего не делает, потому что это зависит от OP, чтобы вставить любые значения, которые они хотят переопределить.
Jduhls
Drupal даже говорит в коде, чтобы переопределить эту функцию: / ** * Изменить значения формы перед отправкой формы. * / Drupal.ajax.prototype.beforeSubmit = function (form_values, element, options) {// Эта функция оставлена ​​пустой, чтобы упростить ее переопределение для модулей //, которые хотят добавить сюда функциональность. };
Jduhls