javascript - w3school - jquery link



كيفية تأخير معالج.keyup() حتى يتوقف المستخدم عن الكتابة؟ (16)

لدي حقل بحث الآن يبحث عن كل لوحة مفاتيح. لذا إذا قام أحدهم بكتابة "Windows" ، فسيقوم بإجراء بحث باستخدام AJAX لكل لوحة مفاتيح: "W" ، "Wi" ، "Win" ، "Wind" ، "Windo" ، "Window" ، "Windows".

أرغب في الحصول على تأخير ، لذلك لا يبحث إلا عندما يتوقف المستخدم عن الكتابة 200 مللي ثانية.

لا يوجد خيار لهذا في وظيفة keyup ، ولقد جربت setTimeout ، لكنها لم تنجح.

كيف أقوم بذلك؟


أنا مندهش أن لا أحد يذكر المشكلة مع العديد من المدخلات في CMS لطيف جدا قصتها.

في الأساس ، سيتعين عليك تحديد متغير التأخير بشكل فردي لكل إدخال. وإلا إذا وضعت sb النص على الإدخال الأول والقفز بسرعة إلى مدخلات أخرى والبدء في الكتابة ، سيتم استدعاء معاودة الاتصال لأول واحد لن يكون!

انظر الكود أدناه جئت بناء على إجابات أخرى:

(function($) {
    /**
     * KeyUp with delay event setup
     * 
     * @link http://.com/questions/1909441/jquery-keyup-delay#answer-12581187
     * @param function callback
     * @param int ms
     */
    $.fn.delayKeyup = function(callback, ms){
            $(this).keyup(function( event ){
                var srcEl = event.currentTarget;
                if( srcEl.delayTimer )
                    clearTimeout (srcEl.delayTimer );
                srcEl.delayTimer = setTimeout(function(){ callback( $(srcEl) ); }, ms);
            });

        return $(this);
    };
})(jQuery);

يحافظ هذا الحل على مرجع setTimeout ضمن متغير delayTimer الخاص بالإدخال. كما يمرر مرجع عنصر لاستدعاء كما اقترح fazzyx.

تم اختباره في IE6 و 8 (comp - 7) و 8 و Opera 12.11.


إذا أراد شخص ما تأخير الوظيفة نفسها ، وبدون متغير خارجي ، فيمكنه استخدام النص التالي:

function MyFunction() {

    //Delaying the function execute
    if (this.timer) {
        window.clearTimeout(this.timer);
    }
    this.timer = window.setTimeout(function() {

        //Execute the function code here...

    }, 500);
}

إلقاء نظرة على البرنامج المساعد autocomplete . أعلم أنه يسمح لك بتحديد تأخير أو الحد الأدنى لعدد الأحرف. حتى في حالة عدم استخدامك للمكوِّن الإضافي ، فإن البحث في الشفرة سيعطيك بعض الأفكار حول كيفية تنفيذه بنفسك.


إليك اقتراح قمت بكتابته يعتني بإدخال متعدد في النموذج الخاص بك.

تحصل هذه الوظيفة على كائن حقل الإدخال ، وتوضع في التعليمات البرمجية

function fieldKeyup(obj){
    //  what you want this to do

} // fieldKeyup

هذه هي وظيفة delayCall الفعلية ، وتعتني بمجالات إدخال متعددة

function delayCall(obj,ms,fn){
    return $(obj).each(function(){
    if ( typeof this.timer == 'undefined' ) {
       // Define an array to keep track of all fields needed delays
       // This is in order to make this a multiple delay handling     
          function
        this.timer = new Array();
    }
    var obj = this;
    if (this.timer[obj.id]){
        clearTimeout(this.timer[obj.id]);
        delete(this.timer[obj.id]);
    }

    this.timer[obj.id] = setTimeout(function(){
        fn(obj);}, ms);
    });
}; // delayCall

الاستعمال:

$("#username").on("keyup",function(){
    delayCall($(this),500,fieldKeyup);
});


استعمال

mytimeout = setTimeout( expression, timeout );

حيث التعبير هو البرنامج النصي لتشغيل و timeout هو وقت الانتظار بالمللي ثانية قبل تشغيله - هذا لا يؤدي إلى إهانة البرنامج النصي ، ولكنه ببساطة يؤخر تنفيذ ذلك الجزء حتى يتم انتهاء المهلة.

clearTimeout(mytimeout);

