How to pause an event in Javascript? - javascript

I'm trying since yesterday with my js code but it still doesn't work. So I have a select list, when I change the selected option it calls an onchange event that calls a DWR function.
The problem is the DWR function takes a while and resets my select options (the first element selected instead of the one selected), I tried to set the previous value but it works only when I add a while loop.
var valeurTypeUo = document.getElementById('selectElement').value;
// DWR function called by this function
forme.getOptions(params);
// console.log(document.getElementById('typesUoChoix').value) is empty String
while (document.getElementById('typesUoChoix').value != valeurTypeUo)
document.getElementById('typesUoChoix').value = valeurTypeUo;
This is my code, it works but there is always an alert if I want to stop the script. Is there any way to replace this while instruction?

You can use setInterval which you can clear instead of while.
Your code can be like:
var stopCheking = false;
var checkingInterval; // interval holder
var valeurTypeUo = document.getElementById('selectElement').value;
// DWR function called by this function
forme.getOptions(params);
// console.log(document.getElementById('typesUoChoix').value) is empty String
checkingInterval= setInterval( function() {
if( stopCheking ) clearInterval(checkingInterval);
}, 2);
When you want to stop the event (interval) in this case, you set the stopCheking flag to true.

You can "pause" functions with ES6 generators(yield keyword), but normally you should not need it in this case. Plain callback on the async call should do it.
Anyways here is the link for generators: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*

Related

how to stop array.filter() function