سيؤدي إلى إعادة ضبط / إلغاء المهلة بحيث لا يتم تشغيل النص البرمجي في التعبير (مثل الإلغاء) طالما لم يتم تنفيذه بعد.


استنادًا إلى إجابة نظام إدارة المحتوى ، يتجاهل فقط الأحداث الرئيسية التي لا تغير القيمة.

var delay = (function(){
    var timer = 0;
    return function(callback, ms){
      clearTimeout (timer);
      timer = setTimeout(callback, ms);
    };
})(); 

var duplicateFilter=(function(){
  var lastContent;
  return function(content,callback){
    content=$.trim(content);
    if(content!=lastContent){
      callback(content);
    }
    lastContent=content;
  };
})();

$("#some-input").on("keyup",function(ev){

  var self=this;
  delay(function(){
    duplicateFilter($(self).val(),function(c){
        //do sth...
        console.log(c);
    });
  }, 1000 );


})

بناءً على إجابة نظام إدارة المحتوى ، إليك طريقة التأخير الجديدة التي تحافظ على "هذا" في استخدامه:

var delay = (function(){
  var timer = 0;
  return function(callback, ms, that){
    clearTimeout (timer);
    timer = setTimeout(callback.bind(that), ms);
  };
})();

الاستعمال:

$('input').keyup(function() {
    delay(function(){
      alert('Time elapsed!');
    }, 1000, this);
});

تعمل هذه الوظيفة على توسيع الوظيفة من إجابة Gaten قليلاً لاستعادة العنصر:

$.fn.delayKeyup = function(callback, ms){
    var timer = 0;
    var el = $(this);
    $(this).keyup(function(){                   
    clearTimeout (timer);
    timer = setTimeout(function(){
        callback(el)
        }, ms);
    });
    return $(this);
};

$('#input').delayKeyup(function(el){
    //alert(el.val());
    // Here I need the input element (value for ajax call) for further process
},1000);

http://jsfiddle.net/Us9bu/2/


حسنا ، أنا أيضا جعلت قطعة من رمز للحد من طلب ajax عالية التردد سبب بواسطة Keyup / Keydown. تحقق من هذا:

https://github.com/raincious/jQueue

استفسارك مثل هذا:

var q = new jQueue(function(type, name, callback) {
    return $.post("/api/account/user_existed/", {Method: type, Value: name}).done(callback);
}, 'Flush', 1500); // Make sure use Flush mode.

وربط الحدث مثل هذا:

$('#field-username').keyup(function() {
    q.run('Username', this.val(), function() { /* calling back */ });
});

طريقة بسيطة للغاية ، مصممة لتشغيل وظيفة بعد أن ينتهي المستخدم من الكتابة في حقل النص ...

<script type="text/javascript">
$(document).ready(function(e) {
    var timeout;
    var delay = 2000;   // 2 seconds

    $('.text-input').keyup(function(e) {
        console.log("User started typing!");
        if(timeout) {
            clearTimeout(timeout);
        }
        timeout = setTimeout(function() {
            myFunction();
        }, delay);
    });

    function myFunction() {
        console.log("Executing function for user!");
    }
});
</script>

<textarea name="text-input" class="text-input"></textarea>

هذا هو الحل على غرار CMS ، لكنه يحل بعض المشاكل الرئيسية بالنسبة لي:

  • يدعم مدخلات متعددة ، والتأخير يمكن أن يعمل في وقت واحد.
  • يتجاهل الأحداث الرئيسية التي لم تغير القيمة (مثل Ctrl ، Alt + Tab).
  • يحل شرط سباق (عند تنفيذ رد الاتصال وتغيير القيمة بالفعل).
var delay = (function() {
    var timer = {}
      , values = {}
    return function(el) {
        var id = el.form.id + '.' + el.name
        return {
            enqueue: function(ms, cb) {
                if (values[id] == el.value) return
                if (!el.value) return
                var original = values[id] = el.value
                clearTimeout(timer[id])
                timer[id] = setTimeout(function() {
                    if (original != el.value) return // solves race condition
                    cb.apply(el)
                }, ms)
            }
        }
    }
}())

الاستعمال:

signup.key.addEventListener('keyup', function() {
    delay(this).enqueue(300, function() {
        console.log(this.value)
    })
})

تمت كتابة التعليمة البرمجية بأسلوب استمتع به ، فقد تحتاج إلى إضافة مجموعة من الفواصل المنقوطة.