Am using custom search filter
HtML
<input type="text" pInputText class="ui-widget ui-text" [(ngModel)]
="gloablFilterValue" (ngModelChange)="splitCustomFilter()" placeholder="Find" />
I am using ngModelChange() event on search box
globalSearch(realData, searchText, columns) {
searchText = searchText.toLowerCase();
return realData.filter(function (o) {
return columns.some(function (k) {
return o[k].toString().toLowerCase().indexOf(searchText) !== -1;
});
});
}
splitCustomFilter() {
let columns =
['PartNoCompleteWheel', 'DescriptionCompleteWheel', 'PartNoTyre', 'DescriptionTyre', 'PartNoRim', 'DescriptionRim','DeletedDateFromKDPStr', 'DateFromKDPStr', 'Status'];
this.tyreAndRimList = this.globalSearch(this.tyreAndRimList, this.gloablFilterValue, columns);
}
The this.tyreAndRimList list of values for the columns which is mentioned in a column variable.
Problem
The filter is working good! But the main problem is filter performance is very poor while the record count is huge(more than 100 rows per every column)
When
The filter is working good if am entering a single character (like a). But when I was typing the character continuously the browser is hanging. the reason is the filter has been firing every typing on the filter box(because of am using ngModelChange()// onchange() event)
What I want
I want to stop filtering if the user typing continuously on the search box. Once the user has stop the typing then only I need to start filtering.
What I did
I have tried to handle this by using setTimeout(). But it just wait the filter call for a second. It is working if the user entered just 2 or 3 character's continuously. But if the user typing more than 7 or 8 or above character's, it continues to hang the browser. because of many filter callbacks are processing on the same time.
setTimeout(() => //code of filtering ,1000);
Question
How to stop filtering while user continuously entering value and start the filtering once the user has been stop the typing?
I am working in angular-2 and typescript. But this question is not related with only for angularjs or angular or JavaScript or typescript because of I want an idea not a solution. So I'll add those all tags for this question. Don't remove it. Thanks
Debounce the function. See how underscore does it here: Function Debouncing with Underscore.js.
You would then generate a debounced version of your function like this:
var globalSearchDebounced = _.debounce(globalSearch, 100, false);
It will only call after the user has stopped typing for at least one second.
It's not possible to interrupt the Array.filter method. Based on what you need you could handle this like this:
let timerId = null
function handleChange() {
if(timerId) {
clearTimeout(timerId)
}
timerId = setTimeout(() => /* Array.filter(...) */, 1000)
}
Explanation
Have a variable which will contain the timerId returned from the setTimeout function. Every time the model get changed the handleChange function will be called (in this example). The function checks if the variable which contains the timerId is set and contains a timerId, when the variable contains the timerId the clearTimeout function will be called to clear the previous timeout after that the handleChange creates a new timeout and assigns the timerId (returned from the setTimeout function) to the variable.
Documentation for setTimeout
Documentation for clearTimeout
Without underscore, and without a Timeout (that will trigger the whole Angular lifecycle by the way), you can use an Observable with the async pipe and a debounce.
In your global search function :
return Observable.of(/* filter here and return the filtered array */).debounceTime(1000)
In your list (that has to be somewhere I guess)
<list-item *ngFor="let x of myFilteredResults | async">...</list-item>
I have complete it by using Subject to debounceTime.
private subject = new Subject<string>()
ngOnInit() {
this.subject.debounceTime(300).subscribe(inputText => {
this.gloablFilterValue = inputText;
this.splitCustomFilter(); // filter method
});
}
Now when I change the value in this.gloablFilterValue object by using change event. It just waiting for the end of event completion.

Why when i call a function with returning value, my onclick event doesn't work?

I minified my work in this simple code that represent my problem:
runSomething();
function runSomething(){
function getRandom(){
var random = Math.floor((Math.random())*10);
return random;
};
document.onclick = getRandom();
};
There is a external function (runSomething()) that contains the next:
A function called getRandom that returns a number between 0 - 9 (that i'm using to a select a random item of a array)
And a the document.onclick = getRandom(); that what is supposed to do, is RUN getRandom(); each time i click any place of the document, to get another new value
But what happens? the document.onclick = getRandom(); just run once (when the document is being loaded) but nothing happens when a click the document
And getRandom() must not be fired when the document is being loaded, because that function is fired in other part of the script, and thats mean that i will get 2 differents new values (remember that getRandom() return different numbers each time that is fired)
What i'm doing wrong?
P.S. I still a rookie in JS
P.P.S. Sorry for my english
Remove the ()
document.onclick = getRandom;
The () will invoke the function immediately on load, you have to pass the function along.
When you assign onClick, you need to assign the function rather than execute it and assign the return value (which is what your () do):
document.onclick = getRandom;

slideshow counter disappears

I have this code that is supposed to generate a counter for a slideshow and then change the picture and the corresponding number color in the counter. However, after the slideshow cycles through twice, the counter changes to display:none and then reappears and disappears every time the slideshow begins its cycle.
//icons for newsreel guide
for(i=0;i<document.getElementsByClassName("news").length;i++){
var count=i+1;
$('#counter').append('<span class="count">'+count+'</span>');
}
//newsreel script
$(".news").hide();
setTimeout (function() {
var wait = $(".news:last").index()*12000+12000;
function newsreel(){
var i=0;
(function showNews(elem){
if(i==document.getElementsByClassName("count").length){
i=0;
}
document.getElementsByClassName("count")[i].style.color="#000";
elem.fadeIn(2000,function(){
elem.delay(8000).fadeOut(2000,function(){
document.getElementsByClassName("count")[i].style.color="#3159a0";
i=i+1;
$(this).next().length && showNews($(this).next());
});
});
})
( $(".news:first"));
setTimeout (arguments.callee, wait);
}/*end newsreel()*/
newsreel();
}, 2000);
At first I thought it was using the deprecated arguments.callee but I changed that and it still happens on cue. Any ideas?
I checked your code, and the problem is in this line :
$(this).next().length && showNews($(this).next())
.next() is getting the next sibling. Your counter is a sibling of .news. To solve your problem, do this:
$(this).next().length && showNews($(this).next('.news'))
That will select the next sibling with the class news.
I suspect it's because your showNews function is never running. I think the JavaScript engine is evaluating
(function showNews(elem){
//...
})
and
( $(".news:first"));
as two different expressions, rather than passing $(".news:first") as a parameter to showNews as you intend. Since ; at the end of a line is optional in JS, the parser will insert one automatically if the result is valid JavaScript. In this case, it defines a function but never calls it, then builds a jQuery sequence but never uses it.
Try removing the carriage return between the two:
(function showNews(elem){
//...
})($(".news:first"));

Trying to get some jQuery functions to run in order. Is callback the issue?

I'm trying to do some things in order, and I'm having some trouble.
When the button with the id #sub_button is clicked,
Make sure each element with class ".verify" has it's own object value (see code)...
... if not, blur that element (will run some other code and create an object for it).
AFTER the above IF check is COMPLETE (now all elements should have an object), THEN run function "isitgood". (The "isitgood" function is running before all elements get their object values, which is done on blur)
$("#sub_button").click(function() {
$(".verify").each(function(){
objtitle = $(this).attr('id');
if (!myObj[objtitle]) {
$("#"+objtitle).blur(); // Define anything undefined
}
}); // end each
isitgood();
}); // end click function
function isitgood(){
if (myObj.login_id == "ok" && myObj.email == "ok") {
// submit the form
} else {
// shows error
}
}
Also, once I get this executing in the right order, it would be nice to do some sort of .each loop to check if all the object values == "ok" instead of specifying all of them in the function. All of the names of the objects (ie. login_id, email) are the ID attr of any element with class name .verify.
Well, you could do a quick index check in the click callback:
var sub_buttons = $("#sub_button");
sub_buttons.click(function() {
$(".verify").each(function(index){
objtitle = $(this).attr('id');
if (!myObj[objtitle]) {
$("#"+objtitle).blur(); // Define anything undefined
}
if (index == sub_buttons.length - 1)
isitgood();
}
}); // end each
}); // end click function
This will check if you're on the last element in the jQuery object, and if so, will run the isitgood() function. This way, you make sure that you're finished with the $.each method before executing isitgood()
Javascript is asynchronous. Your isitgood() will always fire while .each is still doing it's thing.
That said from your code it's not clear what you're trying to accomplish. The way you're using .each seems to indicate that you have multiple of the same ID attributes on your tags. That won't work, IDs have to be unique. Also you seem to be mixing jQuery and regular Javascript. Use one or the other. Actually just use jQuery, you'll save yourself time and effort!
If you do have unique ids then you shouldn't need the .each at all. Just check the appropriate ids with your if statement.
Please provide more of your code and i can update this with a better answer. For instance what does your myObj look like? How do elements of it get the value of ok? It doesn't seem to get set within your call to .each().

List all live events in jQuery

How could I find in jQuery what events are bound with live for a particular element?
Say I have a function, randomFunction, that returns a random function from an array of functions. How can I find which function has been bound to a certain element?
var arrayOfFunctions = []; //a whole bunch of functions
function randomFunction(array){}; //returns one of those functions
$('#certain_element').live('click', randomFunction(arrayOfFunctions));
What is the index of the array that corresponds to the function that was bound by live for $('#certain_element')?
Alright, figured it out.
For a click event, for $('#certain_element'), logging each binding's index to the console:
var relevantHandlers = $.map($(document).data('events').live, function(value){
if(value.origType == 'click' && value.selector == '#certain_element'){
return value.handler;
}
}; //all handlers for #certain_element bound to click by live.
$.each(relevantHandlers, function(){
console.log("the index is: " + $.inArray(this, arrayOfFunctions));
});
Take a look at this plugin. When I last used this, there was a need to slightly modify it for the then latest version of jQuery, but it should give you a direction.
There's a nifty bookmarklet called Visual Event that shows the code that will be called.
But since you're truly calling a random function, maybe doing something as simple as including an alert("function name") or colsone.log("function"), if you're just testing.

Categories

Resources