أشياء لتأخذها بالحسبان:

  • يتم إنشاء معرّف فريد استنادًا إلى معرف النموذج واسم الإدخال ، لذا يجب تحديدهما وفردهما ، أو يمكنك تعديله وفقًا لموقفك.
  • تأخير إرجاع كائن من السهل تمديد لاحتياجاتك الخاصة.
  • يرتبط العنصر الأصلي المستخدم للتأخير بإعادة الاتصال ، لذا يعمل this كما هو متوقع (كما في المثال).
  • يتم تجاهل القيمة الفارغة في التحقق الثاني.
  • احترس من الحقل ، تتوقع ملي ثانية أولا ، أنا أفضل ذلك ، ولكن قد ترغب في تبديل المعلمات لتتناسب مع setTimeout .

يضيف الحل الذي أستخدمه مستوى آخر من التعقيد ، مما يسمح لك بإلغاء التنفيذ ، على سبيل المثال ، ولكن هذه قاعدة جيدة للبناء عليها.


وقد نجحت في ذلك حيث أتأخر عملية البحث المنطقي وأجري تحققًا إذا كانت القيمة نفسها كما تم إدخالها في حقل النص. إذا كانت القيمة نفسها ، فأنا أمضي قدمًا وأجري العملية للبيانات ذات الصلة بقيمة البحث.

$('#searchText').on('keyup',function () {
    var searchValue = $(this).val();
    setTimeout(function(){
        if(searchValue == $('#searchText').val() && searchValue != null && searchValue != "") {
           // logic to fetch data based on searchValue
        }
        else if(searchValue == ''){
           // logic to load all the data
        }
    },300);
});

يمكنك أيضًا الاطلاع على underscore.js ، التي توفر طرقًا debounce مثل debounce :

var lazyLayout = _.debounce(calculateLayout, 300);
$(window).resize(lazyLayout);

تأخير المكالمات متعددة الوظائف باستخدام تسميات

هذا هو الحل الذي أعمل معه. سيؤخر التنفيذ على أي وظيفة تريدها . يمكن أن يكون الاستعلام عن البحث في keydown ، ربما النقر السريع على الأزرار السابقة أو التالية (التي من شأنها أن ترسل طلبًا متعددًا إذا نقرت بسرعة بشكل مستمر ، ولا يتم استخدامها بعد كل شيء). يستخدم هذا كائنًا عموميًا يخزن كل وقت تنفيذ ، ويقارنه بأكثر الطلبات الحالية.

إذاً فالنتيجة هي أن هذه النقرة / الإجراء الأخير فقط ستتم استدعائها بالفعل ، لأنه يتم تخزين تلك الطلبات في قائمة الانتظار ، وذلك بعد استدعاء x مللي ثانية إذا لم يكن هناك طلب آخر بنفس التسمية موجود في قائمة الانتظار!

function delay_method(label,callback,time){
    if(typeof window.delayed_methods=="undefined"){window.delayed_methods={};}  
    delayed_methods[label]=Date.now();
    var t=delayed_methods[label];
    setTimeout(function(){ if(delayed_methods[label]!=t){return;}else{  callback();}}, time||500);
  }

يمكنك ضبط وقت التأخير الخاص بك (اختياري ، الافتراضي إلى 500ms). وإرسال حجج وظيفتك في "إغلاق الموضة".

على سبيل المثال ، إذا كنت تريد استدعاء الوظيفة التالية:

function send_ajax(id){console.log(id);}

لمنع طلبات send_ajax متعددة ، يمكنك تأخيرها باستخدام:

delay_method( "check date", function(){ send_ajax(2); } ,600);

سيتم تشغيل كل طلب يستخدم العلامة "تاريخ التحقق" فقط إذا لم يتم تقديم طلب آخر في الإطار الزمني 600 ميلي ثانية. هذه الوسيطة اختيارية

تصنيف الاستقلاب (استدعاء نفس وظيفة الهدف) ولكن تشغيل كلا:

delay_method("check date parallel", function(){send_ajax(2);});
delay_method("check date", function(){send_ajax(2);});

النتائج في استدعاء نفس الوظيفة ولكن تأخيرها بشكل مستقل بسبب اختلاف علاماتها


var globalTimeout = null;  
$('#search').keyup(function(){
  if(globalTimeout != null) clearTimeout(globalTimeout);  
  globalTimeout =setTimeout(SearchFunc,200);  
});
function SearchFunc(){  
  globalTimeout = null;  
  console.log('Search: '+$('#search').val());
  //ajax code
};




jquery